Game AI using Phaser.io and Synaptic : PART 1

Hey, whats up! Long time writing a tutorial. So here is small series on game development & AI. Not a big game, but enough to get started on your own. Make sure to download the complete project.

Also in the next article, I will be adding an Artificial neural network to this game, so that, it can play on it own.

[wpi_designer_button text=’Download’ link=’https://github.com/arjunsk/phaser_ai_game’ style_id=’48’ icon=’github’ target=’_blank’]

Phaser.io

I was searching for a web based game-dev framework and found Phaser to be a perfect find. Frankly, it is smoother in rendering game objects.

Getting Started:

Here is the basic structure of a Phaser game.

index.html :

<!doctype html>
<html>
    <head>
        <meta charset="UTF-8" />
        <title>Jumbo</title>

        http://lib/phaser.min.js
        http://game_logics.js

    </head>

    <body></body>
</html>

game_logic.js

var w=800;
var h=400;

// #1 : Create game canvas for rendering the game UI 
var game = new Phaser.Game(
			w, h, Phaser.CANVAS, 'phaser-game', 
			{ 
				preload: preload, 
				create: create, 
				update: update, 
				render: render 
			 }
		);

		
//#2 : Loads game assets from directory 
function preload() {
    game.load.image('background', 'assets/game/background.png');
    
}

//#3 : Declare all the game objects
var gameObj1;
var gameObj2;
......

//#4 : Initialise game objects and set its properties
function create() {
    gameObj = game.add.sprite(x-cord, y-cord, 'gameobject_name_in_preload');
}

//#5 : This part handles games fps. For eg:- We can get objects position cordinates, for each frame here.
function update() {
 
    if( jumpButton.isDown ){
        jump(); // modularize function to handle jump event
    }
}


//#6 : Helps in debugging
function render () {

}

If you want to know more in depth about the specific inbuilt functions, refer to this thread.

Now I will be breaking down my game_logic.js into smaller parts, give you a brief overview.

Part 1:

var w=800;
var h=400;

//Game object is the heart of your game, providing quick access to common functions and handling the boot process.
var game = new Phaser.Game(w, h, Phaser.CANVAS, 'phaser-game', { preload: preload, create: create, update: update, render: render });

function preload() {
    //load.image() is used to load normal images
    game.load.image('background', 'assets/game/background.png');
	
    //load.spritesheet() is used to load sprite sheets as shown below( these are turned into animations )
    game.load.spritesheet('player', 'assets/sprites/player.png',32 ,48);

    game.load.image('ufo', 'assets/game/ufo.png');
    game.load.image('bullet', 'assets/sprites/purple_ball.png');

    game.load.image('menu', 'assets/game/menu.png');

    //load.audio() is used to load audio assets
    game.load.audio('jump' ,      'assets/audio/jump.mp3' );
    game.load.audio('game_over' , 'assets/audio/game_over.wav' );
}
Sprite sheet
Sprite sheet

Part 2:

// Game object declarations
var player;
var bg;

var bullet;
var bullet_fired=false;
var ufo;

var jumpButton;

var menu;

var bullet_speed;
var bullet_displacement;
var stay_on_air;
var stay_on_floor;

var auto_mode = false;

// Sound
var soundGameOver;
var soundJump;

PART 3:

function create() {

    // Setting game object's property
    game.physics.startSystem(Phaser.Physics.ARCADE);  // This is the reason why objects fall to ground, rather than floating
    game.physics.arcade.gravity.y = 800; // alter this value to get gravity effects of moon and earth 😛
    game.time.desiredFps = 30; // Setting game fps

    // Adding game objects
    bg = game.add.tileSprite(0, 0, w, h, 'background'); // tiled background ( top-left cord, bottom-right cord,  game object name )
    ufo    = game.add.sprite(w-100, h-70, 'ufo'); // param1 = x-cord, param2 = y-cord , param3 = game object name given in the preload()
    bullet = game.add.sprite(w-100, h, 'bullet');
    player = game.add.sprite(50, h, 'player');


    // Setting player object's property
    game.physics.enable(player);
    player.body.collideWorldBounds = true; // Reason why player doesn't fall off the screen.
    var run = player.animations.add('run'); // Adds player running animation, looping the sprite
    player.animations.play('run', 10, true); // 10 is the fps

    // Setting bullet object's property
    game.physics.enable(bullet); // Adding physics object property, like gravity etc to bullet
    bullet.body.collideWorldBounds = true;

    // Pause Text Label
    // Note: we are positioning everything with respect to w,h
    pause_label = game.add.text(w - 100, 20, 'Pause', { font: '20px Arial', fill: '#fff' });
    pause_label.inputEnabled = true; // reason why it is clickable
    pause_label.events.onInputUp.add(pause, self); // adding onClick function ie pause()
    game.input.onDown.add(un_pause, self); //handles menu button click based on pointer click ( when paused )

    jumpButton = game.input.keyboard.addKey(Phaser.Keyboard.SPACEBAR); // Adding spacebar to key events
 
    //Sound ( initializing audio from game assets )
    soundJump    = game.add.audio('jump');
    soundGameOver=game.add.audio('game_over');

}

PART 4:

function update() {

    bg.tilePosition.x -= 1; //moving background

    // collisionHandler function is called when bullet and player collides
    game.physics.arcade.collide(bullet, player, collisionHandler, null, this);


    // Finding the distance between player and bullet
    bullet_displacement = Math.floor( player.position.x - bullet.position.x );

    // Manual Jump
    if( jumpButton.isDown         &&
        player.body.onFloor()     ){
        jump();
    }


    // Fires again automaitcally
    if( bullet_fired==false ){
        fire();
    }

    //Reload bullet
    if( bullet.position.x <= 0  ){
        reset_state_variables();
    }

}

PART 5:

function getRandomSpeed(min, max) {
    // Returns a random value between min and max
    return Math.floor(Math.random() * (max - min + 1)) + min;
}

function fire(){
    bullet_speed =  -1 * getRandomSpeed(300,800); //-1 because, object should move in the -x direction
    bullet.body.velocity.y = 0 ; // Bullet is not having vertical motion
    bullet.body.velocity.x = bullet_speed ;
    bullet_fired=true;
}

function collisionHandler(){
    soundGameOver.play();
    pause();
}


function pause(){
    game.paused = true; // This pauses the game 
    game.sound.mute = false; // This is used to play the background music even when the game is paused
    menu = game.add.sprite(w/2,h/2, 'menu'); // Here we create a menu as a image in photoshop(shown below)
    menu.anchor.setTo(0.5, 0.5); // set the position of the menu image relative to the x/y coordinates. 
	
    // BTW: menu is of dimensions : 270x180 
}

function un_pause(event){
    if(game.paused){ // checks if game is paused or not
	
        // Calculate the corners of the menu
        var menu_x1 = w/2 - 270/2, menu_x2 = w/2 + 270/2,
            menu_y1 = h/2 - 180/2, menu_y2 = h/2 + 180/2;

        var mouse_x = event.x  ,
            mouse_y = event.y  ;

        //if mouse is clicked within the menu
        if(mouse_x > menu_x1 && mouse_x < menu_x2 && mouse_y > menu_y1 && mouse_y < menu_y2 ){

			
            if(mouse_x >=menu_x1 && mouse_x <=menu_x2 && mouse_y >=menu_y1 && mouse_y <=menu_y1+90){
                // if mouse is clicked on first option
                auto_mode = false;
            }else if (mouse_x >=menu_x1 && mouse_x <=menu_x2 && mouse_y >=menu_y1+90 && mouse_y <=menu_y2) {
                // if mouse is clicked on second option
                auto_mode = true;
            }

            menu.destroy();
            reset_state_variables();
            game.paused = false;

        }
    }
}


function reset_state_variables(){
    //Reset player
    player.body.velocity.x=0;
    player.body.velocity.y=0;
    player.position.x=50;
	
    //Reset bullet
    bullet.body.velocity.x = 0;
    bullet.position.x = w-100;
	
    bullet_fired=false;

}

function jump(){
    soundJump.play();
    player.body.velocity.y = -270; // we give -velocity to y direction for jumping. Consider that this velocity(Force) is against the gravity
}
menu
menu

That is pretty much it. I guess, this covered all the functions related to the game. Now in the next section, I will brief you about integrating AI into this game.

Also, make sure to read the getting started & start your first game section from phaser. (It is not that boring :P)

So inorder to run this game, you need to host it in a web server.  I personally use JetBrains WebStorm IDE which handles this. Also, make sure to run this game on chrome.

Happy coding!

GAME DEMO:

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s