/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var BreakablePlatform = Container.expand(function (platformWidth, platformHeight) {
var self = Container.call(this);
var platformGraphics = self.attachAsset('breakablePlatform', {
anchorX: 0.5,
anchorY: 0.5
});
// Set platform size
self.platformWidth = platformWidth || 200;
self.platformHeight = platformHeight || 166.41;
platformGraphics.width = self.platformWidth;
platformGraphics.height = self.platformHeight;
self.solid = true;
self.breakTimer = 0;
self.maxBreakTime = 120; // 2 seconds at 60fps
self.playerOnPlatform = false;
self.lastPlayerOnPlatform = false;
self.update = function () {
if (self.playerOnPlatform && self.solid) {
self.breakTimer++;
// Flash red as it's about to break
if (self.breakTimer > self.maxBreakTime * 0.7) {
platformGraphics.tint = self.breakTimer % 10 < 5 ? 0xFF0000 : 0xFFFFFF;
}
if (self.breakTimer >= self.maxBreakTime) {
self.solid = false;
platformGraphics.alpha = 0.3;
LK.getSound('platformBreak').play();
}
}
self.lastPlayerOnPlatform = self.playerOnPlatform;
self.playerOnPlatform = false;
};
return self;
});
var Button = Container.expand(function (text, width, height, color) {
var self = Container.call(this);
self.buttonWidth = width || 400;
self.buttonHeight = height || 100;
self.buttonColor = color || 0x4A90E2;
// Create button background
var bg = LK.getAsset('buttonBg', {
width: self.buttonWidth,
height: self.buttonHeight,
color: self.buttonColor,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5
});
self.addChild(bg);
// Create button text
var buttonText = new Text2(text || 'Button', {
size: 50,
fill: '#FFFFFF'
});
buttonText.anchor.set(0.5, 0.5);
self.addChild(buttonText);
self.setText = function (newText) {
buttonText.setText(newText);
};
self.setColor = function (newColor) {
bg.tint = newColor;
};
self.down = function (x, y, obj) {
// Button press effect
self.scaleX = 0.95;
self.scaleY = 0.95;
if (self.onPress) self.onPress();
};
self.up = function (x, y, obj) {
// Button release effect
self.scaleX = 1.0;
self.scaleY = 1.0;
};
return self;
});
var Coin = Container.expand(function () {
var self = Container.call(this);
var coinGraphics = self.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5
});
self.collected = false;
self.bobOffset = 0;
self.initialY = 0;
self.update = function () {
if (!self.collected) {
self.bobOffset += 0.1;
coinGraphics.y = Math.sin(self.bobOffset) * 5;
coinGraphics.rotation += 0.05;
}
};
return self;
});
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 1.0
});
// Make enemies larger for better visibility
enemyGraphics.width = 100; // Increased from 50 to 100
enemyGraphics.height = 100; // Increased from 50 to 100
self.speed = 1;
self.direction = 1;
self.patrolDistance = 100;
self.startX = 0;
self.update = function () {
self.x += self.speed * self.direction;
// Turn around at patrol limits
if (Math.abs(self.x - self.startX) > self.patrolDistance) {
self.direction *= -1;
}
};
return self;
});
var FinishLine = Container.expand(function () {
var self = Container.call(this);
var finishGraphics = self.attachAsset('finishLine', {
anchorX: 0.5,
anchorY: 1.0
});
return self;
});
var FlyingEnemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
enemyGraphics.tint = 0x8844FF; // Purple tint for flying enemies
// Make flying enemies larger for better visibility
enemyGraphics.width = 100; // Increased from 50 to 100
enemyGraphics.height = 100; // Increased from 50 to 100
self.speed = 2;
self.direction = 1;
self.patrolDistance = 200;
self.startX = 0;
self.startY = 0;
self.bobOffset = 0;
self.update = function () {
// Horizontal movement
self.x += self.speed * self.direction;
// Turn around at patrol limits
if (Math.abs(self.x - self.startX) > self.patrolDistance) {
self.direction *= -1;
}
// Vertical bobbing motion
self.bobOffset += 0.05;
self.y = self.startY + Math.sin(self.bobOffset) * 30;
};
return self;
});
var GameUI = Container.expand(function () {
var self = Container.call(this);
// Store button references for positioning updates
self.leftBtn = new Button('◀', 280, 280, 0x333333);
self.leftBtn.alpha = 0.8;
self.leftBtn.down = function () {
moveLeft = true;
moveRight = false;
this.setColor(0x555555);
};
self.leftBtn.up = function () {
moveLeft = false;
this.setColor(0x333333);
};
self.addChild(self.leftBtn);
self.rightBtn = new Button('▶', 280, 280, 0x333333);
self.rightBtn.alpha = 0.8;
self.rightBtn.down = function () {
moveRight = true;
moveLeft = false;
this.setColor(0x555555);
};
self.rightBtn.up = function () {
moveRight = false;
this.setColor(0x333333);
};
self.addChild(self.rightBtn);
self.jumpBtn = new Button('JUMP', 350, 280, 0x4CAF50);
self.jumpBtn.alpha = 0.9;
self.jumpBtn.down = function () {
if (player) player.jump();
this.setColor(0x66BB6A);
};
self.jumpBtn.up = function () {
this.setColor(0x4CAF50);
};
self.addChild(self.jumpBtn);
self.pauseBtn = new Button('II', 150, 150, 0xFF9800);
self.pauseBtn.alpha = 0.8;
self.pauseBtn.onPress = function () {
gameState = 'start';
clearLevel();
showStartScreen();
};
self.addChild(self.pauseBtn);
// Update method to keep buttons positioned relative to camera
self.update = function () {
// Position buttons relative to camera
self.leftBtn.x = cameraX + 220;
self.leftBtn.y = 2450;
self.rightBtn.x = cameraX + 550;
self.rightBtn.y = 2450;
self.jumpBtn.x = cameraX + 1600;
self.jumpBtn.y = 2450;
self.pauseBtn.x = cameraX + 1850;
self.pauseBtn.y = 150;
};
return self;
});
var LevelSelectScreen = Container.expand(function () {
var self = Container.call(this);
// Title
var title = new Text2('SELECT LEVEL', {
size: 100,
fill: '#FFFFFF'
});
title.anchor.set(0.5, 0.5);
title.x = 1024;
title.y = 400;
self.addChild(title);
// Level buttons - larger
for (var i = 1; i <= maxLevel; i++) {
var levelBtn = new Button('LEVEL ' + i, 350, 140, 0x9C27B0);
levelBtn.x = 500 + (i - 1) * 350;
levelBtn.y = 800;
// Store level number in button
levelBtn.levelNumber = i;
levelBtn.onPress = function () {
currentLevel = this.levelNumber;
gameState = 'playing';
startGame();
};
self.addChild(levelBtn);
}
// Back button - larger
var backBtn = new Button('BACK', 400, 120, 0x757575);
backBtn.x = 1024;
backBtn.y = 1600;
backBtn.onPress = function () {
gameState = 'start';
showStartScreen();
};
self.addChild(backBtn);
return self;
});
var MovingPlatform = Container.expand(function (platformWidth, platformHeight) {
var self = Container.call(this);
var platformGraphics = self.attachAsset('platform', {
anchorX: 0.5,
anchorY: 0.5
});
platformGraphics.tint = 0x88FF88; // Green tint to distinguish moving platforms
// Set platform size
self.platformWidth = platformWidth || 200;
self.platformHeight = platformHeight || 158.59;
platformGraphics.width = self.platformWidth;
platformGraphics.height = self.platformHeight;
self.solid = true;
self.speed = 2;
self.direction = 1; // 1 for up, -1 for down
self.moveDistance = 200;
self.startY = 0;
self.lastY = 0;
self.update = function () {
self.lastY = self.y;
self.y += self.speed * self.direction;
// Reverse direction when reaching movement limits
if (Math.abs(self.y - self.startY) > self.moveDistance) {
self.direction *= -1;
}
// Move player with platform if standing on it
if (player && player.groundPlatform === self && player.isGrounded) {
player.y += self.y - self.lastY;
}
};
return self;
});
var Platform = Container.expand(function (platformWidth, platformHeight) {
var self = Container.call(this);
var platformGraphics = self.attachAsset('platform', {
anchorX: 0.5,
anchorY: 0.5
});
// Set platform size
self.platformWidth = platformWidth || 200;
self.platformHeight = platformHeight || 158.59;
platformGraphics.width = self.platformWidth;
platformGraphics.height = self.platformHeight;
self.solid = true;
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 1.0
});
// Apply selected skin
if (selectedSkin !== 0xFFFFFF) {
playerGraphics.tint = selectedSkin;
}
self.velocityX = 0;
self.velocityY = 0;
self.speed = 8;
self.jumpPower = 18;
self.gravity = 0.8;
self.isGrounded = false;
self.groundPlatform = null;
self.update = function () {
// Apply gravity
self.velocityY += self.gravity;
// Apply movement
self.x += self.velocityX;
self.y += self.velocityY;
// Friction when grounded
if (self.isGrounded) {
self.velocityX *= 0.8;
}
// Handle invulnerability
if (self.invulnerable) {
self.invulnerabilityTimer--;
if (self.invulnerabilityTimer <= 0) {
self.invulnerable = false;
self.alpha = 1.0;
}
}
// Check if fell off screen
if (self.y > 2732 + 100) {
playerLives--;
if (playerLives <= 0) {
storage.lastLevel = currentLevel;
LK.showGameOver();
} else {
// Reset player position to start
self.x = 200;
self.y = 2200;
self.velocityX = 0;
self.velocityY = 0;
updateHearts();
LK.effects.flashScreen(0xFF0000, 500);
}
}
};
self.jump = function () {
if (self.isGrounded) {
self.velocityY = -self.jumpPower;
self.isGrounded = false;
self.groundPlatform = null;
LK.getSound('jump').play();
}
};
return self;
});
var SkinSelectScreen = Container.expand(function () {
var self = Container.call(this);
// Title
var title = new Text2('CHOOSE SKIN', {
size: 100,
fill: '#FFFFFF'
});
title.anchor.set(0.5, 0.5);
title.x = 1024;
title.y = 400;
self.addChild(title);
// Skin options
var skinOptions = [{
name: 'DEFAULT',
color: 0xFFFFFF
}, {
name: 'RED',
color: 0xFF4444
}, {
name: 'BLUE',
color: 0x4444FF
}, {
name: 'GREEN',
color: 0x44FF44
}, {
name: 'PURPLE',
color: 0x9C27B0
}, {
name: 'ORANGE',
color: 0xFF9800
}, {
name: 'CYAN',
color: 0x00BCD4
}, {
name: 'PINK',
color: 0xE91E63
}];
for (var i = 0; i < skinOptions.length; i++) {
var skinBtn = new Button(skinOptions[i].name, 280, 120, skinOptions[i].color);
skinBtn.x = 200 + i % 3 * 320;
skinBtn.y = 650 + Math.floor(i / 3) * 160;
// Store skin data
skinBtn.skinColor = skinOptions[i].color;
skinBtn.onPress = function () {
selectedSkin = this.skinColor;
storage.selectedSkin = selectedSkin;
// Update existing player if in game
if (player && player.children && player.children[0]) {
player.children[0].tint = selectedSkin;
}
// Update button appearance to show selection
for (var j = 0; j < self.children.length; j++) {
var child = self.children[j];
if (child.skinColor !== undefined) {
child.scaleX = child.skinColor === selectedSkin ? 1.1 : 1.0;
child.scaleY = child.skinColor === selectedSkin ? 1.1 : 1.0;
}
}
};
// Show selection state
if (skinOptions[i].color === selectedSkin) {
skinBtn.scaleX = 1.1;
skinBtn.scaleY = 1.1;
}
self.addChild(skinBtn);
}
// Back button - larger
var backBtn = new Button('BACK', 400, 120, 0x757575);
backBtn.x = 1024;
backBtn.y = 1600;
backBtn.onPress = function () {
gameState = 'start';
showStartScreen();
};
self.addChild(backBtn);
return self;
});
var StartScreen = Container.expand(function () {
var self = Container.call(this);
// Title
var title = new Text2('PLATFORM COIN RUSH', {
size: 120,
fill: '#FFFFFF'
});
title.anchor.set(0.5, 0.5);
title.x = 1024;
title.y = 500;
self.addChild(title);
// Check if there's a last level to resume
var hasLastLevel = storage.lastLevel && storage.lastLevel > 0;
// Start/Resume button - larger
var startBtn = new Button(hasLastLevel ? 'RESUME LEVEL ' + storage.lastLevel : 'START GAME', 600, 160, 0x4CAF50);
startBtn.x = 1024;
startBtn.y = 1000;
startBtn.onPress = function () {
if (hasLastLevel) {
currentLevel = storage.lastLevel;
gameState = 'playing';
startGame();
} else {
gameState = 'level_select';
showLevelSelect();
}
};
self.addChild(startBtn);
// Level select button - larger
var levelBtn = new Button('SELECT LEVEL', 600, 160, 0x2196F3);
levelBtn.x = 1024;
levelBtn.y = 1200;
levelBtn.onPress = function () {
gameState = 'level_select';
showLevelSelect();
};
self.addChild(levelBtn);
// Skin select button - larger
var skinBtn = new Button('CHOOSE SKIN', 600, 160, 0xFF9800);
skinBtn.x = 1024;
skinBtn.y = 1400;
skinBtn.onPress = function () {
gameState = 'skin_select';
showSkinSelect();
};
self.addChild(skinBtn);
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
var player;
var platforms = [];
var breakablePlatforms = [];
var movingPlatforms = [];
var enemies = [];
var coins = [];
var flyingEnemies = [];
var background;
var finishLine;
// Camera offset
var cameraX = 0;
// Controls
var moveLeft = false;
var moveRight = false;
// Level system
var currentLevel = 1;
var maxLevel = 8;
// Game state management
var gameState = 'start'; // 'start', 'level_select', 'skin_select', 'playing'
var startScreen;
var levelSelectScreen;
var skinSelectScreen;
var gameUI;
// Skin system
var selectedSkin = storage.selectedSkin || 0xFFFFFF;
// Lives system
var playerLives = 3;
var collectedCoins = 0;
// UI
var scoreTxt = new Text2('Coins: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0, 0);
LK.gui.topLeft.addChild(scoreTxt);
// Lives counter with heart icons
var livesContainer = new Container();
livesContainer.x = 120;
livesContainer.y = 100;
LK.gui.topLeft.addChild(livesContainer);
var heartIcons = [];
for (var h = 0; h < 3; h++) {
var heart = LK.getAsset('heart', {
anchorX: 0.5,
anchorY: 0.5
});
heart.x = h * 70;
heart.y = 30;
heartIcons.push(heart);
livesContainer.addChild(heart);
}
function updateHearts() {
for (var h = 0; h < heartIcons.length; h++) {
heartIcons[h].alpha = h < playerLives ? 1.0 : 0.3;
}
}
// Coin counter with icon
var coinContainer = new Container();
coinContainer.x = 120;
coinContainer.y = 200;
LK.gui.topLeft.addChild(coinContainer);
var coinIconDisplay = LK.getAsset('coinIcon', {
anchorX: 0.5,
anchorY: 0.5
});
coinIconDisplay.x = 30;
coinIconDisplay.y = 40;
coinContainer.addChild(coinIconDisplay);
var coinText = new Text2('0', {
size: 80,
fill: 0xFFD700
});
coinText.anchor.set(0, 0.5);
coinText.x = 70;
coinText.y = 40;
coinContainer.addChild(coinText);
// Screen management functions
function showStartScreen() {
clearAllScreens();
startScreen = game.addChild(new StartScreen());
}
function showLevelSelect() {
clearAllScreens();
levelSelectScreen = game.addChild(new LevelSelectScreen());
}
function showSkinSelect() {
clearAllScreens();
skinSelectScreen = game.addChild(new SkinSelectScreen());
}
function clearAllScreens() {
if (startScreen) {
startScreen.destroy();
startScreen = null;
}
if (levelSelectScreen) {
levelSelectScreen.destroy();
levelSelectScreen = null;
}
if (skinSelectScreen) {
skinSelectScreen.destroy();
skinSelectScreen = null;
}
if (gameUI) {
gameUI.destroy();
gameUI = null;
}
}
function startGame() {
clearAllScreens();
clearLevel();
// Reset game state
playerLives = 3;
collectedCoins = 0;
updateHearts();
coinText.setText('Coins: ' + collectedCoins);
createLevel();
gameUI = game.addChild(new GameUI());
}
// Initialize level
function createLevel() {
// Create player
player = game.addChild(new Player());
player.x = 200;
player.y = 2200;
player.invulnerable = false;
player.invulnerabilityTimer = 0;
// Generate level data based on current level
var levelData = generateLevelData(currentLevel);
// Create platforms
levelData.platforms.forEach(function (data) {
if (data.type === 'platform') {
var platform = game.addChild(new Platform(data.width, data.height));
platform.x = data.x;
platform.y = data.y;
platforms.push(platform);
} else if (data.type === 'moving') {
var movingPlatform = game.addChild(new MovingPlatform(data.width, data.height));
movingPlatform.x = data.x;
movingPlatform.y = data.y;
movingPlatform.startY = data.y;
movingPlatform.moveDistance = data.moveDistance || 200;
movingPlatform.speed = data.speed || 2;
movingPlatforms.push(movingPlatform);
} else {
var breakablePlatform = game.addChild(new BreakablePlatform(data.width, data.height));
breakablePlatform.x = data.x;
breakablePlatform.y = data.y;
breakablePlatforms.push(breakablePlatform);
}
});
// Create enemies
levelData.enemies.forEach(function (data) {
if (data.type === 'ground') {
var enemy = game.addChild(new Enemy());
enemy.x = data.x;
enemy.y = data.y;
enemy.startX = data.x;
enemies.push(enemy);
} else if (data.type === 'flying') {
var flyingEnemy = game.addChild(new FlyingEnemy());
flyingEnemy.x = data.x;
flyingEnemy.y = data.y;
flyingEnemy.startX = data.x;
flyingEnemy.startY = data.y;
enemies.push(flyingEnemy);
}
});
// Create tiled background that covers the entire level area
var levelWidth = 5000 + currentLevel * 1000; // Match the max camera bounds - increased for longer levels
var tilesNeeded = Math.ceil(levelWidth / 2048) + 1; // +1 for safety margin
for (var bgTile = 0; bgTile < tilesNeeded; bgTile++) {
var bgTileSprite = game.addChild(LK.getAsset('background', {
anchorX: 0,
anchorY: 0,
x: bgTile * 2048,
y: 0
}));
// Send each background tile to back
game.setChildIndex(bgTileSprite, bgTile);
}
// Create coins
levelData.coins.forEach(function (data) {
var coin = game.addChild(new Coin());
coin.x = data.x;
coin.y = data.y;
coin.initialY = data.y;
coins.push(coin);
});
// Create finish line
finishLine = game.addChild(new FinishLine());
finishLine.x = levelData.finishX;
finishLine.y = levelData.finishY;
}
// Collision detection
function checkPlatformCollisions() {
var allPlatforms = platforms.concat(breakablePlatforms.filter(function (p) {
return p.solid;
})).concat(movingPlatforms);
player.isGrounded = false;
player.groundPlatform = null;
allPlatforms.forEach(function (platform) {
var platformHalfWidth = (platform.platformWidth || 200) / 2;
var platformHalfHeight = (platform.platformHeight || 158.59) / 2;
// Check if player is landing on top of platform
if (player.x > platform.x - platformHalfWidth - 20 && player.x < platform.x + platformHalfWidth + 20 && player.y > platform.y - platformHalfHeight - 30 && player.y < platform.y + platformHalfHeight + 10 && player.velocityY >= 0) {
player.y = platform.y - platformHalfHeight;
player.velocityY = 0;
player.isGrounded = true;
player.groundPlatform = platform;
// Mark breakable platform as having player on it
if (platform.breakTimer !== undefined) {
platform.playerOnPlatform = true;
}
}
});
}
function checkEnemyCollisions() {
enemies.forEach(function (enemy) {
if (player.intersects(enemy) && !player.invulnerable) {
playerLives--;
updateHearts();
LK.effects.flashScreen(0xFF0000, 500);
// Make player temporarily invulnerable
player.invulnerable = true;
player.invulnerabilityTimer = 120; // 2 seconds at 60fps
player.alpha = 0.5;
if (playerLives <= 0) {
storage.lastLevel = currentLevel;
LK.showGameOver();
}
}
});
}
function checkCoinCollisions() {
for (var i = coins.length - 1; i >= 0; i--) {
var coin = coins[i];
if (!coin.collected && player.intersects(coin)) {
coin.collected = true;
coin.alpha = 0;
collectedCoins++;
LK.setScore(LK.getScore() + 1);
scoreTxt.setText('Coins: ' + LK.getScore());
coinText.setText('Coins: ' + collectedCoins);
LK.getSound('coinCollect').play();
coins.splice(i, 1);
coin.destroy();
}
}
}
function checkFinishLine() {
if (player.intersects(finishLine)) {
// Clear last level from storage since level was completed
storage.lastLevel = null;
currentLevel++;
if (currentLevel > maxLevel) {
LK.showYouWin();
} else {
// Clear current level
clearLevel();
// Create next level
createLevel();
}
}
}
function clearLevel() {
// Remove all game objects
platforms.forEach(function (platform) {
platform.destroy();
});
breakablePlatforms.forEach(function (platform) {
platform.destroy();
});
movingPlatforms.forEach(function (platform) {
platform.destroy();
});
enemies.forEach(function (enemy) {
enemy.destroy();
});
coins.forEach(function (coin) {
coin.destroy();
});
// Remove all background tiles
for (var i = game.children.length - 1; i >= 0; i--) {
var child = game.children[i];
if (child && child.texture && child.texture.baseTexture && child.texture.baseTexture.resource && child.texture.baseTexture.resource.src && child.texture.baseTexture.resource.src.includes('687d7d30546d3d568db4f1ad')) {
child.destroy();
}
}
if (finishLine) finishLine.destroy();
if (player) player.destroy();
// Clear arrays
platforms = [];
breakablePlatforms = [];
movingPlatforms = [];
enemies = [];
coins = [];
flyingEnemies = [];
// Reset camera
cameraX = 0;
game.x = 0;
}
function updateCamera() {
// Follow player with camera - extremely close zoom
var targetCameraX = player.x - 100; // Reduced from 200 to 100 for much closer view
cameraX += (targetCameraX - cameraX) * 0.4; // Increased responsiveness from 0.3 to 0.4
// Limit camera bounds - dynamic based on level
if (cameraX < 0) cameraX = 0;
var maxCameraX = 5000 + currentLevel * 1000; // Much longer levels - increased from 3000 + currentLevel * 800
if (cameraX > maxCameraX) cameraX = maxCameraX;
game.x = -cameraX;
}
// Touch controls - only active during gameplay
game.down = function (x, y, obj) {
if (gameState !== 'playing') return;
// Only handle movement, jump is handled by button
if (!obj || obj === game) {
// Move left/right based on screen side
if (x < 1024) {
moveLeft = true;
moveRight = false;
} else {
moveLeft = false;
moveRight = true;
}
}
};
game.up = function (x, y, obj) {
if (gameState !== 'playing') return;
moveLeft = false;
moveRight = false;
};
game.update = function () {
// Only update game logic when playing
if (gameState !== 'playing') return;
// Handle movement input
if (moveLeft) {
player.velocityX = Math.max(player.velocityX - 1, -player.speed);
}
if (moveRight) {
player.velocityX = Math.min(player.velocityX + 1, player.speed);
}
// Check collisions
checkPlatformCollisions();
checkEnemyCollisions();
checkCoinCollisions();
checkFinishLine();
// Update camera
updateCamera();
};
// Initialize with start screen
showStartScreen();
function generateLevelData(level) {
var baseData = {
platforms: [],
enemies: [],
coins: [],
finishX: 0,
finishY: 0
};
// Level-specific layouts
if (level === 1) {
// Easy level - varied platform layout with moving elements
baseData.platforms = [{
x: 200,
y: 2300,
type: 'platform'
}, {
x: 500,
y: 2200,
type: 'platform'
}, {
x: 800,
y: 2100,
type: 'moving',
moveDistance: 150,
speed: 1.5
}, {
x: 650,
y: 1950,
type: 'platform'
}, {
x: 1100,
y: 1850,
type: 'moving',
moveDistance: 200,
speed: 2
}, {
x: 900,
y: 1700,
type: 'platform'
}, {
x: 1350,
y: 1600,
type: 'platform'
}, {
x: 1600,
y: 1450,
type: 'moving',
moveDistance: 180,
speed: 1.8
}, {
x: 1900,
y: 1300,
type: 'platform'
}, {
x: 2200,
y: 1150,
type: 'breakable'
}, {
x: 2500,
y: 1000,
type: 'moving',
moveDistance: 250,
speed: 2.5
}, {
x: 2800,
y: 850,
type: 'platform'
}];
baseData.enemies = [{
x: 150,
y: 1940,
type: 'ground'
}, {
x: 750,
y: 1740,
type: 'ground'
}, {
x: 1400,
y: 1390,
type: 'ground'
}, {
x: 2000,
y: 1090,
type: 'ground'
}, {
x: 1500,
y: 1000,
type: 'flying'
}];
baseData.coins = [{
x: 200,
y: 2180
}, {
x: 500,
y: 2080
}, {
x: 800,
y: 1980
}, {
x: 650,
y: 1830
}, {
x: 1100,
y: 1730
}, {
x: 900,
y: 1580
}, {
x: 1350,
y: 1480
}, {
x: 1600,
y: 1330
}, {
x: 1900,
y: 1180
}, {
x: 2200,
y: 1030
}, {
x: 2500,
y: 880
}, {
x: 2800,
y: 730
}];
baseData.finishX = 2900;
baseData.finishY = 750;
} else if (level === 2) {
// Introduce breakable platforms with varied layout and moving elements
baseData.platforms = [{
x: 200,
y: 2300,
type: 'platform'
}, {
x: 550,
y: 2150,
type: 'breakable'
}, {
x: 350,
y: 2000,
type: 'moving',
moveDistance: 120,
speed: 1.2
}, {
x: 750,
y: 1950,
type: 'breakable'
}, {
x: 1000,
y: 1800,
type: 'moving',
moveDistance: 180,
speed: 2.2
}, {
x: 800,
y: 1650,
type: 'platform'
}, {
x: 1250,
y: 1550,
type: 'breakable'
}, {
x: 1500,
y: 1400,
type: 'moving',
moveDistance: 160,
speed: 1.8
}, {
x: 1750,
y: 1250,
type: 'platform'
}];
baseData.enemies = [{
x: 800,
y: 1590,
type: 'ground'
}, {
x: 1500,
y: 1340,
type: 'ground'
}, {
x: 900,
y: 1400,
type: 'flying'
}];
baseData.coins = [{
x: 300,
y: 2200
}, {
x: 500,
y: 2050
}, {
x: 700,
y: 1900
}, {
x: 900,
y: 1750
}, {
x: 1100,
y: 1600
}, {
x: 1300,
y: 1450
}, {
x: 1500,
y: 1300
}, {
x: 1700,
y: 1150
}];
baseData.finishX = 1900;
baseData.finishY = 1100;
} else if (level === 3) {
// Add flying enemies
baseData.platforms = [{
x: 200,
y: 2300,
type: 'platform'
}, {
x: 450,
y: 2100,
type: 'platform'
}, {
x: 700,
y: 1900,
type: 'breakable'
}, {
x: 950,
y: 1700,
type: 'platform'
}, {
x: 1200,
y: 1500,
type: 'breakable'
}, {
x: 1450,
y: 1300,
type: 'platform'
}, {
x: 1700,
y: 1100,
type: 'platform'
}, {
x: 1950,
y: 900,
type: 'breakable'
}, {
x: 2200,
y: 700,
type: 'platform'
}];
baseData.enemies = [{
x: 950,
y: 1640,
type: 'ground'
}, {
x: 1700,
y: 1040,
type: 'ground'
}, {
x: 1100,
y: 1200,
type: 'flying'
}];
baseData.coins = [{
x: 325,
y: 2200
}, {
x: 575,
y: 2000
}, {
x: 825,
y: 1800
}, {
x: 1075,
y: 1600
}, {
x: 1325,
y: 1400
}, {
x: 1575,
y: 1200
}, {
x: 1825,
y: 1000
}, {
x: 2075,
y: 800
}, {
x: 2325,
y: 600
}];
baseData.finishX = 2300;
baseData.finishY = 700;
} else if (level === 4) {
// More complex layout
baseData.platforms = [{
x: 200,
y: 2300,
type: 'platform'
}, {
x: 400,
y: 2150,
type: 'breakable'
}, {
x: 650,
y: 1950,
type: 'platform'
}, {
x: 850,
y: 1800,
type: 'breakable'
}, {
x: 1100,
y: 1600,
type: 'platform'
}, {
x: 1300,
y: 1450,
type: 'breakable'
}, {
x: 1550,
y: 1250,
type: 'platform'
}, {
x: 1750,
y: 1100,
type: 'breakable'
}, {
x: 2000,
y: 900,
type: 'platform'
}, {
x: 2250,
y: 700,
type: 'platform'
}, {
x: 2500,
y: 500,
type: 'breakable'
}, {
x: 2750,
y: 300,
type: 'platform'
}];
baseData.enemies = [{
x: 1100,
y: 1540,
type: 'ground'
}, {
x: 2000,
y: 840,
type: 'ground'
}, {
x: 1400,
y: 1000,
type: 'flying'
}, {
x: 2400,
y: 600,
type: 'flying'
}];
baseData.coins = [{
x: 300,
y: 2200
}, {
x: 525,
y: 2050
}, {
x: 775,
y: 1850
}, {
x: 975,
y: 1700
}, {
x: 1225,
y: 1500
}, {
x: 1425,
y: 1350
}, {
x: 1675,
y: 1150
}, {
x: 1875,
y: 1000
}, {
x: 2125,
y: 800
}, {
x: 2375,
y: 600
}, {
x: 2625,
y: 400
}];
baseData.finishX = 2850;
baseData.finishY = 300;
} else {
// Generate procedural levels for 5-8 with varied patterns including moving platforms
var platformCount = 45 + level * 8; // Much longer levels - increased from 25 + level * 4
var currentX = 200;
var currentY = 2300;
var direction = 1; // 1 for right, -1 for left
var verticalDirection = -1; // Start going up
var sectionType = 'ascending'; // Track current section type
var sectionLength = 0;
var maxSectionLength = 8 + Math.random() * 6; // 8-14 platforms per section
for (var i = 0; i < platformCount; i++) {
// Change section type periodically for variety
if (sectionLength >= maxSectionLength) {
var sectionRand = Math.random();
if (sectionRand < 0.3) {
sectionType = 'horizontal'; // Horizontal traversal
verticalDirection = 0;
} else if (sectionRand < 0.6) {
sectionType = 'descending'; // Go down briefly
verticalDirection = 1;
} else {
sectionType = 'ascending'; // Go up
verticalDirection = -1;
}
sectionLength = 0;
maxSectionLength = 6 + Math.random() * 8; // 6-14 platforms per section
}
sectionLength++;
var platformType;
var randType = Math.random();
if (randType < 0.3) {
platformType = 'moving';
} else if (randType < 0.7) {
platformType = 'breakable';
} else {
platformType = 'platform';
}
// Generate varied platform sizes
var sizeVariation = Math.random();
var platformWidth, platformHeight;
if (sizeVariation < 0.3) {
// Small platforms (30% chance)
platformWidth = 120 + Math.random() * 80; // 120-200px
platformHeight = platformType === 'breakable' ? 100 + Math.random() * 66 : 95 + Math.random() * 64;
} else if (sizeVariation < 0.7) {
// Medium platforms (40% chance) - default size
platformWidth = 200;
platformHeight = platformType === 'breakable' ? 166.41 : 158.59;
} else {
// Large platforms (30% chance)
platformWidth = 250 + Math.random() * 100; // 250-350px
platformHeight = platformType === 'breakable' ? 200 + Math.random() * 66 : 190 + Math.random() * 64;
}
var platformData = {
x: currentX,
y: currentY,
type: platformType,
width: platformWidth,
height: platformHeight
};
// Add movement properties for moving platforms
if (platformType === 'moving') {
platformData.moveDistance = 100 + Math.random() * 200; // 100-300 pixels
platformData.speed = 1 + Math.random() * 2; // 1-3 speed
}
baseData.platforms.push(platformData);
// Add additional platforms for more complex jumping patterns
if (Math.random() < 0.3 && i > 2) {
// Add a secondary platform at different height
var secondaryX = currentX + (Math.random() - 0.5) * 400;
var secondaryY = currentY + (Math.random() - 0.5) * 200;
baseData.platforms.push({
x: secondaryX,
y: secondaryY,
type: Math.random() < 0.7 ? 'breakable' : 'platform'
});
}
// Add special pattern structures occasionally
if (Math.random() < 0.15 && i > 5) {
var patternType = Math.random();
if (patternType < 0.33) {
// Spiral pattern
for (var spiralIdx = 0; spiralIdx < 4; spiralIdx++) {
var spiralAngle = spiralIdx * Math.PI / 2;
var spiralX = currentX + Math.cos(spiralAngle) * 200;
var spiralY = currentY + Math.sin(spiralAngle) * 100 - spiralIdx * 50;
baseData.platforms.push({
x: spiralX,
y: spiralY,
type: 'platform',
width: 150,
height: 130
});
}
} else if (patternType < 0.66) {
// Zigzag pattern
for (var zigIdx = 0; zigIdx < 3; zigIdx++) {
var zigX = currentX + zigIdx * 180 * (zigIdx % 2 === 0 ? 1 : -1);
var zigY = currentY - zigIdx * 80;
baseData.platforms.push({
x: zigX,
y: zigY,
type: zigIdx === 1 ? 'moving' : 'platform',
width: 160,
height: 140
});
}
} else {
// Vertical tower pattern
for (var towerIdx = 0; towerIdx < 3; towerIdx++) {
baseData.platforms.push({
x: currentX + (Math.random() - 0.5) * 100,
y: currentY - towerIdx * 120,
type: towerIdx === 1 ? 'breakable' : 'platform',
width: 140 + Math.random() * 60,
height: 120 + Math.random() * 40
});
}
}
}
// Add coin near each platform ensuring it's reachable
var coinOffset = (Math.random() - 0.5) * 60; // Reduced from 80 to 60 for better positioning
baseData.coins.push({
x: currentX + coinOffset,
y: currentY - 100 // Moved higher up for better accessibility
});
// Randomly add enemies with better positioning to avoid impossible sections
if (Math.random() < 0.3 && i > 1 && i % 4 !== 0) {
// Reduced frequency and skip every 4th platform to create safe paths
var enemyType = Math.random() < 0.4 ? 'ground' : 'flying'; // Reduced ground enemies
var enemyY = enemyType === 'ground' ? currentY - 60 : currentY - 100;
// Position enemies away from the center of platforms for accessibility
var enemyOffset = Math.random() < 0.5 ? -200 : 200; // Place to sides
var enemyX = currentX + enemyOffset;
// Ensure enemy doesn't block critical path areas
if (i < platformCount - 5) {
// Don't place enemies near the end
baseData.enemies.push({
x: enemyX,
y: enemyY,
type: enemyType
});
}
}
// Reduce enemy clusters and make them less blocking
if (Math.random() < 0.15 && i > 5 && i % 6 !== 0) {
// Much reduced frequency and avoid placing near critical platforms
var clusterEnemyType = 'flying'; // Only flying enemies in clusters
var clusterEnemyY = currentY - 120;
baseData.enemies.push({
x: currentX + 250 + (Math.random() - 0.5) * 100,
y: clusterEnemyY,
type: clusterEnemyType
});
}
// More organic movement pattern based on section type
var xMove = 150 + Math.random() * 200;
var yMove;
if (sectionType === 'horizontal') {
yMove = Math.random() * 40 - 20; // Small vertical variance for horizontal sections
} else if (sectionType === 'descending') {
yMove = -(60 + Math.random() * 80); // Descending movement
} else {
yMove = 80 + Math.random() * 120; // Ascending movement
}
// Sometimes change direction horizontally
if (Math.random() < 0.3) direction *= -1;
// Occasionally create vertical challenges in ascending sections
if (Math.random() < 0.2 && sectionType === 'ascending') yMove *= 1.5;
// Add platform bridges in horizontal sections
if (sectionType === 'horizontal' && Math.random() < 0.4) {
// Create a bridge of smaller platforms
for (var bridgeIdx = 1; bridgeIdx <= 2; bridgeIdx++) {
baseData.platforms.push({
x: currentX + bridgeIdx * 120,
y: currentY + (Math.random() - 0.5) * 60,
type: 'platform',
width: 100,
height: 120
});
}
}
currentX += xMove * direction;
currentY += yMove * (verticalDirection || (Math.random() < 0.5 ? 1 : -1));
// Keep X within reasonable bounds - expanded for longer levels
if (currentX < 100) {
currentX = 100;
direction = 1;
}
if (currentX > 4500 + level * 500) {
// Much wider levels
currentX = 4500 + level * 500;
direction = -1;
}
}
baseData.finishX = currentX + 200;
baseData.finishY = currentY - 100;
}
return baseData;
} /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var BreakablePlatform = Container.expand(function (platformWidth, platformHeight) {
var self = Container.call(this);
var platformGraphics = self.attachAsset('breakablePlatform', {
anchorX: 0.5,
anchorY: 0.5
});
// Set platform size
self.platformWidth = platformWidth || 200;
self.platformHeight = platformHeight || 166.41;
platformGraphics.width = self.platformWidth;
platformGraphics.height = self.platformHeight;
self.solid = true;
self.breakTimer = 0;
self.maxBreakTime = 120; // 2 seconds at 60fps
self.playerOnPlatform = false;
self.lastPlayerOnPlatform = false;
self.update = function () {
if (self.playerOnPlatform && self.solid) {
self.breakTimer++;
// Flash red as it's about to break
if (self.breakTimer > self.maxBreakTime * 0.7) {
platformGraphics.tint = self.breakTimer % 10 < 5 ? 0xFF0000 : 0xFFFFFF;
}
if (self.breakTimer >= self.maxBreakTime) {
self.solid = false;
platformGraphics.alpha = 0.3;
LK.getSound('platformBreak').play();
}
}
self.lastPlayerOnPlatform = self.playerOnPlatform;
self.playerOnPlatform = false;
};
return self;
});
var Button = Container.expand(function (text, width, height, color) {
var self = Container.call(this);
self.buttonWidth = width || 400;
self.buttonHeight = height || 100;
self.buttonColor = color || 0x4A90E2;
// Create button background
var bg = LK.getAsset('buttonBg', {
width: self.buttonWidth,
height: self.buttonHeight,
color: self.buttonColor,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5
});
self.addChild(bg);
// Create button text
var buttonText = new Text2(text || 'Button', {
size: 50,
fill: '#FFFFFF'
});
buttonText.anchor.set(0.5, 0.5);
self.addChild(buttonText);
self.setText = function (newText) {
buttonText.setText(newText);
};
self.setColor = function (newColor) {
bg.tint = newColor;
};
self.down = function (x, y, obj) {
// Button press effect
self.scaleX = 0.95;
self.scaleY = 0.95;
if (self.onPress) self.onPress();
};
self.up = function (x, y, obj) {
// Button release effect
self.scaleX = 1.0;
self.scaleY = 1.0;
};
return self;
});
var Coin = Container.expand(function () {
var self = Container.call(this);
var coinGraphics = self.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5
});
self.collected = false;
self.bobOffset = 0;
self.initialY = 0;
self.update = function () {
if (!self.collected) {
self.bobOffset += 0.1;
coinGraphics.y = Math.sin(self.bobOffset) * 5;
coinGraphics.rotation += 0.05;
}
};
return self;
});
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 1.0
});
// Make enemies larger for better visibility
enemyGraphics.width = 100; // Increased from 50 to 100
enemyGraphics.height = 100; // Increased from 50 to 100
self.speed = 1;
self.direction = 1;
self.patrolDistance = 100;
self.startX = 0;
self.update = function () {
self.x += self.speed * self.direction;
// Turn around at patrol limits
if (Math.abs(self.x - self.startX) > self.patrolDistance) {
self.direction *= -1;
}
};
return self;
});
var FinishLine = Container.expand(function () {
var self = Container.call(this);
var finishGraphics = self.attachAsset('finishLine', {
anchorX: 0.5,
anchorY: 1.0
});
return self;
});
var FlyingEnemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
enemyGraphics.tint = 0x8844FF; // Purple tint for flying enemies
// Make flying enemies larger for better visibility
enemyGraphics.width = 100; // Increased from 50 to 100
enemyGraphics.height = 100; // Increased from 50 to 100
self.speed = 2;
self.direction = 1;
self.patrolDistance = 200;
self.startX = 0;
self.startY = 0;
self.bobOffset = 0;
self.update = function () {
// Horizontal movement
self.x += self.speed * self.direction;
// Turn around at patrol limits
if (Math.abs(self.x - self.startX) > self.patrolDistance) {
self.direction *= -1;
}
// Vertical bobbing motion
self.bobOffset += 0.05;
self.y = self.startY + Math.sin(self.bobOffset) * 30;
};
return self;
});
var GameUI = Container.expand(function () {
var self = Container.call(this);
// Store button references for positioning updates
self.leftBtn = new Button('◀', 280, 280, 0x333333);
self.leftBtn.alpha = 0.8;
self.leftBtn.down = function () {
moveLeft = true;
moveRight = false;
this.setColor(0x555555);
};
self.leftBtn.up = function () {
moveLeft = false;
this.setColor(0x333333);
};
self.addChild(self.leftBtn);
self.rightBtn = new Button('▶', 280, 280, 0x333333);
self.rightBtn.alpha = 0.8;
self.rightBtn.down = function () {
moveRight = true;
moveLeft = false;
this.setColor(0x555555);
};
self.rightBtn.up = function () {
moveRight = false;
this.setColor(0x333333);
};
self.addChild(self.rightBtn);
self.jumpBtn = new Button('JUMP', 350, 280, 0x4CAF50);
self.jumpBtn.alpha = 0.9;
self.jumpBtn.down = function () {
if (player) player.jump();
this.setColor(0x66BB6A);
};
self.jumpBtn.up = function () {
this.setColor(0x4CAF50);
};
self.addChild(self.jumpBtn);
self.pauseBtn = new Button('II', 150, 150, 0xFF9800);
self.pauseBtn.alpha = 0.8;
self.pauseBtn.onPress = function () {
gameState = 'start';
clearLevel();
showStartScreen();
};
self.addChild(self.pauseBtn);
// Update method to keep buttons positioned relative to camera
self.update = function () {
// Position buttons relative to camera
self.leftBtn.x = cameraX + 220;
self.leftBtn.y = 2450;
self.rightBtn.x = cameraX + 550;
self.rightBtn.y = 2450;
self.jumpBtn.x = cameraX + 1600;
self.jumpBtn.y = 2450;
self.pauseBtn.x = cameraX + 1850;
self.pauseBtn.y = 150;
};
return self;
});
var LevelSelectScreen = Container.expand(function () {
var self = Container.call(this);
// Title
var title = new Text2('SELECT LEVEL', {
size: 100,
fill: '#FFFFFF'
});
title.anchor.set(0.5, 0.5);
title.x = 1024;
title.y = 400;
self.addChild(title);
// Level buttons - larger
for (var i = 1; i <= maxLevel; i++) {
var levelBtn = new Button('LEVEL ' + i, 350, 140, 0x9C27B0);
levelBtn.x = 500 + (i - 1) * 350;
levelBtn.y = 800;
// Store level number in button
levelBtn.levelNumber = i;
levelBtn.onPress = function () {
currentLevel = this.levelNumber;
gameState = 'playing';
startGame();
};
self.addChild(levelBtn);
}
// Back button - larger
var backBtn = new Button('BACK', 400, 120, 0x757575);
backBtn.x = 1024;
backBtn.y = 1600;
backBtn.onPress = function () {
gameState = 'start';
showStartScreen();
};
self.addChild(backBtn);
return self;
});
var MovingPlatform = Container.expand(function (platformWidth, platformHeight) {
var self = Container.call(this);
var platformGraphics = self.attachAsset('platform', {
anchorX: 0.5,
anchorY: 0.5
});
platformGraphics.tint = 0x88FF88; // Green tint to distinguish moving platforms
// Set platform size
self.platformWidth = platformWidth || 200;
self.platformHeight = platformHeight || 158.59;
platformGraphics.width = self.platformWidth;
platformGraphics.height = self.platformHeight;
self.solid = true;
self.speed = 2;
self.direction = 1; // 1 for up, -1 for down
self.moveDistance = 200;
self.startY = 0;
self.lastY = 0;
self.update = function () {
self.lastY = self.y;
self.y += self.speed * self.direction;
// Reverse direction when reaching movement limits
if (Math.abs(self.y - self.startY) > self.moveDistance) {
self.direction *= -1;
}
// Move player with platform if standing on it
if (player && player.groundPlatform === self && player.isGrounded) {
player.y += self.y - self.lastY;
}
};
return self;
});
var Platform = Container.expand(function (platformWidth, platformHeight) {
var self = Container.call(this);
var platformGraphics = self.attachAsset('platform', {
anchorX: 0.5,
anchorY: 0.5
});
// Set platform size
self.platformWidth = platformWidth || 200;
self.platformHeight = platformHeight || 158.59;
platformGraphics.width = self.platformWidth;
platformGraphics.height = self.platformHeight;
self.solid = true;
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 1.0
});
// Apply selected skin
if (selectedSkin !== 0xFFFFFF) {
playerGraphics.tint = selectedSkin;
}
self.velocityX = 0;
self.velocityY = 0;
self.speed = 8;
self.jumpPower = 18;
self.gravity = 0.8;
self.isGrounded = false;
self.groundPlatform = null;
self.update = function () {
// Apply gravity
self.velocityY += self.gravity;
// Apply movement
self.x += self.velocityX;
self.y += self.velocityY;
// Friction when grounded
if (self.isGrounded) {
self.velocityX *= 0.8;
}
// Handle invulnerability
if (self.invulnerable) {
self.invulnerabilityTimer--;
if (self.invulnerabilityTimer <= 0) {
self.invulnerable = false;
self.alpha = 1.0;
}
}
// Check if fell off screen
if (self.y > 2732 + 100) {
playerLives--;
if (playerLives <= 0) {
storage.lastLevel = currentLevel;
LK.showGameOver();
} else {
// Reset player position to start
self.x = 200;
self.y = 2200;
self.velocityX = 0;
self.velocityY = 0;
updateHearts();
LK.effects.flashScreen(0xFF0000, 500);
}
}
};
self.jump = function () {
if (self.isGrounded) {
self.velocityY = -self.jumpPower;
self.isGrounded = false;
self.groundPlatform = null;
LK.getSound('jump').play();
}
};
return self;
});
var SkinSelectScreen = Container.expand(function () {
var self = Container.call(this);
// Title
var title = new Text2('CHOOSE SKIN', {
size: 100,
fill: '#FFFFFF'
});
title.anchor.set(0.5, 0.5);
title.x = 1024;
title.y = 400;
self.addChild(title);
// Skin options
var skinOptions = [{
name: 'DEFAULT',
color: 0xFFFFFF
}, {
name: 'RED',
color: 0xFF4444
}, {
name: 'BLUE',
color: 0x4444FF
}, {
name: 'GREEN',
color: 0x44FF44
}, {
name: 'PURPLE',
color: 0x9C27B0
}, {
name: 'ORANGE',
color: 0xFF9800
}, {
name: 'CYAN',
color: 0x00BCD4
}, {
name: 'PINK',
color: 0xE91E63
}];
for (var i = 0; i < skinOptions.length; i++) {
var skinBtn = new Button(skinOptions[i].name, 280, 120, skinOptions[i].color);
skinBtn.x = 200 + i % 3 * 320;
skinBtn.y = 650 + Math.floor(i / 3) * 160;
// Store skin data
skinBtn.skinColor = skinOptions[i].color;
skinBtn.onPress = function () {
selectedSkin = this.skinColor;
storage.selectedSkin = selectedSkin;
// Update existing player if in game
if (player && player.children && player.children[0]) {
player.children[0].tint = selectedSkin;
}
// Update button appearance to show selection
for (var j = 0; j < self.children.length; j++) {
var child = self.children[j];
if (child.skinColor !== undefined) {
child.scaleX = child.skinColor === selectedSkin ? 1.1 : 1.0;
child.scaleY = child.skinColor === selectedSkin ? 1.1 : 1.0;
}
}
};
// Show selection state
if (skinOptions[i].color === selectedSkin) {
skinBtn.scaleX = 1.1;
skinBtn.scaleY = 1.1;
}
self.addChild(skinBtn);
}
// Back button - larger
var backBtn = new Button('BACK', 400, 120, 0x757575);
backBtn.x = 1024;
backBtn.y = 1600;
backBtn.onPress = function () {
gameState = 'start';
showStartScreen();
};
self.addChild(backBtn);
return self;
});
var StartScreen = Container.expand(function () {
var self = Container.call(this);
// Title
var title = new Text2('PLATFORM COIN RUSH', {
size: 120,
fill: '#FFFFFF'
});
title.anchor.set(0.5, 0.5);
title.x = 1024;
title.y = 500;
self.addChild(title);
// Check if there's a last level to resume
var hasLastLevel = storage.lastLevel && storage.lastLevel > 0;
// Start/Resume button - larger
var startBtn = new Button(hasLastLevel ? 'RESUME LEVEL ' + storage.lastLevel : 'START GAME', 600, 160, 0x4CAF50);
startBtn.x = 1024;
startBtn.y = 1000;
startBtn.onPress = function () {
if (hasLastLevel) {
currentLevel = storage.lastLevel;
gameState = 'playing';
startGame();
} else {
gameState = 'level_select';
showLevelSelect();
}
};
self.addChild(startBtn);
// Level select button - larger
var levelBtn = new Button('SELECT LEVEL', 600, 160, 0x2196F3);
levelBtn.x = 1024;
levelBtn.y = 1200;
levelBtn.onPress = function () {
gameState = 'level_select';
showLevelSelect();
};
self.addChild(levelBtn);
// Skin select button - larger
var skinBtn = new Button('CHOOSE SKIN', 600, 160, 0xFF9800);
skinBtn.x = 1024;
skinBtn.y = 1400;
skinBtn.onPress = function () {
gameState = 'skin_select';
showSkinSelect();
};
self.addChild(skinBtn);
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
var player;
var platforms = [];
var breakablePlatforms = [];
var movingPlatforms = [];
var enemies = [];
var coins = [];
var flyingEnemies = [];
var background;
var finishLine;
// Camera offset
var cameraX = 0;
// Controls
var moveLeft = false;
var moveRight = false;
// Level system
var currentLevel = 1;
var maxLevel = 8;
// Game state management
var gameState = 'start'; // 'start', 'level_select', 'skin_select', 'playing'
var startScreen;
var levelSelectScreen;
var skinSelectScreen;
var gameUI;
// Skin system
var selectedSkin = storage.selectedSkin || 0xFFFFFF;
// Lives system
var playerLives = 3;
var collectedCoins = 0;
// UI
var scoreTxt = new Text2('Coins: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0, 0);
LK.gui.topLeft.addChild(scoreTxt);
// Lives counter with heart icons
var livesContainer = new Container();
livesContainer.x = 120;
livesContainer.y = 100;
LK.gui.topLeft.addChild(livesContainer);
var heartIcons = [];
for (var h = 0; h < 3; h++) {
var heart = LK.getAsset('heart', {
anchorX: 0.5,
anchorY: 0.5
});
heart.x = h * 70;
heart.y = 30;
heartIcons.push(heart);
livesContainer.addChild(heart);
}
function updateHearts() {
for (var h = 0; h < heartIcons.length; h++) {
heartIcons[h].alpha = h < playerLives ? 1.0 : 0.3;
}
}
// Coin counter with icon
var coinContainer = new Container();
coinContainer.x = 120;
coinContainer.y = 200;
LK.gui.topLeft.addChild(coinContainer);
var coinIconDisplay = LK.getAsset('coinIcon', {
anchorX: 0.5,
anchorY: 0.5
});
coinIconDisplay.x = 30;
coinIconDisplay.y = 40;
coinContainer.addChild(coinIconDisplay);
var coinText = new Text2('0', {
size: 80,
fill: 0xFFD700
});
coinText.anchor.set(0, 0.5);
coinText.x = 70;
coinText.y = 40;
coinContainer.addChild(coinText);
// Screen management functions
function showStartScreen() {
clearAllScreens();
startScreen = game.addChild(new StartScreen());
}
function showLevelSelect() {
clearAllScreens();
levelSelectScreen = game.addChild(new LevelSelectScreen());
}
function showSkinSelect() {
clearAllScreens();
skinSelectScreen = game.addChild(new SkinSelectScreen());
}
function clearAllScreens() {
if (startScreen) {
startScreen.destroy();
startScreen = null;
}
if (levelSelectScreen) {
levelSelectScreen.destroy();
levelSelectScreen = null;
}
if (skinSelectScreen) {
skinSelectScreen.destroy();
skinSelectScreen = null;
}
if (gameUI) {
gameUI.destroy();
gameUI = null;
}
}
function startGame() {
clearAllScreens();
clearLevel();
// Reset game state
playerLives = 3;
collectedCoins = 0;
updateHearts();
coinText.setText('Coins: ' + collectedCoins);
createLevel();
gameUI = game.addChild(new GameUI());
}
// Initialize level
function createLevel() {
// Create player
player = game.addChild(new Player());
player.x = 200;
player.y = 2200;
player.invulnerable = false;
player.invulnerabilityTimer = 0;
// Generate level data based on current level
var levelData = generateLevelData(currentLevel);
// Create platforms
levelData.platforms.forEach(function (data) {
if (data.type === 'platform') {
var platform = game.addChild(new Platform(data.width, data.height));
platform.x = data.x;
platform.y = data.y;
platforms.push(platform);
} else if (data.type === 'moving') {
var movingPlatform = game.addChild(new MovingPlatform(data.width, data.height));
movingPlatform.x = data.x;
movingPlatform.y = data.y;
movingPlatform.startY = data.y;
movingPlatform.moveDistance = data.moveDistance || 200;
movingPlatform.speed = data.speed || 2;
movingPlatforms.push(movingPlatform);
} else {
var breakablePlatform = game.addChild(new BreakablePlatform(data.width, data.height));
breakablePlatform.x = data.x;
breakablePlatform.y = data.y;
breakablePlatforms.push(breakablePlatform);
}
});
// Create enemies
levelData.enemies.forEach(function (data) {
if (data.type === 'ground') {
var enemy = game.addChild(new Enemy());
enemy.x = data.x;
enemy.y = data.y;
enemy.startX = data.x;
enemies.push(enemy);
} else if (data.type === 'flying') {
var flyingEnemy = game.addChild(new FlyingEnemy());
flyingEnemy.x = data.x;
flyingEnemy.y = data.y;
flyingEnemy.startX = data.x;
flyingEnemy.startY = data.y;
enemies.push(flyingEnemy);
}
});
// Create tiled background that covers the entire level area
var levelWidth = 5000 + currentLevel * 1000; // Match the max camera bounds - increased for longer levels
var tilesNeeded = Math.ceil(levelWidth / 2048) + 1; // +1 for safety margin
for (var bgTile = 0; bgTile < tilesNeeded; bgTile++) {
var bgTileSprite = game.addChild(LK.getAsset('background', {
anchorX: 0,
anchorY: 0,
x: bgTile * 2048,
y: 0
}));
// Send each background tile to back
game.setChildIndex(bgTileSprite, bgTile);
}
// Create coins
levelData.coins.forEach(function (data) {
var coin = game.addChild(new Coin());
coin.x = data.x;
coin.y = data.y;
coin.initialY = data.y;
coins.push(coin);
});
// Create finish line
finishLine = game.addChild(new FinishLine());
finishLine.x = levelData.finishX;
finishLine.y = levelData.finishY;
}
// Collision detection
function checkPlatformCollisions() {
var allPlatforms = platforms.concat(breakablePlatforms.filter(function (p) {
return p.solid;
})).concat(movingPlatforms);
player.isGrounded = false;
player.groundPlatform = null;
allPlatforms.forEach(function (platform) {
var platformHalfWidth = (platform.platformWidth || 200) / 2;
var platformHalfHeight = (platform.platformHeight || 158.59) / 2;
// Check if player is landing on top of platform
if (player.x > platform.x - platformHalfWidth - 20 && player.x < platform.x + platformHalfWidth + 20 && player.y > platform.y - platformHalfHeight - 30 && player.y < platform.y + platformHalfHeight + 10 && player.velocityY >= 0) {
player.y = platform.y - platformHalfHeight;
player.velocityY = 0;
player.isGrounded = true;
player.groundPlatform = platform;
// Mark breakable platform as having player on it
if (platform.breakTimer !== undefined) {
platform.playerOnPlatform = true;
}
}
});
}
function checkEnemyCollisions() {
enemies.forEach(function (enemy) {
if (player.intersects(enemy) && !player.invulnerable) {
playerLives--;
updateHearts();
LK.effects.flashScreen(0xFF0000, 500);
// Make player temporarily invulnerable
player.invulnerable = true;
player.invulnerabilityTimer = 120; // 2 seconds at 60fps
player.alpha = 0.5;
if (playerLives <= 0) {
storage.lastLevel = currentLevel;
LK.showGameOver();
}
}
});
}
function checkCoinCollisions() {
for (var i = coins.length - 1; i >= 0; i--) {
var coin = coins[i];
if (!coin.collected && player.intersects(coin)) {
coin.collected = true;
coin.alpha = 0;
collectedCoins++;
LK.setScore(LK.getScore() + 1);
scoreTxt.setText('Coins: ' + LK.getScore());
coinText.setText('Coins: ' + collectedCoins);
LK.getSound('coinCollect').play();
coins.splice(i, 1);
coin.destroy();
}
}
}
function checkFinishLine() {
if (player.intersects(finishLine)) {
// Clear last level from storage since level was completed
storage.lastLevel = null;
currentLevel++;
if (currentLevel > maxLevel) {
LK.showYouWin();
} else {
// Clear current level
clearLevel();
// Create next level
createLevel();
}
}
}
function clearLevel() {
// Remove all game objects
platforms.forEach(function (platform) {
platform.destroy();
});
breakablePlatforms.forEach(function (platform) {
platform.destroy();
});
movingPlatforms.forEach(function (platform) {
platform.destroy();
});
enemies.forEach(function (enemy) {
enemy.destroy();
});
coins.forEach(function (coin) {
coin.destroy();
});
// Remove all background tiles
for (var i = game.children.length - 1; i >= 0; i--) {
var child = game.children[i];
if (child && child.texture && child.texture.baseTexture && child.texture.baseTexture.resource && child.texture.baseTexture.resource.src && child.texture.baseTexture.resource.src.includes('687d7d30546d3d568db4f1ad')) {
child.destroy();
}
}
if (finishLine) finishLine.destroy();
if (player) player.destroy();
// Clear arrays
platforms = [];
breakablePlatforms = [];
movingPlatforms = [];
enemies = [];
coins = [];
flyingEnemies = [];
// Reset camera
cameraX = 0;
game.x = 0;
}
function updateCamera() {
// Follow player with camera - extremely close zoom
var targetCameraX = player.x - 100; // Reduced from 200 to 100 for much closer view
cameraX += (targetCameraX - cameraX) * 0.4; // Increased responsiveness from 0.3 to 0.4
// Limit camera bounds - dynamic based on level
if (cameraX < 0) cameraX = 0;
var maxCameraX = 5000 + currentLevel * 1000; // Much longer levels - increased from 3000 + currentLevel * 800
if (cameraX > maxCameraX) cameraX = maxCameraX;
game.x = -cameraX;
}
// Touch controls - only active during gameplay
game.down = function (x, y, obj) {
if (gameState !== 'playing') return;
// Only handle movement, jump is handled by button
if (!obj || obj === game) {
// Move left/right based on screen side
if (x < 1024) {
moveLeft = true;
moveRight = false;
} else {
moveLeft = false;
moveRight = true;
}
}
};
game.up = function (x, y, obj) {
if (gameState !== 'playing') return;
moveLeft = false;
moveRight = false;
};
game.update = function () {
// Only update game logic when playing
if (gameState !== 'playing') return;
// Handle movement input
if (moveLeft) {
player.velocityX = Math.max(player.velocityX - 1, -player.speed);
}
if (moveRight) {
player.velocityX = Math.min(player.velocityX + 1, player.speed);
}
// Check collisions
checkPlatformCollisions();
checkEnemyCollisions();
checkCoinCollisions();
checkFinishLine();
// Update camera
updateCamera();
};
// Initialize with start screen
showStartScreen();
function generateLevelData(level) {
var baseData = {
platforms: [],
enemies: [],
coins: [],
finishX: 0,
finishY: 0
};
// Level-specific layouts
if (level === 1) {
// Easy level - varied platform layout with moving elements
baseData.platforms = [{
x: 200,
y: 2300,
type: 'platform'
}, {
x: 500,
y: 2200,
type: 'platform'
}, {
x: 800,
y: 2100,
type: 'moving',
moveDistance: 150,
speed: 1.5
}, {
x: 650,
y: 1950,
type: 'platform'
}, {
x: 1100,
y: 1850,
type: 'moving',
moveDistance: 200,
speed: 2
}, {
x: 900,
y: 1700,
type: 'platform'
}, {
x: 1350,
y: 1600,
type: 'platform'
}, {
x: 1600,
y: 1450,
type: 'moving',
moveDistance: 180,
speed: 1.8
}, {
x: 1900,
y: 1300,
type: 'platform'
}, {
x: 2200,
y: 1150,
type: 'breakable'
}, {
x: 2500,
y: 1000,
type: 'moving',
moveDistance: 250,
speed: 2.5
}, {
x: 2800,
y: 850,
type: 'platform'
}];
baseData.enemies = [{
x: 150,
y: 1940,
type: 'ground'
}, {
x: 750,
y: 1740,
type: 'ground'
}, {
x: 1400,
y: 1390,
type: 'ground'
}, {
x: 2000,
y: 1090,
type: 'ground'
}, {
x: 1500,
y: 1000,
type: 'flying'
}];
baseData.coins = [{
x: 200,
y: 2180
}, {
x: 500,
y: 2080
}, {
x: 800,
y: 1980
}, {
x: 650,
y: 1830
}, {
x: 1100,
y: 1730
}, {
x: 900,
y: 1580
}, {
x: 1350,
y: 1480
}, {
x: 1600,
y: 1330
}, {
x: 1900,
y: 1180
}, {
x: 2200,
y: 1030
}, {
x: 2500,
y: 880
}, {
x: 2800,
y: 730
}];
baseData.finishX = 2900;
baseData.finishY = 750;
} else if (level === 2) {
// Introduce breakable platforms with varied layout and moving elements
baseData.platforms = [{
x: 200,
y: 2300,
type: 'platform'
}, {
x: 550,
y: 2150,
type: 'breakable'
}, {
x: 350,
y: 2000,
type: 'moving',
moveDistance: 120,
speed: 1.2
}, {
x: 750,
y: 1950,
type: 'breakable'
}, {
x: 1000,
y: 1800,
type: 'moving',
moveDistance: 180,
speed: 2.2
}, {
x: 800,
y: 1650,
type: 'platform'
}, {
x: 1250,
y: 1550,
type: 'breakable'
}, {
x: 1500,
y: 1400,
type: 'moving',
moveDistance: 160,
speed: 1.8
}, {
x: 1750,
y: 1250,
type: 'platform'
}];
baseData.enemies = [{
x: 800,
y: 1590,
type: 'ground'
}, {
x: 1500,
y: 1340,
type: 'ground'
}, {
x: 900,
y: 1400,
type: 'flying'
}];
baseData.coins = [{
x: 300,
y: 2200
}, {
x: 500,
y: 2050
}, {
x: 700,
y: 1900
}, {
x: 900,
y: 1750
}, {
x: 1100,
y: 1600
}, {
x: 1300,
y: 1450
}, {
x: 1500,
y: 1300
}, {
x: 1700,
y: 1150
}];
baseData.finishX = 1900;
baseData.finishY = 1100;
} else if (level === 3) {
// Add flying enemies
baseData.platforms = [{
x: 200,
y: 2300,
type: 'platform'
}, {
x: 450,
y: 2100,
type: 'platform'
}, {
x: 700,
y: 1900,
type: 'breakable'
}, {
x: 950,
y: 1700,
type: 'platform'
}, {
x: 1200,
y: 1500,
type: 'breakable'
}, {
x: 1450,
y: 1300,
type: 'platform'
}, {
x: 1700,
y: 1100,
type: 'platform'
}, {
x: 1950,
y: 900,
type: 'breakable'
}, {
x: 2200,
y: 700,
type: 'platform'
}];
baseData.enemies = [{
x: 950,
y: 1640,
type: 'ground'
}, {
x: 1700,
y: 1040,
type: 'ground'
}, {
x: 1100,
y: 1200,
type: 'flying'
}];
baseData.coins = [{
x: 325,
y: 2200
}, {
x: 575,
y: 2000
}, {
x: 825,
y: 1800
}, {
x: 1075,
y: 1600
}, {
x: 1325,
y: 1400
}, {
x: 1575,
y: 1200
}, {
x: 1825,
y: 1000
}, {
x: 2075,
y: 800
}, {
x: 2325,
y: 600
}];
baseData.finishX = 2300;
baseData.finishY = 700;
} else if (level === 4) {
// More complex layout
baseData.platforms = [{
x: 200,
y: 2300,
type: 'platform'
}, {
x: 400,
y: 2150,
type: 'breakable'
}, {
x: 650,
y: 1950,
type: 'platform'
}, {
x: 850,
y: 1800,
type: 'breakable'
}, {
x: 1100,
y: 1600,
type: 'platform'
}, {
x: 1300,
y: 1450,
type: 'breakable'
}, {
x: 1550,
y: 1250,
type: 'platform'
}, {
x: 1750,
y: 1100,
type: 'breakable'
}, {
x: 2000,
y: 900,
type: 'platform'
}, {
x: 2250,
y: 700,
type: 'platform'
}, {
x: 2500,
y: 500,
type: 'breakable'
}, {
x: 2750,
y: 300,
type: 'platform'
}];
baseData.enemies = [{
x: 1100,
y: 1540,
type: 'ground'
}, {
x: 2000,
y: 840,
type: 'ground'
}, {
x: 1400,
y: 1000,
type: 'flying'
}, {
x: 2400,
y: 600,
type: 'flying'
}];
baseData.coins = [{
x: 300,
y: 2200
}, {
x: 525,
y: 2050
}, {
x: 775,
y: 1850
}, {
x: 975,
y: 1700
}, {
x: 1225,
y: 1500
}, {
x: 1425,
y: 1350
}, {
x: 1675,
y: 1150
}, {
x: 1875,
y: 1000
}, {
x: 2125,
y: 800
}, {
x: 2375,
y: 600
}, {
x: 2625,
y: 400
}];
baseData.finishX = 2850;
baseData.finishY = 300;
} else {
// Generate procedural levels for 5-8 with varied patterns including moving platforms
var platformCount = 45 + level * 8; // Much longer levels - increased from 25 + level * 4
var currentX = 200;
var currentY = 2300;
var direction = 1; // 1 for right, -1 for left
var verticalDirection = -1; // Start going up
var sectionType = 'ascending'; // Track current section type
var sectionLength = 0;
var maxSectionLength = 8 + Math.random() * 6; // 8-14 platforms per section
for (var i = 0; i < platformCount; i++) {
// Change section type periodically for variety
if (sectionLength >= maxSectionLength) {
var sectionRand = Math.random();
if (sectionRand < 0.3) {
sectionType = 'horizontal'; // Horizontal traversal
verticalDirection = 0;
} else if (sectionRand < 0.6) {
sectionType = 'descending'; // Go down briefly
verticalDirection = 1;
} else {
sectionType = 'ascending'; // Go up
verticalDirection = -1;
}
sectionLength = 0;
maxSectionLength = 6 + Math.random() * 8; // 6-14 platforms per section
}
sectionLength++;
var platformType;
var randType = Math.random();
if (randType < 0.3) {
platformType = 'moving';
} else if (randType < 0.7) {
platformType = 'breakable';
} else {
platformType = 'platform';
}
// Generate varied platform sizes
var sizeVariation = Math.random();
var platformWidth, platformHeight;
if (sizeVariation < 0.3) {
// Small platforms (30% chance)
platformWidth = 120 + Math.random() * 80; // 120-200px
platformHeight = platformType === 'breakable' ? 100 + Math.random() * 66 : 95 + Math.random() * 64;
} else if (sizeVariation < 0.7) {
// Medium platforms (40% chance) - default size
platformWidth = 200;
platformHeight = platformType === 'breakable' ? 166.41 : 158.59;
} else {
// Large platforms (30% chance)
platformWidth = 250 + Math.random() * 100; // 250-350px
platformHeight = platformType === 'breakable' ? 200 + Math.random() * 66 : 190 + Math.random() * 64;
}
var platformData = {
x: currentX,
y: currentY,
type: platformType,
width: platformWidth,
height: platformHeight
};
// Add movement properties for moving platforms
if (platformType === 'moving') {
platformData.moveDistance = 100 + Math.random() * 200; // 100-300 pixels
platformData.speed = 1 + Math.random() * 2; // 1-3 speed
}
baseData.platforms.push(platformData);
// Add additional platforms for more complex jumping patterns
if (Math.random() < 0.3 && i > 2) {
// Add a secondary platform at different height
var secondaryX = currentX + (Math.random() - 0.5) * 400;
var secondaryY = currentY + (Math.random() - 0.5) * 200;
baseData.platforms.push({
x: secondaryX,
y: secondaryY,
type: Math.random() < 0.7 ? 'breakable' : 'platform'
});
}
// Add special pattern structures occasionally
if (Math.random() < 0.15 && i > 5) {
var patternType = Math.random();
if (patternType < 0.33) {
// Spiral pattern
for (var spiralIdx = 0; spiralIdx < 4; spiralIdx++) {
var spiralAngle = spiralIdx * Math.PI / 2;
var spiralX = currentX + Math.cos(spiralAngle) * 200;
var spiralY = currentY + Math.sin(spiralAngle) * 100 - spiralIdx * 50;
baseData.platforms.push({
x: spiralX,
y: spiralY,
type: 'platform',
width: 150,
height: 130
});
}
} else if (patternType < 0.66) {
// Zigzag pattern
for (var zigIdx = 0; zigIdx < 3; zigIdx++) {
var zigX = currentX + zigIdx * 180 * (zigIdx % 2 === 0 ? 1 : -1);
var zigY = currentY - zigIdx * 80;
baseData.platforms.push({
x: zigX,
y: zigY,
type: zigIdx === 1 ? 'moving' : 'platform',
width: 160,
height: 140
});
}
} else {
// Vertical tower pattern
for (var towerIdx = 0; towerIdx < 3; towerIdx++) {
baseData.platforms.push({
x: currentX + (Math.random() - 0.5) * 100,
y: currentY - towerIdx * 120,
type: towerIdx === 1 ? 'breakable' : 'platform',
width: 140 + Math.random() * 60,
height: 120 + Math.random() * 40
});
}
}
}
// Add coin near each platform ensuring it's reachable
var coinOffset = (Math.random() - 0.5) * 60; // Reduced from 80 to 60 for better positioning
baseData.coins.push({
x: currentX + coinOffset,
y: currentY - 100 // Moved higher up for better accessibility
});
// Randomly add enemies with better positioning to avoid impossible sections
if (Math.random() < 0.3 && i > 1 && i % 4 !== 0) {
// Reduced frequency and skip every 4th platform to create safe paths
var enemyType = Math.random() < 0.4 ? 'ground' : 'flying'; // Reduced ground enemies
var enemyY = enemyType === 'ground' ? currentY - 60 : currentY - 100;
// Position enemies away from the center of platforms for accessibility
var enemyOffset = Math.random() < 0.5 ? -200 : 200; // Place to sides
var enemyX = currentX + enemyOffset;
// Ensure enemy doesn't block critical path areas
if (i < platformCount - 5) {
// Don't place enemies near the end
baseData.enemies.push({
x: enemyX,
y: enemyY,
type: enemyType
});
}
}
// Reduce enemy clusters and make them less blocking
if (Math.random() < 0.15 && i > 5 && i % 6 !== 0) {
// Much reduced frequency and avoid placing near critical platforms
var clusterEnemyType = 'flying'; // Only flying enemies in clusters
var clusterEnemyY = currentY - 120;
baseData.enemies.push({
x: currentX + 250 + (Math.random() - 0.5) * 100,
y: clusterEnemyY,
type: clusterEnemyType
});
}
// More organic movement pattern based on section type
var xMove = 150 + Math.random() * 200;
var yMove;
if (sectionType === 'horizontal') {
yMove = Math.random() * 40 - 20; // Small vertical variance for horizontal sections
} else if (sectionType === 'descending') {
yMove = -(60 + Math.random() * 80); // Descending movement
} else {
yMove = 80 + Math.random() * 120; // Ascending movement
}
// Sometimes change direction horizontally
if (Math.random() < 0.3) direction *= -1;
// Occasionally create vertical challenges in ascending sections
if (Math.random() < 0.2 && sectionType === 'ascending') yMove *= 1.5;
// Add platform bridges in horizontal sections
if (sectionType === 'horizontal' && Math.random() < 0.4) {
// Create a bridge of smaller platforms
for (var bridgeIdx = 1; bridgeIdx <= 2; bridgeIdx++) {
baseData.platforms.push({
x: currentX + bridgeIdx * 120,
y: currentY + (Math.random() - 0.5) * 60,
type: 'platform',
width: 100,
height: 120
});
}
}
currentX += xMove * direction;
currentY += yMove * (verticalDirection || (Math.random() < 0.5 ? 1 : -1));
// Keep X within reasonable bounds - expanded for longer levels
if (currentX < 100) {
currentX = 100;
direction = 1;
}
if (currentX > 4500 + level * 500) {
// Much wider levels
currentX = 4500 + level * 500;
direction = -1;
}
}
baseData.finishX = currentX + 200;
baseData.finishY = currentY - 100;
}
return baseData;
}
Un changón con un tipo piloto peinado que tengo una ropa roja y negra y que sea tipo pixelar. In-Game asset. 2d. High contrast. No shadows
Que los enemigos sean como unas moscas que vuelan por ahí. In-Game asset. 2d. High contrast. No shadows
Que sea tipo una moneda que tenga el signo peso él medio. In-Game asset. 2d. High contrast. No shadows
Que sea una bandera y que tenga como un piso como frametista de carrera algo así. In-Game asset. 2d. High contrast. No shadows
Hace un rectángulo amarillo con un borde naranja una. In-Game asset. 2d. High contrast. No shadows
Un fondo todo celeste con nubes y un sol. In-Game asset. 2d. High contrast. No shadows
Que sea un un bloque alargado dd pasto. In-Game asset. 2d. High contrast. No shadows
Un corazon rojo. In-Game asset. 2d. High contrast. No shadows