/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Enemy (hazard)
var Enemy = Container.expand(function () {
var self = Container.call(this);
var asset = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = asset.width;
self.height = asset.height;
self.moveDir = Math.random() < 0.5 ? 1 : -1;
self.moveSpeed = 3 + Math.random() * 3;
self.range = 400 + Math.random() * 200;
self.baseX = 0;
self.t = 0;
self.init = function () {
self.baseX = self.x;
self.t = Math.random() * 1000;
};
self.update = function () {
self.t += self.moveSpeed;
self.x = self.baseX + Math.sin(self.t / 180) * self.range;
};
return self;
});
// Jumper (player)
var Jumper = Container.expand(function () {
var self = Container.call(this);
var asset = self.attachAsset('jumper', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = asset.width;
self.height = asset.height;
self.vx = 0;
self.vy = 0;
self.jetpackTime = 0;
self.jetpackActive = false;
self.springBoost = false;
self.springTimer = 0;
self.update = function () {
// Jetpack
if (self.jetpackActive) {
self.vy = -38;
self.jetpackTime--;
if (self.jetpackTime <= 0) {
self.jetpackActive = false;
}
}
// Spring
if (self.springBoost) {
self.vy = -48;
self.springBoost = false;
self.springTimer = 10;
}
if (self.springTimer > 0) {
self.springTimer--;
}
// Gravity
if (!self.jetpackActive) {
self.vy += 2.2;
if (self.vy > 60) self.vy = 60;
}
// Move
self.x += self.vx;
self.y += self.vy;
// Wrap horizontally
if (self.x < -self.width / 2) self.x = 2048 + self.width / 2;
if (self.x > 2048 + self.width / 2) self.x = -self.width / 2;
};
self.jump = function (power) {
self.vy = -power;
};
self.activateJetpack = function () {
self.jetpackActive = true;
self.jetpackTime = 90;
};
self.activateSpring = function () {
self.springBoost = true;
};
return self;
});
// Platform types: 'normal', 'break', 'move'
var Platform = Container.expand(function () {
var self = Container.call(this);
self.type = 'normal';
self.broken = false;
self.moveDir = 1; // 1:right, -1:left
self.moveSpeed = 4 + Math.random() * 4;
self.range = 300 + Math.random() * 300;
self.baseX = 0;
self.t = 0;
self.asset = null;
self.init = function (type) {
self.type = type;
if (type === 'normal') {
self.asset = self.attachAsset('platform', {
anchorX: 0.5,
anchorY: 0.5
});
} else if (type === 'break') {
self.asset = self.attachAsset('platform_break', {
anchorX: 0.5,
anchorY: 0.5
});
} else if (type === 'move') {
self.asset = self.attachAsset('platform_move', {
anchorX: 0.5,
anchorY: 0.5
});
}
self.width = self.asset.width;
self.height = self.asset.height;
self.baseX = self.x;
self.t = Math.random() * 1000;
};
self.update = function () {
if (self.type === 'move') {
self.t += self.moveSpeed;
self.x = self.baseX + Math.sin(self.t / 180) * self.range;
}
};
self.breakPlatform = function () {
if (self.type === 'break' && !self.broken) {
self.broken = true;
tween(self.asset, {
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
self.visible = false;
}
});
}
};
return self;
});
// PowerUp: type = 'spring' or 'jetpack'
var PowerUp = Container.expand(function () {
var self = Container.call(this);
self.type = 'spring';
self.active = true;
self.asset = null;
self.init = function (type) {
self.type = type;
if (type === 'spring') {
self.asset = self.attachAsset('spring', {
anchorX: 0.5,
anchorY: 0.5
});
} else if (type === 'jetpack') {
self.asset = self.attachAsset('jetpack', {
anchorX: 0.5,
anchorY: 0.5
});
}
self.width = self.asset.width;
self.height = self.asset.height;
};
self.collect = function () {
self.active = false;
tween(self.asset, {
alpha: 0
}, {
duration: 200,
onFinish: function onFinish() {
self.visible = false;
}
});
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87ceeb // Sky blue
});
/****
* Game Code
****/
// Game constants
// Character: a springy jumper
// Platform: normal
// Platform: breakable
// Platform: moving
// Hazard: enemy
// Power-up: spring
// Power-up: jetpack
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2732;
var PLATFORM_MIN_Y = 200;
var PLATFORM_MAX_Y = 400;
var PLATFORM_WIDTH = 300;
var PLATFORM_HEIGHT = 40;
var JUMPER_START_X = GAME_WIDTH / 2;
var JUMPER_START_Y = GAME_HEIGHT - 400;
var CAMERA_OFFSET = 900; // How far from bottom before camera scrolls
// Game state
var jumper;
var platforms = [];
var enemies = [];
var powerups = [];
var maxY = 0; // Highest Y reached (lowest value, since y decreases as you go up)
var cameraY = 0;
var dragNode = null;
var lastDownX = 0;
var lastDownY = 0;
var scoreTxt;
var gameOver = false;
// Score display
scoreTxt = new Text2('0', {
size: 120,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Helper: create a platform at (x, y) of given type
function createPlatform(x, y, type) {
var plat = new Platform();
plat.x = x;
plat.y = y;
plat.init(type);
platforms.push(plat);
game.addChild(plat);
return plat;
}
// Helper: create an enemy at (x, y)
function createEnemy(x, y) {
var enemy = new Enemy();
enemy.x = x;
enemy.y = y;
enemy.init();
enemies.push(enemy);
game.addChild(enemy);
return enemy;
}
// Helper: create a powerup at (x, y) of given type
function createPowerUp(x, y, type) {
var pu = new PowerUp();
pu.x = x;
pu.y = y;
pu.init(type);
powerups.push(pu);
game.addChild(pu);
return pu;
}
// Reset game state
function resetGame() {
// Remove all platforms, enemies, powerups
for (var i = 0; i < platforms.length; ++i) platforms[i].destroy();
for (var i = 0; i < enemies.length; ++i) enemies[i].destroy();
for (var i = 0; i < powerups.length; ++i) powerups[i].destroy();
platforms = [];
enemies = [];
powerups = [];
// Create initial platform directly under jumper
createPlatform(JUMPER_START_X, JUMPER_START_Y + 80, 'normal');
// Create initial platforms
var y = JUMPER_START_Y + 200;
while (y > -2000) {
var x = 200 + Math.random() * (GAME_WIDTH - 400);
var type = 'normal';
if (Math.random() < 0.12 && y < JUMPER_START_Y - 600) type = 'break';else if (Math.random() < 0.15 && y < JUMPER_START_Y - 800) type = 'move';
createPlatform(x, y, type);
y -= PLATFORM_MIN_Y + Math.random() * (PLATFORM_MAX_Y - PLATFORM_MIN_Y);
}
// Add some enemies and powerups
for (var i = 0; i < 6; ++i) {
var px = 200 + Math.random() * (GAME_WIDTH - 400);
var py = JUMPER_START_Y - 800 - Math.random() * 2000;
createEnemy(px, py);
}
for (var i = 0; i < 4; ++i) {
var px = 200 + Math.random() * (GAME_WIDTH - 400);
var py = JUMPER_START_Y - 600 - Math.random() * 2000;
var type = Math.random() < 0.5 ? 'spring' : 'jetpack';
createPowerUp(px, py, type);
}
// Create jumper
jumper = new Jumper();
jumper.x = JUMPER_START_X;
jumper.y = JUMPER_START_Y;
jumper.vx = 0;
jumper.vy = 0;
game.addChild(jumper);
// Reset camera
cameraY = 0;
maxY = jumper.y;
// Reset score
LK.setScore(0);
scoreTxt.setText('0');
gameOver = false;
}
// Camera scroll
function updateCamera() {
// Camera follows jumper upward, but not downward
var targetY = jumper.y - CAMERA_OFFSET;
if (targetY < cameraY) {
cameraY = targetY;
}
// Move all objects relative to camera
for (var i = 0; i < platforms.length; ++i) platforms[i].yRel = platforms[i].y - cameraY;
for (var i = 0; i < enemies.length; ++i) enemies[i].yRel = enemies[i].y - cameraY;
for (var i = 0; i < powerups.length; ++i) powerups[i].yRel = powerups[i].y - cameraY;
jumper.yRel = jumper.y - cameraY;
// Actually set y for display
for (var i = 0; i < platforms.length; ++i) platforms[i].position.y = platforms[i].yRel;
for (var i = 0; i < enemies.length; ++i) enemies[i].position.y = enemies[i].yRel;
for (var i = 0; i < powerups.length; ++i) powerups[i].position.y = powerups[i].yRel;
jumper.position.y = jumper.yRel;
}
// Generate new platforms as needed
function generatePlatforms() {
// Find highest platform
var minY = 999999;
for (var i = 0; i < platforms.length; ++i) {
if (platforms[i].y < minY) minY = platforms[i].y;
}
// If highest platform is above screen, add more
while (minY > cameraY - 800) {
var x = 200 + Math.random() * (GAME_WIDTH - 400);
var y = minY - (PLATFORM_MIN_Y + Math.random() * (PLATFORM_MAX_Y - PLATFORM_MIN_Y));
var type = 'normal';
if (Math.random() < 0.13) type = 'break';else if (Math.random() < 0.17) type = 'move';
createPlatform(x, y, type);
// Maybe add enemy or powerup
if (Math.random() < 0.08) createEnemy(x, y - 100);
if (Math.random() < 0.07) createPowerUp(x, y - 60, Math.random() < 0.5 ? 'spring' : 'jetpack');
minY = y;
}
}
// Remove offscreen objects
function cleanupObjects() {
// Platforms
for (var i = platforms.length - 1; i >= 0; --i) {
if (platforms[i].yRel > GAME_HEIGHT + 200) {
platforms[i].destroy();
platforms.splice(i, 1);
}
}
// Enemies
for (var i = enemies.length - 1; i >= 0; --i) {
if (enemies[i].yRel > GAME_HEIGHT + 200) {
enemies[i].destroy();
enemies.splice(i, 1);
}
}
// Powerups
for (var i = powerups.length - 1; i >= 0; --i) {
if (powerups[i].yRel > GAME_HEIGHT + 200 || !powerups[i].active) {
powerups[i].destroy();
powerups.splice(i, 1);
}
}
}
// Platform collision
function checkPlatformCollision() {
if (jumper.vy > 0) {
// Only when falling
for (var i = 0; i < platforms.length; ++i) {
var plat = platforms[i];
if (!plat.visible || plat.broken) continue;
// Simple AABB
var px = plat.x,
py = plat.yRel;
var pw = plat.width,
ph = plat.height;
var jx = jumper.x,
jy = jumper.yRel;
var jw = jumper.width,
jh = jumper.height;
if (jy + jh / 2 > py - ph / 2 && jy + jh / 2 < py + ph / 2) {
if (jx + jw / 2 > px - pw / 2 && jx - jw / 2 < px + pw / 2) {
// Landed on platform
if (plat.type === 'break') {
plat.breakPlatform();
return;
}
jumper.jump(38);
// Score: 1 per platform landed
LK.setScore(LK.getScore() + 1);
scoreTxt.setText(LK.getScore());
return;
}
}
}
}
}
// Powerup collision
function checkPowerUpCollision() {
for (var i = 0; i < powerups.length; ++i) {
var pu = powerups[i];
if (!pu.active) continue;
var px = pu.x,
py = pu.yRel;
var pw = pu.width,
ph = pu.height;
var jx = jumper.x,
jy = jumper.yRel;
var jw = jumper.width,
jh = jumper.height;
if (Math.abs(jx - px) < (jw + pw) / 2 && Math.abs(jy - py) < (jh + ph) / 2) {
// Collect
pu.collect();
if (pu.type === 'spring') {
jumper.activateSpring();
} else if (pu.type === 'jetpack') {
jumper.activateJetpack();
}
}
}
}
// Enemy collision
function checkEnemyCollision() {
for (var i = 0; i < enemies.length; ++i) {
var en = enemies[i];
var ex = en.x,
ey = en.yRel;
var ew = en.width,
eh = en.height;
var jx = jumper.x,
jy = jumper.yRel;
var jw = jumper.width,
jh = jumper.height;
if (Math.abs(jx - ex) < (jw + ew) / 2 - 10 && Math.abs(jy - ey) < (jh + eh) / 2 - 10) {
// Collided
LK.effects.flashScreen(0xff0000, 800);
gameOver = true;
LK.showGameOver();
return;
}
}
}
// Game over if fall off screen
function checkFall() {
if (jumper.yRel > GAME_HEIGHT + 100) {
LK.effects.flashScreen(0xff0000, 800);
gameOver = true;
LK.showGameOver();
}
}
// Touch controls: drag left/right
game.down = function (x, y, obj) {
if (gameOver) return;
dragNode = jumper;
lastDownX = x;
lastDownY = y;
};
game.move = function (x, y, obj) {
if (gameOver) return;
if (dragNode) {
var dx = x - lastDownX;
jumper.x += dx;
lastDownX = x;
lastDownY = y;
}
};
game.up = function (x, y, obj) {
dragNode = null;
};
// Main update loop
game.update = function () {
if (gameOver) return;
jumper.update();
for (var i = 0; i < platforms.length; ++i) platforms[i].update();
for (var i = 0; i < enemies.length; ++i) enemies[i].update();
// Camera
updateCamera();
// Generate new platforms
generatePlatforms();
// Remove offscreen
cleanupObjects();
// Collisions
checkPlatformCollision();
checkPowerUpCollision();
checkEnemyCollision();
checkFall();
// Update maxY and score
if (jumper.y < maxY) {
maxY = jumper.y;
var sc = Math.floor((JUMPER_START_Y - maxY) / 10);
if (sc > LK.getScore()) {
LK.setScore(sc);
scoreTxt.setText(sc);
}
}
};
// Start game
resetGame(); /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Enemy (hazard)
var Enemy = Container.expand(function () {
var self = Container.call(this);
var asset = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = asset.width;
self.height = asset.height;
self.moveDir = Math.random() < 0.5 ? 1 : -1;
self.moveSpeed = 3 + Math.random() * 3;
self.range = 400 + Math.random() * 200;
self.baseX = 0;
self.t = 0;
self.init = function () {
self.baseX = self.x;
self.t = Math.random() * 1000;
};
self.update = function () {
self.t += self.moveSpeed;
self.x = self.baseX + Math.sin(self.t / 180) * self.range;
};
return self;
});
// Jumper (player)
var Jumper = Container.expand(function () {
var self = Container.call(this);
var asset = self.attachAsset('jumper', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = asset.width;
self.height = asset.height;
self.vx = 0;
self.vy = 0;
self.jetpackTime = 0;
self.jetpackActive = false;
self.springBoost = false;
self.springTimer = 0;
self.update = function () {
// Jetpack
if (self.jetpackActive) {
self.vy = -38;
self.jetpackTime--;
if (self.jetpackTime <= 0) {
self.jetpackActive = false;
}
}
// Spring
if (self.springBoost) {
self.vy = -48;
self.springBoost = false;
self.springTimer = 10;
}
if (self.springTimer > 0) {
self.springTimer--;
}
// Gravity
if (!self.jetpackActive) {
self.vy += 2.2;
if (self.vy > 60) self.vy = 60;
}
// Move
self.x += self.vx;
self.y += self.vy;
// Wrap horizontally
if (self.x < -self.width / 2) self.x = 2048 + self.width / 2;
if (self.x > 2048 + self.width / 2) self.x = -self.width / 2;
};
self.jump = function (power) {
self.vy = -power;
};
self.activateJetpack = function () {
self.jetpackActive = true;
self.jetpackTime = 90;
};
self.activateSpring = function () {
self.springBoost = true;
};
return self;
});
// Platform types: 'normal', 'break', 'move'
var Platform = Container.expand(function () {
var self = Container.call(this);
self.type = 'normal';
self.broken = false;
self.moveDir = 1; // 1:right, -1:left
self.moveSpeed = 4 + Math.random() * 4;
self.range = 300 + Math.random() * 300;
self.baseX = 0;
self.t = 0;
self.asset = null;
self.init = function (type) {
self.type = type;
if (type === 'normal') {
self.asset = self.attachAsset('platform', {
anchorX: 0.5,
anchorY: 0.5
});
} else if (type === 'break') {
self.asset = self.attachAsset('platform_break', {
anchorX: 0.5,
anchorY: 0.5
});
} else if (type === 'move') {
self.asset = self.attachAsset('platform_move', {
anchorX: 0.5,
anchorY: 0.5
});
}
self.width = self.asset.width;
self.height = self.asset.height;
self.baseX = self.x;
self.t = Math.random() * 1000;
};
self.update = function () {
if (self.type === 'move') {
self.t += self.moveSpeed;
self.x = self.baseX + Math.sin(self.t / 180) * self.range;
}
};
self.breakPlatform = function () {
if (self.type === 'break' && !self.broken) {
self.broken = true;
tween(self.asset, {
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
self.visible = false;
}
});
}
};
return self;
});
// PowerUp: type = 'spring' or 'jetpack'
var PowerUp = Container.expand(function () {
var self = Container.call(this);
self.type = 'spring';
self.active = true;
self.asset = null;
self.init = function (type) {
self.type = type;
if (type === 'spring') {
self.asset = self.attachAsset('spring', {
anchorX: 0.5,
anchorY: 0.5
});
} else if (type === 'jetpack') {
self.asset = self.attachAsset('jetpack', {
anchorX: 0.5,
anchorY: 0.5
});
}
self.width = self.asset.width;
self.height = self.asset.height;
};
self.collect = function () {
self.active = false;
tween(self.asset, {
alpha: 0
}, {
duration: 200,
onFinish: function onFinish() {
self.visible = false;
}
});
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87ceeb // Sky blue
});
/****
* Game Code
****/
// Game constants
// Character: a springy jumper
// Platform: normal
// Platform: breakable
// Platform: moving
// Hazard: enemy
// Power-up: spring
// Power-up: jetpack
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2732;
var PLATFORM_MIN_Y = 200;
var PLATFORM_MAX_Y = 400;
var PLATFORM_WIDTH = 300;
var PLATFORM_HEIGHT = 40;
var JUMPER_START_X = GAME_WIDTH / 2;
var JUMPER_START_Y = GAME_HEIGHT - 400;
var CAMERA_OFFSET = 900; // How far from bottom before camera scrolls
// Game state
var jumper;
var platforms = [];
var enemies = [];
var powerups = [];
var maxY = 0; // Highest Y reached (lowest value, since y decreases as you go up)
var cameraY = 0;
var dragNode = null;
var lastDownX = 0;
var lastDownY = 0;
var scoreTxt;
var gameOver = false;
// Score display
scoreTxt = new Text2('0', {
size: 120,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Helper: create a platform at (x, y) of given type
function createPlatform(x, y, type) {
var plat = new Platform();
plat.x = x;
plat.y = y;
plat.init(type);
platforms.push(plat);
game.addChild(plat);
return plat;
}
// Helper: create an enemy at (x, y)
function createEnemy(x, y) {
var enemy = new Enemy();
enemy.x = x;
enemy.y = y;
enemy.init();
enemies.push(enemy);
game.addChild(enemy);
return enemy;
}
// Helper: create a powerup at (x, y) of given type
function createPowerUp(x, y, type) {
var pu = new PowerUp();
pu.x = x;
pu.y = y;
pu.init(type);
powerups.push(pu);
game.addChild(pu);
return pu;
}
// Reset game state
function resetGame() {
// Remove all platforms, enemies, powerups
for (var i = 0; i < platforms.length; ++i) platforms[i].destroy();
for (var i = 0; i < enemies.length; ++i) enemies[i].destroy();
for (var i = 0; i < powerups.length; ++i) powerups[i].destroy();
platforms = [];
enemies = [];
powerups = [];
// Create initial platform directly under jumper
createPlatform(JUMPER_START_X, JUMPER_START_Y + 80, 'normal');
// Create initial platforms
var y = JUMPER_START_Y + 200;
while (y > -2000) {
var x = 200 + Math.random() * (GAME_WIDTH - 400);
var type = 'normal';
if (Math.random() < 0.12 && y < JUMPER_START_Y - 600) type = 'break';else if (Math.random() < 0.15 && y < JUMPER_START_Y - 800) type = 'move';
createPlatform(x, y, type);
y -= PLATFORM_MIN_Y + Math.random() * (PLATFORM_MAX_Y - PLATFORM_MIN_Y);
}
// Add some enemies and powerups
for (var i = 0; i < 6; ++i) {
var px = 200 + Math.random() * (GAME_WIDTH - 400);
var py = JUMPER_START_Y - 800 - Math.random() * 2000;
createEnemy(px, py);
}
for (var i = 0; i < 4; ++i) {
var px = 200 + Math.random() * (GAME_WIDTH - 400);
var py = JUMPER_START_Y - 600 - Math.random() * 2000;
var type = Math.random() < 0.5 ? 'spring' : 'jetpack';
createPowerUp(px, py, type);
}
// Create jumper
jumper = new Jumper();
jumper.x = JUMPER_START_X;
jumper.y = JUMPER_START_Y;
jumper.vx = 0;
jumper.vy = 0;
game.addChild(jumper);
// Reset camera
cameraY = 0;
maxY = jumper.y;
// Reset score
LK.setScore(0);
scoreTxt.setText('0');
gameOver = false;
}
// Camera scroll
function updateCamera() {
// Camera follows jumper upward, but not downward
var targetY = jumper.y - CAMERA_OFFSET;
if (targetY < cameraY) {
cameraY = targetY;
}
// Move all objects relative to camera
for (var i = 0; i < platforms.length; ++i) platforms[i].yRel = platforms[i].y - cameraY;
for (var i = 0; i < enemies.length; ++i) enemies[i].yRel = enemies[i].y - cameraY;
for (var i = 0; i < powerups.length; ++i) powerups[i].yRel = powerups[i].y - cameraY;
jumper.yRel = jumper.y - cameraY;
// Actually set y for display
for (var i = 0; i < platforms.length; ++i) platforms[i].position.y = platforms[i].yRel;
for (var i = 0; i < enemies.length; ++i) enemies[i].position.y = enemies[i].yRel;
for (var i = 0; i < powerups.length; ++i) powerups[i].position.y = powerups[i].yRel;
jumper.position.y = jumper.yRel;
}
// Generate new platforms as needed
function generatePlatforms() {
// Find highest platform
var minY = 999999;
for (var i = 0; i < platforms.length; ++i) {
if (platforms[i].y < minY) minY = platforms[i].y;
}
// If highest platform is above screen, add more
while (minY > cameraY - 800) {
var x = 200 + Math.random() * (GAME_WIDTH - 400);
var y = minY - (PLATFORM_MIN_Y + Math.random() * (PLATFORM_MAX_Y - PLATFORM_MIN_Y));
var type = 'normal';
if (Math.random() < 0.13) type = 'break';else if (Math.random() < 0.17) type = 'move';
createPlatform(x, y, type);
// Maybe add enemy or powerup
if (Math.random() < 0.08) createEnemy(x, y - 100);
if (Math.random() < 0.07) createPowerUp(x, y - 60, Math.random() < 0.5 ? 'spring' : 'jetpack');
minY = y;
}
}
// Remove offscreen objects
function cleanupObjects() {
// Platforms
for (var i = platforms.length - 1; i >= 0; --i) {
if (platforms[i].yRel > GAME_HEIGHT + 200) {
platforms[i].destroy();
platforms.splice(i, 1);
}
}
// Enemies
for (var i = enemies.length - 1; i >= 0; --i) {
if (enemies[i].yRel > GAME_HEIGHT + 200) {
enemies[i].destroy();
enemies.splice(i, 1);
}
}
// Powerups
for (var i = powerups.length - 1; i >= 0; --i) {
if (powerups[i].yRel > GAME_HEIGHT + 200 || !powerups[i].active) {
powerups[i].destroy();
powerups.splice(i, 1);
}
}
}
// Platform collision
function checkPlatformCollision() {
if (jumper.vy > 0) {
// Only when falling
for (var i = 0; i < platforms.length; ++i) {
var plat = platforms[i];
if (!plat.visible || plat.broken) continue;
// Simple AABB
var px = plat.x,
py = plat.yRel;
var pw = plat.width,
ph = plat.height;
var jx = jumper.x,
jy = jumper.yRel;
var jw = jumper.width,
jh = jumper.height;
if (jy + jh / 2 > py - ph / 2 && jy + jh / 2 < py + ph / 2) {
if (jx + jw / 2 > px - pw / 2 && jx - jw / 2 < px + pw / 2) {
// Landed on platform
if (plat.type === 'break') {
plat.breakPlatform();
return;
}
jumper.jump(38);
// Score: 1 per platform landed
LK.setScore(LK.getScore() + 1);
scoreTxt.setText(LK.getScore());
return;
}
}
}
}
}
// Powerup collision
function checkPowerUpCollision() {
for (var i = 0; i < powerups.length; ++i) {
var pu = powerups[i];
if (!pu.active) continue;
var px = pu.x,
py = pu.yRel;
var pw = pu.width,
ph = pu.height;
var jx = jumper.x,
jy = jumper.yRel;
var jw = jumper.width,
jh = jumper.height;
if (Math.abs(jx - px) < (jw + pw) / 2 && Math.abs(jy - py) < (jh + ph) / 2) {
// Collect
pu.collect();
if (pu.type === 'spring') {
jumper.activateSpring();
} else if (pu.type === 'jetpack') {
jumper.activateJetpack();
}
}
}
}
// Enemy collision
function checkEnemyCollision() {
for (var i = 0; i < enemies.length; ++i) {
var en = enemies[i];
var ex = en.x,
ey = en.yRel;
var ew = en.width,
eh = en.height;
var jx = jumper.x,
jy = jumper.yRel;
var jw = jumper.width,
jh = jumper.height;
if (Math.abs(jx - ex) < (jw + ew) / 2 - 10 && Math.abs(jy - ey) < (jh + eh) / 2 - 10) {
// Collided
LK.effects.flashScreen(0xff0000, 800);
gameOver = true;
LK.showGameOver();
return;
}
}
}
// Game over if fall off screen
function checkFall() {
if (jumper.yRel > GAME_HEIGHT + 100) {
LK.effects.flashScreen(0xff0000, 800);
gameOver = true;
LK.showGameOver();
}
}
// Touch controls: drag left/right
game.down = function (x, y, obj) {
if (gameOver) return;
dragNode = jumper;
lastDownX = x;
lastDownY = y;
};
game.move = function (x, y, obj) {
if (gameOver) return;
if (dragNode) {
var dx = x - lastDownX;
jumper.x += dx;
lastDownX = x;
lastDownY = y;
}
};
game.up = function (x, y, obj) {
dragNode = null;
};
// Main update loop
game.update = function () {
if (gameOver) return;
jumper.update();
for (var i = 0; i < platforms.length; ++i) platforms[i].update();
for (var i = 0; i < enemies.length; ++i) enemies[i].update();
// Camera
updateCamera();
// Generate new platforms
generatePlatforms();
// Remove offscreen
cleanupObjects();
// Collisions
checkPlatformCollision();
checkPowerUpCollision();
checkEnemyCollision();
checkFall();
// Update maxY and score
if (jumper.y < maxY) {
maxY = jumper.y;
var sc = Math.floor((JUMPER_START_Y - maxY) / 10);
if (sc > LK.getScore()) {
LK.setScore(sc);
scoreTxt.setText(sc);
}
}
};
// Start game
resetGame();
Character. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
Enemy. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
A jetpack. In-Game asset. 2d. High contrast. No shadows
A spring.. In-Game asset. 2d. High contrast. No shadows
Platform. In-Game asset. 2d. High contrast. No shadows
Platform break.. In-Game asset. 2d. High contrast. No shadows
Paltform move.. In-Game asset. 2d. High contrast. No shadows