DEV Community

Cover image for Applying What I've Learned to Update A Past Project
Jess
Jess

Posted on • Updated on

Applying What I've Learned to Update A Past Project

After entering JS13k (you can read about my experience here) I decided to revisit one of my previous projects that I did during my time in Flatiron School. The project is a game called Invasion!, about my dog Penny dreaming of fighting squirrels in space. I previously wrote about it here.


animated gif of gameplay

Things I Added/Changed

Resize Game Based on Window Size

When I first made the game I hardcoded a height and width for the canvas. I didn't know how to make it resize to different window dimensions and any changes I made to the size affected how the game sprites looked as well as the collision detection. Because I had a deadline I left it as it was to focus on other aspects that I needed to get done.

As I was making my game for JS13k I wanted it to be resizable so I did a lot of research into it and wrote a post about how to do it. By using this technique I didn't have to make any changes to the sprite sizes or collision detection because the native gameplay resolution is separate from the canvas resolution.


resizing the game

Create Background with JavaScript

The initial background was a very large .png of stars in space. For my JS13k game, I created a starry space background using JavaScript, so I decided to use that technique here instead of an image as well.

To create this effect, I added a separate canvas behind the one that contained all my gameplay. I created a function that simply looped over the window dimensions and placed a white pixel at random x/y points. I incremented my loop variables by 32 to space the stars out. 32 was just a random value I went with; depending on how many stars you want you could increase or decrease the value.

function buildBackground(ctx) {
  for (let i = 0; i < window.innerWidth; i += 32) {
    for (let j = 0; j < window.innerHeight; j += 32) {
      const randX = Math.floor(Math.random() * window.innerWidth);
      const randY = Math.floor(Math.random() * window.innerHeight);
      ctx.fillStyle = 'white';
      ctx.fillRect(randX, randY, 1, 1);
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

This function runs once at start and there is no need to redraw to this canvas again.

P-Bombs

This is THE feature I really wanted to add the first time around but ran out of time. I thought it would be cool if my other dog, Pixel, had a role in Penny's dream. Now, Penny can deploy 3 P-Bombs, and Pixel will quickly move across the screen shooting at the enemy squirrels.

To create the P-Bombs, I added some properties to the Player class to keep track of if there is a P-Bomb currently activated, how many remain, and an interval ID because the P-Bomb needed to create a new BulletObject every 300ms.

Instead of creating a whole new class and adding collisions, I made the P-Bomb itself another "player", but instead of having its movement controlled by a user, its moveLeft property is set to true so it moves across the screen on its own.

(The hardcoded values correspond to location on my spritesheet and they're halved for a more appropriate size.)

pBombShootAction(gameWidth, gameHeight) {
    // create
    this.pBombs--;
    this.pBomb = new Player(gameWidth, gameHeight);
    this.pBomb.spriteObj.sourceX = 224;
    this.pBomb.spriteObj.sourceWidth = 219;
    this.pBomb.spriteObj.sourceHeight = 157;
    this.pBomb.spriteObj.x = gameWidth + 219;
    this.pBomb.spriteObj.y = gameHeight - 157 / 2 - 30;
    this.pBomb.spriteObj.width = 219 / 2;
    this.pBomb.spriteObj.height = 157 / 2;
    this.pBombActive = true;
    this.pBomb.moveLeft = true;
    this.pBomb.type = 'pBomb';

    // shoot
    this.pBombIntervalId = setInterval(() => {
      const { x, y, width, height } = this.pBomb.spriteObj, speed = 30;
      new BulletObject("playerBullet", speed, { x, y, width, height });
    }, 300)
}
Enter fullscreen mode Exit fullscreen mode

Now, the player update function checks for whether or not a P-Bomb is active and shooting and reacts accordingly.

if (this.pBombShoot) {
  this.pBombShootAction(gameWidth, gameHeight);
  this.pBombShoot = false;
}

if (this.pBombActive) {
  if (this.pBomb.spriteObj.x + this.pBomb.spriteObj.width < 0) {
    this.stopPBomb();
  }
}
Enter fullscreen mode Exit fullscreen mode

Cooldown Feature and Fluid Movement

I decided to change how the player movement works. Before the user had to tap left or right repeatedly instead of being able to hold down the keys. I made it that way because it seemed too easy to dodge around the enemy bullets and shoot enemies if you could move fluidly. I added a cooldown feature to keep the player from spamming the shoot key, and this allowed me to improve the player movement.

To create the cooldown, I added a boolean property to the player which is set to true when the player presses the spacebar. Then I created a timeout for 1300ms and, after that time, the cooldown property is set back to false and the player can shoot again.

 if (!game.player.isBarkCooldown) {
    game.player.shoot = true;
    game.player.isBarkCooldown = true;
    setTimeout(() => {
      game.player.isBarkCooldown = false;
    }, 1300)
}
Enter fullscreen mode Exit fullscreen mode

--
Those were the major changes I made but there are still some things I'd like to add. I think my next update will be touch controls for mobile since it currently only works on desktop.

Discussion (0)