/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var Button = Container.expand(function () { var self = Container.call(this); // Create button var buttonShape = self.attachAsset('platform', { anchorX: 0.5, anchorY: 0.5, width: 100, height: 100 }); // Text for button var buttonText = new Text2('', { size: 50, fill: 0xFFFFFF }); buttonText.anchor.set(0.5, 0.5); self.addChild(buttonText); // Setup button self.setup = function (text, color) { buttonText.setText(text); buttonShape.tint = color || 0x444444; }; // Event handlers self.down = function (x, y, obj) { buttonShape.alpha = 0.7; if (self.onPress) { self.onPress(); } }; self.up = function (x, y, obj) { buttonShape.alpha = 1; }; return self; }); var Coin = Container.expand(function () { var self = Container.call(this); // Create coin sprite var coinSprite = self.attachAsset('coin', { anchorX: 0.5, anchorY: 0.5 }); // Add spinning animation self.update = function () { coinSprite.rotation += 0.05; }; // Collect animation self.collect = function () { // Play collection sound LK.getSound('coin').play(); // Animate coin collection tween(self, { scaleX: 0, scaleY: 0, alpha: 0 }, { duration: 300, easing: tween.easeOut, onFinish: function onFinish() { self.destroy(); } }); }; return self; }); var Enemy = Container.expand(function () { var self = Container.call(this); // Create enemy sprite var enemySprite = self.attachAsset('enemy', { anchorX: 0.5, anchorY: 0.5 }); // Physics and behavior properties self.vx = -2; // Initial direction self.patrolDistance = 300; self.startX = 0; // Initialize patrol points self.setup = function (startX) { self.startX = startX; self.leftBound = startX - self.patrolDistance / 2; self.rightBound = startX + self.patrolDistance / 2; self.x = startX; }; // Update enemy behavior self.update = function () { // Move horizontally self.x += self.vx; // Change direction if reached patrol bounds if (self.x <= self.leftBound) { self.vx = Math.abs(self.vx); } else if (self.x >= self.rightBound) { self.vx = -Math.abs(self.vx); } }; return self; }); var HeartDisplay = Container.expand(function () { var self = Container.call(this); var hearts = []; var maxHearts = 3; // Initialize hearts self.init = function () { for (var i = 0; i < maxHearts; i++) { var heart = self.attachAsset('heart', { anchorX: 0.5, anchorY: 0.5, x: i * 50 }); hearts.push(heart); } }; // Update hearts based on current health self.updateHearts = function (health) { for (var i = 0; i < maxHearts; i++) { hearts[i].visible = i < health; } }; return self; }); var Hero = Container.expand(function () { var self = Container.call(this); // Create hero sprite var heroSprite = self.attachAsset('hero', { anchorX: 0.5, anchorY: 0.5 }); // Physics properties self.vx = 0; self.vy = 0; self.onGround = false; self.jumpForce = -30; self.gravity = 1; self.maxVy = 20; self.speed = 10; self.health = 3; // Flag to track if hero is moving self.isMovingRight = false; self.isMovingLeft = false; // Used to track if jump button is pressed self.isJumping = false; // Update hero physics self.update = function () { // Apply movement based on direction if (self.isMovingRight) { self.vx = self.speed; } else if (self.isMovingLeft) { self.vx = -self.speed; } else { self.vx = 0; } // Try to jump if jump button is pressed if (self.isJumping && self.onGround) { self.jump(); } // Apply gravity if (!self.onGround) { self.vy += self.gravity; if (self.vy > self.maxVy) { self.vy = self.maxVy; } } // Update position self.x += self.vx; self.y += self.vy; // Reset onGround flag every frame // Will be set to true during collision detection if applicable self.onGround = false; }; // Handle jump self.jump = function () { // Check if jump button is pressed or if isJumping flag is set if (self.onGround && self.isJumping) { self.vy = self.jumpForce; self.onGround = false; LK.getSound('jump').play(); } }; // Handle collision with platforms self.handlePlatformCollision = function (platform) { // Get bounding boxes var heroBox = { x: self.x - heroSprite.width / 2, y: self.y - heroSprite.height / 2, width: heroSprite.width, height: heroSprite.height }; var platformBox = { x: platform.x - platform.width / 2, y: platform.y - platform.height / 2, width: platform.width, height: platform.height }; // Calculate overlap var overlapX = Math.max(0, Math.min(heroBox.x + heroBox.width, platformBox.x + platformBox.width) - Math.max(heroBox.x, platformBox.x)); var overlapY = Math.max(0, Math.min(heroBox.y + heroBox.height, platformBox.y + platformBox.height) - Math.max(heroBox.y, platformBox.y)); // Handle collision if there is overlap if (overlapX > 0 && overlapY > 0) { // Determine if collision is more horizontal or vertical if (overlapX > overlapY) { // Vertical collision // Coming from above if (heroBox.y + heroBox.height / 2 < platformBox.y + platformBox.height / 2) { self.y = platformBox.y - heroBox.height / 2; self.vy = 0; self.onGround = true; } // Coming from below else if (self.vy < 0) { self.y = platformBox.y + platformBox.height + heroBox.height / 2; self.vy = 0; } } else { // Horizontal collision if (heroBox.x + heroBox.width / 2 < platformBox.x + platformBox.width / 2) { self.x = platformBox.x - heroBox.width / 2; } else { self.x = platformBox.x + platformBox.width + heroBox.width / 2; } self.vx = 0; } return true; } return false; }; // Handle damage self.takeDamage = function () { if (!self.invulnerable) { self.health--; self.invulnerable = true; // Flash effect LK.effects.flashObject(self, 0xFF0000, 1000); // Make vulnerable again after 1.5 seconds LK.setTimeout(function () { self.invulnerable = false; }, 1500); // Play hit sound LK.getSound('hit').play(); // Update heart display updateUI(); // Check for game over if (self.health <= 0) { LK.showGameOver(); } } }; return self; }); var Platform = Container.expand(function () { var self = Container.call(this); // Create platform sprite var platformSprite = self.attachAsset('platform', { anchorX: 0.5, anchorY: 0.5 }); return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 // Always backgroundColor is black }); /**** * Game Code ****/ // Background music // Sound effects // Collectible assets // Character assets // Platform assets // Game state variables var hero; var platforms = []; var enemies = []; var coins = []; var level = 1; var score = 0; var cameraOffset = 0; var gameStarted = false; var leftButton; var rightButton; var jumpButton; // UI elements var scoreTxt; var levelTxt; var healthTxt; var heartDisplay; // Level configuration var levelConfig = { // Platform configurations for different levels platforms: [ // Level 1 [{ x: 300, y: 2500 }, { x: 600, y: 2300 }, { x: 900, y: 2100 }, { x: 1200, y: 2300 }, { x: 1500, y: 2100 }, { x: 1800, y: 1900 }, { x: 300, y: 1700 }, { x: 600, y: 1500 }, { x: 1200, y: 1500 }, { x: 1800, y: 1300 }, { x: 300, y: 1100 }, { x: 600, y: 900 }, { x: 900, y: 700 }, { x: 1200, y: 500 }, { x: 1500, y: 300 }, { x: 1800, y: 100 }]], // Enemy configurations enemies: [ // Level 1 [{ x: 900, y: 2070 }, { x: 1500, y: 2070 }, { x: 600, y: 1470 }, { x: 1200, y: 1470 }, { x: 900, y: 670 }]], // Coin configurations coins: [ // Level 1 [{ x: 300, y: 2450 }, { x: 600, y: 2250 }, { x: 900, y: 2050 }, { x: 1200, y: 2250 }, { x: 1500, y: 2050 }, { x: 1800, y: 1850 }, { x: 300, y: 1650 }, { x: 600, y: 1450 }, { x: 1200, y: 1450 }, { x: 1800, y: 1250 }, { x: 300, y: 1050 }, { x: 600, y: 850 }, { x: 900, y: 650 }, { x: 1200, y: 450 }, { x: 1500, y: 250 }, { x: 1800, y: 50 }]] }; // Initialize level function setupLevel() { // Clear existing objects clearLevel(); // Create ground var ground = new Platform(); ground.x = 2048 / 2; ground.y = 2732 - 40; game.addChild(ground); platforms.push(ground); // Create platforms var levelPlatforms = levelConfig.platforms[level - 1] || levelConfig.platforms[0]; for (var i = 0; i < levelPlatforms.length; i++) { var platform = new Platform(); platform.x = levelPlatforms[i].x; platform.y = levelPlatforms[i].y; game.addChild(platform); platforms.push(platform); } // Create enemies var levelEnemies = levelConfig.enemies[level - 1] || levelConfig.enemies[0]; for (var i = 0; i < levelEnemies.length; i++) { var enemy = new Enemy(); enemy.setup(levelEnemies[i].x); enemy.y = levelEnemies[i].y; game.addChild(enemy); enemies.push(enemy); } // Create coins var levelCoins = levelConfig.coins[level - 1] || levelConfig.coins[0]; for (var i = 0; i < levelCoins.length; i++) { var coin = new Coin(); coin.x = levelCoins[i].x; coin.y = levelCoins[i].y; game.addChild(coin); coins.push(coin); } // Create hero hero = new Hero(); // Store the initial spawn platform for respawn var initialSpawnPlatform = platforms[1] || platforms[0]; // platforms[1] is the first non-ground platform if (initialSpawnPlatform) { hero.x = initialSpawnPlatform.x; hero.y = initialSpawnPlatform.y - 70; } else { hero.x = 200; hero.y = 2400; } game.addChild(hero); // Update score display updateUI(); } // Clear all level objects function clearLevel() { // Remove platforms for (var i = platforms.length - 1; i >= 0; i--) { platforms[i].destroy(); } platforms = []; // Remove enemies for (var i = enemies.length - 1; i >= 0; i--) { enemies[i].destroy(); } enemies = []; // Remove coins for (var i = coins.length - 1; i >= 0; i--) { coins[i].destroy(); } coins = []; // Remove hero if exists if (hero) { hero.destroy(); hero = null; } } // Update UI displays function updateUI() { scoreTxt.setText("Score: " + score); levelTxt.setText("Level: " + level); healthTxt.setText("Health: " + (hero ? hero.health : 0)); if (heartDisplay && hero) { heartDisplay.updateHearts(hero.health); } } // Setup controls function setupControls() { // Left movement button leftButton = new Button(); leftButton.setup("<", 0x4444FF); leftButton.x = 150; leftButton.y = 2532; leftButton.onPress = function () { hero.isMovingLeft = true; hero.isMovingRight = false; }; leftButton.up = function () { hero.isMovingLeft = false; }; game.addChild(leftButton); // Right movement button rightButton = new Button(); rightButton.setup(">", 0x4444FF); rightButton.x = 300; rightButton.y = 2532; rightButton.onPress = function () { hero.isMovingRight = true; hero.isMovingLeft = false; }; rightButton.up = function () { hero.isMovingRight = false; }; game.addChild(rightButton); // Jump button jumpButton = new Button(); jumpButton.setup("^", 0xFF4444); jumpButton.x = 450; // Position next to the right movement button jumpButton.y = 2532; jumpButton.onPress = function () { hero.isJumping = true; // We don't need to call hero.jump() here, it will be handled in the update loop }; jumpButton.up = function () { hero.isJumping = false; }; game.addChild(jumpButton); } // Setup UI function setupUI() { // Score display scoreTxt = new Text2("Score: 0", { size: 60, fill: 0xFFFFFF }); scoreTxt.anchor.set(0, 0); LK.gui.topRight.addChild(scoreTxt); // Add 'BetlSrc' label to the top right corner var betlsrcLabel = new Text2("BetlSrc", { size: 60, fill: 0xFFFFFF }); betlsrcLabel.anchor.set(1, 0); betlsrcLabel.x = -20; // Slightly inset from the right edge betlsrcLabel.y = 0; LK.gui.topRight.addChild(betlsrcLabel); // Level display levelTxt = new Text2("Level: 1", { size: 60, fill: 0xFFFFFF }); levelTxt.anchor.set(0.5, 0); LK.gui.top.addChild(levelTxt); // Health display healthTxt = new Text2("Health: 3", { size: 60, fill: 0xFFFFFF }); healthTxt.anchor.set(1, 0); LK.gui.topLeft.addChild(healthTxt); healthTxt.x = 250; // Move further right as requested // Heart display heartDisplay = new HeartDisplay(); heartDisplay.x = 200; heartDisplay.y = 100; heartDisplay.init(); LK.gui.topLeft.addChild(heartDisplay); // Make sure hearts are visible and properly spaced heartDisplay.updateHearts(3); } // Initialize game function initGame() { // Set score to zero score = 0; LK.setScore(0); // Setup UI elements setupUI(); // Setup level setupLevel(); // Setup controls setupControls(); // Play background music LK.playMusic('bgmusic', { fade: { start: 0, end: 0.7, duration: 1000 } }); // Mark game as started gameStarted = true; } // Handle collisions function handleCollisions() { // Hero-platform collisions for (var i = 0; i < platforms.length; i++) { hero.handlePlatformCollision(platforms[i]); } // Hero-enemy collisions for (var i = enemies.length - 1; i >= 0; i--) { if (hero.intersects(enemies[i])) { // Check if hero is jumping on enemy from above if (hero.vy > 0 && hero.y < enemies[i].y - 30) { // Destroy enemy enemies[i].destroy(); enemies.splice(i, 1); // Bounce hero hero.vy = hero.jumpForce * 0.6; // Add score score += 100; LK.setScore(score); updateUI(); } else { // Hero takes damage hero.takeDamage(); updateUI(); } } } // Hero-coin collisions for (var i = coins.length - 1; i >= 0; i--) { if (hero.intersects(coins[i])) { // Collect coin coins[i].collect(); coins.splice(i, 1); // Add score score += 10; LK.setScore(score); updateUI(); } } // Check for level completion (all coins collected) if (coins.length === 0) { // Level completed level++; // Check if player completed all levels if (level > levelConfig.platforms.length) { // Game completed LK.showYouWin(); } else { // Setup next level setupLevel(); } } } // Keep hero within bounds function enforceWorldBounds() { // Keep hero within horizontal bounds if (hero.x < 50) { hero.x = 50; } else if (hero.x > 2048 - 50) { hero.x = 2048 - 50; } // Check if hero fell off the bottom if (hero.y > 2732 + 100) { hero.takeDamage(); // Respawn on the initial spawn platform if (typeof initialSpawnPlatform !== "undefined" && initialSpawnPlatform) { hero.x = initialSpawnPlatform.x; hero.y = initialSpawnPlatform.y - 70; } else { // fallback if not set hero.x = 200; hero.y = 2400; } hero.vx = 0; hero.vy = 0; updateUI(); } // Check if hero reached the top (level complete) if (hero.y < 0) { // Level completed level++; // Check if player completed all levels if (level > levelConfig.platforms.length) { // Game completed LK.showYouWin(); } else { // Setup next level setupLevel(); } } } // Handle global touch events game.down = function (x, y, obj) { if (!gameStarted) { initGame(); } }; // Game update loop game.update = function () { if (!gameStarted) { return; } // Update hero if (hero) { hero.update(); } // Update enemies for (var i = 0; i < enemies.length; i++) { enemies[i].update(); } // Update coins for (var i = 0; i < coins.length; i++) { coins[i].update(); } // Handle collisions handleCollisions(); // Enforce world boundaries enforceWorldBounds(); }; // Setup initial "tap to start" message var startText = new Text2("Tap to Start", { size: 100, fill: 0xFFFFFF }); startText.anchor.set(0.5, 0.5); startText.x = 2048 / 2; startText.y = 2732 / 2; game.addChild(startText); // Remove start text when game starts LK.setInterval(function () { if (gameStarted && startText.parent) { startText.destroy(); } }, 100);
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Button = Container.expand(function () {
var self = Container.call(this);
// Create button
var buttonShape = self.attachAsset('platform', {
anchorX: 0.5,
anchorY: 0.5,
width: 100,
height: 100
});
// Text for button
var buttonText = new Text2('', {
size: 50,
fill: 0xFFFFFF
});
buttonText.anchor.set(0.5, 0.5);
self.addChild(buttonText);
// Setup button
self.setup = function (text, color) {
buttonText.setText(text);
buttonShape.tint = color || 0x444444;
};
// Event handlers
self.down = function (x, y, obj) {
buttonShape.alpha = 0.7;
if (self.onPress) {
self.onPress();
}
};
self.up = function (x, y, obj) {
buttonShape.alpha = 1;
};
return self;
});
var Coin = Container.expand(function () {
var self = Container.call(this);
// Create coin sprite
var coinSprite = self.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5
});
// Add spinning animation
self.update = function () {
coinSprite.rotation += 0.05;
};
// Collect animation
self.collect = function () {
// Play collection sound
LK.getSound('coin').play();
// Animate coin collection
tween(self, {
scaleX: 0,
scaleY: 0,
alpha: 0
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
self.destroy();
}
});
};
return self;
});
var Enemy = Container.expand(function () {
var self = Container.call(this);
// Create enemy sprite
var enemySprite = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
// Physics and behavior properties
self.vx = -2; // Initial direction
self.patrolDistance = 300;
self.startX = 0;
// Initialize patrol points
self.setup = function (startX) {
self.startX = startX;
self.leftBound = startX - self.patrolDistance / 2;
self.rightBound = startX + self.patrolDistance / 2;
self.x = startX;
};
// Update enemy behavior
self.update = function () {
// Move horizontally
self.x += self.vx;
// Change direction if reached patrol bounds
if (self.x <= self.leftBound) {
self.vx = Math.abs(self.vx);
} else if (self.x >= self.rightBound) {
self.vx = -Math.abs(self.vx);
}
};
return self;
});
var HeartDisplay = Container.expand(function () {
var self = Container.call(this);
var hearts = [];
var maxHearts = 3;
// Initialize hearts
self.init = function () {
for (var i = 0; i < maxHearts; i++) {
var heart = self.attachAsset('heart', {
anchorX: 0.5,
anchorY: 0.5,
x: i * 50
});
hearts.push(heart);
}
};
// Update hearts based on current health
self.updateHearts = function (health) {
for (var i = 0; i < maxHearts; i++) {
hearts[i].visible = i < health;
}
};
return self;
});
var Hero = Container.expand(function () {
var self = Container.call(this);
// Create hero sprite
var heroSprite = self.attachAsset('hero', {
anchorX: 0.5,
anchorY: 0.5
});
// Physics properties
self.vx = 0;
self.vy = 0;
self.onGround = false;
self.jumpForce = -30;
self.gravity = 1;
self.maxVy = 20;
self.speed = 10;
self.health = 3;
// Flag to track if hero is moving
self.isMovingRight = false;
self.isMovingLeft = false;
// Used to track if jump button is pressed
self.isJumping = false;
// Update hero physics
self.update = function () {
// Apply movement based on direction
if (self.isMovingRight) {
self.vx = self.speed;
} else if (self.isMovingLeft) {
self.vx = -self.speed;
} else {
self.vx = 0;
}
// Try to jump if jump button is pressed
if (self.isJumping && self.onGround) {
self.jump();
}
// Apply gravity
if (!self.onGround) {
self.vy += self.gravity;
if (self.vy > self.maxVy) {
self.vy = self.maxVy;
}
}
// Update position
self.x += self.vx;
self.y += self.vy;
// Reset onGround flag every frame
// Will be set to true during collision detection if applicable
self.onGround = false;
};
// Handle jump
self.jump = function () {
// Check if jump button is pressed or if isJumping flag is set
if (self.onGround && self.isJumping) {
self.vy = self.jumpForce;
self.onGround = false;
LK.getSound('jump').play();
}
};
// Handle collision with platforms
self.handlePlatformCollision = function (platform) {
// Get bounding boxes
var heroBox = {
x: self.x - heroSprite.width / 2,
y: self.y - heroSprite.height / 2,
width: heroSprite.width,
height: heroSprite.height
};
var platformBox = {
x: platform.x - platform.width / 2,
y: platform.y - platform.height / 2,
width: platform.width,
height: platform.height
};
// Calculate overlap
var overlapX = Math.max(0, Math.min(heroBox.x + heroBox.width, platformBox.x + platformBox.width) - Math.max(heroBox.x, platformBox.x));
var overlapY = Math.max(0, Math.min(heroBox.y + heroBox.height, platformBox.y + platformBox.height) - Math.max(heroBox.y, platformBox.y));
// Handle collision if there is overlap
if (overlapX > 0 && overlapY > 0) {
// Determine if collision is more horizontal or vertical
if (overlapX > overlapY) {
// Vertical collision
// Coming from above
if (heroBox.y + heroBox.height / 2 < platformBox.y + platformBox.height / 2) {
self.y = platformBox.y - heroBox.height / 2;
self.vy = 0;
self.onGround = true;
}
// Coming from below
else if (self.vy < 0) {
self.y = platformBox.y + platformBox.height + heroBox.height / 2;
self.vy = 0;
}
} else {
// Horizontal collision
if (heroBox.x + heroBox.width / 2 < platformBox.x + platformBox.width / 2) {
self.x = platformBox.x - heroBox.width / 2;
} else {
self.x = platformBox.x + platformBox.width + heroBox.width / 2;
}
self.vx = 0;
}
return true;
}
return false;
};
// Handle damage
self.takeDamage = function () {
if (!self.invulnerable) {
self.health--;
self.invulnerable = true;
// Flash effect
LK.effects.flashObject(self, 0xFF0000, 1000);
// Make vulnerable again after 1.5 seconds
LK.setTimeout(function () {
self.invulnerable = false;
}, 1500);
// Play hit sound
LK.getSound('hit').play();
// Update heart display
updateUI();
// Check for game over
if (self.health <= 0) {
LK.showGameOver();
}
}
};
return self;
});
var Platform = Container.expand(function () {
var self = Container.call(this);
// Create platform sprite
var platformSprite = self.attachAsset('platform', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000 // Always backgroundColor is black
});
/****
* Game Code
****/
// Background music
// Sound effects
// Collectible assets
// Character assets
// Platform assets
// Game state variables
var hero;
var platforms = [];
var enemies = [];
var coins = [];
var level = 1;
var score = 0;
var cameraOffset = 0;
var gameStarted = false;
var leftButton;
var rightButton;
var jumpButton;
// UI elements
var scoreTxt;
var levelTxt;
var healthTxt;
var heartDisplay;
// Level configuration
var levelConfig = {
// Platform configurations for different levels
platforms: [
// Level 1
[{
x: 300,
y: 2500
}, {
x: 600,
y: 2300
}, {
x: 900,
y: 2100
}, {
x: 1200,
y: 2300
}, {
x: 1500,
y: 2100
}, {
x: 1800,
y: 1900
}, {
x: 300,
y: 1700
}, {
x: 600,
y: 1500
}, {
x: 1200,
y: 1500
}, {
x: 1800,
y: 1300
}, {
x: 300,
y: 1100
}, {
x: 600,
y: 900
}, {
x: 900,
y: 700
}, {
x: 1200,
y: 500
}, {
x: 1500,
y: 300
}, {
x: 1800,
y: 100
}]],
// Enemy configurations
enemies: [
// Level 1
[{
x: 900,
y: 2070
}, {
x: 1500,
y: 2070
}, {
x: 600,
y: 1470
}, {
x: 1200,
y: 1470
}, {
x: 900,
y: 670
}]],
// Coin configurations
coins: [
// Level 1
[{
x: 300,
y: 2450
}, {
x: 600,
y: 2250
}, {
x: 900,
y: 2050
}, {
x: 1200,
y: 2250
}, {
x: 1500,
y: 2050
}, {
x: 1800,
y: 1850
}, {
x: 300,
y: 1650
}, {
x: 600,
y: 1450
}, {
x: 1200,
y: 1450
}, {
x: 1800,
y: 1250
}, {
x: 300,
y: 1050
}, {
x: 600,
y: 850
}, {
x: 900,
y: 650
}, {
x: 1200,
y: 450
}, {
x: 1500,
y: 250
}, {
x: 1800,
y: 50
}]]
};
// Initialize level
function setupLevel() {
// Clear existing objects
clearLevel();
// Create ground
var ground = new Platform();
ground.x = 2048 / 2;
ground.y = 2732 - 40;
game.addChild(ground);
platforms.push(ground);
// Create platforms
var levelPlatforms = levelConfig.platforms[level - 1] || levelConfig.platforms[0];
for (var i = 0; i < levelPlatforms.length; i++) {
var platform = new Platform();
platform.x = levelPlatforms[i].x;
platform.y = levelPlatforms[i].y;
game.addChild(platform);
platforms.push(platform);
}
// Create enemies
var levelEnemies = levelConfig.enemies[level - 1] || levelConfig.enemies[0];
for (var i = 0; i < levelEnemies.length; i++) {
var enemy = new Enemy();
enemy.setup(levelEnemies[i].x);
enemy.y = levelEnemies[i].y;
game.addChild(enemy);
enemies.push(enemy);
}
// Create coins
var levelCoins = levelConfig.coins[level - 1] || levelConfig.coins[0];
for (var i = 0; i < levelCoins.length; i++) {
var coin = new Coin();
coin.x = levelCoins[i].x;
coin.y = levelCoins[i].y;
game.addChild(coin);
coins.push(coin);
}
// Create hero
hero = new Hero();
// Store the initial spawn platform for respawn
var initialSpawnPlatform = platforms[1] || platforms[0]; // platforms[1] is the first non-ground platform
if (initialSpawnPlatform) {
hero.x = initialSpawnPlatform.x;
hero.y = initialSpawnPlatform.y - 70;
} else {
hero.x = 200;
hero.y = 2400;
}
game.addChild(hero);
// Update score display
updateUI();
}
// Clear all level objects
function clearLevel() {
// Remove platforms
for (var i = platforms.length - 1; i >= 0; i--) {
platforms[i].destroy();
}
platforms = [];
// Remove enemies
for (var i = enemies.length - 1; i >= 0; i--) {
enemies[i].destroy();
}
enemies = [];
// Remove coins
for (var i = coins.length - 1; i >= 0; i--) {
coins[i].destroy();
}
coins = [];
// Remove hero if exists
if (hero) {
hero.destroy();
hero = null;
}
}
// Update UI displays
function updateUI() {
scoreTxt.setText("Score: " + score);
levelTxt.setText("Level: " + level);
healthTxt.setText("Health: " + (hero ? hero.health : 0));
if (heartDisplay && hero) {
heartDisplay.updateHearts(hero.health);
}
}
// Setup controls
function setupControls() {
// Left movement button
leftButton = new Button();
leftButton.setup("<", 0x4444FF);
leftButton.x = 150;
leftButton.y = 2532;
leftButton.onPress = function () {
hero.isMovingLeft = true;
hero.isMovingRight = false;
};
leftButton.up = function () {
hero.isMovingLeft = false;
};
game.addChild(leftButton);
// Right movement button
rightButton = new Button();
rightButton.setup(">", 0x4444FF);
rightButton.x = 300;
rightButton.y = 2532;
rightButton.onPress = function () {
hero.isMovingRight = true;
hero.isMovingLeft = false;
};
rightButton.up = function () {
hero.isMovingRight = false;
};
game.addChild(rightButton);
// Jump button
jumpButton = new Button();
jumpButton.setup("^", 0xFF4444);
jumpButton.x = 450; // Position next to the right movement button
jumpButton.y = 2532;
jumpButton.onPress = function () {
hero.isJumping = true;
// We don't need to call hero.jump() here, it will be handled in the update loop
};
jumpButton.up = function () {
hero.isJumping = false;
};
game.addChild(jumpButton);
}
// Setup UI
function setupUI() {
// Score display
scoreTxt = new Text2("Score: 0", {
size: 60,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0, 0);
LK.gui.topRight.addChild(scoreTxt);
// Add 'BetlSrc' label to the top right corner
var betlsrcLabel = new Text2("BetlSrc", {
size: 60,
fill: 0xFFFFFF
});
betlsrcLabel.anchor.set(1, 0);
betlsrcLabel.x = -20; // Slightly inset from the right edge
betlsrcLabel.y = 0;
LK.gui.topRight.addChild(betlsrcLabel);
// Level display
levelTxt = new Text2("Level: 1", {
size: 60,
fill: 0xFFFFFF
});
levelTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(levelTxt);
// Health display
healthTxt = new Text2("Health: 3", {
size: 60,
fill: 0xFFFFFF
});
healthTxt.anchor.set(1, 0);
LK.gui.topLeft.addChild(healthTxt);
healthTxt.x = 250; // Move further right as requested
// Heart display
heartDisplay = new HeartDisplay();
heartDisplay.x = 200;
heartDisplay.y = 100;
heartDisplay.init();
LK.gui.topLeft.addChild(heartDisplay);
// Make sure hearts are visible and properly spaced
heartDisplay.updateHearts(3);
}
// Initialize game
function initGame() {
// Set score to zero
score = 0;
LK.setScore(0);
// Setup UI elements
setupUI();
// Setup level
setupLevel();
// Setup controls
setupControls();
// Play background music
LK.playMusic('bgmusic', {
fade: {
start: 0,
end: 0.7,
duration: 1000
}
});
// Mark game as started
gameStarted = true;
}
// Handle collisions
function handleCollisions() {
// Hero-platform collisions
for (var i = 0; i < platforms.length; i++) {
hero.handlePlatformCollision(platforms[i]);
}
// Hero-enemy collisions
for (var i = enemies.length - 1; i >= 0; i--) {
if (hero.intersects(enemies[i])) {
// Check if hero is jumping on enemy from above
if (hero.vy > 0 && hero.y < enemies[i].y - 30) {
// Destroy enemy
enemies[i].destroy();
enemies.splice(i, 1);
// Bounce hero
hero.vy = hero.jumpForce * 0.6;
// Add score
score += 100;
LK.setScore(score);
updateUI();
} else {
// Hero takes damage
hero.takeDamage();
updateUI();
}
}
}
// Hero-coin collisions
for (var i = coins.length - 1; i >= 0; i--) {
if (hero.intersects(coins[i])) {
// Collect coin
coins[i].collect();
coins.splice(i, 1);
// Add score
score += 10;
LK.setScore(score);
updateUI();
}
}
// Check for level completion (all coins collected)
if (coins.length === 0) {
// Level completed
level++;
// Check if player completed all levels
if (level > levelConfig.platforms.length) {
// Game completed
LK.showYouWin();
} else {
// Setup next level
setupLevel();
}
}
}
// Keep hero within bounds
function enforceWorldBounds() {
// Keep hero within horizontal bounds
if (hero.x < 50) {
hero.x = 50;
} else if (hero.x > 2048 - 50) {
hero.x = 2048 - 50;
}
// Check if hero fell off the bottom
if (hero.y > 2732 + 100) {
hero.takeDamage();
// Respawn on the initial spawn platform
if (typeof initialSpawnPlatform !== "undefined" && initialSpawnPlatform) {
hero.x = initialSpawnPlatform.x;
hero.y = initialSpawnPlatform.y - 70;
} else {
// fallback if not set
hero.x = 200;
hero.y = 2400;
}
hero.vx = 0;
hero.vy = 0;
updateUI();
}
// Check if hero reached the top (level complete)
if (hero.y < 0) {
// Level completed
level++;
// Check if player completed all levels
if (level > levelConfig.platforms.length) {
// Game completed
LK.showYouWin();
} else {
// Setup next level
setupLevel();
}
}
}
// Handle global touch events
game.down = function (x, y, obj) {
if (!gameStarted) {
initGame();
}
};
// Game update loop
game.update = function () {
if (!gameStarted) {
return;
}
// Update hero
if (hero) {
hero.update();
}
// Update enemies
for (var i = 0; i < enemies.length; i++) {
enemies[i].update();
}
// Update coins
for (var i = 0; i < coins.length; i++) {
coins[i].update();
}
// Handle collisions
handleCollisions();
// Enforce world boundaries
enforceWorldBounds();
};
// Setup initial "tap to start" message
var startText = new Text2("Tap to Start", {
size: 100,
fill: 0xFFFFFF
});
startText.anchor.set(0.5, 0.5);
startText.x = 2048 / 2;
startText.y = 2732 / 2;
game.addChild(startText);
// Remove start text when game starts
LK.setInterval(function () {
if (gameStarted && startText.parent) {
startText.destroy();
}
}, 100);