Do you like my tutorials?

Then consider supporting me on Ko-fi

Talking about 2 Cars game, Game development, HTML5, Javascript and Phaser.

Here we are with the second part of “2 Cars” game prototype. In the first part we created the bare bones of the prototype, now we are adding targets to collect and a steering effect to the car when it moves through lanes. As in the original game, missing a target means “game over”, although in our prototype I simply restart the game. Also, I added more difficult by increasing the amount of stuff – target and obstacles – in the game. So, let’s have a look at the final result:
Click on a lane to make the car change lane, avoid blocks and collect targets. Here are the new source code with new lines highlighted:
var game;

var cars = [];
var carColors = [0xff0000, 0x0000ff];
var carTurnSpeed = 250;

var carGroup;
var obstacleGroup;
var targetGroup;

var obstacleSpeed = 150;
var obstacleDelay = 1400;

window.onload = function() {	
	game = new Phaser.Game(320, 480, Phaser.AUTO, "");
     game.state.add("PlayGame",playGame);
     game.state.start("PlayGame");
}

var playGame = function(game){};

playGame.prototype = {
	preload: function(){
          game.load.image("road", "road.png");
          game.load.image("target", "target.png");
          game.load.image("car", "car.png");
          game.load.image("obstacle", "obstacle.png");
	},
  	create: function(){
          game.add.image(0, 0, "road");
          game.physics.startSystem(Phaser.Physics.ARCADE);
          carGroup = game.add.group();
          obstacleGroup = game.add.group();
          targetGroup = game.add.group();
          for(var i = 0; i < 2; i++){
               cars[i] = game.add.sprite(0, game.height - 80, "car");
               cars[i].positions = [game.width * (i * 4 + 1) / 8, game.width * (i * 4 + 3) / 8];
               cars[i].anchor.set(0.5);
               cars[i].tint = carColors[i];  
               cars[i].canMove = true;
               cars[i].side = i;
               cars[i].x = cars[i].positions[cars[i].side];
               game.physics.enable(cars[i], Phaser.Physics.ARCADE); 
               cars[i].body.allowRotation = false;
               cars[i].body.moves = false;  
               carGroup.add(cars[i]);
          }
          game.input.onDown.add(moveCar);
          game.time.events.loop(obstacleDelay, function(){
               for(var i = 0; i < 2; i++){
                    if(game.rnd.between(0, 1) == 1){
                         var obstacle = new Obstacle(game, i);
                         game.add.existing(obstacle);
                         obstacleGroup.add(obstacle);  
                    }
                    else{
                         var target = new Target(game, i);
                         game.add.existing(target);
                         targetGroup.add(target);        
                    }
               }
          });          
	},
     update: function(){
          game.physics.arcade.collide(carGroup, obstacleGroup, function(){
               game.state.start("PlayGame");     
          });
          game.physics.arcade.collide(carGroup, targetGroup, function(c, t){
               t.destroy();
          });
     }
}

function moveCar(e){
     var carToMove = Math.floor(e.position.x / (game.width / 2));
     if(cars[carToMove].canMove){
          cars[carToMove].canMove = false;
          var steerTween = game.add.tween(cars[carToMove]).to({
               angle: 20 - 40 * cars[carToMove].side
          }, carTurnSpeed / 2, Phaser.Easing.Linear.None, true);
          steerTween.onComplete.add(function(){
               var steerTween = game.add.tween(cars[carToMove]).to({
                    angle: 0
               }, carTurnSpeed / 2, Phaser.Easing.Linear.None, true);
          })
          cars[carToMove].side = 1 - cars[carToMove].side;
          var moveTween = game.add.tween(cars[carToMove]).to({ 
               x: cars[carToMove].positions[cars[carToMove].side],
          }, carTurnSpeed, Phaser.Easing.Linear.None, true);
          moveTween.onComplete.add(function(){
               cars[carToMove].canMove = true;
          })
     }
}

Obstacle = function (game, lane) {
     var position = game.rnd.between(0, 1) + 2 * lane;
	Phaser.Sprite.call(this, game, game.width * (position * 2 + 1) / 8, -20, "obstacle");
	game.physics.enable(this, Phaser.Physics.ARCADE);
     this.anchor.set(0.5);
     this.tint = carColors[Math.floor(position / 2)];
};

Obstacle.prototype = Object.create(Phaser.Sprite.prototype);
Obstacle.prototype.constructor = Obstacle;

Obstacle.prototype.update = function() {
	this.body.velocity.y = obstacleSpeed;
	if(this.y > game.height){
		this.destroy();
	}
};

Target = function (game, lane) {
     var position = game.rnd.between(0, 1) + 2 * lane;
	Phaser.Sprite.call(this, game, game.width * (position * 2 + 1) / 8, -20, "target");
	game.physics.enable(this, Phaser.Physics.ARCADE);
     this.anchor.set(0.5);
     this.tint = carColors[Math.floor(position / 2)];
};

Target.prototype = Object.create(Phaser.Sprite.prototype);
Target.prototype.constructor = Target;

Target.prototype.update = function() {
	this.body.velocity.y = obstacleSpeed;
	if(this.y > game.height - this.height / 2){
		game.state.start("PlayGame");   
	}
};
It’s not that much more than a new class and a couple of tweens, but now the game looks better. Next time we’ll see the main menu, some particle effects and how to keep track of the best scores – although you should know how to do it – and the game will be completed. Meanwhile, download the source code of this example.

Never miss an update! Subscribe, and I will bother you by email only when a new game or full source code comes out.