382 lines
21 KiB
Python
382 lines
21 KiB
Python
#!/usr/bin/env python
|
|
"""
|
|
heroes renaissance
|
|
copyright 2008 - Johannes 'josch' Schauer <j.schauer@email.de>
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
"""
|
|
|
|
import pyglet
|
|
from ctypes import create_string_buffer, memmove
|
|
from lib import h3m
|
|
import os
|
|
|
|
class OrderedTextureGroup(pyglet.graphics.Group):
|
|
def __init__(self, order, texture, parent=None):
|
|
super(OrderedTextureGroup, self).__init__(parent)
|
|
self.texture = texture
|
|
self.order = order
|
|
|
|
def set_state(self):
|
|
pyglet.gl.glEnable(self.texture.target)
|
|
pyglet.gl.glBindTexture(self.texture.target, self.texture.id)
|
|
|
|
def unset_state(self):
|
|
pyglet.gl.glDisable(self.texture.target)
|
|
|
|
def __hash__(self):
|
|
return hash((self.order, self.texture.target, self.texture.id,
|
|
self.parent))
|
|
|
|
def __eq__(self, other):
|
|
return (self.__class__ is other.__class__ and
|
|
self.order == other.order and
|
|
self.texture.target == other.texture.target and
|
|
self.texture.id == other.texture.id and
|
|
self.parent == self.parent)
|
|
|
|
def __repr__(self):
|
|
return '%s(id=%d)' % (self.__class__.__name__, self.order,
|
|
self.texture.id)
|
|
|
|
def __cmp__(self, other):
|
|
if isinstance(other, OrderedTextureGroup):
|
|
return cmp(self.order, other.order)
|
|
return -1
|
|
|
|
class Animation(object):
|
|
def __init__(self, tex_region, frames, flip_x=False, flip_y=False):
|
|
self.texgroup = tex_region.group
|
|
if flip_x or flip_y:
|
|
self.tex = tex_region.get_transform(flip_x=flip_x, flip_y=flip_y)
|
|
else:
|
|
self.tex = tex_region
|
|
self.__frames = []
|
|
for img in frames:
|
|
data_pitch = abs(img._current_pitch)
|
|
buf = create_string_buffer(len(img._current_data))
|
|
memmove(buf, img._current_data, len(img._current_data))
|
|
data = buf.raw
|
|
rows = [data[i:i + abs(data_pitch)] for i in
|
|
xrange(len(img._current_data)-abs(data_pitch),
|
|
-1, -abs(data_pitch))]
|
|
self.__frames.append(''.join(rows))
|
|
self.__animation = 0
|
|
self.width = self.tex.width
|
|
self.height = self.tex.height
|
|
self.__hash = hash(self.__frames[0])
|
|
|
|
def next_frame(self):
|
|
self.__animation = (self.__animation + 1) % len(self.__frames)
|
|
return self.__frames[self.__animation]
|
|
|
|
@property
|
|
def tex_coords(self):
|
|
return self.tex.tex_coords
|
|
|
|
@property
|
|
def group(self):
|
|
return self.texgroup
|
|
|
|
def __hash__(self):
|
|
return self.__hash
|
|
|
|
def __eq__(self, other):
|
|
return self.__hash == other.__hash
|
|
|
|
class MapSet(object):
|
|
def load_map_object(self, file, order=0):
|
|
image = pyglet.image.load(None, file=pyglet.resource.file(file))
|
|
try:
|
|
texture_region = self.current_atlas.add(image)
|
|
except pyglet.image.atlas.AllocatorException:
|
|
self.current_atlas = pyglet.image.atlas.TextureAtlas(1024, 1024)
|
|
texture_region = self.current_atlas.add(image)
|
|
group = OrderedTextureGroup(order, self.current_atlas.texture)
|
|
|
|
if group not in self.groups:
|
|
self.groups.append(group)
|
|
|
|
texture_region.group = self.groups.index(group)
|
|
return texture_region
|
|
|
|
def __init__(self, map_name):
|
|
h3m_data = h3m.extract(os.path.join(pyglet.resource._default_loader._script_home,"maps","%s.h3m" % map_name))
|
|
edge_map = [[] for i in xrange(len(h3m_data["upper_terrain"])+16)]
|
|
for num in xrange(len(edge_map)):
|
|
if num < 7 or num > len(edge_map)-8:
|
|
line = []
|
|
line.extend([[-1, 0+(i-1)%4+4*(num%4), 0, 0, 0, 0, 0] for i in xrange(len(h3m_data["upper_terrain"][0])+18)])
|
|
elif num == 7:
|
|
line = []
|
|
line.extend([[-1, 0+(i-1)%4+4*(num%4), 0, 0, 0, 0, 0] for i in xrange(8)])
|
|
line.append([-1, 16, 0, 0, 0, 0, 0])
|
|
line.extend([[-1, 20+i%4, 0, 0, 0, 0, 0] for i in xrange(len(h3m_data["upper_terrain"][0]))])
|
|
line.append([-1, 17, 0, 0, 0, 0, 0])
|
|
line.extend([[-1, 0+(i-1)%4+4*(num%4), 0, 0, 0, 0, 0] for i in xrange(8)])
|
|
elif num == len(edge_map)-8:
|
|
line = []
|
|
line.extend([[-1, 0+(i-1)%4+4*(num%4), 0, 0, 0, 0, 0] for i in xrange(8)])
|
|
line.append([-1, 19, 0, 0, 0, 0, 0])
|
|
line.extend([[-1, 28+i%4, 0, 0, 0, 0, 0] for i in xrange(len(h3m_data["upper_terrain"][0]))])
|
|
line.append([-1, 18, 0, 0, 0, 0, 0])
|
|
line.extend([[-1, 0+(i-1)%4+4*(num%4), 0, 0, 0, 0, 0] for i in xrange(8)])
|
|
else:
|
|
line = []
|
|
line.extend([[-1, 0+(i-1)%4+4*(num%4), 0, 0, 0, 0, 0] for i in xrange(8)])
|
|
line.append([-1, 32+num%4, 0, 0, 0, 0, 0])
|
|
line.extend(h3m_data["upper_terrain"][num-8])
|
|
line.append([-1, 24+num%4, 0, 0, 0, 0, 0])
|
|
line.extend([[-1, 0+(i-1)%4+4*(num%4), 0, 0, 0, 0, 0] for i in xrange(8)])
|
|
edge_map[num] = line
|
|
h3m_data["upper_terrain"] = edge_map
|
|
|
|
self.width = len(h3m_data["upper_terrain"][0])
|
|
self.height = len(h3m_data["upper_terrain"])
|
|
|
|
self.current_atlas = pyglet.image.atlas.TextureAtlas(1024, 1024)
|
|
|
|
self.groups = []
|
|
|
|
self.__tiles = {}
|
|
tile_textures = {}
|
|
for y, line in enumerate(h3m_data["upper_terrain"]):
|
|
for x, tile in enumerate(line):
|
|
if tile[0] == -1: #edge
|
|
if "edg" not in tile_textures.keys():
|
|
tile_textures["edg"] = [self.load_map_object('data/advmap_tiles/edg.def/%d.png'%i, 100) for i in xrange(36)]
|
|
self.__tiles[x,y] = [tile_textures["edg"][tile[1]]]
|
|
elif tile[0] == 0: #dirt
|
|
if "dirttl" not in tile_textures.keys():
|
|
tile_textures["dirttl"] = [self.load_map_object('data/advmap_tiles/dirttl.def/%d.png'%i, 0) for i in xrange(46)]
|
|
flip_x = bool(tile[6] & 1)
|
|
flip_y = bool(tile[6] & 2)
|
|
if flip_x or flip_y:
|
|
new = tile_textures["dirttl"][tile[1]].get_transform(flip_x=flip_x, flip_y=flip_y)
|
|
new.group = tile_textures["dirttl"][tile[1]].group
|
|
self.__tiles[x,y] = [new]
|
|
else:
|
|
self.__tiles[x,y] = [tile_textures["dirttl"][tile[1]]]
|
|
elif tile[0] == 1: #sand
|
|
if "sandtl" not in tile_textures.keys():
|
|
tile_textures["sandtl"] = [self.load_map_object('data/advmap_tiles/sandtl.def/%d.png'%i, 0) for i in xrange(24)]
|
|
self.__tiles[x,y] = [tile_textures["sandtl"][tile[1]]]
|
|
elif tile[0] == 2: #grass
|
|
if "grastl" not in tile_textures.keys():
|
|
tile_textures["grastl"] = [self.load_map_object('data/advmap_tiles/grastl.def/%d.png'%i, 0) for i in xrange(79)]
|
|
flip_x = bool(tile[6] & 1)
|
|
flip_y = bool(tile[6] & 2)
|
|
if flip_x or flip_y:
|
|
new = tile_textures["grastl"][tile[1]].get_transform(flip_x=flip_x, flip_y=flip_y)
|
|
new.group = tile_textures["grastl"][tile[1]].group
|
|
self.__tiles[x,y] = [new]
|
|
else:
|
|
self.__tiles[x,y] = [tile_textures["grastl"][tile[1]]]
|
|
elif tile[0] == 3: #snow
|
|
if "snowtl" not in tile_textures.keys():
|
|
tile_textures["snowtl"] = [self.load_map_object('data/advmap_tiles/snowtl.def/%d.png'%i, 0) for i in xrange(79)]
|
|
flip_x = bool(tile[6] & 1)
|
|
flip_y = bool(tile[6] & 2)
|
|
if flip_x or flip_y:
|
|
new = tile_textures["snowtl"][tile[1]].get_transform(flip_x=flip_x, flip_y=flip_y)
|
|
new.group = tile_textures["snowtl"][tile[1]].group
|
|
self.__tiles[x,y] = [new]
|
|
else:
|
|
self.__tiles[x,y] = [tile_textures["snowtl"][tile[1]]]
|
|
elif tile[0] == 4: #swamp
|
|
if "swmptl" not in tile_textures.keys():
|
|
tile_textures["swmptl"] = [self.load_map_object('data/advmap_tiles/swmptl.def/%d.png'%i, 0) for i in xrange(79)]
|
|
flip_x = bool(tile[6] & 1)
|
|
flip_y = bool(tile[6] & 2)
|
|
if flip_x or flip_y:
|
|
new = tile_textures["swmptl"][tile[1]].get_transform(flip_x=flip_x, flip_y=flip_y)
|
|
new.group = tile_textures["swmptl"][tile[1]].group
|
|
self.__tiles[x,y] = [new]
|
|
else:
|
|
self.__tiles[x,y] = [tile_textures["swmptl"][tile[1]]]
|
|
elif tile[0] == 5: #rough
|
|
if "rougtl" not in tile_textures.keys():
|
|
tile_textures["rougtl"] = [self.load_map_object('data/advmap_tiles/rougtl.def/%d.png'%i, 0) for i in xrange(79)]
|
|
flip_x = bool(tile[6] & 1)
|
|
flip_y = bool(tile[6] & 2)
|
|
if flip_x or flip_y:
|
|
new = tile_textures["rougtl"][tile[1]].get_transform(flip_x=flip_x, flip_y=flip_y)
|
|
new.group = tile_textures["rougtl"][tile[1]].group
|
|
self.__tiles[x,y] = [new]
|
|
else:
|
|
self.__tiles[x,y] = [tile_textures["rougtl"][tile[1]]]
|
|
elif tile[0] == 7: #lava
|
|
if "lavatl" not in tile_textures.keys():
|
|
tile_textures["lavatl"] = [self.load_map_object('data/advmap_tiles/lavatl.def/%d.png'%i, 0) for i in xrange(79)]
|
|
flip_x = bool(tile[6] & 1)
|
|
flip_y = bool(tile[6] & 2)
|
|
if flip_x or flip_y:
|
|
new = tile_textures["lavatl"][tile[1]].get_transform(flip_x=flip_x, flip_y=flip_y)
|
|
new.group = tile_textures["lavatl"][tile[1]].group
|
|
self.__tiles[x,y] = [new]
|
|
else:
|
|
self.__tiles[x,y] = [tile_textures["lavatl"][tile[1]]]
|
|
elif tile[0] == 8: #water 12 anims
|
|
if "watrtl" not in tile_textures.keys():
|
|
textures = [self.load_map_object('data/advmap_tiles/watrtl.def/%d/0.png'%i, 0) for i in xrange(33)]
|
|
images = [[pyglet.image.load(None, file=pyglet.resource.file('data/advmap_tiles/watrtl.def/%d/%d.png'%(i,j))) for j in xrange(12)] for i in xrange(33)]
|
|
tile_textures["watrtl"] = {
|
|
(0,0):[Animation(texture, images[i]) for i, texture in enumerate(textures)],
|
|
(1,0):[Animation(texture, images[i], flip_x=True) for i, texture in enumerate(textures)],
|
|
(0,1):[Animation(texture, images[i], flip_y=True) for i, texture in enumerate(textures)],
|
|
(1,1):[Animation(texture, images[i], flip_x=True, flip_y=True) for i, texture in enumerate(textures)],
|
|
}
|
|
flip_x = (tile[6]>>0)&1
|
|
flip_y = (tile[6]>>1)&1
|
|
self.__tiles[x,y] = [tile_textures["watrtl"][flip_x, flip_y][tile[1]]]
|
|
elif tile[0] == 9: #rock
|
|
if "rocktl" not in tile_textures.keys():
|
|
tile_textures["rocktl"] = [self.load_map_object('data/advmap_tiles/rocktl.def/%d.png'%i, 0) for i in xrange(48)]
|
|
self.__tiles[x,y] = [tile_textures["rocktl"][tile[1]]]
|
|
else:
|
|
raise NotImplementedError
|
|
|
|
if tile[2] == 0: #no river
|
|
pass
|
|
elif tile[2] == 1: #clrrvr 12 anims
|
|
if "clrrvr" not in tile_textures.keys():
|
|
textures = [self.load_map_object('data/advmap_tiles/clrrvr.def/%d/0.png'%i, 1) for i in xrange(13)]
|
|
images = [[pyglet.image.load(None, file=pyglet.resource.file('data/advmap_tiles/clrrvr.def/%d/%d.png'%(i,j))) for j in xrange(12)] for i in xrange(13)]
|
|
tile_textures["clrrvr"] = {
|
|
(0,0):[Animation(texture, images[i]) for i, texture in enumerate(textures)],
|
|
(1,0):[Animation(texture, images[i], flip_x=True) for i, texture in enumerate(textures)],
|
|
(0,1):[Animation(texture, images[i], flip_y=True) for i, texture in enumerate(textures)],
|
|
(1,1):[Animation(texture, images[i], flip_x=True, flip_y=True) for i, texture in enumerate(textures)],
|
|
}
|
|
flip_x = (tile[6]>>2)&1
|
|
flip_y = (tile[6]>>3)&1
|
|
self.__tiles[x,y].append(tile_textures["clrrvr"][flip_x, flip_y][tile[3]])
|
|
elif tile[2] == 2: #icyrvr
|
|
if "icyrvr" not in tile_textures.keys():
|
|
tile_textures["icyrvr"] = [self.load_map_object('data/advmap_tiles/icyrvr.def/%d.png'%i, 1) for i in xrange(13)]
|
|
flip_x = bool(tile[6] & 4)
|
|
flip_y = bool(tile[6] & 8)
|
|
if flip_x or flip_y:
|
|
new = tile_textures["icyrvr"][tile[3]].get_transform(flip_x=flip_x, flip_y=flip_y)
|
|
new.group = tile_textures["icyrvr"][tile[3]].group
|
|
self.__tiles[x, y].append(new)
|
|
else:
|
|
self.__tiles[x, y].append(tile_textures["icyrvr"][tile[3]])
|
|
elif tile[2] == 3: #mudrvr
|
|
if "mudrvr" not in tile_textures.keys():
|
|
textures = [self.load_map_object('data/advmap_tiles/mudrvr.def/%d/0.png'%i, 1) for i in xrange(13)]
|
|
images = [[pyglet.image.load(None, file=pyglet.resource.file('data/advmap_tiles/clrrvr.def/%d/%d.png'%(i,j))) for j in xrange(12)] for i in xrange(13)]
|
|
tile_textures["mudrvr"] = {
|
|
(0,0):[Animation(texture, images[i]) for i, texture in enumerate(textures)],
|
|
(1,0):[Animation(texture, images[i], flip_x=True) for i, texture in enumerate(textures)],
|
|
(0,1):[Animation(texture, images[i], flip_y=True) for i, texture in enumerate(textures)],
|
|
(1,1):[Animation(texture, images[i], flip_x=True, flip_y=True) for i, texture in enumerate(textures)],
|
|
}
|
|
flip_x = (tile[6]>>2)&1
|
|
flip_y = (tile[6]>>3)&1
|
|
self.__tiles[x,y].append(tile_textures["mudrvr"][flip_x, flip_y][tile[3]])
|
|
elif tile[2] == 4: #lavrvr
|
|
if "lavrvr" not in tile_textures.keys():
|
|
textures = [self.load_map_object('data/advmap_tiles/lavrvr.def/%d/0.png'%i, 1) for i in xrange(13)]
|
|
images = [[pyglet.image.load(None, file=pyglet.resource.file('data/advmap_tiles/clrrvr.def/%d/%d.png'%(i,j))) for j in xrange(9)] for i in xrange(13)]
|
|
tile_textures["lavrvr"] = {
|
|
(0,0):[Animation(texture, images[i]) for i, texture in enumerate(textures)],
|
|
(1,0):[Animation(texture, images[i], flip_x=True) for i, texture in enumerate(textures)],
|
|
(0,1):[Animation(texture, images[i], flip_y=True) for i, texture in enumerate(textures)],
|
|
(1,1):[Animation(texture, images[i], flip_x=True, flip_y=True) for i, texture in enumerate(textures)],
|
|
}
|
|
flip_x = (tile[6]>>2)&1
|
|
flip_y = (tile[6]>>3)&1
|
|
self.__tiles[x,y].append(tile_textures["lavrvr"][flip_x, flip_y][tile[3]])
|
|
else:
|
|
raise NotImplementedError, tile[2]
|
|
|
|
if tile[4] == 0: #no road
|
|
pass
|
|
elif tile[4] == 1: #dirtrd
|
|
if "dirtrd" not in tile_textures.keys():
|
|
tile_textures["dirtrd"] = [self.load_map_object('data/advmap_tiles/dirtrd.def/%d.png'%i, 1) for i in xrange(17)]
|
|
flip_x = bool(tile[6] & 16)
|
|
flip_y = bool(tile[6] & 32)
|
|
if flip_x or flip_y:
|
|
new = tile_textures["dirtrd"][tile[5]].get_transform(flip_x=flip_x, flip_y=flip_y)
|
|
new.group = tile_textures["dirtrd"][tile[5]].group
|
|
self.__tiles[x, y].append(new)
|
|
else:
|
|
self.__tiles[x, y].append(tile_textures["dirtrd"][tile[5]])
|
|
elif tile[4] == 2: #gravrd
|
|
if "gravrd" not in tile_textures.keys():
|
|
tile_textures["gravrd"] = [self.load_map_object('data/advmap_tiles/gravrd.def/%d.png'%i, 1) for i in xrange(17)]
|
|
flip_x = bool(tile[6] & 16)
|
|
flip_y = bool(tile[6] & 32)
|
|
if flip_x or flip_y:
|
|
new = tile_textures["gravrd"][tile[5]].get_transform(flip_x=flip_x, flip_y=flip_y)
|
|
new.group = tile_textures["gravrd"][tile[5]].group
|
|
self.__tiles[x, y].append(new)
|
|
else:
|
|
self.__tiles[x, y].append(tile_textures["gravrd"][tile[5]])
|
|
elif tile[4] == 3: #cobbrd
|
|
if "cobbrd" not in tile_textures.keys():
|
|
tile_textures["cobbrd"] = [self.load_map_object('data/advmap_tiles/cobbrd.def/%d.png'%i, 1) for i in xrange(17)]
|
|
flip_x = bool(tile[6] & 16)
|
|
flip_y = bool(tile[6] & 32)
|
|
if flip_x or flip_y:
|
|
new = tile_textures["cobbrd"][tile[5]].get_transform(flip_x=flip_x, flip_y=flip_y)
|
|
new.group = tile_textures["cobbrd"][tile[5]].group
|
|
self.__tiles[x, y].append(new)
|
|
else:
|
|
self.__tiles[x, y].append(tile_textures["cobbrd"][tile[5]])
|
|
else:
|
|
raise NotImplementedError, tile[4]
|
|
|
|
images = []
|
|
for order, obj in enumerate(h3m_data["objects"]):
|
|
imgs = []
|
|
i = 0
|
|
while 1:
|
|
imgs.append(pyglet.image.load(None, file=pyglet.resource.file("data/advmap_objects/" + obj["filename"] + "/%d.png"%i)))
|
|
i += 1
|
|
if "data/advmap_objects/" + obj["filename"] + "/%d.png" % i not in pyglet.resource._default_loader._index.keys():
|
|
break;
|
|
images.append((imgs, order))
|
|
|
|
self.objects = []
|
|
for imgs in sorted(images, key=lambda i:i[0][0].height, reverse=True):
|
|
try:
|
|
texture = self.current_atlas.add(imgs[0][0])
|
|
except pyglet.image.atlas.AllocatorException:
|
|
self.current_atlas = pyglet.image.atlas.TextureAtlas(1024, 1024)
|
|
texture = self.current_atlas.add(imgs[0][0])
|
|
group = OrderedTextureGroup(2, self.current_atlas.texture)
|
|
if group not in self.groups:
|
|
self.groups.append(group)
|
|
group = self.groups.index(group)
|
|
texture.group = group
|
|
self.objects.append((Animation(texture, imgs[0]), imgs[1]))
|
|
|
|
self.objects = [i[0] for i in sorted(self.objects, key=lambda i:i[1])]
|
|
|
|
self.tunedobj = {}
|
|
for obj in [i for i in h3m_data["tunedobj"] if i["z"]==0]:
|
|
self.__tiles[obj["x"] + 9,obj["y"] + 8].append(self.objects[obj["id"]])
|
|
|
|
def get_tiles(self, tiles_x, tiles_y, div_x, div_y):
|
|
for y in xrange(tiles_y - 1, -6, -1):
|
|
y1 = y * 32
|
|
for x in xrange(tiles_x + 5 - 1, -1, -1):
|
|
for obj in self.__tiles.get((x - div_x, div_y - y), []):
|
|
x1 = x * 32 - obj.width + 32
|
|
x2 = x1 + obj.width
|
|
y2 = y1 + obj.height
|
|
yield obj, [x1, y1, x2, y1, x2, y2, x1, y2]
|