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
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