X-Git-Url: https://scm.cri.ensmp.fr/git/minwii.git/blobdiff_plain/346a9b8e1fcfe30629f0d1ee4675e9e8f89890cf..4c4732c6ed8cb0aaa70fb2d4c6e5a958868c5349:/src/pgu/vid.py?ds=inline diff --git a/src/pgu/vid.py b/src/pgu/vid.py deleted file mode 100644 index 6890e5d..0000000 --- a/src/pgu/vid.py +++ /dev/null @@ -1,560 +0,0 @@ -"""Sprite and tile engine. - -

[[tilevid]], [[isovid]], [[hexvid]] are all subclasses of -this interface.

- -

Includes support for:

- - - -

This code was previously known as the King James Version (named after the -Bible of the same name for historical reasons.)

-""" - -import pygame -from pygame.rect import Rect -from pygame.locals import * -import math - -class Sprite: - """The object used for Sprites. - -
Sprite(ishape,pos)
- -
-
ishape
an image, or an image, rectstyle. The rectstyle will - describe the shape of the image, used for collision - detection. -
pos
initial (x,y) position of the Sprite. -
- - Attributes -
-
rect
the current position of the Sprite -
_rect
the previous position of the Sprite -
groups
the groups the Sprite is in -
agroups
the groups the Sprite can hit in a collision -
hit
the handler for hits -- hit(g,s,a) -
loop
the loop handler, called once a frame -
- """ - def __init__(self,ishape,pos): - if not isinstance(ishape, tuple): - ishape = ishape,None - image,shape = ishape - if shape == None: - shape = pygame.Rect(0,0,image.get_width(),image.get_height()) - if isinstance(shape, tuple): shape = pygame.Rect(shape) - self.image = image - self._image = self.image - self.shape = shape - self.rect = pygame.Rect(pos[0],pos[1],shape.w,shape.h) - self._rect = pygame.Rect(self.rect) - self.irect = pygame.Rect(pos[0]-self.shape.x,pos[1]-self.shape.y, - image.get_width(),image.get_height()) - self._irect = pygame.Rect(self.irect) - self.groups = 0 - self.agroups = 0 - self.updated = 1 - - def setimage(self,ishape): - """Set the image of the Sprite. - -
Sprite.setimage(ishape)
- -
-
ishape
an image, or an image, rectstyle. The rectstyle will - describe the shape of the image, used for collision detection. -
- """ - if not isinstance(ishape, tuple): - ishape = ishape,None - image,shape = ishape - if shape == None: - shape = pygame.Rect(0,0,image.get_width(),image.get_height()) - if isinstance(shape, tuple): - shape = pygame.Rect(shape) - self.image = image - self.shape = shape - self.rect.w,self.rect.h = shape.w,shape.h - self.irect.w,self.irect.h = image.get_width(),image.get_height() - self.updated = 1 - - -class Tile: - """Tile Object used by TileCollide. - -
Tile(image=None)
-
-
image
an image for the Tile. -
- - Attributes -
-
agroups
the groups the Tile can hit in a collision -
hit
the handler for hits -- hit(g,t,a) -
- """ - def __init__(self,image=None): - self.image = image - self.agroups = 0 - - def __setattr__(self,k,v): - if k == 'image' and v != None: - self.image_h = v.get_height() - self.image_w = v.get_width() - self.__dict__[k] = v - -class _Sprites(list): - def __init__(self): - list.__init__(self) - self.removed = [] - - def append(self,v): - list.append(self,v) - v.updated = 1 - - def remove(self,v): - list.remove(self,v) - v.updated = 1 - self.removed.append(v) - -class Vid: - """An engine for rendering Sprites and Tiles. - -
Vid()
- - Attributes -
-
sprites
a list of the Sprites to be displayed. You may append and - remove Sprites from it. -
images
a dict for images to be put in. -
size
the width, height in Tiles of the layers. Do not modify. -
view
a pygame.Rect of the viewed area. You may change .x, .y, - etc to move the viewed area around. -
bounds
a pygame.Rect (set to None by default) that sets the bounds - of the viewable area. Useful for setting certain borders - as not viewable. -
tlayer
the foreground tiles layer -
clayer
the code layer (optional) -
blayer
the background tiles layer (optional) -
groups
a hash of group names to group values (32 groups max, as a tile/sprites - membership in a group is determined by the bits in an integer) -
- """ - - def __init__(self): - self.tiles = [None for x in xrange(0,256)] - self.sprites = _Sprites() - self.images = {} #just a store for images. - self.layers = None - self.size = None - self.view = pygame.Rect(0,0,0,0) - self._view = pygame.Rect(self.view) - self.bounds = None - self.updates = [] - self.groups = {} - - - def resize(self,size,bg=0): - """Resize the layers. - -
Vid.resize(size,bg=0)
- -
-
size
w,h in Tiles of the layers -
bg
set to 1 if you wish to use both a foreground layer and a - background layer -
- """ - self.size = size - w,h = size - self.layers = [[[0 for x in xrange(0,w)] for y in xrange(0,h)] - for z in xrange(0,4)] - self.tlayer = self.layers[0] - self.blayer = self.layers[1] - if not bg: self.blayer = None - self.clayer = self.layers[2] - self.alayer = self.layers[3] - - self.view.x, self.view.y = 0,0 - self._view.x, self.view.y = 0,0 - self.bounds = None - - self.updates = [] - - def set(self,pos,v): - """Set a tile in the foreground to a value. - -

Use this method to set tiles in the foreground, as it will make - sure the screen is updated with the change. Directly changing - the tlayer will not guarantee updates unless you are using .paint() -

- -
Vid.set(pos,v)
- -
-
pos
(x,y) of tile -
v
value -
- """ - if self.tlayer[pos[1]][pos[0]] == v: return - self.tlayer[pos[1]][pos[0]] = v - self.alayer[pos[1]][pos[0]] = 1 - self.updates.append(pos) - - def get(self,pos): - """Get the tlayer at pos. - -
Vid.get(pos): return value
- -
-
pos
(x,y) of tile -
- """ - return self.tlayer[pos[1]][pos[0]] - - def paint(self,s): - """Paint the screen. - -
Vid.paint(screen): return [updates]
- -
-
screen
a pygame.Surface to paint to -
- -

returns the updated portion of the screen (all of it)

- """ - return [] - - def update(self,s): - """Update the screen. - -
Vid.update(screen): return [updates]
- -
-
screen
a pygame.Rect to update -
- -

returns a list of updated rectangles.

- """ - self.updates = [] - return [] - - def tga_load_level(self,fname,bg=0): - """Load a TGA level. - -
Vid.tga_load_level(fname,bg=0)
- -
-
g
a Tilevid instance -
fname
tga image to load -
bg
set to 1 if you wish to load the background layer -
- """ - if type(fname) == str: img = pygame.image.load(fname) - else: img = fname - w,h = img.get_width(),img.get_height() - self.resize((w,h),bg) - for y in range(0,h): - for x in range(0,w): - t,b,c,_a = img.get_at((x,y)) - self.tlayer[y][x] = t - if bg: self.blayer[y][x] = b - self.clayer[y][x] = c - - def tga_save_level(self,fname): - """Save a TGA level. - -
Vid.tga_save_level(fname)
- -
-
fname
tga image to save to -
- """ - w,h = self.size - img = pygame.Surface((w,h),SWSURFACE,32) - img.fill((0,0,0,0)) - for y in range(0,h): - for x in range(0,w): - t = self.tlayer[y][x] - b = 0 - if self.blayer: - b = self.blayer[y][x] - c = self.clayer[y][x] - _a = 0 - img.set_at((x,y),(t,b,c,_a)) - pygame.image.save(img,fname) - - - - def tga_load_tiles(self,fname,size,tdata={}): - """Load a TGA tileset. - -
Vid.tga_load_tiles(fname,size,tdata={})
- -
-
g
a Tilevid instance -
fname
tga image to load -
size
(w,h) size of tiles in pixels -
tdata
tile data, a dict of tile:(agroups, hit handler, config) -
- """ - TW,TH = size - if type(fname) == str: img = pygame.image.load(fname).convert_alpha() - else: img = fname - w,h = img.get_width(),img.get_height() - - n = 0 - for y in range(0,h,TH): - for x in range(0,w,TW): - i = img.subsurface((x,y,TW,TH)) - tile = Tile(i) - self.tiles[n] = tile - if n in tdata: - agroups,hit,config = tdata[n] - tile.agroups = self.string2groups(agroups) - tile.hit = hit - tile.config = config - n += 1 - - - def load_images(self,idata): - """Load images. - -
Vid.load_images(idata)
- -
-
idata
a list of (name, fname, shape) -
- """ - for name,fname,shape in idata: - self.images[name] = pygame.image.load(fname).convert_alpha(),shape - - def run_codes(self,cdata,rect): - """Run codes. - -
Vid.run_codes(cdata,rect)
- -
-
cdata
a dict of code:(handler function, value) -
rect
a tile rect of the parts of the layer that should have - their codes run -
- """ - tw,th = self.tiles[0].image.get_width(),self.tiles[0].image.get_height() - - x1,y1,w,h = rect - clayer = self.clayer - t = Tile() - for y in range(y1,y1+h): - for x in range(x1,x1+w): - n = clayer[y][x] - if n in cdata: - fnc,value = cdata[n] - t.tx,t.ty = x,y - t.rect = pygame.Rect(x*tw,y*th,tw,th) - fnc(self,t,value) - - - def string2groups(self,str): - """Convert a string to groups. - -
Vid.string2groups(str): return groups
- """ - if str == None: return 0 - return self.list2groups(str.split(",")) - - def list2groups(self,igroups): - """Convert a list to groups. -
Vid.list2groups(igroups): return groups
- """ - for s in igroups: - if not s in self.groups: - self.groups[s] = 2**len(self.groups) - v = 0 - for s,n in self.groups.items(): - if s in igroups: v|=n - return v - - def groups2list(self,groups): - """Convert a groups to a list. -
Vid.groups2list(groups): return list
- """ - v = [] - for s,n in self.groups.items(): - if (n&groups)!=0: v.append(s) - return v - - def hit(self,x,y,t,s): - tiles = self.tiles - tw,th = tiles[0].image.get_width(),tiles[0].image.get_height() - t.tx = x - t.ty = y - t.rect = Rect(x*tw,y*th,tw,th) - t._rect = t.rect - if hasattr(t,'hit'): - t.hit(self,t,s) - - def loop(self): - """Update and hit testing loop. Run this once per frame. -
Vid.loop()
- """ - self.loop_sprites() #sprites may move - self.loop_tilehits() #sprites move - self.loop_spritehits() #no sprites should move - for s in self.sprites: - s._rect = pygame.Rect(s.rect) - - def loop_sprites(self): - as_ = self.sprites[:] - for s in as_: - if hasattr(s,'loop'): - s.loop(self,s) - - def loop_tilehits(self): - tiles = self.tiles - tw,th = tiles[0].image.get_width(),tiles[0].image.get_height() - - layer = self.layers[0] - - as_ = self.sprites[:] - for s in as_: - self._tilehits(s) - - def _tilehits(self,s): - tiles = self.tiles - tw,th = tiles[0].image.get_width(),tiles[0].image.get_height() - layer = self.layers[0] - - for _z in (0,): - if s.groups != 0: - - _rect = s._rect - rect = s.rect - - _rectx = _rect.x - _recty = _rect.y - _rectw = _rect.w - _recth = _rect.h - - rectx = rect.x - recty = rect.y - rectw = rect.w - recth = rect.h - - rect.y = _rect.y - rect.h = _rect.h - - hits = [] - ct,cb,cl,cr = rect.top,rect.bottom,rect.left,rect.right - #nasty ol loops - y = ct/th*th - while y < cb: - x = cl/tw*tw - yy = y/th - while x < cr: - xx = x/tw - t = tiles[layer[yy][xx]] - if (s.groups & t.agroups)!=0: - #self.hit(xx,yy,t,s) - d = math.hypot(rect.centerx-(xx*tw+tw/2), - rect.centery-(yy*th+th/2)) - hits.append((d,t,xx,yy)) - - x += tw - y += th - - hits.sort() - #if len(hits) > 0: print self.frame,hits - for d,t,xx,yy in hits: - self.hit(xx,yy,t,s) - - #switching directions... - _rect.x = rect.x - _rect.w = rect.w - rect.y = recty - rect.h = recth - - hits = [] - ct,cb,cl,cr = rect.top,rect.bottom,rect.left,rect.right - #nasty ol loops - y = ct/th*th - while y < cb: - x = cl/tw*tw - yy = y/th - while x < cr: - xx = x/tw - t = tiles[layer[yy][xx]] - if (s.groups & t.agroups)!=0: - d = math.hypot(rect.centerx-(xx*tw+tw/2), - rect.centery-(yy*th+th/2)) - hits.append((d,t,xx,yy)) - #self.hit(xx,yy,t,s) - x += tw - y += th - - hits.sort() - #if len(hits) > 0: print self.frame,hits - for d,t,xx,yy in hits: - self.hit(xx,yy,t,s) - - #done with loops - _rect.x = _rectx - _rect.y = _recty - - - def loop_spritehits(self): - as_ = self.sprites[:] - - groups = {} - for n in range(0,31): - groups[1<>= 1 - n <<= 1 - - for s in as_: - if s.agroups!=0: - rect1,rect2 = s.rect,Rect(s.rect) - #if rect1.centerx < 320: rect2.x += 640 - #else: rect2.x -= 640 - g = s.agroups - n = 1 - while g: - if (g&1)!=0: - for b in groups[n]: - if (s != b and (s.agroups & b.groups)!=0 - and s.rect.colliderect(b.rect)): - s.hit(self,s,b) - - g >>= 1 - n <<= 1 - - - def screen_to_tile(self,pos): - """Convert a screen position to a tile position. -
Vid.screen_to_tile(pos): return pos
- """ - return pos - - def tile_to_screen(self,pos): - """Convert a tile position to a screen position. -
Vid.tile_to_screen(pos): return pos
- """ - return pos - -# vim: set filetype=python sts=4 sw=4 noet si :