/****
* Classes
****/
var DashEffect = Container.expand(function () {
var self = Container.call(this);
var effectGraphics = self.attachAsset('dashEffect', {
anchorX: 0.5,
anchorY: 0.5
});
self.lifetime = 10;
self.alpha = 0.8;
self.update = function () {
self.lifetime--;
self.alpha = self.lifetime / 10;
self.x -= 15 * 0.7;
if (self.lifetime <= 0) {
self.destroy();
return true;
}
return false;
};
});
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemyShape', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 10;
self.verticalSpeed = Math.random() * 4 - 2;
self.verticalDirection = 1;
self.verticalDistance = 0;
self.maxVerticalDistance = 100 + Math.random() * 200;
self.update = function (gameSpeed) {
self.x -= self.speed * gameSpeed * 0.7;
// Vertical movement
self.verticalDistance += Math.abs(self.verticalSpeed);
if (self.verticalDistance > self.maxVerticalDistance) {
self.verticalDirection *= -1;
self.verticalDistance = 0;
}
self.y += self.verticalSpeed * self.verticalDirection;
// Keep within bounds
if (self.y < self.height / 2) {
self.y = self.height / 2;
self.verticalDirection *= -1;
} else if (self.y > 2732 - 400) {
self.y = 2732 - 400;
self.verticalDirection *= -1;
}
return self.x < -100;
};
});
var Obstacle = Container.expand(function () {
var self = Container.call(this);
var obstacleGraphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 15;
self.update = function (gameSpeed) {
self.x -= self.speed * gameSpeed * 0.7;
return self.x < -100;
};
});
var Particle = Container.expand(function () {
var self = Container.call(this);
var particleGraphics = self.attachAsset('particle', {
anchorX: 0.5,
anchorY: 0.5
});
self.lifetime = 30;
self.alpha = 1;
self.scale.set(1);
self.update = function () {
self.lifetime--;
self.alpha = self.lifetime / 30;
self.scale.set(1 - self.lifetime / 30 * 0.5);
if (self.lifetime <= 0) {
self.destroy();
return true;
}
return false;
};
});
var Platform = Container.expand(function (width, layer) {
var self = Container.call(this);
var platformWidth = width || 200;
var platformGraphics = self.attachAsset('platform', {
anchorX: 0.5,
anchorY: 0.5,
width: platformWidth
});
// Color platforms based on layer
var layerColors = [0x00ffff, 0x00ccff, 0x0099ff, 0x0066ff, 0x0033ff];
if (layer !== undefined && layer < layerColors.length) {
platformGraphics.tint = layerColors[layer];
}
self.speed = 12;
self.layer = layer || 0;
self.update = function (gameSpeed) {
self.x -= self.speed * gameSpeed * 0.7;
return self.x < -platformWidth / 2;
};
self.getWidth = function () {
return platformWidth;
};
self.getHeight = function () {
return platformGraphics.height;
};
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('platform', {
anchorX: 0.5,
anchorY: 0.5,
width: 60,
height: 60
});
playerGraphics.tint = 0x00ffaa;
self.velocity = {
x: 0,
y: 0
};
self.baseX = 300;
self.speed = 20;
self.jumpForce = -25;
self.gravity = 1;
self.isJumping = false;
self.isDashing = false;
self.dashCooldown = 0;
self.dashDuration = 0;
self.dashDistance = 0;
self.dashMaxDistance = 200;
self.hasShield = false;
self.shieldObj = null;
self.particles = [];
self.onPlatform = false;
self.currentPlatform = null;
self.jump = function () {
if (!self.isJumping || self.onPlatform) {
self.velocity.y = self.jumpForce;
self.isJumping = true;
self.onPlatform = false;
self.currentPlatform = null;
LK.getSound('jump').play(); // Play jump sound
}
};
self.dash = function () {
if (self.dashCooldown <= 0) {
LK.getSound('dash-fast').play();
self.isDashing = true;
self.dashDuration = 15;
self.dashCooldown = 60;
self.dashDistance = 0;
// Create dash effect
var effect = new DashEffect();
effect.x = self.x - 50;
effect.y = self.y;
self.parent.addChild(effect);
}
};
self.activateShield = function () {
self.hasShield = true;
if (!self.shieldObj) {
self.shieldObj = self.addChild(new Shield());
}
};
self.deactivateShield = function () {
self.hasShield = false;
if (self.shieldObj) {
self.shieldObj.destroy();
self.shieldObj = null;
}
};
self.update = function () {
// Apply gravity if jumping
if (self.isJumping && !self.onPlatform) {
self.velocity.y += self.gravity;
}
// Update position
self.y += self.velocity.y;
// Handle dash
if (self.isDashing) {
if (self.dashDistance < self.dashMaxDistance) {
self.x += 15 * 0.7;
self.dashDistance += 15 * 0.7;
} else {
self.x = Math.max(self.x - 10, self.baseX);
if (self.x <= self.baseX) {
self.isDashing = false;
}
}
self.dashDuration--;
if (self.dashDuration <= 0) {
self.isDashing = false;
}
} else {
// Return to base position if not dashing
if (self.x > self.baseX) {
self.x = Math.max(self.x - 5, self.baseX);
}
}
// Update dash cooldown
if (self.dashCooldown > 0) {
self.dashCooldown--;
}
// Ceiling collision
if (self.y < 60) {
self.y = 60;
self.velocity.y = 0;
}
// Platform collision
self.onPlatform = false;
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
// Check if player is above platform and falling
if (self.velocity.y >= 0 && self.y + 30 >= platform.y - platform.getHeight() / 2 && self.y - 30 <= platform.y - platform.getHeight() / 2 && self.x + 30 >= platform.x - platform.getWidth() / 2 && self.x - 30 <= platform.x + platform.getWidth() / 2) {
self.y = platform.y - platform.getHeight() / 2 - 30;
self.velocity.y = 0;
self.isJumping = false;
self.onPlatform = true;
self.currentPlatform = platform;
break;
}
}
// If was on platform but platform moved away
if (self.currentPlatform && !self.onPlatform) {
self.isJumping = true;
self.currentPlatform = null;
}
// Create trail particles
if (LK.ticks % 3 === 0) {
var particle = new Particle();
particle.x = self.x - 30;
particle.y = self.y;
particle.tint = self.isDashing ? 0xffffff : 0x00ffaa;
self.parent.addChild(particle);
self.particles.push(particle);
}
// Update particles
for (var j = self.particles.length - 1; j >= 0; j--) {
if (self.particles[j].update()) {
self.particles.splice(j, 1);
}
}
};
});
var PowerUp = Container.expand(function () {
var self = Container.call(this);
var powerupGraphics = self.attachAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5
});
self.type = Math.random() < 0.5 ? 'shield' : 'score';
powerupGraphics.tint = self.type === 'shield' ? 0x3399ff : 0xffff00;
self.speed = 8;
self.rotation = 0;
self.update = function (gameSpeed) {
self.x -= self.speed * gameSpeed * 0.7;
self.rotation += 0.05;
return self.x < -100;
};
});
var ScorePopup = Container.expand(function (value, color) {
var self = Container.call(this);
var scoreTxt = new Text2("+" + value, {
size: 40,
fill: color || 0xffff00
});
scoreTxt.anchor.set(0.5);
self.addChild(scoreTxt);
self.lifetime = 30;
self.update = function () {
self.lifetime--;
self.y -= 2;
self.alpha = self.lifetime / 30;
if (self.lifetime <= 0) {
self.destroy();
return true;
}
return false;
};
});
var Shield = Container.expand(function () {
var self = Container.call(this);
var shieldGraphics = self.attachAsset('shield', {
anchorX: 0.5,
anchorY: 0.5
});
shieldGraphics.alpha = 0.5;
self.update = function () {
self.rotation += 0.02;
};
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000033
});
/****
* Game Code
****/
// Play background music in a loop
LK.playMusic('background', {
loop: true
});
// Update player
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2732;
var PLATFORM_SPEED = 8;
var PLAYER_WIDTH = 60;
var MIN_GAP = PLAYER_WIDTH * 2;
var LAYERS = 3;
var LAYER_HEIGHT = 250;
var FLOOR_HEIGHT = GAME_HEIGHT - 350;
// Background
var background = game.attachAsset('background', {});
game.addChildAt(background, 0);
// Death zone
var deathZone = game.attachAsset('deathZone', {
anchorX: 0.5,
anchorY: 0
});
deathZone.x = GAME_WIDTH / 2;
deathZone.y = GAME_HEIGHT - 100;
deathZone.alpha = 0.5;
game.addChildAt(deathZone, 1);
// Game variables
var player = game.addChild(new Player());
player.x = 300;
player.y = FLOOR_HEIGHT - 400;
var obstacles = [];
var powerups = [];
var enemies = [];
var platforms = [];
var rightmostPlatforms = []; // Tracks the rightmost platform in each layer
var effects = [];
var scorePopups = [];
var score = 0;
var distance = 0;
var gameSpeed = 1;
var isGameOver = false;
// Initialize rightmostPlatforms array
for (var i = 0; i < LAYERS; i++) {
rightmostPlatforms[i] = null;
}
// Create initial platforms
for (var layer = 0; layer < LAYERS; layer++) {
var layerY = FLOOR_HEIGHT - layer * LAYER_HEIGHT;
// Create wider starting platforms for each layer
var initialWidth = layer === 0 ? 800 : 600 - layer * 50;
var startingPlatform = new Platform(initialWidth, layer);
startingPlatform.x = initialWidth / 2 + 100;
startingPlatform.y = layerY;
platforms.push(startingPlatform);
game.addChild(startingPlatform);
rightmostPlatforms[layer] = startingPlatform;
// Add a series of additional starting platforms for each layer
for (var p = 0; p < 3; p++) {
var additionalWidth = initialWidth * 0.7;
var additionalPlatform = new Platform(additionalWidth, layer);
var gap = layer === 0 ? MIN_GAP + 20 : MIN_GAP + layer * 40;
additionalPlatform.x = rightmostPlatforms[layer].x + rightmostPlatforms[layer].getWidth() / 2 + gap + additionalWidth / 2;
additionalPlatform.y = layerY;
platforms.push(additionalPlatform);
game.addChild(additionalPlatform);
rightmostPlatforms[layer] = additionalPlatform;
}
}
// Place player on the first platform
player.y = rightmostPlatforms[0].y - rightmostPlatforms[0].getHeight() / 2 - player.height / 2;
// UI elements
var scoreTxt = new Text2('SCORE: 0', {
size: 50,
fill: 0xffffff
});
scoreTxt.anchor.set(0, 0);
scoreTxt.x = 20;
scoreTxt.y = 20;
LK.gui.top.addChild(scoreTxt);
var distanceTxt = new Text2('DISTANCE: 0m', {
size: 50,
fill: 0xffffff
});
distanceTxt.anchor.set(0, 0);
distanceTxt.x = 20;
distanceTxt.y = 80;
LK.gui.top.addChild(distanceTxt);
var dashMeter = new Container();
dashMeter.x = 20;
dashMeter.y = 140;
LK.gui.top.addChild(dashMeter);
var dashBg = new Container();
var dashBgGraphics = dashBg.attachAsset('dashEffect', {
anchorX: 0,
anchorY: 0
});
dashBgGraphics.width = 200;
dashBgGraphics.height = 20;
dashBgGraphics.tint = 0x333333;
dashMeter.addChild(dashBg);
var dashFill = new Container();
var dashFillGraphics = dashFill.attachAsset('dashEffect', {
anchorX: 0,
anchorY: 0
});
dashFillGraphics.width = 200;
dashFillGraphics.height = 20;
dashFillGraphics.tint = 0x00ffaa;
dashMeter.addChild(dashFill);
var dashTxt = new Text2('DASH', {
size: 30,
fill: 0xffffff
});
dashTxt.anchor.set(0, 0.5);
dashTxt.x = 210;
dashTxt.y = 10;
dashMeter.addChild(dashTxt);
// Control hints
var controlsContainer = new Container();
controlsContainer.y = GAME_HEIGHT - 150;
game.addChild(controlsContainer);
var leftControlBg = new Container();
var leftControlGraphics = leftControlBg.attachAsset('platform', {
anchorX: 0,
anchorY: 0,
width: GAME_WIDTH / 2,
height: 100
});
leftControlGraphics.alpha = 0.2;
controlsContainer.addChild(leftControlBg);
var rightControlBg = new Container();
var rightControlGraphics = rightControlBg.attachAsset('platform', {
anchorX: 0,
anchorY: 0,
width: GAME_WIDTH / 2,
height: 100
});
rightControlGraphics.alpha = 0.2;
rightControlBg.x = GAME_WIDTH / 2;
controlsContainer.addChild(rightControlBg);
var jumpTxt = new Text2('JUMP', {
size: 40,
fill: 0xffffff
});
jumpTxt.anchor.set(0.5);
jumpTxt.x = GAME_WIDTH / 4;
jumpTxt.y = 50;
controlsContainer.addChild(jumpTxt);
var dashControlTxt = new Text2('DASH', {
size: 40,
fill: 0xffffff
});
dashControlTxt.anchor.set(0.5);
dashControlTxt.x = GAME_WIDTH / 4 * 3;
dashControlTxt.y = 50;
controlsContainer.addChild(dashControlTxt);
// Input handling
game.on('down', function (x, y, obj) {
if (isGameOver) {
return;
}
var event = obj;
var pos = game.toLocal(event.global);
if (pos.x < GAME_WIDTH / 2) {
player.jump();
} else {
player.dash();
}
});
// Game loop
LK.on('tick', function () {
if (isGameOver) {
return;
}
// Update player
player.update();
// Update dash meter
dashFill.scale.x = (60 - player.dashCooldown) / 60;
// Update game speed
gameSpeed = (1.5 + distance / 5000) * 0.7;
// Update distance
distance += gameSpeed;
distanceTxt.setText('DISTANCE: ' + Math.floor(distance) + 'm');
// Check if player fell to death zone
if (player.y > GAME_HEIGHT - 160) {
gameOver();
return;
}
// Platform generation logic
for (var layer = 0; layer < LAYERS; layer++) {
// Calculate layer-specific values
var layerY = FLOOR_HEIGHT - layer * LAYER_HEIGHT;
var platformWidth = 400 - layer * 70 + Math.random() * 100; // Wider platforms at bottom
var gapMultiplier = 1 + layer * 0.4; // Larger gaps at higher layers
var minGap = MIN_GAP * gapMultiplier;
var maxGap = minGap * 1.5;
var actualGap = minGap + Math.random() * (maxGap - minGap);
// Check if we need to generate a new platform
if (!rightmostPlatforms[layer] || rightmostPlatforms[layer].x < GAME_WIDTH + 200) {
// Determine new platform position
var newX;
if (rightmostPlatforms[layer]) {
newX = rightmostPlatforms[layer].x + rightmostPlatforms[layer].getWidth() / 2 + actualGap + platformWidth / 2;
} else {
newX = GAME_WIDTH + platformWidth / 2;
}
// Create new platform
var newPlatform = new Platform(platformWidth, layer);
newPlatform.x = newX;
newPlatform.y = layerY;
platforms.push(newPlatform);
game.addChild(newPlatform);
rightmostPlatforms[layer] = newPlatform;
}
}
// Spawn obstacles (less frequently)
if (LK.ticks % Math.floor(90 / gameSpeed) === 0 && Math.random() < 0.3) {
var obstacle = new Obstacle();
obstacle.x = GAME_WIDTH + 100;
// Place obstacles on platforms or in air
if (platforms.length > 0 && Math.random() < 0.7) {
// Find platforms that are currently on screen or just off to the right
var viablePlatforms = platforms.filter(function (p) {
return p.x > player.x && p.x < GAME_WIDTH + 200;
});
if (viablePlatforms.length > 0) {
var randomPlatform = viablePlatforms[Math.floor(Math.random() * viablePlatforms.length)];
obstacle.x = randomPlatform.x;
obstacle.y = randomPlatform.y - randomPlatform.getHeight() / 2 - obstacle.height / 2;
} else {
obstacle.y = player.y + (Math.random() * 200 - 100);
}
} else {
obstacle.y = player.y + (Math.random() * 200 - 100);
}
obstacles.push(obstacle);
game.addChild(obstacle);
}
// Spawn enemies (more frequently)
if (LK.ticks % Math.floor(60 / gameSpeed) === 0 && Math.random() < 0.6) {
var enemy = new Enemy();
enemy.x = GAME_WIDTH + 100;
// Spawn enemies close to player height
enemy.y = player.y + (Math.random() * 300 - 150);
// Keep within playable bounds
enemy.y = Math.max(100, Math.min(GAME_HEIGHT - 400, enemy.y));
enemies.push(enemy);
game.addChild(enemy);
}
// Spawn powerups (occasionally)
if (LK.ticks % Math.floor(180 / gameSpeed) === 0 && Math.random() < 0.4) {
var powerup = new PowerUp();
powerup.x = GAME_WIDTH + 100;
// Place powerups on platforms or in air
if (platforms.length > 0 && Math.random() < 0.7) {
// Find platforms that are currently on screen or just off to the right
var viablePlatforms = platforms.filter(function (p) {
return p.x > GAME_WIDTH / 2 && p.x < GAME_WIDTH + 200;
});
if (viablePlatforms.length > 0) {
var randomPlatform = viablePlatforms[Math.floor(Math.random() * viablePlatforms.length)];
powerup.x = randomPlatform.x;
powerup.y = randomPlatform.y - randomPlatform.getHeight() / 2 - powerup.height / 2;
} else {
powerup.y = FLOOR_HEIGHT - 200 - Math.random() * 300;
}
} else {
powerup.y = FLOOR_HEIGHT - 200 - Math.random() * 300;
}
powerups.push(powerup);
game.addChild(powerup);
}
// Update platforms
for (var p = platforms.length - 1; p >= 0; p--) {
if (platforms[p].update(gameSpeed)) {
// If this was a rightmost platform, clear that reference
for (var l = 0; l < LAYERS; l++) {
if (rightmostPlatforms[l] === platforms[p]) {
rightmostPlatforms[l] = null;
}
}
platforms[p].destroy();
platforms.splice(p, 1);
}
}
// Update obstacles
for (var i = obstacles.length - 1; i >= 0; i--) {
if (obstacles[i].update(gameSpeed)) {
obstacles[i].destroy();
obstacles.splice(i, 1);
continue;
}
// Collision with player
if (obstacles[i].intersects(player)) {
if (player.isDashing) {
// Destroy obstacle when dashing
var points = 50;
score += points;
var popup = new ScorePopup(points, 0x00ffaa);
popup.x = obstacles[i].x;
popup.y = obstacles[i].y;
scorePopups.push(popup);
game.addChild(popup);
obstacles[i].destroy();
obstacles.splice(i, 1);
} else if (player.hasShield) {
// Shield protects from one hit
player.deactivateShield();
obstacles[i].destroy();
obstacles.splice(i, 1);
} else {
// Game over
gameOver();
}
}
}
// Update powerups
for (var j = powerups.length - 1; j >= 0; j--) {
if (powerups[j].update(gameSpeed)) {
powerups[j].destroy();
powerups.splice(j, 1);
continue;
}
// Collision with player
if (powerups[j].intersects(player)) {
if (powerups[j].type === 'shield') {
player.activateShield();
var shieldPopup = new ScorePopup("SHIELD", 0x3399ff);
shieldPopup.x = powerups[j].x;
shieldPopup.y = powerups[j].y;
scorePopups.push(shieldPopup);
game.addChild(shieldPopup);
LK.getSound('pick-shield').play(); // Play pick-shield sound
} else {
var bonusPoints = 100;
score += bonusPoints;
var scoreBonus = new ScorePopup(bonusPoints);
scoreBonus.x = powerups[j].x;
scoreBonus.y = powerups[j].y;
scorePopups.push(scoreBonus);
game.addChild(scoreBonus);
LK.getSound('pick-powerup').play(); // Play pick-powerup sound
}
powerups[j].destroy();
powerups.splice(j, 1);
}
}
// Update enemies
for (var k = enemies.length - 1; k >= 0; k--) {
if (enemies[k].update(gameSpeed)) {
enemies[k].destroy();
enemies.splice(k, 1);
continue;
}
// Collision with player
if (enemies[k].intersects(player)) {
if (player.isDashing) {
// Destroy enemy when dashing
var enemyPoints = 200;
score += enemyPoints;
var enemyPopup = new ScorePopup(enemyPoints, 0xff00ff);
enemyPopup.x = enemies[k].x;
enemyPopup.y = enemies[k].y;
scorePopups.push(enemyPopup);
game.addChild(enemyPopup);
enemies[k].destroy();
enemies.splice(k, 1);
} else if (player.hasShield) {
// Shield protects from one hit
player.deactivateShield();
enemies[k].destroy();
enemies.splice(k, 1);
} else {
// Game over
gameOver();
}
}
}
// Update shield
if (player.shieldObj) {
player.shieldObj.update();
}
// Update score popups
for (var m = scorePopups.length - 1; m >= 0; m--) {
if (scorePopups[m].update()) {
scorePopups.splice(m, 1);
}
}
// Update score
score += Math.floor(gameSpeed);
scoreTxt.setText('SCORE: ' + score);
LK.setScore(score);
});
function gameOver() {
isGameOver = true;
LK.showGameOver();
} /****
* Classes
****/
var DashEffect = Container.expand(function () {
var self = Container.call(this);
var effectGraphics = self.attachAsset('dashEffect', {
anchorX: 0.5,
anchorY: 0.5
});
self.lifetime = 10;
self.alpha = 0.8;
self.update = function () {
self.lifetime--;
self.alpha = self.lifetime / 10;
self.x -= 15 * 0.7;
if (self.lifetime <= 0) {
self.destroy();
return true;
}
return false;
};
});
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemyShape', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 10;
self.verticalSpeed = Math.random() * 4 - 2;
self.verticalDirection = 1;
self.verticalDistance = 0;
self.maxVerticalDistance = 100 + Math.random() * 200;
self.update = function (gameSpeed) {
self.x -= self.speed * gameSpeed * 0.7;
// Vertical movement
self.verticalDistance += Math.abs(self.verticalSpeed);
if (self.verticalDistance > self.maxVerticalDistance) {
self.verticalDirection *= -1;
self.verticalDistance = 0;
}
self.y += self.verticalSpeed * self.verticalDirection;
// Keep within bounds
if (self.y < self.height / 2) {
self.y = self.height / 2;
self.verticalDirection *= -1;
} else if (self.y > 2732 - 400) {
self.y = 2732 - 400;
self.verticalDirection *= -1;
}
return self.x < -100;
};
});
var Obstacle = Container.expand(function () {
var self = Container.call(this);
var obstacleGraphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 15;
self.update = function (gameSpeed) {
self.x -= self.speed * gameSpeed * 0.7;
return self.x < -100;
};
});
var Particle = Container.expand(function () {
var self = Container.call(this);
var particleGraphics = self.attachAsset('particle', {
anchorX: 0.5,
anchorY: 0.5
});
self.lifetime = 30;
self.alpha = 1;
self.scale.set(1);
self.update = function () {
self.lifetime--;
self.alpha = self.lifetime / 30;
self.scale.set(1 - self.lifetime / 30 * 0.5);
if (self.lifetime <= 0) {
self.destroy();
return true;
}
return false;
};
});
var Platform = Container.expand(function (width, layer) {
var self = Container.call(this);
var platformWidth = width || 200;
var platformGraphics = self.attachAsset('platform', {
anchorX: 0.5,
anchorY: 0.5,
width: platformWidth
});
// Color platforms based on layer
var layerColors = [0x00ffff, 0x00ccff, 0x0099ff, 0x0066ff, 0x0033ff];
if (layer !== undefined && layer < layerColors.length) {
platformGraphics.tint = layerColors[layer];
}
self.speed = 12;
self.layer = layer || 0;
self.update = function (gameSpeed) {
self.x -= self.speed * gameSpeed * 0.7;
return self.x < -platformWidth / 2;
};
self.getWidth = function () {
return platformWidth;
};
self.getHeight = function () {
return platformGraphics.height;
};
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('platform', {
anchorX: 0.5,
anchorY: 0.5,
width: 60,
height: 60
});
playerGraphics.tint = 0x00ffaa;
self.velocity = {
x: 0,
y: 0
};
self.baseX = 300;
self.speed = 20;
self.jumpForce = -25;
self.gravity = 1;
self.isJumping = false;
self.isDashing = false;
self.dashCooldown = 0;
self.dashDuration = 0;
self.dashDistance = 0;
self.dashMaxDistance = 200;
self.hasShield = false;
self.shieldObj = null;
self.particles = [];
self.onPlatform = false;
self.currentPlatform = null;
self.jump = function () {
if (!self.isJumping || self.onPlatform) {
self.velocity.y = self.jumpForce;
self.isJumping = true;
self.onPlatform = false;
self.currentPlatform = null;
LK.getSound('jump').play(); // Play jump sound
}
};
self.dash = function () {
if (self.dashCooldown <= 0) {
LK.getSound('dash-fast').play();
self.isDashing = true;
self.dashDuration = 15;
self.dashCooldown = 60;
self.dashDistance = 0;
// Create dash effect
var effect = new DashEffect();
effect.x = self.x - 50;
effect.y = self.y;
self.parent.addChild(effect);
}
};
self.activateShield = function () {
self.hasShield = true;
if (!self.shieldObj) {
self.shieldObj = self.addChild(new Shield());
}
};
self.deactivateShield = function () {
self.hasShield = false;
if (self.shieldObj) {
self.shieldObj.destroy();
self.shieldObj = null;
}
};
self.update = function () {
// Apply gravity if jumping
if (self.isJumping && !self.onPlatform) {
self.velocity.y += self.gravity;
}
// Update position
self.y += self.velocity.y;
// Handle dash
if (self.isDashing) {
if (self.dashDistance < self.dashMaxDistance) {
self.x += 15 * 0.7;
self.dashDistance += 15 * 0.7;
} else {
self.x = Math.max(self.x - 10, self.baseX);
if (self.x <= self.baseX) {
self.isDashing = false;
}
}
self.dashDuration--;
if (self.dashDuration <= 0) {
self.isDashing = false;
}
} else {
// Return to base position if not dashing
if (self.x > self.baseX) {
self.x = Math.max(self.x - 5, self.baseX);
}
}
// Update dash cooldown
if (self.dashCooldown > 0) {
self.dashCooldown--;
}
// Ceiling collision
if (self.y < 60) {
self.y = 60;
self.velocity.y = 0;
}
// Platform collision
self.onPlatform = false;
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
// Check if player is above platform and falling
if (self.velocity.y >= 0 && self.y + 30 >= platform.y - platform.getHeight() / 2 && self.y - 30 <= platform.y - platform.getHeight() / 2 && self.x + 30 >= platform.x - platform.getWidth() / 2 && self.x - 30 <= platform.x + platform.getWidth() / 2) {
self.y = platform.y - platform.getHeight() / 2 - 30;
self.velocity.y = 0;
self.isJumping = false;
self.onPlatform = true;
self.currentPlatform = platform;
break;
}
}
// If was on platform but platform moved away
if (self.currentPlatform && !self.onPlatform) {
self.isJumping = true;
self.currentPlatform = null;
}
// Create trail particles
if (LK.ticks % 3 === 0) {
var particle = new Particle();
particle.x = self.x - 30;
particle.y = self.y;
particle.tint = self.isDashing ? 0xffffff : 0x00ffaa;
self.parent.addChild(particle);
self.particles.push(particle);
}
// Update particles
for (var j = self.particles.length - 1; j >= 0; j--) {
if (self.particles[j].update()) {
self.particles.splice(j, 1);
}
}
};
});
var PowerUp = Container.expand(function () {
var self = Container.call(this);
var powerupGraphics = self.attachAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5
});
self.type = Math.random() < 0.5 ? 'shield' : 'score';
powerupGraphics.tint = self.type === 'shield' ? 0x3399ff : 0xffff00;
self.speed = 8;
self.rotation = 0;
self.update = function (gameSpeed) {
self.x -= self.speed * gameSpeed * 0.7;
self.rotation += 0.05;
return self.x < -100;
};
});
var ScorePopup = Container.expand(function (value, color) {
var self = Container.call(this);
var scoreTxt = new Text2("+" + value, {
size: 40,
fill: color || 0xffff00
});
scoreTxt.anchor.set(0.5);
self.addChild(scoreTxt);
self.lifetime = 30;
self.update = function () {
self.lifetime--;
self.y -= 2;
self.alpha = self.lifetime / 30;
if (self.lifetime <= 0) {
self.destroy();
return true;
}
return false;
};
});
var Shield = Container.expand(function () {
var self = Container.call(this);
var shieldGraphics = self.attachAsset('shield', {
anchorX: 0.5,
anchorY: 0.5
});
shieldGraphics.alpha = 0.5;
self.update = function () {
self.rotation += 0.02;
};
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000033
});
/****
* Game Code
****/
// Play background music in a loop
LK.playMusic('background', {
loop: true
});
// Update player
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2732;
var PLATFORM_SPEED = 8;
var PLAYER_WIDTH = 60;
var MIN_GAP = PLAYER_WIDTH * 2;
var LAYERS = 3;
var LAYER_HEIGHT = 250;
var FLOOR_HEIGHT = GAME_HEIGHT - 350;
// Background
var background = game.attachAsset('background', {});
game.addChildAt(background, 0);
// Death zone
var deathZone = game.attachAsset('deathZone', {
anchorX: 0.5,
anchorY: 0
});
deathZone.x = GAME_WIDTH / 2;
deathZone.y = GAME_HEIGHT - 100;
deathZone.alpha = 0.5;
game.addChildAt(deathZone, 1);
// Game variables
var player = game.addChild(new Player());
player.x = 300;
player.y = FLOOR_HEIGHT - 400;
var obstacles = [];
var powerups = [];
var enemies = [];
var platforms = [];
var rightmostPlatforms = []; // Tracks the rightmost platform in each layer
var effects = [];
var scorePopups = [];
var score = 0;
var distance = 0;
var gameSpeed = 1;
var isGameOver = false;
// Initialize rightmostPlatforms array
for (var i = 0; i < LAYERS; i++) {
rightmostPlatforms[i] = null;
}
// Create initial platforms
for (var layer = 0; layer < LAYERS; layer++) {
var layerY = FLOOR_HEIGHT - layer * LAYER_HEIGHT;
// Create wider starting platforms for each layer
var initialWidth = layer === 0 ? 800 : 600 - layer * 50;
var startingPlatform = new Platform(initialWidth, layer);
startingPlatform.x = initialWidth / 2 + 100;
startingPlatform.y = layerY;
platforms.push(startingPlatform);
game.addChild(startingPlatform);
rightmostPlatforms[layer] = startingPlatform;
// Add a series of additional starting platforms for each layer
for (var p = 0; p < 3; p++) {
var additionalWidth = initialWidth * 0.7;
var additionalPlatform = new Platform(additionalWidth, layer);
var gap = layer === 0 ? MIN_GAP + 20 : MIN_GAP + layer * 40;
additionalPlatform.x = rightmostPlatforms[layer].x + rightmostPlatforms[layer].getWidth() / 2 + gap + additionalWidth / 2;
additionalPlatform.y = layerY;
platforms.push(additionalPlatform);
game.addChild(additionalPlatform);
rightmostPlatforms[layer] = additionalPlatform;
}
}
// Place player on the first platform
player.y = rightmostPlatforms[0].y - rightmostPlatforms[0].getHeight() / 2 - player.height / 2;
// UI elements
var scoreTxt = new Text2('SCORE: 0', {
size: 50,
fill: 0xffffff
});
scoreTxt.anchor.set(0, 0);
scoreTxt.x = 20;
scoreTxt.y = 20;
LK.gui.top.addChild(scoreTxt);
var distanceTxt = new Text2('DISTANCE: 0m', {
size: 50,
fill: 0xffffff
});
distanceTxt.anchor.set(0, 0);
distanceTxt.x = 20;
distanceTxt.y = 80;
LK.gui.top.addChild(distanceTxt);
var dashMeter = new Container();
dashMeter.x = 20;
dashMeter.y = 140;
LK.gui.top.addChild(dashMeter);
var dashBg = new Container();
var dashBgGraphics = dashBg.attachAsset('dashEffect', {
anchorX: 0,
anchorY: 0
});
dashBgGraphics.width = 200;
dashBgGraphics.height = 20;
dashBgGraphics.tint = 0x333333;
dashMeter.addChild(dashBg);
var dashFill = new Container();
var dashFillGraphics = dashFill.attachAsset('dashEffect', {
anchorX: 0,
anchorY: 0
});
dashFillGraphics.width = 200;
dashFillGraphics.height = 20;
dashFillGraphics.tint = 0x00ffaa;
dashMeter.addChild(dashFill);
var dashTxt = new Text2('DASH', {
size: 30,
fill: 0xffffff
});
dashTxt.anchor.set(0, 0.5);
dashTxt.x = 210;
dashTxt.y = 10;
dashMeter.addChild(dashTxt);
// Control hints
var controlsContainer = new Container();
controlsContainer.y = GAME_HEIGHT - 150;
game.addChild(controlsContainer);
var leftControlBg = new Container();
var leftControlGraphics = leftControlBg.attachAsset('platform', {
anchorX: 0,
anchorY: 0,
width: GAME_WIDTH / 2,
height: 100
});
leftControlGraphics.alpha = 0.2;
controlsContainer.addChild(leftControlBg);
var rightControlBg = new Container();
var rightControlGraphics = rightControlBg.attachAsset('platform', {
anchorX: 0,
anchorY: 0,
width: GAME_WIDTH / 2,
height: 100
});
rightControlGraphics.alpha = 0.2;
rightControlBg.x = GAME_WIDTH / 2;
controlsContainer.addChild(rightControlBg);
var jumpTxt = new Text2('JUMP', {
size: 40,
fill: 0xffffff
});
jumpTxt.anchor.set(0.5);
jumpTxt.x = GAME_WIDTH / 4;
jumpTxt.y = 50;
controlsContainer.addChild(jumpTxt);
var dashControlTxt = new Text2('DASH', {
size: 40,
fill: 0xffffff
});
dashControlTxt.anchor.set(0.5);
dashControlTxt.x = GAME_WIDTH / 4 * 3;
dashControlTxt.y = 50;
controlsContainer.addChild(dashControlTxt);
// Input handling
game.on('down', function (x, y, obj) {
if (isGameOver) {
return;
}
var event = obj;
var pos = game.toLocal(event.global);
if (pos.x < GAME_WIDTH / 2) {
player.jump();
} else {
player.dash();
}
});
// Game loop
LK.on('tick', function () {
if (isGameOver) {
return;
}
// Update player
player.update();
// Update dash meter
dashFill.scale.x = (60 - player.dashCooldown) / 60;
// Update game speed
gameSpeed = (1.5 + distance / 5000) * 0.7;
// Update distance
distance += gameSpeed;
distanceTxt.setText('DISTANCE: ' + Math.floor(distance) + 'm');
// Check if player fell to death zone
if (player.y > GAME_HEIGHT - 160) {
gameOver();
return;
}
// Platform generation logic
for (var layer = 0; layer < LAYERS; layer++) {
// Calculate layer-specific values
var layerY = FLOOR_HEIGHT - layer * LAYER_HEIGHT;
var platformWidth = 400 - layer * 70 + Math.random() * 100; // Wider platforms at bottom
var gapMultiplier = 1 + layer * 0.4; // Larger gaps at higher layers
var minGap = MIN_GAP * gapMultiplier;
var maxGap = minGap * 1.5;
var actualGap = minGap + Math.random() * (maxGap - minGap);
// Check if we need to generate a new platform
if (!rightmostPlatforms[layer] || rightmostPlatforms[layer].x < GAME_WIDTH + 200) {
// Determine new platform position
var newX;
if (rightmostPlatforms[layer]) {
newX = rightmostPlatforms[layer].x + rightmostPlatforms[layer].getWidth() / 2 + actualGap + platformWidth / 2;
} else {
newX = GAME_WIDTH + platformWidth / 2;
}
// Create new platform
var newPlatform = new Platform(platformWidth, layer);
newPlatform.x = newX;
newPlatform.y = layerY;
platforms.push(newPlatform);
game.addChild(newPlatform);
rightmostPlatforms[layer] = newPlatform;
}
}
// Spawn obstacles (less frequently)
if (LK.ticks % Math.floor(90 / gameSpeed) === 0 && Math.random() < 0.3) {
var obstacle = new Obstacle();
obstacle.x = GAME_WIDTH + 100;
// Place obstacles on platforms or in air
if (platforms.length > 0 && Math.random() < 0.7) {
// Find platforms that are currently on screen or just off to the right
var viablePlatforms = platforms.filter(function (p) {
return p.x > player.x && p.x < GAME_WIDTH + 200;
});
if (viablePlatforms.length > 0) {
var randomPlatform = viablePlatforms[Math.floor(Math.random() * viablePlatforms.length)];
obstacle.x = randomPlatform.x;
obstacle.y = randomPlatform.y - randomPlatform.getHeight() / 2 - obstacle.height / 2;
} else {
obstacle.y = player.y + (Math.random() * 200 - 100);
}
} else {
obstacle.y = player.y + (Math.random() * 200 - 100);
}
obstacles.push(obstacle);
game.addChild(obstacle);
}
// Spawn enemies (more frequently)
if (LK.ticks % Math.floor(60 / gameSpeed) === 0 && Math.random() < 0.6) {
var enemy = new Enemy();
enemy.x = GAME_WIDTH + 100;
// Spawn enemies close to player height
enemy.y = player.y + (Math.random() * 300 - 150);
// Keep within playable bounds
enemy.y = Math.max(100, Math.min(GAME_HEIGHT - 400, enemy.y));
enemies.push(enemy);
game.addChild(enemy);
}
// Spawn powerups (occasionally)
if (LK.ticks % Math.floor(180 / gameSpeed) === 0 && Math.random() < 0.4) {
var powerup = new PowerUp();
powerup.x = GAME_WIDTH + 100;
// Place powerups on platforms or in air
if (platforms.length > 0 && Math.random() < 0.7) {
// Find platforms that are currently on screen or just off to the right
var viablePlatforms = platforms.filter(function (p) {
return p.x > GAME_WIDTH / 2 && p.x < GAME_WIDTH + 200;
});
if (viablePlatforms.length > 0) {
var randomPlatform = viablePlatforms[Math.floor(Math.random() * viablePlatforms.length)];
powerup.x = randomPlatform.x;
powerup.y = randomPlatform.y - randomPlatform.getHeight() / 2 - powerup.height / 2;
} else {
powerup.y = FLOOR_HEIGHT - 200 - Math.random() * 300;
}
} else {
powerup.y = FLOOR_HEIGHT - 200 - Math.random() * 300;
}
powerups.push(powerup);
game.addChild(powerup);
}
// Update platforms
for (var p = platforms.length - 1; p >= 0; p--) {
if (platforms[p].update(gameSpeed)) {
// If this was a rightmost platform, clear that reference
for (var l = 0; l < LAYERS; l++) {
if (rightmostPlatforms[l] === platforms[p]) {
rightmostPlatforms[l] = null;
}
}
platforms[p].destroy();
platforms.splice(p, 1);
}
}
// Update obstacles
for (var i = obstacles.length - 1; i >= 0; i--) {
if (obstacles[i].update(gameSpeed)) {
obstacles[i].destroy();
obstacles.splice(i, 1);
continue;
}
// Collision with player
if (obstacles[i].intersects(player)) {
if (player.isDashing) {
// Destroy obstacle when dashing
var points = 50;
score += points;
var popup = new ScorePopup(points, 0x00ffaa);
popup.x = obstacles[i].x;
popup.y = obstacles[i].y;
scorePopups.push(popup);
game.addChild(popup);
obstacles[i].destroy();
obstacles.splice(i, 1);
} else if (player.hasShield) {
// Shield protects from one hit
player.deactivateShield();
obstacles[i].destroy();
obstacles.splice(i, 1);
} else {
// Game over
gameOver();
}
}
}
// Update powerups
for (var j = powerups.length - 1; j >= 0; j--) {
if (powerups[j].update(gameSpeed)) {
powerups[j].destroy();
powerups.splice(j, 1);
continue;
}
// Collision with player
if (powerups[j].intersects(player)) {
if (powerups[j].type === 'shield') {
player.activateShield();
var shieldPopup = new ScorePopup("SHIELD", 0x3399ff);
shieldPopup.x = powerups[j].x;
shieldPopup.y = powerups[j].y;
scorePopups.push(shieldPopup);
game.addChild(shieldPopup);
LK.getSound('pick-shield').play(); // Play pick-shield sound
} else {
var bonusPoints = 100;
score += bonusPoints;
var scoreBonus = new ScorePopup(bonusPoints);
scoreBonus.x = powerups[j].x;
scoreBonus.y = powerups[j].y;
scorePopups.push(scoreBonus);
game.addChild(scoreBonus);
LK.getSound('pick-powerup').play(); // Play pick-powerup sound
}
powerups[j].destroy();
powerups.splice(j, 1);
}
}
// Update enemies
for (var k = enemies.length - 1; k >= 0; k--) {
if (enemies[k].update(gameSpeed)) {
enemies[k].destroy();
enemies.splice(k, 1);
continue;
}
// Collision with player
if (enemies[k].intersects(player)) {
if (player.isDashing) {
// Destroy enemy when dashing
var enemyPoints = 200;
score += enemyPoints;
var enemyPopup = new ScorePopup(enemyPoints, 0xff00ff);
enemyPopup.x = enemies[k].x;
enemyPopup.y = enemies[k].y;
scorePopups.push(enemyPopup);
game.addChild(enemyPopup);
enemies[k].destroy();
enemies.splice(k, 1);
} else if (player.hasShield) {
// Shield protects from one hit
player.deactivateShield();
enemies[k].destroy();
enemies.splice(k, 1);
} else {
// Game over
gameOver();
}
}
}
// Update shield
if (player.shieldObj) {
player.shieldObj.update();
}
// Update score popups
for (var m = scorePopups.length - 1; m >= 0; m--) {
if (scorePopups[m].update()) {
scorePopups.splice(m, 1);
}
}
// Update score
score += Math.floor(gameSpeed);
scoreTxt.setText('SCORE: ' + score);
LK.setScore(score);
});
function gameOver() {
isGameOver = true;
LK.showGameOver();
}
neon for obstacle in endless runner game, like a spiky obstacle but still many rectangle or angled surfaces, not round, pink neon colors. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows. neon. polygon shapes
flying neon enemy, blocky, sharp angles. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows