We now have a playfield, a sprite base class and a keyboard handler. It's time we add the player ship.
The class for the playership needs some information from us:
- the user input for ship navigation
- the boundary of the playfield so that the ship can't be navigated outside
- the ship's speed
The ship is equipped with weapons. We'll add a cannon to it. The cannon can be fired, but needs to recharge itself, so that the firing won't happen too quickly.
There are several options to fire a bullet. One of them is that the player's ship spawns the bullets. But for that it would need to know about the bullet layer. So I'd rather prefer we only indicate that a bullet is fired and let the sprite manager, i. e. for now a method call in the game loop do the bullet spawning for us.
The player class:
public class Player extends SpriteBase { double playerShipMinX; double playerShipMaxX; double playerShipMinY; double playerShipMaxY; Input input; double speed; double cannonChargeTime = 6; // the cannon can fire every n frames double cannonChargeCounter = cannonChargeTime; // initially the cannon is charged double cannonChargeCounterDelta = 1; // counter is increased by this value each frame double cannonBullets = 5; // number of bullets which the cannon can fire in 1 shot (center, left, right) double cannonBulletSpread = 0.6; // dx of left and right bullets double cannonBulletSpeed = 8.0; // speed of each bullet public Player(Pane layer, Image image, double x, double y, double r, double dx, double dy, double dr, double health, double damage, double speed, Input input) { super(layer, image, x, y, r, dx, dy, dr, health, damage); this.speed = speed; this.input = input; init(); } private void init() { // calculate movement bounds of the player ship // allow half of the ship to be outside of the screen playerShipMinX = 0 - image.getWidth() / 2.0; playerShipMaxX = Settings.SCENE_WIDTH - image.getWidth() / 2.0; playerShipMinY = 0 - image.getHeight() / 2.0; playerShipMaxY = Settings.SCENE_HEIGHT -image.getHeight() / 2.0; } public void processInput() { // ------------------------------------ // movement // ------------------------------------ // vertical direction if( input.isMoveUp()) { dy = -speed; } else if( input.isMoveDown()) { dy = speed; } else { dy = 0d; } // horizontal direction if( input.isMoveLeft()) { dx = -speed; } else if( input.isMoveRight()) { dx = speed; } else { dx = 0d; } } @Override public void move() { super.move(); // ensure the ship can't move outside of the screen checkBounds(); } private void checkBounds() { // vertical if( Double.compare( y, playerShipMinY) < 0) { y = playerShipMinY; } else if( Double.compare(y, playerShipMaxY) > 0) { y = playerShipMaxY; } // horizontal if( Double.compare( x, playerShipMinX) < 0) { x = playerShipMinX; } else if( Double.compare(x, playerShipMaxX) > 0) { x = playerShipMaxX; } } @Override public void checkRemovability() { // TODO will be added later when the player ship explodes } public boolean isFirePrimaryWeapon() { boolean isCannonCharged = cannonChargeCounter >= cannonChargeTime; return input.isFirePrimaryWeapon() && isCannonCharged; } public void chargePrimaryWeapon() { // limit weapon fire // --------------------------- // charge weapon: increase a counter by some delta. once it reaches a limit, the weapon is considered charged cannonChargeCounter += cannonChargeCounterDelta; if( cannonChargeCounter > cannonChargeTime) { cannonChargeCounter = cannonChargeTime; } } public void unchargePrimaryWeapon() { // player bullet uncharged cannonChargeCounter = 0; } public double getPrimaryWeaponX() { return x + image.getWidth() / 2.0; // center of the ship } public double getPrimaryWeaponY() { return y; } public double getPrimaryWeaponBulletSpread() { return cannonBulletSpread; } public double getPrimaryWeaponBulletCount() { return cannonBullets; } public double getPrimaryWeaponBulletSpeed() { return cannonBulletSpeed; } }
Now we have the playfield, scrolling environment, enemies, bullets, player and the input. What's left to do is to put it all together.
No comments:
Post a Comment