/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Coin class
var Coin = Container.expand(function () {
var self = Container.call(this);
var coinSprite = self.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = coinSprite.width;
self.height = coinSprite.height;
return self;
});
// Enemy class
var Enemy = Container.expand(function () {
var self = Container.call(this);
// Attach enemy asset (blue box)
var enemySprite = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0
});
self.width = enemySprite.width;
self.height = enemySprite.height;
// Enemy stays on the ground and moves only a little left-right
self.vx = 0;
self.moveRange = 40; // smaller movement range
self.baseX = 0;
self.update = function () {
// Always keep enemy at ground level
// Find the highest platform directly under the enemy's x position
var bestPlatY = groundY;
for (var i = 0; i < platforms.length; i++) {
var plat = platforms[i];
// Check if enemy is horizontally over the platform
if (self.x + self.width * 0.4 > plat.x && self.x - self.width * 0.4 < plat.x + plat.width) {
if (plat.y < bestPlatY) {
bestPlatY = plat.y;
}
}
}
self.y = bestPlatY - self.height;
// Optionally, add some small movement
if (self.baseX === 0) {
self.baseX = self.x;
}
self.x = self.baseX + Math.sin(LK.ticks / 60) * self.moveRange;
};
return self;
});
// Flag class
var Flag = Container.expand(function () {
var self = Container.call(this);
var flagSprite = self.attachAsset('flag', {
anchorX: 0.5,
anchorY: 1
});
self.width = flagSprite.width;
self.height = flagSprite.height;
return self;
});
// Platform class
var Platform = Container.expand(function () {
var self = Container.call(this);
// Attach platform asset (green box)
var platformSprite = self.attachAsset('platform', {
anchorX: 0,
anchorY: 0
});
self.width = platformSprite.width;
self.height = platformSprite.height;
// Platforms are static, but can be moved for scrolling
self.update = function () {
// Platforms are stationary; do not move.
};
return self;
});
// Player class
var Player = Container.expand(function () {
var self = Container.call(this);
// Attach player asset (red box)
var playerSprite = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 1
});
// Physics properties
self.vx = 0;
self.vy = 0;
self.isOnGround = false;
self.width = playerSprite.width;
self.height = playerSprite.height;
// Jumping state
self.isJumping = false;
// Update method called every tick
self.update = function () {
// Gravity
self.vy += gravity;
// Horizontal movement (auto-run)
self.x += self.vx;
// Vertical movement
self.y += self.vy;
// Prevent falling below ground
if (self.y > groundY) {
self.y = groundY;
self.vy = 0;
self.isOnGround = true;
self.isJumping = false;
} else {
self.isOnGround = false;
}
};
// Jump method
self.jump = function () {
if (self.isOnGround && !self.isJumping) {
self.vy = -jumpStrength;
self.isJumping = true;
self.isOnGround = false;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87ceeb // Sky blue
});
/****
* Game Code
****/
// --- Game constants ---
// Tween plugin for animations
var gravity = 1.2;
var jumpStrength = 32;
var scrollSpeed = 7;
var groundY = 2300; // Y position of the ground/platforms
// --- Game state ---
var player;
var platforms = [];
var enemies = [];
var flag;
var coin;
var lives = 3;
var level = 1;
var isGameOver = false;
var isYouWin = false;
// --- GUI elements ---
var livesTxt = new Text2('♥♥♥', {
size: 100,
fill: 0xFF4444
});
// Anchor left, top
livesTxt.anchor.set(0, 0);
// Place at x=110 to avoid top-left menu, y=0
livesTxt.x = 110;
livesTxt.y = 0;
LK.gui.top.addChild(livesTxt);
// Score variable and score text
var score = 0;
var scoreTxt = new Text2('0', {
size: 100,
fill: 0xffffff
});
scoreTxt.anchor.set(0.5, 0); // center, top
scoreTxt.x = 2048 / 2;
scoreTxt.y = 0;
LK.gui.top.addChild(scoreTxt);
// --- Asset initialization (shapes) ---
// --- Helper functions ---
// Create a platform at (x, y) with optional width
function createPlatform(x, y, width) {
var plat = new Platform();
plat.x = x;
plat.y = y;
if (width) {
plat.width = width;
}
platforms.push(plat);
game.addChild(plat);
return plat;
}
// Create an enemy at (x, y)
function createEnemy(x, y) {
var enemy = new Enemy();
enemy.x = x;
enemy.y = y;
enemies.push(enemy);
game.addChild(enemy);
return enemy;
}
// Reset game state for new game or level
function resetGame() {
// Remove all platforms and enemies
for (var i = 0; i < platforms.length; i++) {
platforms[i].destroy();
}
for (var i = 0; i < enemies.length; i++) {
enemies[i].destroy();
}
if (flag) {
flag.destroy();
flag = null;
}
if (coin) {
coin.destroy();
coin = null;
}
platforms = [];
enemies = [];
// Reset lives
lives = 3;
level = 1;
isGameOver = false;
isYouWin = false;
livesTxt.setText('♥♥♥');
// Reset score
score = 0;
scoreTxt.setText(score);
// Create player
if (player) {
player.destroy();
}
player = new Player();
player.x = 300;
player.y = groundY;
player.vx = scrollSpeed;
game.addChild(player);
// Create level
createLevel(level);
}
// Create a level layout
function createLevel(levelNum) {
// Simple level: ground platform, some floating platforms, coins, enemies
// Ground (very extended)
createPlatform(0, groundY, 20000);
// No floating platforms
// Enemies (on ground, spread out and more of them)
createEnemy(1200, groundY - 160 + 240);
createEnemy(2000, groundY - 160 + 240);
createEnemy(3000, groundY - 160 + 240);
createEnemy(4000, groundY - 160 + 240);
createEnemy(5200, groundY - 160 + 240);
createEnemy(6500, groundY - 160 + 240);
createEnemy(7500, groundY - 160 + 240);
// End flag (no floating platform needed)
// Place flag much farther to the right and keep it stationary
flag = new Flag();
flag.x = 8000;
flag.y = groundY;
game.addChild(flag);
}
// --- Collision detection ---
function rectsIntersect(a, b) {
return a.x - a.width * 0.5 < b.x + b.width * 0.5 && a.x + a.width * 0.5 > b.x - b.width * 0.5 && a.y - a.height < b.y && a.y > b.y - b.height;
}
// --- Touch controls ---
// Touch anywhere to jump
game.down = function (x, y, obj) {
if (isGameOver || isYouWin) {
return;
}
player.jump();
};
// --- Main game update loop ---
game.update = function () {
if (isGameOver || isYouWin) {
return;
}
// Update player
player.update();
// Camera: keep player at 1/3 of screen, scroll world
var cameraX = player.x - 600;
if (cameraX < 0) {
cameraX = 0;
}
// Move the game container so the player is always followed by the camera
game.x = -cameraX;
// Update platforms
for (var i = platforms.length - 1; i >= 0; i--) {
var plat = platforms[i];
plat.update();
// Remove platforms that are off screen
if (plat.x + plat.width < cameraX - 200) {
plat.destroy();
platforms.splice(i, 1);
}
}
// Update enemies
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
enemy.update();
// Remove enemies that are off screen
if (enemy.x < cameraX - 200) {
enemy.destroy();
enemies.splice(i, 1);
continue;
}
// Player hits enemy (from above)
if (rectsIntersect(player, enemy) && player.vy > 0 && player.y - player.height < enemy.y - enemy.height + 30) {
// Defeat enemy
enemy.destroy();
enemies.splice(i, 1);
player.vy = -jumpStrength * 0.7; // Bounce
// Increase score
score += 1;
scoreTxt.setText(score);
}
// Player collides with enemy (side or bottom)
else if (rectsIntersect(player, enemy)) {
loseLife();
}
}
// Platform collision (only check platforms under player)
var onPlatform = false;
for (var i = 0; i < platforms.length; i++) {
var plat = platforms[i];
// Check if player is falling and above platform
if (player.vy >= 0 && player.x + player.width * 0.4 > plat.x && player.x - player.width * 0.4 < plat.x + plat.width && player.y > plat.y - 10 && player.y < plat.y + 40) {
// Land on platform
player.y = plat.y;
player.vy = 0;
player.isOnGround = true;
player.isJumping = false;
onPlatform = true;
break;
}
}
if (!onPlatform && player.y < groundY) {
player.isOnGround = false;
}
// Check for falling off screen
if (player.y > 2732 + 200) {
loseLife();
}
// Check for level end (reaching far right)
if (flag && rectsIntersect(player, flag)) {
isYouWin = true;
LK.showYouWin();
}
};
// Lose a life and handle game over
function loseLife() {
if (isGameOver) {
return;
}
lives -= 1;
if (lives < 0) {
lives = 0;
}
var livesStr = '';
for (var i = 0; i < lives; i++) {
livesStr += '♥';
}
livesTxt.setText(livesStr);
// Flash screen red
LK.effects.flashScreen(0xff0000, 800);
if (lives <= 0) {
isGameOver = true;
LK.showGameOver();
} else {
// Reset player position
player.x = 300;
player.y = groundY;
player.vx = scrollSpeed;
player.vy = 0;
}
}
// --- Start game ---
resetGame(); /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Coin class
var Coin = Container.expand(function () {
var self = Container.call(this);
var coinSprite = self.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = coinSprite.width;
self.height = coinSprite.height;
return self;
});
// Enemy class
var Enemy = Container.expand(function () {
var self = Container.call(this);
// Attach enemy asset (blue box)
var enemySprite = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0
});
self.width = enemySprite.width;
self.height = enemySprite.height;
// Enemy stays on the ground and moves only a little left-right
self.vx = 0;
self.moveRange = 40; // smaller movement range
self.baseX = 0;
self.update = function () {
// Always keep enemy at ground level
// Find the highest platform directly under the enemy's x position
var bestPlatY = groundY;
for (var i = 0; i < platforms.length; i++) {
var plat = platforms[i];
// Check if enemy is horizontally over the platform
if (self.x + self.width * 0.4 > plat.x && self.x - self.width * 0.4 < plat.x + plat.width) {
if (plat.y < bestPlatY) {
bestPlatY = plat.y;
}
}
}
self.y = bestPlatY - self.height;
// Optionally, add some small movement
if (self.baseX === 0) {
self.baseX = self.x;
}
self.x = self.baseX + Math.sin(LK.ticks / 60) * self.moveRange;
};
return self;
});
// Flag class
var Flag = Container.expand(function () {
var self = Container.call(this);
var flagSprite = self.attachAsset('flag', {
anchorX: 0.5,
anchorY: 1
});
self.width = flagSprite.width;
self.height = flagSprite.height;
return self;
});
// Platform class
var Platform = Container.expand(function () {
var self = Container.call(this);
// Attach platform asset (green box)
var platformSprite = self.attachAsset('platform', {
anchorX: 0,
anchorY: 0
});
self.width = platformSprite.width;
self.height = platformSprite.height;
// Platforms are static, but can be moved for scrolling
self.update = function () {
// Platforms are stationary; do not move.
};
return self;
});
// Player class
var Player = Container.expand(function () {
var self = Container.call(this);
// Attach player asset (red box)
var playerSprite = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 1
});
// Physics properties
self.vx = 0;
self.vy = 0;
self.isOnGround = false;
self.width = playerSprite.width;
self.height = playerSprite.height;
// Jumping state
self.isJumping = false;
// Update method called every tick
self.update = function () {
// Gravity
self.vy += gravity;
// Horizontal movement (auto-run)
self.x += self.vx;
// Vertical movement
self.y += self.vy;
// Prevent falling below ground
if (self.y > groundY) {
self.y = groundY;
self.vy = 0;
self.isOnGround = true;
self.isJumping = false;
} else {
self.isOnGround = false;
}
};
// Jump method
self.jump = function () {
if (self.isOnGround && !self.isJumping) {
self.vy = -jumpStrength;
self.isJumping = true;
self.isOnGround = false;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87ceeb // Sky blue
});
/****
* Game Code
****/
// --- Game constants ---
// Tween plugin for animations
var gravity = 1.2;
var jumpStrength = 32;
var scrollSpeed = 7;
var groundY = 2300; // Y position of the ground/platforms
// --- Game state ---
var player;
var platforms = [];
var enemies = [];
var flag;
var coin;
var lives = 3;
var level = 1;
var isGameOver = false;
var isYouWin = false;
// --- GUI elements ---
var livesTxt = new Text2('♥♥♥', {
size: 100,
fill: 0xFF4444
});
// Anchor left, top
livesTxt.anchor.set(0, 0);
// Place at x=110 to avoid top-left menu, y=0
livesTxt.x = 110;
livesTxt.y = 0;
LK.gui.top.addChild(livesTxt);
// Score variable and score text
var score = 0;
var scoreTxt = new Text2('0', {
size: 100,
fill: 0xffffff
});
scoreTxt.anchor.set(0.5, 0); // center, top
scoreTxt.x = 2048 / 2;
scoreTxt.y = 0;
LK.gui.top.addChild(scoreTxt);
// --- Asset initialization (shapes) ---
// --- Helper functions ---
// Create a platform at (x, y) with optional width
function createPlatform(x, y, width) {
var plat = new Platform();
plat.x = x;
plat.y = y;
if (width) {
plat.width = width;
}
platforms.push(plat);
game.addChild(plat);
return plat;
}
// Create an enemy at (x, y)
function createEnemy(x, y) {
var enemy = new Enemy();
enemy.x = x;
enemy.y = y;
enemies.push(enemy);
game.addChild(enemy);
return enemy;
}
// Reset game state for new game or level
function resetGame() {
// Remove all platforms and enemies
for (var i = 0; i < platforms.length; i++) {
platforms[i].destroy();
}
for (var i = 0; i < enemies.length; i++) {
enemies[i].destroy();
}
if (flag) {
flag.destroy();
flag = null;
}
if (coin) {
coin.destroy();
coin = null;
}
platforms = [];
enemies = [];
// Reset lives
lives = 3;
level = 1;
isGameOver = false;
isYouWin = false;
livesTxt.setText('♥♥♥');
// Reset score
score = 0;
scoreTxt.setText(score);
// Create player
if (player) {
player.destroy();
}
player = new Player();
player.x = 300;
player.y = groundY;
player.vx = scrollSpeed;
game.addChild(player);
// Create level
createLevel(level);
}
// Create a level layout
function createLevel(levelNum) {
// Simple level: ground platform, some floating platforms, coins, enemies
// Ground (very extended)
createPlatform(0, groundY, 20000);
// No floating platforms
// Enemies (on ground, spread out and more of them)
createEnemy(1200, groundY - 160 + 240);
createEnemy(2000, groundY - 160 + 240);
createEnemy(3000, groundY - 160 + 240);
createEnemy(4000, groundY - 160 + 240);
createEnemy(5200, groundY - 160 + 240);
createEnemy(6500, groundY - 160 + 240);
createEnemy(7500, groundY - 160 + 240);
// End flag (no floating platform needed)
// Place flag much farther to the right and keep it stationary
flag = new Flag();
flag.x = 8000;
flag.y = groundY;
game.addChild(flag);
}
// --- Collision detection ---
function rectsIntersect(a, b) {
return a.x - a.width * 0.5 < b.x + b.width * 0.5 && a.x + a.width * 0.5 > b.x - b.width * 0.5 && a.y - a.height < b.y && a.y > b.y - b.height;
}
// --- Touch controls ---
// Touch anywhere to jump
game.down = function (x, y, obj) {
if (isGameOver || isYouWin) {
return;
}
player.jump();
};
// --- Main game update loop ---
game.update = function () {
if (isGameOver || isYouWin) {
return;
}
// Update player
player.update();
// Camera: keep player at 1/3 of screen, scroll world
var cameraX = player.x - 600;
if (cameraX < 0) {
cameraX = 0;
}
// Move the game container so the player is always followed by the camera
game.x = -cameraX;
// Update platforms
for (var i = platforms.length - 1; i >= 0; i--) {
var plat = platforms[i];
plat.update();
// Remove platforms that are off screen
if (plat.x + plat.width < cameraX - 200) {
plat.destroy();
platforms.splice(i, 1);
}
}
// Update enemies
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
enemy.update();
// Remove enemies that are off screen
if (enemy.x < cameraX - 200) {
enemy.destroy();
enemies.splice(i, 1);
continue;
}
// Player hits enemy (from above)
if (rectsIntersect(player, enemy) && player.vy > 0 && player.y - player.height < enemy.y - enemy.height + 30) {
// Defeat enemy
enemy.destroy();
enemies.splice(i, 1);
player.vy = -jumpStrength * 0.7; // Bounce
// Increase score
score += 1;
scoreTxt.setText(score);
}
// Player collides with enemy (side or bottom)
else if (rectsIntersect(player, enemy)) {
loseLife();
}
}
// Platform collision (only check platforms under player)
var onPlatform = false;
for (var i = 0; i < platforms.length; i++) {
var plat = platforms[i];
// Check if player is falling and above platform
if (player.vy >= 0 && player.x + player.width * 0.4 > plat.x && player.x - player.width * 0.4 < plat.x + plat.width && player.y > plat.y - 10 && player.y < plat.y + 40) {
// Land on platform
player.y = plat.y;
player.vy = 0;
player.isOnGround = true;
player.isJumping = false;
onPlatform = true;
break;
}
}
if (!onPlatform && player.y < groundY) {
player.isOnGround = false;
}
// Check for falling off screen
if (player.y > 2732 + 200) {
loseLife();
}
// Check for level end (reaching far right)
if (flag && rectsIntersect(player, flag)) {
isYouWin = true;
LK.showYouWin();
}
};
// Lose a life and handle game over
function loseLife() {
if (isGameOver) {
return;
}
lives -= 1;
if (lives < 0) {
lives = 0;
}
var livesStr = '';
for (var i = 0; i < lives; i++) {
livesStr += '♥';
}
livesTxt.setText(livesStr);
// Flash screen red
LK.effects.flashScreen(0xff0000, 800);
if (lives <= 0) {
isGameOver = true;
LK.showGameOver();
} else {
// Reset player position
player.x = 300;
player.y = groundY;
player.vx = scrollSpeed;
player.vy = 0;
}
}
// --- Start game ---
resetGame();