/**** * Classes ****/ // Collectible (Star) var Collectible = Container.expand(function () { var self = Container.call(this); var sprite = self.attachAsset('star', { anchorX: 0.5, anchorY: 0.5 }); self.width = 80; self.height = 80; return self; }); // Enemy (Alien or Robot) var Enemy = Container.expand(function () { var self = Container.call(this); var sprite = self.attachAsset('alien', { anchorX: 0.5, anchorY: 0.5 }); self.width = ENEMY_WIDTH; self.height = ENEMY_HEIGHT; self.vx = 3 + Math.random() * 2; self.direction = Math.random() < 0.5 ? -1 : 1; self.lastX = 0; self.update = function () { self.x += self.vx * self.direction; // Turn at platform edges for (var i = 0; i < platforms.length; ++i) { var p = platforms[i]; if (Math.abs(self.y - p.y) < 10) { if (self.x - self.width / 2 < p.x - p.width / 2 || self.x + self.width / 2 > p.x + p.width / 2) { self.direction *= -1; } } } // Clamp to world if (self.x < ENEMY_WIDTH / 2) self.direction = 1; if (self.x > 2048 - ENEMY_WIDTH / 2) self.direction = -1; self.lastX = self.x; }; return self; }); // Platform var Platform = Container.expand(function () { var self = Container.call(this); var sprite = self.attachAsset('platform', { anchorX: 0.5, anchorY: 0.5 }); self.width = PLATFORM_WIDTH; self.height = PLATFORM_HEIGHT; return self; }); // --- ASSET CLASSES --- // Player (Astronaut) var Player = Container.expand(function () { var self = Container.call(this); var sprite = self.attachAsset('astronaut', { anchorX: 0.5, anchorY: 0.5 }); self.width = PLAYER_WIDTH; self.height = PLAYER_HEIGHT; self.vx = 0; self.vy = 0; self.isOnGround = false; self.canDoubleJump = true; self.lastY = 0; self.lastX = 0; self.lastWasIntersectingEnemy = false; self.lastWasIntersectingRocket = false; self.jetpackExhaust = null; self.update = function () { // Gravity self.vy += GRAVITY; // Jetpack exhaust effect (show when jumping or double jumping) if (self.vy < -2) { if (!self.jetpackExhaust) { self.jetpackExhaust = self.attachAsset('star', { anchorX: 0.5, anchorY: 0.0, scaleX: 0.3, scaleY: 0.3, y: self.height / 2 + 10 }); self.jetpackExhaust.alpha = 0.7; } self.jetpackExhaust.x = 0; self.jetpackExhaust.y = self.height / 2 + 10; self.jetpackExhaust.visible = true; } else if (self.jetpackExhaust) { self.jetpackExhaust.visible = false; } // Move self.x += self.vx; self.y += self.vy; // Clamp to world bounds if (self.x < PLAYER_WIDTH / 2) self.x = PLAYER_WIDTH / 2; if (self.x > 2048 - PLAYER_WIDTH / 2) self.x = 2048 - PLAYER_WIDTH / 2; if (self.y > 2732 - PLAYER_HEIGHT / 2) self.y = 2732 - PLAYER_HEIGHT / 2; // Platform collision self.isOnGround = false; for (var i = 0; i < platforms.length; ++i) { var p = platforms[i]; // Only check if falling if (self.vy >= 0 && self.y + self.height / 2 > p.y - p.height / 2 && self.y + self.height / 2 - self.vy <= p.y - p.height / 2) { // Check horizontal overlap if (self.x + self.width / 2 > p.x - p.width / 2 && self.x - self.width / 2 < p.x + p.width / 2) { // Land on platform self.y = p.y - p.height / 2 - self.height / 2; self.vy = 0; self.isOnGround = true; self.canDoubleJump = true; isJumping = false; } } } // Enemy collision var hitEnemy = null; for (var i = 0; i < enemies.length; ++i) { var e = enemies[i]; if (self.intersects(e)) { // Check if landing on top if (self.lastY + self.height / 2 <= e.y - e.height / 2 && self.y + self.height / 2 > e.y - e.height / 2 && self.vy > 0) { // Defeat enemy hitEnemy = e; break; } else { // Hit from side or below: lose life if (!self.lastWasIntersectingEnemy) { loseLife(); self.lastWasIntersectingEnemy = true; } } } else { self.lastWasIntersectingEnemy = false; } } if (hitEnemy) { // Remove enemy, bounce up score += 100; updateScore(); if (LK.getSound && LK.getSound('enemyDefeat')) LK.getSound('enemyDefeat').play(); hitEnemy.destroy(); enemies.splice(enemies.indexOf(hitEnemy), 1); self.vy = JUMP_VELOCITY / 1.5; } // Collectibles for (var i = collectibles.length - 1; i >= 0; --i) { var c = collectibles[i]; if (self.intersects(c)) { score += 50; updateScore(); if (LK.getSound && LK.getSound('collect')) LK.getSound('collect').play(); c.destroy(); collectibles.splice(i, 1); } } // Rocket (level end) if (!self.lastWasIntersectingRocket && self.intersects(rocket)) { // Win! LK.showYouWin(); lastYouWin = true; } self.lastWasIntersectingRocket = self.intersects(rocket); // Fall off screen if (self.y > 2732) { loseLife(); } // Update last positions self.lastY = self.y; self.lastX = self.x; }; return self; }); // Rocket (Level End) var Rocket = Container.expand(function () { var self = Container.call(this); var sprite = self.attachAsset('rocket', { anchorX: 0.5, anchorY: 0.5 }); self.width = 180; self.height = 260; return self; }); /**** * Initialize Game ****/ // --- UI --- var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ // --- Astro Jump: Space Platformer Main Game Logic --- // --- GLOBALS --- var GRAVITY = 0.3; // Low gravity for floaty jumps var JUMP_VELOCITY = -18; // High jump var PLAYER_MOVE_SPEED = 12; var PLAYER_START_LIVES = 3; var PLAYER_WIDTH = 120; var PLAYER_HEIGHT = 140; var ENEMY_WIDTH = 110; var ENEMY_HEIGHT = 110; var PLATFORM_WIDTH = 320; var PLATFORM_HEIGHT = 60; var LEVEL_END_X = 1800; var LEVEL_END_Y = 400; var platforms = []; var enemies = []; var collectibles = []; var player = null; var rocket = null; var score = 0; var lives = PLAYER_START_LIVES; var scoreTxt = null; var livesTxt = null; var isJumping = false; var isFalling = false; var jumpKeyDown = false; var dragNode = null; var lastGameOver = false; var lastYouWin = false; // --- CUSTOM IMAGE BACKGROUND --- // Replace parallax starfield with a custom image background that scrolls horizontally with the player // Please upload your background image to LK and use its asset id below: var bgImage = LK.getAsset('space_bg', { anchorX: 0, anchorY: 0, scaleX: 1, scaleY: 1, x: 0, y: 0 }); game.addChildAt(bgImage, 0); // Always behind everything // Used to track last player X for background scroll var lastPlayerX = 0; // --- UI --- scoreTxt = new Text2('Score: 0', { size: 90, fill: "#fff" }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // Pixel heart asset livesTxt = new Container(); livesTxt.hearts = []; for (var i = 0; i < PLAYER_START_LIVES; ++i) { var heart = LK.getAsset('heart', { anchorX: 0.5, anchorY: 0.5 }); heart.x = i * 70; heart.y = 0; livesTxt.addChild(heart); livesTxt.hearts.push(heart); } livesTxt.x = 0; livesTxt.y = 0; LK.gui.topRight.addChild(livesTxt); // --- LEVEL SETUP --- function setupLevel() { // Clear previous 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 < collectibles.length; ++i) collectibles[i].destroy(); if (player) player.destroy(); if (rocket) rocket.destroy(); platforms = []; enemies = []; collectibles = []; // Platforms var platData = [{ x: 400, y: 2200 }, { x: 800, y: 1800 }, { x: 1200, y: 1500 }, { x: 1600, y: 1200 }, { x: 1800, y: 900 }, { x: 1200, y: 600 }, { x: LEVEL_END_X, y: LEVEL_END_Y }]; for (var i = 0; i < platData.length; ++i) { var p = new Platform(); p.x = platData[i].x; p.y = platData[i].y; platforms.push(p); game.addChild(p); } // Enemies var enemyData = [{ x: 800, y: 1700 }, { x: 1200, y: 1400 }, { x: 1600, y: 1100 }]; for (var i = 0; i < enemyData.length; ++i) { var e = new Enemy(); e.x = enemyData[i].x; e.y = enemyData[i].y; enemies.push(e); game.addChild(e); } // Collectibles var starData = [{ x: 400, y: 2100 }, { x: 1200, y: 1400 }, { x: 1800, y: 800 }]; for (var i = 0; i < starData.length; ++i) { var c = new Collectible(); c.x = starData[i].x; c.y = starData[i].y; collectibles.push(c); game.addChild(c); } // Rocket rocket = new Rocket(); rocket.x = LEVEL_END_X; rocket.y = LEVEL_END_Y - 100; game.addChild(rocket); // Player player = new Player(); player.x = 400; player.y = 2100; game.addChild(player); // Reset UI updateScore(); updateLives(); lastGameOver = false; lastYouWin = false; } setupLevel(); LK.playMusic('chiptune'); // --- UI Update --- function updateScore() { scoreTxt.setText('Score: ' + score); } function updateLives() { for (var i = 0; i < livesTxt.hearts.length; ++i) { livesTxt.hearts[i].visible = i < lives; } } // --- Lose Life --- function loseLife() { if (lastGameOver) return; lives -= 1; updateLives(); if (lives <= 0) { LK.showGameOver(); lastGameOver = true; } else { // Respawn player player.x = 400; player.y = 2100; player.vx = 0; player.vy = 0; } } // --- GAME CONTROLS (Touch/Drag) --- game.down = function (x, y, obj) { // Only allow controls if player exists if (!player) return; // Get screen width and height var screenWidth = 2048; var screenHeight = 2732; // Define control regions var leftRegion = screenWidth * 0.5; var jumpRegionY = screenHeight * 0.7; // bottom 30% of screen // If tap is in bottom 30% of screen, treat as jump if (y > jumpRegionY) { if (player.isOnGround) { player.vy = JUMP_VELOCITY; player.isOnGround = false; player.canDoubleJump = true; if (LK.getSound && LK.getSound('jump')) LK.getSound('jump').play(); } else if (player.canDoubleJump) { player.vy = JUMP_VELOCITY; player.canDoubleJump = false; if (LK.getSound && LK.getSound('jump')) LK.getSound('jump').play(); } // No horizontal movement on jump tap // player.vx = 0; // Don't stop movement on jump return; } // If tap is on left half, move left if (x < leftRegion) { player.vx = -PLAYER_MOVE_SPEED; } // If tap is on right half, move right else { player.vx = PLAYER_MOVE_SPEED; } }; game.up = function (x, y, obj) { dragNode = null; if (player) { player.vx = 0; } }; game.move = function (x, y, obj) { // No drag-based movement; handled by vx in update }; // --- GAME LOOP --- game.update = function () { // --- Custom background image scroll --- // Only scroll if player exists if (player) { // Calculate horizontal movement since last frame var dx = player.x - lastPlayerX; // Scroll background horizontally at a slow rate for parallax effect // (Adjust 0.3 for desired parallax speed) bgImage.x -= dx * 0.3; // Wrap background horizontally for infinite effect if (bgImage.x <= -2048) { bgImage.x += 2048; } else if (bgImage.x >= 2048) { bgImage.x -= 2048; } lastPlayerX = player.x; } // Player update if (player) player.update(); // Enemies update for (var i = 0; i < enemies.length; ++i) { enemies[i].update(); } // Win/Lose handled in player.update };
/****
* Classes
****/
// Collectible (Star)
var Collectible = Container.expand(function () {
var self = Container.call(this);
var sprite = self.attachAsset('star', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = 80;
self.height = 80;
return self;
});
// Enemy (Alien or Robot)
var Enemy = Container.expand(function () {
var self = Container.call(this);
var sprite = self.attachAsset('alien', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = ENEMY_WIDTH;
self.height = ENEMY_HEIGHT;
self.vx = 3 + Math.random() * 2;
self.direction = Math.random() < 0.5 ? -1 : 1;
self.lastX = 0;
self.update = function () {
self.x += self.vx * self.direction;
// Turn at platform edges
for (var i = 0; i < platforms.length; ++i) {
var p = platforms[i];
if (Math.abs(self.y - p.y) < 10) {
if (self.x - self.width / 2 < p.x - p.width / 2 || self.x + self.width / 2 > p.x + p.width / 2) {
self.direction *= -1;
}
}
}
// Clamp to world
if (self.x < ENEMY_WIDTH / 2) self.direction = 1;
if (self.x > 2048 - ENEMY_WIDTH / 2) self.direction = -1;
self.lastX = self.x;
};
return self;
});
// Platform
var Platform = Container.expand(function () {
var self = Container.call(this);
var sprite = self.attachAsset('platform', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = PLATFORM_WIDTH;
self.height = PLATFORM_HEIGHT;
return self;
});
// --- ASSET CLASSES ---
// Player (Astronaut)
var Player = Container.expand(function () {
var self = Container.call(this);
var sprite = self.attachAsset('astronaut', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = PLAYER_WIDTH;
self.height = PLAYER_HEIGHT;
self.vx = 0;
self.vy = 0;
self.isOnGround = false;
self.canDoubleJump = true;
self.lastY = 0;
self.lastX = 0;
self.lastWasIntersectingEnemy = false;
self.lastWasIntersectingRocket = false;
self.jetpackExhaust = null;
self.update = function () {
// Gravity
self.vy += GRAVITY;
// Jetpack exhaust effect (show when jumping or double jumping)
if (self.vy < -2) {
if (!self.jetpackExhaust) {
self.jetpackExhaust = self.attachAsset('star', {
anchorX: 0.5,
anchorY: 0.0,
scaleX: 0.3,
scaleY: 0.3,
y: self.height / 2 + 10
});
self.jetpackExhaust.alpha = 0.7;
}
self.jetpackExhaust.x = 0;
self.jetpackExhaust.y = self.height / 2 + 10;
self.jetpackExhaust.visible = true;
} else if (self.jetpackExhaust) {
self.jetpackExhaust.visible = false;
}
// Move
self.x += self.vx;
self.y += self.vy;
// Clamp to world bounds
if (self.x < PLAYER_WIDTH / 2) self.x = PLAYER_WIDTH / 2;
if (self.x > 2048 - PLAYER_WIDTH / 2) self.x = 2048 - PLAYER_WIDTH / 2;
if (self.y > 2732 - PLAYER_HEIGHT / 2) self.y = 2732 - PLAYER_HEIGHT / 2;
// Platform collision
self.isOnGround = false;
for (var i = 0; i < platforms.length; ++i) {
var p = platforms[i];
// Only check if falling
if (self.vy >= 0 && self.y + self.height / 2 > p.y - p.height / 2 && self.y + self.height / 2 - self.vy <= p.y - p.height / 2) {
// Check horizontal overlap
if (self.x + self.width / 2 > p.x - p.width / 2 && self.x - self.width / 2 < p.x + p.width / 2) {
// Land on platform
self.y = p.y - p.height / 2 - self.height / 2;
self.vy = 0;
self.isOnGround = true;
self.canDoubleJump = true;
isJumping = false;
}
}
}
// Enemy collision
var hitEnemy = null;
for (var i = 0; i < enemies.length; ++i) {
var e = enemies[i];
if (self.intersects(e)) {
// Check if landing on top
if (self.lastY + self.height / 2 <= e.y - e.height / 2 && self.y + self.height / 2 > e.y - e.height / 2 && self.vy > 0) {
// Defeat enemy
hitEnemy = e;
break;
} else {
// Hit from side or below: lose life
if (!self.lastWasIntersectingEnemy) {
loseLife();
self.lastWasIntersectingEnemy = true;
}
}
} else {
self.lastWasIntersectingEnemy = false;
}
}
if (hitEnemy) {
// Remove enemy, bounce up
score += 100;
updateScore();
if (LK.getSound && LK.getSound('enemyDefeat')) LK.getSound('enemyDefeat').play();
hitEnemy.destroy();
enemies.splice(enemies.indexOf(hitEnemy), 1);
self.vy = JUMP_VELOCITY / 1.5;
}
// Collectibles
for (var i = collectibles.length - 1; i >= 0; --i) {
var c = collectibles[i];
if (self.intersects(c)) {
score += 50;
updateScore();
if (LK.getSound && LK.getSound('collect')) LK.getSound('collect').play();
c.destroy();
collectibles.splice(i, 1);
}
}
// Rocket (level end)
if (!self.lastWasIntersectingRocket && self.intersects(rocket)) {
// Win!
LK.showYouWin();
lastYouWin = true;
}
self.lastWasIntersectingRocket = self.intersects(rocket);
// Fall off screen
if (self.y > 2732) {
loseLife();
}
// Update last positions
self.lastY = self.y;
self.lastX = self.x;
};
return self;
});
// Rocket (Level End)
var Rocket = Container.expand(function () {
var self = Container.call(this);
var sprite = self.attachAsset('rocket', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = 180;
self.height = 260;
return self;
});
/****
* Initialize Game
****/
// --- UI ---
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// --- Astro Jump: Space Platformer Main Game Logic ---
// --- GLOBALS ---
var GRAVITY = 0.3; // Low gravity for floaty jumps
var JUMP_VELOCITY = -18; // High jump
var PLAYER_MOVE_SPEED = 12;
var PLAYER_START_LIVES = 3;
var PLAYER_WIDTH = 120;
var PLAYER_HEIGHT = 140;
var ENEMY_WIDTH = 110;
var ENEMY_HEIGHT = 110;
var PLATFORM_WIDTH = 320;
var PLATFORM_HEIGHT = 60;
var LEVEL_END_X = 1800;
var LEVEL_END_Y = 400;
var platforms = [];
var enemies = [];
var collectibles = [];
var player = null;
var rocket = null;
var score = 0;
var lives = PLAYER_START_LIVES;
var scoreTxt = null;
var livesTxt = null;
var isJumping = false;
var isFalling = false;
var jumpKeyDown = false;
var dragNode = null;
var lastGameOver = false;
var lastYouWin = false;
// --- CUSTOM IMAGE BACKGROUND ---
// Replace parallax starfield with a custom image background that scrolls horizontally with the player
// Please upload your background image to LK and use its asset id below:
var bgImage = LK.getAsset('space_bg', {
anchorX: 0,
anchorY: 0,
scaleX: 1,
scaleY: 1,
x: 0,
y: 0
});
game.addChildAt(bgImage, 0); // Always behind everything
// Used to track last player X for background scroll
var lastPlayerX = 0;
// --- UI ---
scoreTxt = new Text2('Score: 0', {
size: 90,
fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Pixel heart asset
livesTxt = new Container();
livesTxt.hearts = [];
for (var i = 0; i < PLAYER_START_LIVES; ++i) {
var heart = LK.getAsset('heart', {
anchorX: 0.5,
anchorY: 0.5
});
heart.x = i * 70;
heart.y = 0;
livesTxt.addChild(heart);
livesTxt.hearts.push(heart);
}
livesTxt.x = 0;
livesTxt.y = 0;
LK.gui.topRight.addChild(livesTxt);
// --- LEVEL SETUP ---
function setupLevel() {
// Clear previous
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 < collectibles.length; ++i) collectibles[i].destroy();
if (player) player.destroy();
if (rocket) rocket.destroy();
platforms = [];
enemies = [];
collectibles = [];
// Platforms
var platData = [{
x: 400,
y: 2200
}, {
x: 800,
y: 1800
}, {
x: 1200,
y: 1500
}, {
x: 1600,
y: 1200
}, {
x: 1800,
y: 900
}, {
x: 1200,
y: 600
}, {
x: LEVEL_END_X,
y: LEVEL_END_Y
}];
for (var i = 0; i < platData.length; ++i) {
var p = new Platform();
p.x = platData[i].x;
p.y = platData[i].y;
platforms.push(p);
game.addChild(p);
}
// Enemies
var enemyData = [{
x: 800,
y: 1700
}, {
x: 1200,
y: 1400
}, {
x: 1600,
y: 1100
}];
for (var i = 0; i < enemyData.length; ++i) {
var e = new Enemy();
e.x = enemyData[i].x;
e.y = enemyData[i].y;
enemies.push(e);
game.addChild(e);
}
// Collectibles
var starData = [{
x: 400,
y: 2100
}, {
x: 1200,
y: 1400
}, {
x: 1800,
y: 800
}];
for (var i = 0; i < starData.length; ++i) {
var c = new Collectible();
c.x = starData[i].x;
c.y = starData[i].y;
collectibles.push(c);
game.addChild(c);
}
// Rocket
rocket = new Rocket();
rocket.x = LEVEL_END_X;
rocket.y = LEVEL_END_Y - 100;
game.addChild(rocket);
// Player
player = new Player();
player.x = 400;
player.y = 2100;
game.addChild(player);
// Reset UI
updateScore();
updateLives();
lastGameOver = false;
lastYouWin = false;
}
setupLevel();
LK.playMusic('chiptune');
// --- UI Update ---
function updateScore() {
scoreTxt.setText('Score: ' + score);
}
function updateLives() {
for (var i = 0; i < livesTxt.hearts.length; ++i) {
livesTxt.hearts[i].visible = i < lives;
}
}
// --- Lose Life ---
function loseLife() {
if (lastGameOver) return;
lives -= 1;
updateLives();
if (lives <= 0) {
LK.showGameOver();
lastGameOver = true;
} else {
// Respawn player
player.x = 400;
player.y = 2100;
player.vx = 0;
player.vy = 0;
}
}
// --- GAME CONTROLS (Touch/Drag) ---
game.down = function (x, y, obj) {
// Only allow controls if player exists
if (!player) return;
// Get screen width and height
var screenWidth = 2048;
var screenHeight = 2732;
// Define control regions
var leftRegion = screenWidth * 0.5;
var jumpRegionY = screenHeight * 0.7; // bottom 30% of screen
// If tap is in bottom 30% of screen, treat as jump
if (y > jumpRegionY) {
if (player.isOnGround) {
player.vy = JUMP_VELOCITY;
player.isOnGround = false;
player.canDoubleJump = true;
if (LK.getSound && LK.getSound('jump')) LK.getSound('jump').play();
} else if (player.canDoubleJump) {
player.vy = JUMP_VELOCITY;
player.canDoubleJump = false;
if (LK.getSound && LK.getSound('jump')) LK.getSound('jump').play();
}
// No horizontal movement on jump tap
// player.vx = 0; // Don't stop movement on jump
return;
}
// If tap is on left half, move left
if (x < leftRegion) {
player.vx = -PLAYER_MOVE_SPEED;
}
// If tap is on right half, move right
else {
player.vx = PLAYER_MOVE_SPEED;
}
};
game.up = function (x, y, obj) {
dragNode = null;
if (player) {
player.vx = 0;
}
};
game.move = function (x, y, obj) {
// No drag-based movement; handled by vx in update
};
// --- GAME LOOP ---
game.update = function () {
// --- Custom background image scroll ---
// Only scroll if player exists
if (player) {
// Calculate horizontal movement since last frame
var dx = player.x - lastPlayerX;
// Scroll background horizontally at a slow rate for parallax effect
// (Adjust 0.3 for desired parallax speed)
bgImage.x -= dx * 0.3;
// Wrap background horizontally for infinite effect
if (bgImage.x <= -2048) {
bgImage.x += 2048;
} else if (bgImage.x >= 2048) {
bgImage.x -= 2048;
}
lastPlayerX = player.x;
}
// Player update
if (player) player.update();
// Enemies update
for (var i = 0; i < enemies.length; ++i) {
enemies[i].update();
}
// Win/Lose handled in player.update
};