HTML5 prototype of a circular endless runner featuring double jump built with Phaser – handling collisions without physics
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.
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.graphics = this.add.graphics();
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.top = new Phaser.Math.Vector2(spikeX + gameOptions.spikeSize[1] * Math.cos(randomAngleRadians), spikeY + gameOptions.spikeSize[1] * Math.sin(randomAngleRadians));
spike.base1 = new Phaser.Math.Vector2(spikeX + gameOptions.spikeSize[0] / 2 * Math.cos(randomAngleRadians + Math.PI / 2), spikeY + gameOptions.spikeSize[0] / 2 * Math.sin(randomAngleRadians + Math.PI / 2));
spike.base2 = new Phaser.Math.Vector2(spikeX + gameOptions.spikeSize[0] / 2 * Math.cos(randomAngleRadians - Math.PI / 2), spikeY + gameOptions.spikeSize[0] / 2 * Math.sin(randomAngleRadians - Math.PI / 2));
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.graphics.clear();
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){
this.graphics.lineStyle(4, 0xff0000);
this.graphics.beginPath();
this.graphics.moveTo(spike.top.x, spike.top.y);
this.graphics.lineTo(spike.base1.x, spike.base1.y);
this.graphics.closePath();
this.graphics.strokePath();
this.graphics.beginPath();
this.graphics.moveTo(spike.top.x, spike.top.y);
this.graphics.lineTo(spike.base2.x, spike.base2.y);
this.graphics.closePath();
this.graphics.strokePath();
if(this.distToSegmentSquared(new Phaser.Math.Vector2(this.player.x, this.player.y), gameOptions.playerRadius, spike.top, spike.base1) || this.distToSegmentSquared(new Phaser.Math.Vector2(this.player.x, this.player.y), gameOptions.playerRadius, spike.top, spike.base2)){
this.scene.start("PlayGame");
}
if(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);
}
getDistance(p1, p2){
return (p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y);
}
distToSegmentSquared(circleCenter, circleRadius, segmentStart, segmentEnd){
var l2 = this.getDistance(segmentStart, segmentEnd);
var t = ((circleCenter.x - segmentStart.x) * (segmentEnd.x - segmentStart.x) + (circleCenter.y - segmentStart.y) * (segmentEnd.y - segmentStart.y)) / l2;
t = Math.max(0, Math.min(1, t));
var tX = segmentStart.x + t * (segmentEnd.x - segmentStart.x);
var tY = segmentStart.y + t * (segmentEnd.y - segmentStart.y);
var tPoint = {
x: tX,
y: tY
}
return this.getDistance(circleCenter, tPoint) < circleRadius * circleRadius;
}
}
// 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.