/****
* 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);