# # GameObject.py # # 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; version 2 of the License. # # 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. # # Copyright # Author: Nicholas F. Hoover # Contributors: Salvatore S. Gionfriddo # Created: 2007.06.18 # Last Modified: 2007.07.24 # import pygame from Animation import Animation RESOURCE_MANAGER = None def gameObjectPosCompare(gameObject1, gameObject2): return gameObject1.rect.top - gameObject2.rect.top class GameObject(pygame.sprite.Sprite): RIGHT = 0 LEFT = 1 DEFAULT_ANIMATI0N = 0 DEFAULT_POSITION = (0,0) RECT_SIZE = (0,0) COLLISION_RECT_SIZE = (0,0) COLLISION_RECT_POSITION = (0,0) def __init__(self, fps = 30): pygame.sprite.Sprite.__init__(self) self.linkAnimations(fps) self.image = pygame.Surface(GameObject.RECT_SIZE) self.rect = pygame.Rect(self.DEFAULT_POSITION, self.RECT_SIZE) (x,y) = self.DEFAULT_POSITION x += self.COLLISION_RECT_POSITION[0] y += self.COLLISION_RECT_POSITION[1] self.collision_rect = pygame.Rect((x,y), self.COLLISION_RECT_SIZE) self.attachedGameObjects = OrderedUpdatesDraw() self.reset() def reset(self): self.currentAnimation = self.DEFAULT_ANIMATION self.facing = self.RIGHT self.setPosition(self.DEFAULT_POSITION) self.updateCurrentImage() def setPosition(self,position): self.rect.topleft = position (x,y) = position x += self.COLLISION_RECT_POSITION[0] y += self.COLLISION_RECT_POSITION[1] self.collision_rect.topleft = (x,y) #generically loads all animation listed in animation table of subclasses def linkAnimations(self, fps): self.animations = range(self.NUM_ANIMATIONS *2) for element in self.ANIMATION_TABLE: if len(element) == 4: (index, name, frameTicks, keyFrame) = element rotate = False elif len(element) == 5: (index, name, frameTicks, keyFrame, rotate) = element print element self.animations[index] = Animation(RESOURCE_MANAGER.getAnimationFrames(name + '_Right'), frameTicks, keyFrame, rotate) self.animations[index + self.LEFT] = Animation(RESOURCE_MANAGER.getAnimationFrames(name + '_Left'), frameTicks, keyFrame, rotate) def updateCurrentAnimation(self): return self.animations[self.currentAnimation].update() def resetCurrentAnimation(self): self.animations[self.currentAnimation].reset() def updateCurrentImage(self): self.image = self.animations[self.currentAnimation].image def isActionComplete(self, action): return self.isActing(action) and self.animations[self.currentAnimation].isComplete() def isActionActive(self,action): return self.isActing(action) and self.animations[self.currentAnimation].isKeyFrame() def isActing(self,action): return self.getAnimationType() == action def setFacing(self, facing): self.facing = facing def getAnimationType(self): return self.currentAnimation - self.facing def setAnimation(self, animation, facing = None, reset = True): if facing != None: self.setFacing(facing) self.currentAnimation = animation + self.facing if reset: self.resetCurrentAnimation() def update(self): self.animations[self.currentAnimation].update() self.updateCurrentImage() def playSound(self, sound): RESOURCE_MANAGER.playSound(sound) def updateAttached(self): for sprite in self.attachedGameObjects: sprite.update() def attachGameObject(self, gameObject): self.attachedGameObjects.add(gameObject) def removeAttachedByType(self, removeType): for sprite in self.attachedGameObjects.sprites(): if type(sprite) is removeType: self.attachedGameObjects.remove(sprite) def draw(self, surface): rects = self.attachedGameObjects.draw(surface) rects.append(surface.blit(self.image, self.rect)) return rects class TimedGameObject(GameObject): TICKS_TO_LIVE = 0 def __init__(self, onKillFunction = None): GameObject.__init__(self) self.ticksLeft = self.TICKS_TO_LIVE self.onKill = onKillFunction def update(self): self.ticksLeft -= 1 if self.ticksLeft == 0: if callable(self.onKill): self.onKill() self.kill() else: GameObject.update(self) class OrderedUpdatesDraw(pygame.sprite.OrderedUpdates): def draw(self, surface): spritedict = self.spritedict surface_blit = surface.blit dirty = self.lostsprites self.lostsprites = [] dirty_append = dirty.append for s in self.sprites(): r = spritedict[s] newrects = s.draw(surface) newrect = newrects.pop() for rect in newrects: dirty_append(rect) if r is 0: dirty_append(newrect) else: if newrect.colliderect(r): dirty_append(newrect.union(r)) else: dirty_append(newrect) dirty_append(r) spritedict[s] = newrect return dirty