Flux – Day 1 – Game Design, Setup and Making Bullets Fly

One of my new years resolution was to create a mobile game this year and I will be using this blog to document my journey. It will be a great learning experience for me and it will allow me to mess with all these new tools. So I have a game idea that has been constantly evolving. I think the process of game design is a very interesting topic and I would like to share the thoughts that lead up to my game design.

So mobile games usually have very simple buttons. Usually just a click on the screen. This is because there’s not much space on a tiny screen for anything else and multiple buttons would just be hard on the user to actually see the screen with their fingers blocking everything. So I thought back on old classic simple games which I played before. And I remembered Jezzball. Jezzball is an extremely old Windows game. The point of the game is to separate the balls by building walls without the balls touching the walls while it’s constructing. The game only required two buttons: one to switch directions and one to build the wall. So in order to limit that to one button click, I decide to make the walls circular. So by holding on to a certain area on the screen, a wall would build around the bouncing balls! One problem with that though is that it’s hard to see the ball you’re trying to trace with your fat fingers blocking it. Would be great for a PC with a mouse but a terrible experience for a mobile user. Also capturing balls all day doesn’t seem that captivating so let’s throw in something that would make it more interesting. Adding in higher stakes.

jezzballclassic

I decide to throw in a space ship and make this one of those 2D shooter airplane game. That way, you can protect your ship from all these bouncing balls. Though that would be hard to explain why there are bouncing balls in the first place. So it was time to add enemy ships who shoot circular bullets where I have to capture. But that idea of your finger covering up the ball still haunted me. I knew it was an interesting concept but the player would be frustrated by this problem. And that’s not something I want my players to feel when they play my game. But I LOVE the idea of not having your own bullets and using what’s around you to win.

The name Flux came from a Heroes of Newerth character. His ultimate power isn’t about doing damage, but about dragging or pushing away the enemies. That idea is so interesting because it leads to insane plays depending on the environment and the cards he is dealt. So with that in mind, I thought about creating a ship where you can either pull in or push out bullets. Combining that with only one button makes this challenging but we’ll just have to wait and see how enjoyable it will be.

Since I don’t have an any iOS, I decide to create it for the Android. But after reading up and setting up my environment, I remembered how painful and ugly Java was. And since I love Javascript, I decide to make an HTML5 game instead.

Setup was a pain. Got VMPlayer to boot up Ubuntu. Installed and setup all my necessary files and programs for this project (node, git, etc). I created a Github repository (https://github.com/jdnguyen/flux). And my IDE of choice has always been something from JetBrains because I’ve been using RubyMine before and it has been amazing. So I got their Javascript IDE, WebStorm. I also installed Coffeescript and hooked it up to WebStorm. Coffeescript just makes it so much easier to code and read. I setup a watcher on the project so it could translate any Coffeescript files immediately to Javascript after each save. I can explain this long tedious task in another post if anyone is interested.

Next up was to actually start an empty project. Quick Googling showed me HTML5 Boilerplate (http://html5boilerplate.com/). It basically starts an empty HTML5 project for you. Which is amazing because it takes into account all browsers, setup all your necessary files, and puts them in an extremely neat format. Made my life so much easier.

Next step, finding a good game engine. I found this great HTML5 Engine called EaselJS (http://createjs.com/#!/EaselJS) which seemed to have what I need: Basic shape drawing, mouse interaction, hit detection, and really easy to update and draw frames. I downloaded the minified Javascript file and loaded that into my project.

Time to start actual coding. First step is to draw my canvas where the game will take place. This should go inside your index.html file in the body block (I took out the brackets because the blog was being weird about showing html):

  canvas id="canvas" width="500" height="500"

You should probably add a black background-color to the stylesheet for this canvas to make the background black (since we’re in space). Everything now will be in Coffeescript because it’s beautiful. I put it all into main.cofeee which would translate to main.js. I initialized the canvas and ship:

stage = new createjs.Stage("canvas")
_my_ship = new createjs.Shape()
_ship_width = 80
_ship_height = 30

init = ->
  _my_ship.graphics.beginFill("blue").drawRect 0, 0, _ship_width, _ship_height
  _my_ship.x = 100
  _my_ship.y = stage.canvas.height - _ship_height
  stage.addChild _my_ship
  stage.update()

  stage.on "stagemousemove", (evt) ->
    _my_ship.x = evt.stageX - _ship_width/2
    stage.update()

init()

This creates a canvas, create my ship, puts it on the bottom of the screen, and it will move along the x-coordinate with my mouse. stage.update() draws the screen so I have to update the stage each time the mouse moves around the campus. Basic controls are done. Next step is drawing enemies and making them shoot bullets.

I created an array that would store all the enemies. Then I created a method to spawn enemies. These ships will spawn on the far top right of the screen and move left. The enemy would also hold a shootDelay which will be how many cycles before it shoots another bullet and shootCounter to keep track of the current cycle:

_enemy_ships = []
spawnEnemy = ->
  shape = new createjs.Shape()
  shape.graphics.beginFill("red").drawRect 0, 0, _ship_width, _ship_height
  shape.x = stage.canvas.width
  shape.y = 100
  _enemy_ship=
    shape: shape
    shootDelay: 40
    shootCounter: 0
  _enemy_ships.push _enemy_ship
  stage.addChild shape

Now that we have a method to spawn enemies, we need to call it. So I created two more global fields. One to keep track of how many cycles til it spawns another enemy and what cycle we’re currently on. Now we need this to run constantly regardless of human’s interaction. So there needs to be a game loop that keeps track of enemy’s movement and spawning. Good thing for EaselJS, this is relatively easy to set up. So I end up adding this this:

_enemy_spawn_counter = 0
_enemy_spawn_rate = 240

init = ->
  _enemy_ships = []
  _enemy_bullets = []

  _my_ship.graphics.beginFill("blue").drawRect 0, 0, _ship_width, _ship_height
  _my_ship.x = 100
  _my_ship.y = stage.canvas.height - _ship_height
  stage.addChild _my_ship

  stage.on "stagemousemove", (evt) ->
    _my_ship.x = evt.stageX - _ship_width/2

  createjs.Ticker.on "tick", update
  createjs.Ticker.setFPS 60
  spawnEnemy()

update = ->
  enemyShipSpawn()
  stage.update()

enemyShipSpawn = ->
  _enemy_spawn_counter++
  if _enemy_spawn_counter >= _enemy_spawn_rate
    _enemy_spawn_counter = 0
    spawnEnemy()

So the Ticker is set to 60 frames per second. That means it will run my update method 60 times a second. I set my spawn counter to 240. That means an enemy will spawn every 6 seconds. But now the enemies are not moving yet. They’re just spawning in the top right corner. We need to get them to move left until they’re off the screen and then unhook them because we don’t want to keep track of things off the screen. There’s no point to it and it will just slow down the game. Also I like to point out that I removed the stage.update() from the mouse movement. The game is already redrawing 60 times a second right now which is more than enough. Redrawing extra when the mouse is moving would only cause unnecessary code execution.

I created another method called enemyShipMovement and called it inside my update method:

enemyShipMovement = ->
  i = _enemy_ships.length - 1
  while i >= 0
    ship = _enemy_ships[i]
    ship.shape.x -= 2
    if ship.shape.x + _ship_width <= 0
      stage.removeChild ship.shape
      _enemy_ships.splice(i, 1)

It goes through my array of enemy ships and move it to the left by 2 pixels each cycle. Since the coordinates of the ship is in the top left corner, I have to make sure that the right corner of the ship is off the screen before deleting the ship. So I add the ship’s width to the x coordinate to make sure that it’s less than 0 before deleting. Deletion comes in two parts. I have to first remove the actual shape from the stage and then remove the ship’s hash info from my array. You might have noticed I traversed through the array from the back as opposed to starting i = 0. I did that at first but it caused me a bug. When I delete ships, it would throw off the i counter and skip through ships moving. Now we have ships moving to the left and deleting themselves once they his the left side of the screen.

Time to create the bullets. I created two different methods. One to spawn bullets and one to move the bullets. Spawning the bullets is a bit harder though. It’s spawning on the enemy with the intention of hitting the player. Once the bullet leaves the enemy, it will travel at a certain speed and direction. So I have to keep these info on the bullet. When something moves, it moves with a velocity in the x and y direction. The bullet should always carry the seem speed regardless of the angle it is shooting so we’re gonna need some basic math. The Pythagorean theorem to be more exact.

createBullet = (start_x, start_y) ->
  shape = new createjs.Shape()
  shape.graphics.beginFill("yellow").drawCircle 0, 0, _bullet_size
  shape.x = start_x + _ship_width/2
  shape.y = start_y + _ship_height
  target_x = _my_ship.x + _ship_width/2
  target_y = _my_ship.y + _ship_height/2

  dist = Math.sqrt( Math.pow(target_x - shape.x,2) + Math.pow(target_y - shape.y,2)) / _bullet_speed
  nx = (target_x - shape.x)/dist
  ny = (target_y - shape.y)/dist

  _bullet=
    shape: shape
    dir_x: nx
    dir_y: ny
  _enemy_bullets.push _bullet
  stage.addChild shape

As you can see, I pass the bullet the starting location of the ship. I spawn it in the center to the enemy ship with it’s target being the center of my ship. The _bullet_speed is a global variable with the speed you want. It just multiples with our directional velocity. With some basic math I’m sure you guys can figure out, I get the x and y velocity and store it into a hash with the shape itself. I then pump that into an array to loop through. I create the second method: the bullet flying.

enemyBulletTravel = ->
  i = _enemy_bullets.length - 1
  while i >= 0
    bullet = _enemy_bullets[i]
    bullet.shape.x += bullet.dir_x
    bullet.shape.y += bullet.dir_y
    if bullet.shape.y >= stage.canvas.height
      stage.removeChild bullet.shape
      _enemy_bullets.splice(i, 1)

It looks the same as the ship moving but it can move along the x and y coordinate and that the bullet gets deleted once it goes to the bottom of the screen. I add this method to my update method so it will move the bullets 60 times a second. Now how do I shoot these bullets? I need to tell the ship when to add create these bullets for it to fly. I add on to the enemy ship movement method:

enemyShipMovement = ->
  i = _enemy_ships.length - 1
  while i >= 0
    ship = _enemy_ships[i]
    ship.shape.x -= 2
    if ship.shape.x + _ship_width = ship.shootDelay
        ship.shootCounter = 0
        createBullet(ship.shape.x, ship.shape.y)
    i--

If my ship isn’t destroyed, they it will add to the shoot counter. Once the shoot counter fills up, it will create a bullet from it’s current location and then reset the counter again. If you run the program, you will see plenty of bullets flying at your space ship with enemies flying over. You can tweek with the global variables to get them to shoot more bullets or fly faster.

Last thing I want to do today is to get basic hit detection with the bullets hitting your ship. And with EaselJS, this is really easy. So I add on to the enemy bullet travel method:

enemyBulletTravel = ->
  i = _enemy_bullets.length - 1
  while i >= 0
    bullet = _enemy_bullets[i]
    bullet.shape.x += bullet.dir_x
    bullet.shape.y += bullet.dir_y
    if bullet.shape.y <= 0
      stage.removeChild bullet.shape
      _enemy_bullets.splice(i, 1)
    else
      pt = bullet.shape.localToLocal(0,0,_my_ship)
      if _my_ship.hitTest(pt.x, pt.y)
        stage.removeChild bullet.shape
        _enemy_bullets.splice(i, 1)
        console.log "MY SHIP GOT HIT"
    i--

If the bullet is not off the screen, it will check the bullets location with my current ships location. EaselJs has a method called hitTest which will return true of the shapes are colliding in any way. If it is true, I destroy the bullet and print out a message. And there we have it for day 1. Flying ships, bullets and hit detection.

2 thoughts on “Flux – Day 1 – Game Design, Setup and Making Bullets Fly

Leave a comment