Exemplo n.º 1
0
class CBoundingBox(Component):
    '''
    Encapsulates geometric Bounding box data for a GameObject.

    Needs access to Position and Size components.
    '''
    cType = ComponentType.BOUNDING_BOX
    
    dependencies = [
        ComponentType.POSITION,
        ComponentType.OBJECT_SIZE
    ]
    
    COLLISION_WIDTH_DIV = 4
    COLLISION_BOX_H_OFFSET = 1
    boundingBox = None
    
    def __init__(self, p, s):
        self._createRect()
        return

    def _createRect(self):
        size = self.gameObject.getComponent(
            ComponentType.OBJECT_SIZE)
        pos = self.gameObject.getComponent(
            ComponentType.POSITION)
        
        self.xLeftOffsetCollisionBox = (
            size.getWidth() / self.COLLISION_WIDTH_DIV)
        collisionBoxHeight = (
            size.getHeight() - self.COLLISION_BOX_H_OFFSET)
        
        self.boundingBox = Rectangle(
            pos.getX(),
            pos.getY(),
            (size.width / 2),
            collisionBoxHeight)
    
    def getBoundingBox(self):
        '''
        Updates the position of the bounding box and returns it.
        '''
        pos = self.gameObject.getComponent(
            ComponentType.POS)
        
        self.boundingBox.setX(
            pos.getX())# + self.xLeftOffsetCollisionBox)
        self.boundingBox.setY(self.pos.getY())
        return self.boundingBox
Exemplo n.º 2
0
class Player(objects.BaseLevelObject):
    '''
    The human-controlled main game character.
    '''
    input # InputProviderListener
    
    HEIGHT_WALK_DIVIDER = 5
    ACCEL_WALK_SPEED_DIVIDER = 10
    MAX_RUN_WALK_MULTIPLIER = 2
    ACCEL_MAX_RATE_MULTIPLIER = 2
    INIT_JUMP_WALK_SPEED_MULTIPLIER = 0.2
    MAX_JUMP_INIT_JUMP_MULTIPLIER = 2
    MAX_FALL_MAX_JUMP_MULTIPLIER = 2.5
    MAX_CHARGE = 20.34
    CHARGE_INCR = 0.4
    BOW_Y_OFFSET_NORMAL = -2
    BOW_Y_OFFSET_AIM_UP = -10
    BOW_Y_OFFSET_AIM_DOWN = 6
    ARROW_Y_OFFSET = 15
    setUp = False
    canJump = False
    userHoldingLeftXOrRight = False
    isChargingArrow = False
    isJumping = False
    jumpKeyDown = False
    outOfBounds = False
    
    xSpeed = float()
    ySpeed = float()
    
    prevXSpeed = float()
    prevYSpeed = float()
    
    accelX = float()
    
    bowCharge = float()
    bowX = float()
    bowY = float()
    bowYCurrentOffset = float()
    accelerationRate = float()
    maxAccelRate = float()
    initialJumpSpeed = float()
    maxJumpSpeed = float()
    jumpIncr = float()
    maxFallSpeed = float()
    walkSpeed = float()
    maxRunSpeed = float()
    
    MAX_HEALTH = 20
    BOW_AIM_UP_TRIGGER = 50
    BOW_AIM_DOWN_TRIGGER = 110
    BOW_X_OFFSET = 5
    BOW_ANGLE_OFFSET = 90
    COLLISION_WIDTH_DIV = 4
    
    health = MAX_HEALTH
    mouseX = 0
    mouseY = 0
    BOW_BUTTON = Input.MOUSE_LEFT_BUTTON
    xLeftOffsetCollisionBox = 0
    height = 0
    width = 0

    minReleaseCharge = 7
    # ^ minimum bow charge to fire an arrow
    
    jump = None
    left = None
    right = None
    playNote1 = None
    run = None
    
    collisionBox = None
    currentArrow = None
    
    firedArrows = []
    
    facing = enums.Direction.LEFT
    moving = enums.Direction.LEFT
    
    bowLeftPath = 'data/player_images/STICKMAN_BOW_LEFT.png'
    leftWalkPaths = 'data/player_images/8.png'
    leftStandPaths = 'data/player_images/standing.png'
    
    leftWalk = None
    rightWalk = None
    leftStand = None
    rightStand = None
    currentAnim = None

    
    bowLeft = None
    bowRight = None
    currentBow = None
    
    startTile = None
    # ^ player's initial location. Parsed from tmx Level file.

    COLLISION_BOX_H_OFFSET = 1
    
    collisionBoxHeight = 0
    currentInstrument = None
    playNote1KeyDown = None
    fastMoveMode = None
    hasInstrument = None
    hasInput = None

    def __init__(self, l, t):
        self.startTile = t
        setLevel(l)
        self.setUpStartPosition()
        print '----------> new Player'
        if not self.setUp:
            self.initAnim()
            self.setUpCollisionBox()
            self.initBow()
            self.setUpPlayerSpeed()
            self.setUp = True

    def setUpPlayerSpeed(self):
        self.calculateMovementSpeeds()
        print 'height : ' + self.height
        print '\nsetupPlayerSpeed'
        print '=============='
        print '  walkSpeed        : ' + self.walkSpeed
        print '  maxRunSpeed      : ' + self.maxRunSpeed
        print '  accelerationRate : ' + self.accelerationRate
        print '  maxAccelRate     : ' + self.maxAccelRate
        print '  initialJumpSpeed : ' + self.initialJumpSpeed
        print '  maxJumpSpeed     : ' + self.maxJumpSpeed
        print '  jumpIncr         : ' + self.jumpIncr
        print '  maxFallSpeed     : ' + self.maxFallSpeed

    def calculateMovementSpeeds(self):
        self.walkSpeed = self.height / self.HEIGHT_WALK_DIVIDER
        self.maxRunSpeed = self.walkSpeed * self.MAX_RUN_WALK_MULTIPLIER
        self.accelerationRate = self.walkSpeed / self.ACCEL_WALK_SPEED_DIVIDER
        self.maxAccelRate = self.accelerationRate * self.ACCEL_MAX_RATE_MULTIPLIER
        self.initialJumpSpeed = -self.walkSpeed * self.INIT_JUMP_WALK_SPEED_MULTIPLIER
        self.maxJumpSpeed = self.initialJumpSpeed * self.MAX_JUMP_INIT_JUMP_MULTIPLIER
        self.jumpIncr = -self.maxJumpSpeed - self.initialJumpSpeed / 10.3
        self.maxFallSpeed = -self.maxJumpSpeed * self.MAX_FALL_MAX_JUMP_MULTIPLIER

    def accelerate(self):
        if self.accelX < self.maxAccelRate:
            self.accelX += self.accelerationRate

    def setUpCollisionBox(self):
        self.xLeftOffsetCollisionBox = self.width / self.COLLISION_WIDTH_DIV
        self.collisionBoxHeight = self.height - self.COLLISION_BOX_H_OFFSET
        self.collisionBox = Rectangle(xPos, yPos, self.width / 2, self.collisionBoxHeight)

    def getWidth(self):
        return self.width

    def getHeight(self):
        return self.height

    def setCanJump(self, b):
        self.canJump = b
        self.isJumping = not b

    def setUpStartPosition(self):
        self.xPos = self.startTile.xPos
        self.yPos = self.startTile.yPos - self.startTile.tileHeight
        yPos -= 1
        print 'Player is on level ' + level + ' at position x: ' + xPos + ', y: ' + yPos

    def initBow(self):
        self.bowLeft = AnimCreator.loadImage(self.bowLeftPath)
        self.bowRight = self.bowLeft.getFlippedCopy(True, False)
        self.currentBow = self.bowLeft

    def getZone(self):
        return self.getLevel().getActorZone(self)

    def associateInputProvider(self, prov, inputStream):
        if self.hasInput:
            print 'Already associated an input provider'
            return
        prov.addListener(self)
        self.jump = BasicCommand('jump')
        self.left = BasicCommand('left')
        self.right = BasicCommand('right')
        self.playNote1 = BasicCommand('playNote1')
        self.run = BasicCommand('run')
        prov.bindCommand(KeyControl(Input.KEY_A), self.left)
        prov.bindCommand(KeyControl(Input.KEY_D), self.right)
        prov.bindCommand(KeyControl(Input.KEY_W), self.jump)
        prov.bindCommand(KeyControl(Input.KEY_1), self.playNote1)
        prov.bindCommand(KeyControl(Input.KEY_LSHIFT), self.run)

        def mousePressed(self, button, x, y):
            if button == self.BOW_BUTTON:
                c = self.getLevel().getCollisionTileAt(x, y)
                if c is not None:
                    print 'Mouse pressed Tile ' + c.xCoord + ', ' + c.yCoord
                self.mouseX = x
                self.mouseY = y
                self.readyArrow()
            else:
                if (button == slick.Input.MOUSE_RIGHT_BUTTON):
                    enemies = self.getLevel.getEnemies()
                    ## for-while
                    i = 0
                    while i < len(enemies):
                        e = enemies[i]
                        i += 1

        def mouseReleased(self, button, x, y):
            if (button == self.BOW_BUTTON):
                self.releaseArrow()

        def isAcceptingInput(self):
            return True

        def mouseMoved(self, oldx, oldy, newx, newy):
            self.mouseX = newx
            self.mouseY = newy

        def mouseWheelMoved(self, change):
            pass

        def mouseClicked(self, button, x, y, clicks):
            pass

        def mouseDragged(self, oldx, oldy, newx, newy):
            pass

        def inputEnded(self):
            pass

        def inputStarted(self):
            pass

        def setInput(self, input):
            pass

        inputStream.addMouseListener(MouseListener())
        self.hasInput = True

    def controlReleased(self, com):
        if com == self.left:
            if self.moving == Direction.LEFT:
                self.userHoldingLeftXOrRight = False
        elif com == self.right:
            if self.moving == Direction.RIGHT:
                self.userHoldingLeftXOrRight = False
        elif com == self.jump:
            print 'jump key released'
            self.jumpKeyDown = False
        elif com == self.playNote1:
            print 'playNote1 key released'
            self.playNote1KeyDown = False
        elif com == self.run:
            print '-- Shift released'
            self.fastMoveMode = False

    def controlPressed(self, com):
        if com == self.left:
            self.setMovingDir(Direction.LEFT)
            self.userHoldingLeftXOrRight = True
        else:
            if com == self.right:
                self.setMovingDir(Direction.RIGHT)
                self.userHoldingLeftXOrRight = True
            else:
                if com == self.jump:
                    self.jumpKeyDown = True
                    if self.canJump:
                        self.startJump()
                else:
                    if com == self.playNote1:
                        print 'playNote1 key pressed'
                        self.playNote1KeyDown = True
                        if self.hasInstrument:
                            self.currentInstrument.play(0)
                    else:
                        if com == self.run:
                            print '-- Shift is down'
                            self.fastMoveMode = True

    def pickUp(self, pi):
        print 'Player.pickUp( ' + pi + ')'

    def readyArrow(self):
        print 'Readying arrow'
        self.currentArrow = Arrow(xPos, yPos, level, self.mouseX, self.mouseY)
        self.isChargingArrow = True

    def chargeArrow(self):
        if self.bowCharge < self.MAX_CHARGE:
            self.bowCharge += self.CHARGE_INCR
        self.currentArrow.updateAiming(self.mouseX, self.mouseY)
        if self.currentArrow.getMovementAngle() >= 0:
            self.currentBow = self.bowRight
            self.setFacing(Direction.RIGHT)
            self.bowX = xPos + self.BOW_X_OFFSET + self.getCurrentFrameWidth() / 2
            self.currentBow.setRotation(self.currentArrow.getMovementAngle() - self.BOW_ANGLE_OFFSET)
        else:
            self.setFacing(Direction.LEFT)
            self.currentBow = self.bowLeft
            self.bowX = xPos - self.BOW_X_OFFSET
            self.currentBow.setRotation(self.currentArrow.getMovementAngle() + self.BOW_ANGLE_OFFSET)
        self.updateBowPosition()
        self.currentArrow.setPosition(self.getHoldingArrowX(), self.getHoldingArrowY())

    def getHealth(self):
        return self.health

    def die(self):
        print 'Player is dead!'

    def updateBowPosition(self):
        ANGLE = Math.abs(self.currentArrow.getMovementAngle())
        if ANGLE < self.BOW_AIM_UP_TRIGGER:
            self.bowYCurrentOffset = self.BOW_Y_OFFSET_AIM_UP
        else:
            if ANGLE < self.BOW_AIM_DOWN_TRIGGER:
                self.bowYCurrentOffset = self.BOW_Y_OFFSET_NORMAL
            else:
                self.bowYCurrentOffset = self.BOW_Y_OFFSET_AIM_DOWN
        self.bowY = yPos + self.bowYCurrentOffset

    def getHoldingArrowX(self):
        return xPos + self.getCurrentFrameWidth() / 2

    def getCurrentFrameWidth(self):
        return AnimCreator.getCurrentFrameRect(self).getWidth()

    def getHoldingArrowY(self):
        return yPos + self.ARROW_Y_OFFSET

    def releaseArrow(self):
        if self.bowCharge >= self.minReleaseCharge:
            self.currentArrow.release(self.bowCharge)
            self.firedArrows.add(self.currentArrow)
            print 'released arrow, power ' + self.bowCharge + ' angle ' + self.currentArrow.getMovementAngle()
        self.isChargingArrow = False
        self.currentArrow = None
        self.bowCharge = 0

    def getFiredProjectiles(self):
        return ArrayList(self.firedArrows)

    def setFacing(self, dir):
        self.facing = dir
        if not self.userHoldingLeftXOrRight:
            self.setStandingAnim()

    def setMovingDir(self, dir):
        if (self.moving != dir):
            self.xSpeed = 0
            print 'xSpeed = 0'
            self.resetAccelX()
        self.moving = dir
        self.setFacing(dir)

    def setStandingAnim(self):
        if self.facing == Direction.RIGHT:
            self.currentAnim = self.rightStand
        else:
            if self.facing == Direction.LEFT:
                self.currentAnim = self.leftStand
            else:
                raise IllegalStateException('standing dir neither left or right')

    def applySpeed(self, dir):
        self.accelerate()
        if dir == Direction.RIGHT:
            self.currentAnim = self.rightWalk
            self.xSpeed = self.accelX
        else:
            if dir == Direction.LEFT:
                self.currentAnim = self.leftWalk
                self.xSpeed = -self.accelX

    def applyFriction(self):
        self.xSpeed *= Level.FRICTION

    def update(self):
        ObjectMover.applyGravity(self)
        self.applyFriction()
        if self.userHoldingLeftXOrRight:
            self.applySpeed(self.moving)
        else:
            self.decelerate()
        if self.isJumping:
            if not self.jumpKeyDown:
                self.isJumping = False
            else:
                self.updateJump()
        if self.isChargingArrow:
            self.chargeArrow()
        Arrow.updateFiredArrows(self.firedArrows)
        ObjectMover.move(self)
        if self.xSpeed > 1 and (self.prevXSpeed != self.xSpeed):
            System.out.printf('xSpeed : %f | accelX : %f\n', self.xSpeed, self.accelX)
        if self.ySpeed < -1 and (self.prevYSpeed != self.ySpeed):
            pass
        self.prevYSpeed = self.ySpeed
        self.prevXSpeed = self.xSpeed

    def getLevel(self):
        return level

    def getCurrentAnim(self):
        return self.currentAnim

    def canJump(self):
        return self.canJump

    def printSpeed(self):
        print 'accelX==' + self.accelX + ', ' + 'xSpeed==' + self.xSpeed + ', ySpeed==' + self.ySpeed

    def printPosition(self):
        print 'xPos==' + xPos + ', yPos==' + yPos

    def startJump(self):
        print 'calling Player.jump()'
        self.setYSpeed(self.initialJumpSpeed)
        self.setCanJump(False)

    def updateJump(self):
        if self.isJumping and self.jumpKeyDown:
            if self.ySpeed > self.maxJumpSpeed:
                self.ySpeed -= self.jumpIncr
                print '  Player.updateJump( : ' + self.ySpeed + ')'
            else:
                print 'updateJump( --> maximum jump speed reached : ' + self.ySpeed + ')'
                self.isJumping = False

    def decelerate(self):
        self.accelX -= self.accelerationRate
        if self.accelX < 0:
            self.resetAccelX()

    def resetAccelY(self):
        pass

    def resetAccelX(self):
        self.accelX = 0
        self.setStandingAnim()

    def getFacing(self):
        return self.facing

    def getYSpeed(self):
        return self.ySpeed

    def getXSpeed(self):
        return self.xSpeed

    def setYSpeed(self, f):
        self.ySpeed = f

    def setXSpeed(self, f):
        self.xSpeed = f

    def getMaxFallSpeed(self):
        return self.maxFallSpeed

    def draw(self, g):
        g.drawAnimation(self.currentAnim, getX(), getY())
        self.drawArrows(g)
        if self.isChargingArrow:
            g.drawImage(self.currentBow, self.bowX, self.bowY)

    def drawArrows(self, g):
        if self.currentArrow is not None:
            self.currentArrow.draw(g)
        ## for-while
        i = 0
        while i < len(self.firedArrows):
            a = self.firedArrows[i]
            a.draw(g)
            i += 1

    def initAnim(self):
        leftWalkImgs = [Image() for __idx0 in range(self.leftWalkPaths.length)]
        rightWalkImgs = [Image() for __idx0 in range(self.leftWalkPaths.length)]
        leftStandImgs = [Image() for __idx0 in range(self.leftStandPaths.length)]
        rightStandImgs = [Image() for __idx0 in range(self.leftStandPaths.length)]
        leftWalkImgs = AnimCreator.getImagesFromPaths(self.leftWalkPaths).toArray(leftWalkImgs)
        self.height = leftWalkImgs[0].getHeight()
        rightWalkImgs = AnimCreator.getHorizontallyFlippedCopy(leftWalkImgs).toArray(rightWalkImgs)
        leftStandImgs = AnimCreator.getImagesFromPaths(self.leftStandPaths).toArray(leftStandImgs)
        rightStandImgs = AnimCreator.getHorizontallyFlippedCopy(leftStandImgs).toArray(rightStandImgs)
        autoUpdate = True
        self.leftWalk = Animation(leftWalkImgs, Actor.ANIM_DURATION, autoUpdate)
        self.rightWalk = Animation(rightWalkImgs, Actor.ANIM_DURATION, autoUpdate)
        self.leftStand = Animation(leftStandImgs, Actor.ANIM_DURATION, autoUpdate)
        self.rightStand = Animation(rightStandImgs, Actor.ANIM_DURATION, autoUpdate)
        self.setInitialAnim()

    def setInitialAnim(self):
        if (level.playerFacing == Direction.LEFT):
            self.currentAnim = self.leftWalk
        else:
            self.currentAnim = self.rightWalk
        i = self.currentAnim.getCurrentFrame()
        self.width = i.getWidth()
        self.height = i.getHeight()

    def isOutOfBounds(self):
        return self.outOfBounds

    def setOutOfBounds(self, b):
        self.outOfBounds = b

    def getCollisionBox(self):
        self.collisionBox.setX(xPos + self.xLeftOffsetCollisionBox)
        self.collisionBox.setY(yPos)
        return self.collisionBox