HTML5 prototype of a circular endless runner featuring double jump built with Phaser – how to create endless obstacles?
Talking about Circular endless runner game, Game development, HTML5, Javascript and Phaser.
Learn cross platform HTML5 game development
Check my Gumroad page for commented source code, games and books.
approaching
is set to false
.
Once the angle between the player and the spike is less than a given value, it means the player is approaching the spike, so approaching
property is set to true
.
As the player keeps running, the angle between the player and the spike will get smaller and smaller, then it will start getting bigger once the player jumped over the spike.
At this time, the spike can be removed and placed elsewhere. I just wait for the player to be at a certain distance before removing the spike, so I will be waiting for the angle between the spike and the player to be greater than a given value if approaching
is true.
At this time the spike is removed and placed elsewhere.
Look at the prototype:
Click or tap to jump and double jump – won’t check for collisions at the moment, just look how spikes are removed and placed elsewhere as the player keeps running.
And this is the source code, still uncommented but easy to understand:
var game;
var gameOptions = {
bigCircleRadius: 250,
playerRadius: 25,
playerSpeed: 1,
worldGravity: 0.8,
jumpForce: [12, 8],
spikeSize: [25, 50],
closeToSpike: 10,
farFromSpike: 25
}
window.onload = function() {
var gameConfig = {
thpe: Phaser.CANVAS,
width: 800,
height: 800,
scene: [playGame]
}
game = new Phaser.Game(gameConfig);
window.focus()
resize();
window.addEventListener("resize", resize, false);
}
class playGame extends Phaser.Scene{
constructor(){
super("PlayGame");
}
preload(){
this.load.image("bigcircle", "bigcircle.png");
this.load.image("player", "player.png");
this.load.image("spike", "spike.png");
}
create(){
this.bigCircle = this.add.sprite(game.config.width / 2, game.config.height / 2, "bigcircle");
this.bigCircle.displayWidth = gameOptions.bigCircleRadius * 2;
this.bigCircle.displayHeight = gameOptions.bigCircleRadius * 2;
this.player = this.add.sprite(game.config.width / 2, game.config.height / 2 - gameOptions.bigCircleRadius - gameOptions.playerRadius, "player");
this.player.displayWidth = gameOptions.playerRadius * 2;
this.player.displayHeight = gameOptions.playerRadius * 2;
this.player.currentAngle = -90;
this.player.jumpOffset = 0;
this.player.jumps = 0;
this.player.jumpForce = 0;
this.spikeGroup = this.add.group();
this.input.on("pointerdown", function(e){
if(this.player.jumps < 2){
this.player.jumps ++;
this.player.jumpForce = gameOptions.jumpForce[this.player.jumps - 1];
}
}, this);
for(var i = 0; i < 6; i ++){
var spike = this.add.sprite(0, 0, "spike");
spike.setOrigin(0, 0.5);
this.spikeGroup.add(spike);
this.placeSpike(spike, Math.floor(i / 2));
}
}
placeSpike(spike, quadrant){
var randomAngle = Phaser.Math.Between(quadrant * 90, (quadrant + 1) * 90);
randomAngle = Phaser.Math.Angle.WrapDegrees(randomAngle);
var randomAngleRadians = Phaser.Math.DegToRad(randomAngle);
var spikeX = this.bigCircle.x + (gameOptions.bigCircleRadius - 4) * Math.cos(randomAngleRadians);
var spikeY = this.bigCircle.y + (gameOptions.bigCircleRadius - 4) * Math.sin(randomAngleRadians);
spike.x = spikeX;
spike.y = spikeY;
spike.quadrant = quadrant;
spike.angle = randomAngle;
spike.approaching = false;
}
update(){
if(this.player.jumps > 0){
this.player.jumpOffset += this.player.jumpForce;
this.player.jumpForce -= gameOptions.worldGravity;
if(this.player.jumpOffset < 0){
this.player.jumpOffset = 0;
this.player.jumps = 0;
this.player.jumpForce = 0;
}
}
this.player.currentAngle = Phaser.Math.Angle.WrapDegrees(this.player.currentAngle + gameOptions.playerSpeed);
var radians = Phaser.Math.DegToRad(this.player.currentAngle);
var distanceFromCenter = (gameOptions.bigCircleRadius * 2 + gameOptions.playerRadius * 2) / 2 + this.player.jumpOffset;
this.player.x = this.bigCircle.x + distanceFromCenter * Math.cos(radians);
this.player.y = this.bigCircle.y + distanceFromCenter * Math.sin(radians);
var revolutions = (gameOptions.bigCircleRadius * 2) / (gameOptions.playerRadius * 2) + 1;
this.player.angle = this.player.currentAngle * revolutions;
this.spikeGroup.children.iterate(function(spike){
var angleDiff = this.getAngleDifference(spike.angle, this.player.currentAngle);
if(!spike.approaching && angleDiff < gameOptions.closeToSpike){
spike.approaching = true;
}
if(spike.approaching && angleDiff > gameOptions.farFromSpike){
this.placeSpike(spike, (spike.quadrant + 3) % 4);
}
}, this)
}
getAngleDifference(a1, a2){
var angleDifference = a1 - a2
angleDifference += (angleDifference > 180) ? -360 : (angleDifference < -180) ? 360 : 0
return Math.abs(angleDifference);
}
}
// pure javascript to scale the game
function resize() {
var canvas = document.querySelector("canvas");
var windowWidth = window.innerWidth;
var windowHeight = window.innerHeight;
var windowRatio = windowWidth / windowHeight;
var gameRatio = game.config.width / game.config.height;
if(windowRatio < gameRatio){
canvas.style.width = windowWidth + "px";
canvas.style.height = (windowWidth / gameRatio) + "px";
}
else{
canvas.style.width = (windowHeight * gameRatio) + "px";
canvas.style.height = windowHeight + "px";
}
}
Never miss an update! Subscribe, and I will bother you by email only when a new game or full source code comes out.