Sunday, January 18, 2015

Anansi: Bullets


Let's add some game to our game. We now have

  • a sprite manager
  • a mechanims to create moving sprites
  • a player ship
  • a keyboard event handler

With that it should be easy to spawn some bullets using the primary weapon key (space bar). Adding bullets is just more of the same.

We let the bullets fly on their own layer. We place it right below the playfield layer.

Pane bulletLayer = new Pane();
...
bulletLayer = new Pane();
...
root.getChildren().add( bulletLayer);
And then create a global image variable and load the image in our loadGame() method.
Image playerBullet;
...
playerBullet = new Image( getClass().getResource( "assets/bullets/bullet_01.png").toExternalForm());
The bullets fly at a given speed. Varying the speed gives us the opportunity to start at slower speeds and increase it when the player picks up some bonus from the playfield. We declare a global variable for the player bullet speed.
double cannonBulletSpeed = 8.0;
And all that's left is to make it fly upon keypress. We add the mechanism for that to the game loop. The speed is given as positive value. But since the bullets flies from bottom to top, we need it to be negative in order to decrease the y position.
// fire player bullets
// ---------------------------
if( isSpacePressed) {
 
 // x-position: center bullet on center of the ship
 double bulletX = playerShip.getLayoutX() + playerShip.getImage().getWidth() / 2.0 - playerBullet.getWidth() / 2.0;
 // y-position: let bullet come out on top of the ship
 double bulletY = playerShip.getLayoutY();

 // create sprite
 ImageView imgv = new ImageView( playerBullet);
 Sprite sprite = new Sprite( bulletLayer, imgv, bulletX, bulletY, 0, -cannonBulletSpeed);
 sprites.add( sprite);

}

And there we have it: We can shoot bullets from our ship.

This all happens in our game loop at 60 frames per second, which means a lot of bullets are getting spawned. It makes the shooting look more like a straight laser:


What we need now is some kind of charging delay.

Think in terms of the game loop. Something is happening 60 times a second. So we add a counter and depending on the status of that counter we allow the player to fire a bullet, even though he keeps on pressing the primary weapon fire key on the keyboard. We introduce a few variables for the cannon-charging mechanism.
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 
And we extend our cannon firing code.
// limit bullet fire
// ---------------------------
// charge player cannon: increase a counter by some delta. once it reaches a limit, the cannon is considered charged
cannonChargeCounter += cannonChargeCounterDelta;
if( cannonChargeCounter > cannonChargeTime) {
 cannonChargeCounter = cannonChargeTime;
}

// fire player bullets
// ---------------------------
boolean isCannonCharged = cannonChargeCounter >= cannonChargeTime;
if( isSpacePressed && isCannonCharged) {
 
 // x-position: center bullet on center of the ship
 double bulletX = playerShip.getLayoutX() + playerShip.getImage().getWidth() / 2.0 - playerBullet.getWidth() / 2.0;
 // y-position: let bullet come out on top of the ship
 double bulletY = playerShip.getLayoutY();

 // create sprite
 ImageView imgv = new ImageView( playerBullet);
 Sprite sprite = new Sprite( bulletLayer, imgv, bulletX, bulletY, 0, -cannonBulletSpeed);
 sprites.add( sprite);

 // player bullet uncharged
 cannonChargeCounter = 0;
}
This gives us a nice cannon firing delay which looks like this:


I mentioned player bonus earlier. In addition to increasing the cannon firing speed we could also add more bullets. We don't want more bullets in the same firing line, so we add a bullet spread. Of course the spread should vary depending on the player's bonus level. We introduce new variables.
double cannonBullets = 9; // number of bullets which the cannon can fire in 1 shot (center, left, right)
double cannonBulletSpread = 0.6; // dx of left and right bullets
And extend our code so that the bullets spread left/center/right.
// left/right: vary x-axis position
for( int i=0; i < cannonBullets / 2.0; i++) {

 // left
 imgv = new ImageView( playerBullet);
 sprite = new Sprite( bulletLayer, imgv, bulletX, bulletY, -cannonBulletSpread * i, -cannonBulletSpeed);
 sprites.add( sprite);
 
 // right
 imgv = new ImageView( playerBullet);
 sprite = new Sprite( bulletLayer, imgv, bulletX, bulletY, cannonBulletSpread * i, -cannonBulletSpeed);
 sprites.add( sprite);

}
This is how it looks like:



Very nice. Now we have a powerful cannon, we can expect lots of enemy targets. In the next lesson they come ;-)

No comments:

Post a Comment