Deprecated: Automatic conversion of false to array is deprecated in /home/wcc1969/public_html/phasergames.com/wp-content/plugins/publitio-offloading/includes/class-publitio-offloading.php on line 577
Deprecated: Automatic conversion of false to array is deprecated in /home/wcc1969/public_html/phasergames.com/wp-content/plugins/publitio-offloading/includes/class-publitio-offloading.php on line 577
Now that we have the real runner graphics in place, it is time to add some scrolling to the game to really make it look like our guy is really running.
First though, let’s clean up some of the graphics.
The Bird
The first thing is to is to replace the bird block with an animation. We will do this in the same way that we did for the runner, by using a sprite sheet with a .json file
Bird Sprite Sheet
Replace the line
game.load.image("bird", "images/bird.png");
With
game.load.atlasJSONHash('bird','images/bird.png','images/bird.json');
Then we just need to add the animations to the bird. lines 3 and 4 below.
//add the bird sprite to the game this.bird = game.add.sprite(game.width + 100, birdY, "bird"); this.bird.animations.add("fly",this.makeArray(0,8),12,true); this.bird.animations.play("fly");
If we leave the bird graphics as they are, it will be too big for the screen, so we can set the bird’s width to 10 percent of the game’s width and then scale the bird’s height proportionately.
this.bird.width=game.width*.1; this.bird.scale.y=this.bird.scale.x;
If you run the code now you’ll see the bird is the right size, but facing the wrong direction. We can reverse it by flipping the scale.x property
this.bird.scale.x=-this.bird.scale.x;
I also replaced some of the temporary graphics with real ones and added a background and simply stretched it to fit the game’s width and height.
//in preload game.load.image("background","images/background.png");
//in the create function //background this.background=game.add.sprite(0,0,"background"); this.background.width=game.width; this.background.height=game.height;
Scroll The Ground
Currently, we are using the graphic below and stretching it to fit the width.
ground.png
Let’s replace it with something more suitable for our game.
grass.png
Replace the line
game.load.image("ground", "images/ground.png");
with
game.load.image("grass", "images/grass.png");
Now, of course, if we are to take that block and stretch it, the ground would look distorted. By one of the very nice features of Phaser is the tileSprite.
It is similar in nature to a normal sprite, but as the name implies, it tiles, or repeat the image.
A tilesprite is added to the game by using the following code
game.add.tileSprite(x,y,width,height,imageKey);
The tile sprite will fill in the space provided by width and height settings with the image. In other words tile the space as if it were a floor.
If we were to give the width and height as 250 x 250 Phaser would fill in our sprite like this
game.add.tileSprite(0,0,250,250,"grass");
We would get this result.
To get a horizontal line, we need only restrict the height in the tileSprite to equal that of the image, which in this case is 50 px.
game.add.tileSprite(0,0,250,50,"grass");
So to get a line of grass blocks to stretch across the bottom we just need to set the width to equal the game width and adjust the y position.
We will replace the original ground sprite code with
// this.ground = game.add.sprite(0, game.height * .9, "ground"); this.ground=game.add.tileSprite(0,game.height*.9,game.width,50,"grass");
Now here is were the magic come in. A tileSprite has a function called autoScroll. We can set that to scroll by an x and y value and just leave Phaser to do its work. (I won’t take the time to explain all the hours I wasted getting this to work in Flash)
this.ground.autoScroll(xScroll,yScroll);
//we only want to scroll by x, so leave y at 0 this.ground.autoScroll(-150,0);
Now our ground moves along with our runner! I had to try several different values to get the running and the scrolling just right.
I also used the same technique to add some mountains and replaced the clouds, and put autoScroll on all of them.
Here is what my StateMain.js looks like now:
var StateMain = { preload: function() { //game.load.image("ground", "images/ground.png"); // game.load.image("hero", "images/hero.png"); game.load.image("bar", "images/powerbar.png"); game.load.image("block", "images/block.png"); game.load.image("grass", "images/grass.png"); game.load.atlasJSONHash('bird','images/bird.png','images/bird.json'); game.load.image("playAgain", "images/playAgain.png"); game.load.image("clouds", "images/clouds.png"); game.load.atlasJSONHash('hero', 'images/explorer.png', 'images/explorer.json'); // // // game.load.image("background","images/background.png"); game.load.image("mountains1","images/mountains1.png"); game.load.image("mountains2","images/mountains2.png"); }, create: function() { this.clickLock = false; this.power = 0; //turn the background sky blue game.stage.backgroundColor = "#00ffff"; //background // this.background=game.add.sprite(0,0,"background"); this.background.width=game.width; this.background.height=game.height; //mountains // this.mountain1=game.add.tileSprite(0,0,game.width,game.height/2,"mountains1"); this.mountain1.y=game.height-this.mountain1.height; this.mountain2=game.add.tileSprite(0,0,game.width,game.height/3,"mountains2"); this.mountain2.y=game.height-this.mountain2.height; this.mountain1.autoScroll(-50,0); this.mountain2.autoScroll(-150,0); //add the ground // this.ground = game.add.sprite(0, game.height * .9, "ground"); this.ground=game.add.tileSprite(0,game.height*.9,game.width,50,"grass"); this.ground.autoScroll(-150,0); // // //add the hero in this.hero = game.add.sprite(game.width * .2, this.ground.y, "hero"); //make animations this.hero.animations.add("die", this.makeArray(0, 10), 12, false); this.hero.animations.add("jump", this.makeArray(20, 30), 12, false); this.hero.animations.add("run", this.makeArray(30, 40), 12, true); this.hero.animations.play("run"); this.hero.width = game.width / 12; this.hero.scale.y = this.hero.scale.x; this.hero.anchor.set(0.5, 1); //add the power bar just above the head of the hero this.powerBar = game.add.sprite(this.hero.x + this.hero.width / 2, this.hero.y - this.hero.height / 2, "bar"); this.powerBar.width = 0; //add the clouds this.clouds=game.add.tileSprite(0,0,game.width*1.1,100,"clouds"); this.clouds.autoScroll(-50,0); //start the physics engine // // game.physics.startSystem(Phaser.Physics.ARCADE); //enable the hero for physics // // game.physics.enable(this.hero, Phaser.Physics.ARCADE); game.physics.enable(this.ground, Phaser.Physics.ARCADE); //game.physics.arcade.gravity.y = 100; // // this.hero.body.gravity.y = 200; this.hero.body.collideWorldBounds = true; //this.hero.body.bounce.set(0, .2); this.ground.body.immovable = true; //record the initial position this.startY = this.hero.y; //set listeners game.input.onDown.add(this.mouseDown, this); this.blocks = game.add.group(); this.makeBlocks(); this.makeBird(); }, makeArray: function(start, end) { var myArray = []; for (var i = start; i < end; i++) { myArray.push(i); } return myArray; }, mouseDown: function() { if (this.clickLock == true) { return; } if (this.hero.y != this.startY) { return; } game.input.onDown.remove(this.mouseDown, this); this.timer = game.time.events.loop(Phaser.Timer.SECOND / 1000, this.increasePower, this); game.input.onUp.add(this.mouseUp, this); }, mouseUp: function() { game.input.onUp.remove(this.mouseUp, this); this.doJump(); game.time.events.remove(this.timer); this.power = 0; this.powerBar.width = 0; game.input.onDown.add(this.mouseDown, this); this.hero.animations.play("jump"); }, increasePower: function() { this.power++; this.powerBar.width = this.power; if (this.power > 50) { this.power = 50; } }, doJump: function() { this.hero.body.velocity.y = -this.power * 12; }, makeBlocks: function() { this.blocks.removeAll(); var wallHeight = game.rnd.integerInRange(1, 4); for (var i = 0; i < wallHeight; i++) { var block = game.add.sprite(0, -i * 50, "block"); this.blocks.add(block); } this.blocks.x = game.width - this.blocks.width this.blocks.y = this.ground.y - 50; // //Loop through each block //and apply physics this.blocks.forEach(function(block) { //enable physics game.physics.enable(block, Phaser.Physics.ARCADE); //set the x velocity to -160 block.body.velocity.x = -150; //apply some gravity to the block //not too much or the blocks will bounce //against each other block.body.gravity.y = 4; //set the bounce so the blocks //will react to the runner block.body.bounce.set(1, 1); }); }, makeBird: function() { //if the bird already exists //destory it if (this.bird) { this.bird.destroy(); } //pick a number at the top of the screen //between 10 percent and 40 percent of the height of the screen var birdY = game.rnd.integerInRange(game.height * .1, game.height * .4); //add the bird sprite to the game this.bird = game.add.sprite(game.width + 100, birdY, "bird"); this.bird.animations.add("fly",this.makeArray(0,8),12,true); this.bird.animations.play("fly"); // // //enable the sprite for physics game.physics.enable(this.bird, Phaser.Physics.ARCADE); //set the x velocity at -200 which is a little faster than the blocks this.bird.body.velocity.x = -200; //set the bounce for the bird this.bird.body.bounce.set(2, 2); this.bird.width=game.width*.1; this.bird.scale.y=this.bird.scale.x; this.bird.scale.x=-this.bird.scale.x; }, onGround() { if (this.hero) { this.hero.animations.play("run"); } }, update: function() { game.physics.arcade.collide(this.hero, this.ground, this.onGround, null, this); // //collide the hero with the blocks // game.physics.arcade.collide(this.hero, this.blocks, this.delayOver, null, this); // //collide the blocks with the ground // game.physics.arcade.collide(this.ground, this.blocks); // //when only specifying one group, all children in that //group will collide with each other // game.physics.arcade.collide(this.blocks); //colide the hero with the bird // game.physics.arcade.collide(this.hero, this.bird, this.delayOver, null, this); // //get the first child var fchild = this.blocks.getChildAt(0); //if off the screen reset the blocks if (fchild.x < -game.width) { this.makeBlocks(); } //if the bird has flown off screen //reset it if (this.bird.x < 0) { this.makeBird(); } if (this.hero.y < this.hero.height) { this.hero.body.velocity.y = 200; this.delayOver(); } }, delayOver: function() { this.clickLock = true; if (this.hero) { this.hero.animations.play("die"); this.hero.body.velocity.y = 100; } game.time.events.add(Phaser.Timer.SECOND, this.gameOver, this); }, gameOver: function() { game.state.start("StateOver"); } }
You can see the result here
Hello! I have a question. I’m trying to run this in Phaser 3. atlasJSONHash is not a function is the error I am getting. Is there a different want to do the bird and explorer?
There are ways to do this. You could just space out the images and load it a spritesheet with frameHeight and frameWidth set.
This tutorial is for Phaser 2. If you want to use Phaser 3 with JSON data and sprites, it needs a different format. I use a program called texture packer. It has settings for Phaser 2 and 3.