示例#1
0
class Gamestate(SchedulerInterface, EventInterface):
    
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.player_starting_pos = (128, 48)
        self.game_flags = {}
        self.trophies_obtained = {}
        self.player_health = 3
        self.fade_darkener = Darkener()
        self.bg = GraphicInterface()
        self.bg.setSprite(toStringPath(BG_GRAPHICS_FULL_PATH + ["loading.png"]))
        self.bg.setSpriteLayer(LOADING_LAYER)
        self.mappe = None
        
        self.ending_player = None
        self.ending_text = None
        self.ending_text2 = None
        self.ending_text3 = None
        self.ending_squids = []
        
        self.player_health_sprites = []
        for i in range(3):
            self.player_health_sprites.append(GraphicInterface())
            self.player_health_sprites[-1].setSprite(toStringPath(UI_GRAPHICS_FULL_PATH  + ["health.png"]))
            self.player_health_sprites[-1].setPos(HEALTH_X_OFFSET + HEALTH_X_STEP*i, getWindowDimensionsScaled()[1] + HEALTH_Y_OFFSET)
            self.player_health_sprites[-1].setSpriteFollowCamera(True)
            self.player_health_sprites[-1].setSpriteLayer(UI_LAYER)
            
        self.squid_trophy_sprites = []
        for i in range(3):
            self.squid_trophy_sprites.append(GraphicInterface())
            self.squid_trophy_sprites[-1].setSpriteFollowCamera(True)
            self.squid_trophy_sprites[-1].setPos(SQUID_X_OFFSET + SQUID_X_STEP*i, getWindowDimensionsScaled()[1] + SQUID_Y_OFFSET)
            self.squid_trophy_sprites[-1].setSpriteLayer(UI_LAYER)
            
        
        self.Schedule(self.createStartingMap, 2)
        
        self.addCustomListener(SQUID_TROPHY_OBTAINED_EVENT, self.squidTrophyObtained)
        self.addQueryListener(SQUID_TROPHY_OBTAINED_QUERY, self.checkTrophyObtained)
        self.addQueryListener(ALL_SQUID_TROPHIES_OBTAINED_QUERY, self.hasAllTrophies)
        self.addCustomListener(PLAYER_REDUCE_HP_EVENT, self.reduceHP)
        self.addCustomListener(PLAYER_MAX_HP_EVENT, self.maxHP)
        self.addQueryListener(CHECK_PLAYER_DEAD_QUERY, self.checkPlayerDead)
        self.addCustomListener(PUSH_SAVE_EVENT, self.pushSave)
        self.addCustomListener(FINAL_SQUID_OBTAINED_EVENT , self.finalSquidObtained)
        self.addCustomListener(GAME_LOST_EVENT, self.gameLost)
        
        self.loadSave()
        
    def createStartingMap(self):
        self.mappe = createMap(MAP_NAME, self.player_starting_pos) #just one map for now
        self.fade_darkener.fadeIn(60)
        if self.bg:
            self.bg.destroy()
        self.bg = None
        playMusic(toStringPath(FULL_MUSIC_PATH + ["bgmusic.ogg"]))
        
        
    def getMapTileAtPos(self, *args, **kwargs):
        if self.mappe:
            return self.mappe.getMapTileAtPos(*args, **kwargs)
        return None
    
    def squidTrophyObtained(self, trophy_index):
        self.trophies_obtained[trophy_index] = True
        self.updateTrophyGraphics()
        
    def updateTrophyGraphics(self):
        for trophy in self.squid_trophy_sprites:
            trophy.setSpriteAlpha(0.0)
        for trophy_index in self.trophies_obtained.keys():
            index = SQUID_ENUM.get(trophy_index, 999)
            try:
                self.squid_trophy_sprites[index].setSprite(toStringPath(CHAR_GRAPHICS_FULL_PATH + [SQUID_GRAPHICS[trophy_index]]))
                self.squid_trophy_sprites[index].setSpriteAlpha(1.0)
            except (KeyError, IndexError):
                pass
        
    def checkTrophyObtained(self, trophy_index):
        return self.trophies_obtained.get(trophy_index, False)
    
    def hasAllTrophies(self):
        for i in {SQUID_TROPHY_BLUE_INDEX, SQUID_TROPHY_RED_INDEX, SQUID_TROPHY_GREEN_INDEX}:
            if not self.checkTrophyObtained(i):
                return False
        return True
    
    def maxHP(self):
        self.player_health = 3
        self.updateHealth()
        
    def reduceHP(self):
        self.player_health -= 1
        self.updateHealth()
        
    def updateHealth(self):
        for i in range(3):
            if i < self.player_health:
                self.player_health_sprites[i].setSpriteAnimation("FULL")
            else:
                self.player_health_sprites[i].setSpriteAnimation("EMPTY")
                
    def checkPlayerDead(self):
        return self.player_health <= 0
    
    def setEventFlag(self, key, val):
        self.game_flags[key] = val
        
    def getEventFlag(self, key, default = "asdfadsgiangiang"):
        try:
            return self.game_flags[key] 
        except KeyError:
            if default != "asdfadsgiangiang":
                return default
            raise
            
    def pushSave(self):
        savegame.setValue(SAVE_TROPHIES, copy.deepcopy(self.trophies_obtained))
        savegame.setValue(SAVE_EVENT_FLAGS, copy.deepcopy(self.game_flags))
        savegame.setValue(SAVE_PLAYER_POS, callQuery(PLAYER_GET_POS_QUERY))
        savegame.commitSave(SAVE_GAME_NAME)
        
    def loadSave(self):
        try:
            savegame.loadSave(SAVE_GAME_NAME)
        except ResourceUnavailableError:
            pass
        self.game_flags = copy.deepcopy(savegame.getValue(SAVE_EVENT_FLAGS, {}))
        self.trophies_obtained = copy.deepcopy(savegame.getValue(SAVE_TROPHIES, {}))
        playerpos = savegame.getValue(SAVE_PLAYER_POS, None)
        if playerpos is None:
            playerpos = (128, 48)
        self.player_starting_pos = playerpos
        self.updateTrophyGraphics()
        
    def finalSquidObtained(self):
        for actor in self.mappe.getAllActors():
            actor.pauseActor()
        self.fade_darkener.fadeOut(60)
        self.Schedule(self.startCredits, 60)
        
        
    def startCredits(self):
        self.removeMapData()
        resetLag()
        self.fade_darkener.fadeIn(60)
        playMusic(toStringPath(FULL_MUSIC_PATH + ["ending.ogg"]))
        self.removeEndingData()
        self.ending_player = GraphicInterface()
        self.ending_player.setSprite(toStringPath(CHAR_GRAPHICS_FULL_PATH + ["char.png"]))
        self.ending_player.setPos(128,128)
        self.ending_player.setSpriteCenter(True, True)
        self.ending_player.setSpriteFollowCamera(True)
        self.ending_player.setSpriteAnimation("WALK_DOWN")
        self.ending_text = createLabel("Thanks for playing!", font = "kaimono3.gfont2")
        self.ending_text.setPos(128, 64)
        self.ending_text.follow_camera = True
        self.ending_text.setCenter(True,True)
        self.ending_text2 = createLabel("You got the", font = "kaimono3.gfont2")
        self.ending_text2.setPos(128, 192)
        self.ending_text2.follow_camera = True
        self.ending_text2.setCenter(True,True)
        self.ending_text3 = createLabel("Golden Squid!", font = "kaimono3.gfont2")
        self.ending_text3.setPos(128, 176)
        self.ending_text3.follow_camera = True
        self.ending_text3.setCenter(True,True)
        xoffset = getWindowDimensionsScaled()[0]/2 - (len(SQUID_GRAPHICS)-1)*ENDING_SQUID_X_SPACING/2
        for i, val in enumerate(SQUID_GRAPHICS.values()):
            self.ending_squids.append(GraphicInterface())
            self.ending_squids[-1].setSprite(toStringPath(CHAR_GRAPHICS_FULL_PATH + [val]))
            self.ending_squids[-1].setSpriteCenter(True, True)
            self.ending_squids[-1].setSpriteFollowCamera(True)
            self.ending_squids[-1].setPos(xoffset + i*ENDING_SQUID_X_SPACING, 96)
        
    def removeMapData(self):
        if self.mappe:
            self.mappe.destroy()
        self.mappe = None
        if self.bg:
            self.bg.destroy()
        self.bg = None
        for sprite in self.player_health_sprites:
            sprite.destroy()
        self.player_health_sprites.clear()
        for sprite in self.squid_trophy_sprites:
            sprite.destroy()
        self.squid_trophy_sprites.clear()
        
    def removeEndingData(self):
        if self.ending_player:
            self.ending_player.destroy()
        self.ending_player = None
        if self.ending_text:
            self.ending_text.destroy()
        self.ending_text = None
        if self.ending_text2:
            self.ending_text2.destroy()
        self.ending_text2 = None
        if self.ending_text3:
            self.ending_text3.destroy()
        self.ending_text3 = None
        for squid in self.ending_squids:
            squid.destroy()
        self.ending_squids.clear()
        
    def gameLost(self):
        self.fade_darkener.fadeOut(60)
        self.Schedule(self.resetToSave, 60)
        
    def resetToSave(self):
        stopMusic()
        if self.mappe:
            self.mappe.destroy()
        self.loadSave()
        if self.bg:
            self.bg.destroy()
        self.fade_darkener.fadeIn(1)
        self.bg = GraphicInterface()
        self.bg.setSprite(toStringPath(BG_GRAPHICS_FULL_PATH + ["loading.png"]))
        self.bg.setSpriteLayer(LOADING_LAYER)
        self.bg.setSpriteFollowCamera(True)
        self.Schedule(self.createStartingMap, 2)
        
        
    def destroy(self):
        super().destroy()
        self.removeMapData()
        self.removeEndingData()
        if self.fade_darkener:
            self.fade_darkener.destroy()
        self.fade_darkener = None
        
示例#2
0
class BaseEnemy(BaseActor):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.enemy = True
        self.enemy_index = None
        self.stunned = False
        self.stun_knockback = False
        self.stun_stars = None

        self.Schedule(self.updateOffscreen, 10, True)

    def getEnemyIndex(self):
        return self.enemy_index

    def startWander(self):
        if self.checkWanderAction():
            self.setVelocity(*random.choice(WANDER_VELS))
        self.Schedule(self._wanderWait, WANDER_FREQUENCY)

    def _wanderWait(self):
        if self.checkWanderAction():
            self.setVelocity(0, 0)
        self.Schedule(self.startWander, WANDER_FREQUENCY)

    def checkWanderAction(self):
        return not self.isHurt() and not self.isStunned()

    def updateOffscreen(self):
        if self.checkSpriteOffscreen():
            self.cleanupSelf()

    def stunEnemy(self, x, y):
        self.setStunned(True)
        self.setSpriteAnimation(
            ACTOR_MOVEMENT_ANIMATION_DICT[self.facing][False][0])
        self.setKnockbackVel(x, y, STUN_VEL)
        self.Schedule(self._finishStunKnockback, STUN_KNOCKBACK_TIME)
        self.stun_knockback = True
        self.removeStunStars()
        self.stun_stars = GraphicInterface()
        self.stun_stars.setSprite(
            toStringPath(EFFECTS_GRAPHICS_FULL_PATH + ["stun_stars.png"]))
        self.stun_stars.setSpriteOffset(y=STUN_STAR_HEIGHT)
        self.stun_stars.setSpriteLayer(STUN_STAR_LAYER)
        self.stun_stars.setSpriteCenter(True, True)
        self._updateSpritePos()
        return False  #for minotaur charge

    def _finishStunKnockback(self):
        self.stun_knockback = False
        self.setVelocity(0, 0)

    def isStunned(self):
        return self.stunned

    def setStunned(self, val):
        self.stunned = val

    def removeStunStars(self):
        if self.stun_stars:
            self.stun_stars.destroy()
        self.stun_stars = None

    #overwritten stuff

    def _updateSpritePos(self):
        super()._updateSpritePos()
        if self.stun_stars:
            self.stun_stars.setPos(*self.getPos())

    def updateMovementAnimation(self):
        if not self.isStunned():
            super().updateMovementAnimation()

    def _endHurt(self):
        super()._endHurt()
        self.cleanupSelf()

    def destroy(self):
        super().destroy()
        self.removeStunStars()
示例#3
0
class BaseActor(GraphicInterface, MovementInterfaceFrames, SchedulerInterface,
                EventInterface):
    def __init__(self, mappe, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.shadow = GraphicInterface()
        self.shadow.setSprite(
            toStringPath(CHAR_GRAPHICS_FULL_PATH + ["playershadow.png"]))
        self.shadow.setSpriteCenter(True, True)
        self.shadow.setSpriteLayer(SHADOW_LAYER)
        self.actor_id = -1
        self.paused = False
        self._mappe = weakRef(mappe)
        self.facing = DIRECTION_DOWN
        self.moving = False
        self.collision = True
        self.flying = False
        self.base_layer = ACTOR_LAYER
        self.z_pos = 0
        self.enemy = False
        self.player = False
        self.room_index = (0, 0)
        self.hurt = False
        self.event_flag = None  #used for some enemies

        self.updateActorLayer(0)
        self.setSpriteCenter(x=True)

        self.Schedule(self.updateAnimation, 1, True)

    @property
    def mappe(self):
        return unWeakRef(self._mappe)

    @mappe.setter
    def mappe(self, val):
        debugMessage("Cannot set map directly")

    def setActorId(self, actor_id):
        self.actor_id = actor_id

    def getActorId(self):
        return self.actor_id

    def setBaseLayer(self, val):
        self.base_layer = val

    def getBaseLayer(self):
        return self.base_layer

    def updateActorLayer(self, offset):
        self.setSpriteLayer(self.base_layer + offset)

    def setRoomIndex(self, val):
        self.room_index = val

    def getRoomIndex(self):
        return self.room_index

    def checkCollision(self, x=None, y=None):
        if x is None: x = self.getPos()[0]
        if y is None: y = self.getPos()[1]
        tile = getMapTileAtPos(x, y)
        return tile is None or tile.getCollision()

    def checkOverPit(self, x=None, y=None):
        if x is None: x = self.getPos()[0]
        if y is None: y = self.getPos()[1]
        tile = getMapTileAtPos(x, y)
        return tile is not None and tile.getPit()

    def updateAnimation(self):
        #check state
        self.updateMoving()
        self.updateMovementAnimation()

    def updateMovementAnimation(self):
        ani, flip = ACTOR_MOVEMENT_ANIMATION_DICT[self.facing][self.moving]
        self.setSpriteAnimation(ani, False, "DEFAULT")
        self.setSpriteFlip(flip)

    def updateMoving(self):
        if abs(self.velocity[1]) + abs(self.velocity[0]) != 0:
            self.moving = True
        else:
            self.moving = False

    def cleanupSelf(self):
        if not self.destroyed:
            self.mappe.removeActor(self.getActorId())

    def isEnemy(self):
        return self.enemy

    def isFlying(self):
        return self.flying

    def isPlayer(self):
        return self.player

    def pauseActor(self):
        if not self.paused:
            self.pauseMovement()
            self.pauseSpriteAnimations()
            self.pauseAllScheduledListeners()
            self.paused = True

    def unpauseActor(self):
        if self.paused:
            self.unpauseMovement()
            self.unpauseSpriteAnimations()
            self.unpauseAllScheduledListeners()
            self.paused = False

    def removeShadow(self):
        if self.shadow:
            self.shadow.destroy()
        self.shadow = None

    def setHurt(self, time):
        self.hurt = True
        self.Unschedule(self._hurtFlash)
        self.Schedule(self._hurtFlash, 2, True)
        self.Unschedule(self._endHurt)
        self.Schedule(self._endHurt, time)

    def _hurtFlash(self):
        self.setSpriteAlpha(abs(self.getSpriteAlpha() - 1.0))

    def _endHurt(self):
        self.Unschedule(self._hurtFlash)
        self.setSpriteAlpha(1.0)
        self.hurt = False

    def isHurt(self):
        return self.hurt

    def updateFacing(self):
        if abs(self.velocity[1]) > abs(self.velocity[0]):
            if self.velocity[1] > 0:
                self.facing = DIRECTION_UP
            else:
                self.facing = DIRECTION_DOWN
        elif abs(self.velocity[1]) != abs(self.velocity[0]):
            if self.velocity[0] > 0:
                self.facing = DIRECTION_RIGHT
            elif self.velocity[0] < 0:
                self.facing = DIRECTION_LEFT
        if self.velocity[0] > 0 and self.facing == DIRECTION_LEFT:
            self.facing = DIRECTION_RIGHT
        elif self.velocity[0] < 0 and self.facing == DIRECTION_RIGHT:
            self.facing = DIRECTION_LEFT
        elif self.velocity[1] > 0 and self.facing == DIRECTION_DOWN:
            self.facing = DIRECTION_UP
        elif self.velocity[1] < 0 and self.facing == DIRECTION_UP:
            self.facing = DIRECTION_DOWN

    def setKnockbackVel(self, x, y, vel):
        xoffset, yoffset = map(operator.sub, self.getPos(), (x, y))
        hypot = math.sqrt(xoffset**2 + yoffset**2)
        if hypot == 0:  #avoid divide by 0
            hypot = 1
            xoffset = 1
            yoffset = 0
        self.setVelocity(vel * xoffset / hypot, vel * yoffset / hypot)

    def setEventFlag(self, val):
        self.event_flag = val

    #overwritten stuff

    def setSprite(self, *args, **kwargs):
        super().setSprite(*args, **kwargs)
        self.setSpriteOtherOffset(ACTOR_Y_OFFSET,
                                  y=-self.getSpriteHeight() / 6)

    def _updateSpritePos(self):
        x, y = self.getPos()
        try:
            self.sprite.setPos(x, y + self.z_pos)
        except AttributeError:
            pass
        if self.shadow:
            self.shadow.setPos(x, y - 2)

    def runMovement(self, *args, **kwargs):
        super().runMovement(*args, **kwargs)
        self.updateFacing()
        self.updateAnimation()

    def setPos(self, x=None, y=None):
        if not self.collision or self.checkCollision() or (
                not self.isFlying()
                and self.checkOverPit()):  #failsafe if already in a wall
            super().setPos(x, y)
        else:
            oldpos = self.getPos()
            if x is None: x = oldpos[0]
            if y is None: y = oldpos[1]
            if not self.checkCollision(x) and (
                    self.isFlying()
                    or not self.checkOverPit(x)):  #extremely simple collision
                super().setPos(x)
            if not self.checkCollision(y=y) and (self.isFlying() or
                                                 not self.checkOverPit(y=y)):
                super().setPos(y=y)

    def destroy(self):
        super().destroy()
        self.removeShadow()
示例#4
0
class Player(SchedulerInterface, GraphicInterface, EventInterface):
    
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.jumping = False
        self.invulnerable = False
        self.z_pos = 0
        self.jump_speed = 0
        self.jumping_y_speed = 0
        self.jumping_x_speed = 0
        self.dead = False
        
        self.shadow = GraphicInterface()
        self.shadow.setSprite(toStringPath(*PLAYER_SHADOW_PATH))
        self.shadow.setSpriteCenter(True,True)
        self.shadow.setSpriteLayer(0.5)
        
        self.setSprite(toStringPath(*PLAYER_CHAR_PATH))
        
        self.Schedule(self.updateMovement, 1, True)
        
        self.addCustomListener(PLAYER_JUMP_EVENT, self.playerJump)
        
        
    def getZPos(self):
        return self.z_pos
        
    def updateMovement(self):
        self.z_pos += self.jump_speed
        if self.z_pos < 0:
            self.jumpFinished()
        pos = list(self.getPos())
        xspeed = 0
        yspeed = 0
        if not self.jumping:
            if not self.dead:
                if checkKeyHeld(MOVE_UP):
                    yspeed = PLAYER_MOVEMENT_SPEED_Y
                elif checkKeyHeld(MOVE_DOWN):
                    yspeed = -PLAYER_MOVEMENT_SPEED_Y
                if checkKeyHeld(MOVE_RIGHT):
                    xspeed = PLAYER_MOVEMENT_SPEED_X
                elif checkKeyHeld(MOVE_LEFT):
                    xspeed = -PLAYER_MOVEMENT_SPEED_X
        else:
            yspeed = self.jumping_y_speed
            xspeed = self.jumping_x_speed
        if not self.dead:
            pos[0] = max(0, min(getWindowDimensionsScaled()[0] - self.getSpriteWidth(), pos[0] + xspeed))
        pos[1] = max(0, min(MAX_Y_POSITION, pos[1] + yspeed))
        self.setPos(*pos)
        
    def playerJump(self):
        if not self.jumping and not self.invulnerable:
            self.jumping_y_speed = 0
            self.jumping_x_speed = 0
            if checkKeyHeld(MOVE_UP):
                self.jumping_y_speed = PLAYER_MOVEMENT_SPEED_Y
            elif checkKeyHeld(MOVE_DOWN):
                self.jumping_y_speed = -PLAYER_MOVEMENT_SPEED_Y
            if checkKeyHeld(MOVE_RIGHT):
                self.jumping_x_speed = PLAYER_MOVEMENT_SPEED_X
            elif checkKeyHeld(MOVE_LEFT):
                self.jumping_x_speed = -PLAYER_MOVEMENT_SPEED_X
            self.jumping = True
            self.setSpriteAnimation("JUMP")
            self.jump_speed = JUMP_STARTING_SPEED
            self.scheduleUnique(self.updateGravity, 1, True)
            
    def jumpFinished(self):
        self.z_pos = 0
        self.jump_speed = 0
        self.Unschedule(self.updateGravity)
        self.jumping = False
        if not self.invulnerable:
            self.setSpriteAnimation("RUN")
        
    def updateGravity(self):
        self.jump_speed -= JUMP_GRAVITY
        
    def checkInvulnerable(self):
        return self.invulnerable
    
    def gotHit(self):
        self.invulnerable = True
        self.setSpriteAnimation("HURT")
        self.Schedule(self.flashAnimation, 2, True)
        self.Schedule(self.finishInvulnerability, INVULNERABLE_TIME)
        
    def flashAnimation(self):
        self.setSpriteAlpha(abs(self.getSpriteAlpha() - 1.0))
        
    def finishInvulnerability(self):
        self.Unschedule(self.flashAnimation)
        self.setSpriteAlpha(1.0)
        if not self.dead:
            self.setSpriteAnimation("RUN")
        else:
            self.setSpriteAnimation("DEAD")
            self.Schedule(self.deathFallBehind, 1, True)
        self.invulnerable = False
        
    def setKilled(self):
        self.dead = True
        
    def checkDead(self):
        return self.dead
        
    def deathFallBehind(self):
        self.setPos(self.getPos()[0] - BG_SCROLL_RATE)
        
    #overwritten stuff
    
    
    def _updateSpritePos(self):
        pos = self.getPos()
        try: self.sprite.setPos(pos[0], pos[1] + self.z_pos)
        except AttributeError: pass
        self.shadow.setPos(pos[0] + self.getSpriteWidth()/2, pos[1] + 1)
        
        
    def destroy(self):
        super().destroy()
        if self.shadow:
            self.shadow.destroy()
        self.shadow = None