/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var BossStickFigure = Container.expand(function (x, y) {
var self = Container.call(this);
// Create red boss body parts - scaled up to make boss bigger
self.head = self.attachAsset('bossHead', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
});
self.body = self.attachAsset('bossBody', {
anchorX: 0.5,
anchorY: 0,
scaleX: 1.5,
scaleY: 1.5
});
self.leftArm = self.attachAsset('bossArm', {
anchorX: 0.5,
anchorY: 0,
scaleX: 1.5,
scaleY: 1.5
});
self.rightArm = self.attachAsset('bossArm', {
anchorX: 0.5,
anchorY: 0,
scaleX: 1.5,
scaleY: 1.5
});
self.leftLeg = self.attachAsset('bossLeg', {
anchorX: 0.5,
anchorY: 0,
scaleX: 1.5,
scaleY: 1.5
});
self.rightLeg = self.attachAsset('bossLeg', {
anchorX: 0.5,
anchorY: 0,
scaleX: 1.5,
scaleY: 1.5
});
// Create horns - scaled up to match boss size
self.leftHorn = self.attachAsset('bossHorn', {
anchorX: 0.5,
anchorY: 1,
scaleX: 1.5,
scaleY: 1.5
});
self.rightHorn = self.attachAsset('bossHorn', {
anchorX: 0.5,
anchorY: 1,
scaleX: 1.5,
scaleY: 1.5
});
// Position body parts - adjusted for larger scale
self.head.x = 0;
self.head.y = -200;
self.body.x = 0;
self.body.y = -165;
self.leftArm.x = -30;
self.leftArm.y = -145;
self.rightArm.x = 30;
self.rightArm.y = -145;
self.leftLeg.x = -18;
self.leftLeg.y = -55;
self.rightLeg.x = 18;
self.rightLeg.y = -55;
// Position horns on head - adjusted for larger scale
self.leftHorn.x = -22;
self.leftHorn.y = -215;
self.rightHorn.x = 22;
self.rightHorn.y = -215;
// Rotate horns to look like triangular horns
self.leftHorn.rotation = -0.3;
self.rightHorn.rotation = 0.3;
self.x = x;
self.y = y;
self.health = 100;
self.maxHealth = 100;
self.lastHealth = 100;
return self;
});
var Cloud = Container.expand(function (x, y) {
var self = Container.call(this);
var graphics = self.attachAsset('cloud', {
anchorX: 0.5,
anchorY: 0.5
});
self.x = x;
self.y = y;
self.speed = Math.random() * 0.5 + 0.2; // Random speed between 0.2 and 0.7
self.alpha = Math.random() * 0.4 + 0.3; // Random opacity between 0.3 and 0.7
// Random scale for variety
var scale = Math.random() * 0.8 + 0.6; // Scale between 0.6 and 1.4
graphics.scaleX = scale;
graphics.scaleY = scale * 0.7; // Make clouds flatter
self.update = function () {
self.x += self.speed;
// Reset cloud position when it goes off screen
if (self.x > 2200) {
self.x = -200;
self.y = Math.random() * 800 + 200; // Random Y between 200 and 1000
self.speed = Math.random() * 0.5 + 0.2;
}
};
return self;
});
var DifficultyButton = Container.expand(function (difficulty, x, y) {
var self = Container.call(this);
self.difficulty = difficulty;
self.isSelected = difficulty === currentDifficulty;
// Create button background
self.background = self.attachAsset(self.isSelected ? 'selectedDifficultyButton' : 'difficultyButton', {
anchorX: 0.5,
anchorY: 0.5
});
// Create button text
self.text = new Text2(difficulty.toUpperCase(), {
size: 32,
fill: 0xffffff
});
self.text.anchor.set(0.5, 0.5);
self.addChild(self.text);
self.x = x;
self.y = y;
self.setSelected = function (selected) {
self.isSelected = selected;
self.removeChild(self.background);
self.background = self.attachAsset(self.isSelected ? 'selectedDifficultyButton' : 'difficultyButton', {
anchorX: 0.5,
anchorY: 0.5
});
// Move text to front
self.removeChild(self.text);
self.addChild(self.text);
};
self.down = function (x, y, obj) {
// Update difficulty
currentDifficulty = self.difficulty;
// Update all buttons' selected state
for (var i = 0; i < difficultyButtons.length; i++) {
difficultyButtons[i].setSelected(difficultyButtons[i].difficulty === currentDifficulty);
}
// Apply difficulty changes to current level
applyDifficultySettings();
};
return self;
});
var EnemyStickFigure = Container.expand(function (x, y, patrolRange) {
var self = Container.call(this);
// Create red body parts
self.head = self.attachAsset('enemyHead', {
anchorX: 0.5,
anchorY: 0.5
});
self.body = self.attachAsset('enemyBody', {
anchorX: 0.5,
anchorY: 0
});
self.leftArm = self.attachAsset('enemyArm', {
anchorX: 0.5,
anchorY: 0
});
self.rightArm = self.attachAsset('enemyArm', {
anchorX: 0.5,
anchorY: 0
});
self.leftLeg = self.attachAsset('enemyLeg', {
anchorX: 0.5,
anchorY: 0
});
self.rightLeg = self.attachAsset('enemyLeg', {
anchorX: 0.5,
anchorY: 0
});
// Position body parts
self.head.x = 0;
self.head.y = -105;
self.body.x = 0;
self.body.y = -90;
self.leftArm.x = -12;
self.leftArm.y = -75;
self.rightArm.x = 12;
self.rightArm.y = -75;
self.leftLeg.x = -8;
self.leftLeg.y = -30;
self.rightLeg.x = 8;
self.rightLeg.y = -30;
// Set initial rotations
self.leftArm.rotation = 0.3;
self.rightArm.rotation = -0.3;
self.x = x;
self.y = y;
self.startX = x;
self.patrolRange = patrolRange || 150;
self.speed = 2.0;
self.direction = 1;
self.animationTime = 0;
self.state = 'patrol'; // 'patrol', 'chase', 'returning'
self.detectionRange = 300; // How far enemy can see player
self.chaseSpeed = 4.0; // Speed when chasing
self.patrolSpeed = 2.0; // Speed when patrolling
self.lastPlayerX = 0; // Track last known player position
self.returnTimer = 0; // Timer for returning to patrol
self.animateWalk = function () {
self.animationTime += 0.2;
var walkCycle = Math.sin(self.animationTime);
// Animate legs
tween(self.leftLeg, {
rotation: walkCycle * 0.4
}, {
duration: 150,
easing: tween.linear
});
tween(self.rightLeg, {
rotation: -walkCycle * 0.4
}, {
duration: 150,
easing: tween.linear
});
// Animate arms
tween(self.leftArm, {
rotation: -walkCycle * 0.2 + 0.3
}, {
duration: 150,
easing: tween.linear
});
tween(self.rightArm, {
rotation: walkCycle * 0.2 - 0.3
}, {
duration: 150,
easing: tween.linear
});
};
self.update = function () {
// Get distance to player
var distanceToPlayer = Math.abs(player.x - self.x);
var playerOnMovingPlatform = false;
// Check if player is on a moving platform
for (var p = 0; p < obstacles.length; p++) {
if (obstacles[p].obstacleType === 'movingPlatform') {
if (player.intersects(obstacles[p]) && player.velocityY >= 0 && player.y - 60 <= obstacles[p].y - 15) {
playerOnMovingPlatform = true;
break;
}
}
}
// State machine for enemy behavior
if (self.state === 'patrol') {
// Check if player is in detection range and not on moving platform
if (distanceToPlayer <= self.detectionRange && !playerOnMovingPlatform) {
self.state = 'chase';
self.lastPlayerX = player.x;
} else {
// Normal patrol movement
self.x += self.direction * self.patrolSpeed;
// Check patrol bounds
if (self.x > self.startX + self.patrolRange) {
self.direction = -1;
} else if (self.x < self.startX - self.patrolRange) {
self.direction = 1;
}
}
} else if (self.state === 'chase') {
// Chase the player
if (distanceToPlayer > self.detectionRange * 1.5 || playerOnMovingPlatform) {
// Player too far or on moving platform - start returning
self.state = 'returning';
self.returnTimer = 60; // Return for 1 second at 60fps
} else {
// Move towards player
if (player.x > self.x) {
self.direction = 1;
} else {
self.direction = -1;
}
self.x += self.direction * self.chaseSpeed;
self.lastPlayerX = player.x;
}
} else if (self.state === 'returning') {
// Return to patrol area
self.returnTimer--;
if (self.returnTimer <= 0) {
self.state = 'patrol';
} else {
// Move back towards patrol center
if (self.startX > self.x) {
self.direction = 1;
} else if (self.startX < self.x) {
self.direction = -1;
}
self.x += self.direction * self.patrolSpeed;
}
}
// Animate walking
self.animateWalk();
};
return self;
});
var FinishFlag = Container.expand(function (x, y) {
var self = Container.call(this);
var graphics = self.attachAsset('finishFlag', {
anchorX: 0.5,
anchorY: 1.0
});
self.x = x;
self.y = y;
return self;
});
var Obstacle = Container.expand(function (type, x, y) {
var self = Container.call(this);
self.obstacleType = type;
if (type === 'spike') {
var graphics = self.attachAsset('spike', {
anchorX: 0.5,
anchorY: 1.0
});
} else if (type === 'movingPlatform') {
var graphics = self.attachAsset('movingPlatform', {
anchorX: 0.5,
anchorY: 0.5
});
self.direction = 1;
self.speed = 2;
self.startX = x;
self.range = 200;
}
self.x = x;
self.y = y;
self.update = function () {
if (self.obstacleType === 'movingPlatform') {
self.x += self.direction * self.speed;
if (self.x > self.startX + self.range || self.x < self.startX - self.range) {
self.direction *= -1;
}
}
};
return self;
});
var Projectile = Container.expand(function (x, y, targetX, targetY) {
var self = Container.call(this);
var graphics = self.attachAsset('projectile', {
anchorX: 0.5,
anchorY: 0.5
});
self.x = x;
self.y = y;
// Calculate direction to target
var deltaX = targetX - x;
var deltaY = targetY - y;
var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
self.velocityX = deltaX / distance * 8;
self.velocityY = deltaY / distance * 8;
self.update = function () {
self.x += self.velocityX;
self.y += self.velocityY;
};
return self;
});
var StickFigure = Container.expand(function () {
var self = Container.call(this);
// Create body parts
self.head = self.attachAsset('stickFigureHead', {
anchorX: 0.5,
anchorY: 0.5
});
self.body = self.attachAsset('stickFigureBody', {
anchorX: 0.5,
anchorY: 0
});
self.leftArm = self.attachAsset('stickFigureArm', {
anchorX: 0.5,
anchorY: 0
});
self.rightArm = self.attachAsset('stickFigureArm', {
anchorX: 0.5,
anchorY: 0
});
self.leftLeg = self.attachAsset('stickFigureLeg', {
anchorX: 0.5,
anchorY: 0
});
self.rightLeg = self.attachAsset('stickFigureLeg', {
anchorX: 0.5,
anchorY: 0
});
// Position body parts
self.head.x = 0;
self.head.y = -105;
self.body.x = 0;
self.body.y = -90;
self.leftArm.x = -12;
self.leftArm.y = -75;
self.rightArm.x = 12;
self.rightArm.y = -75;
self.leftLeg.x = -8;
self.leftLeg.y = -30;
self.rightLeg.x = 8;
self.rightLeg.y = -30;
// Set initial rotations
self.leftArm.rotation = 0.2;
self.rightArm.rotation = -0.2;
self.leftLeg.rotation = 0;
self.rightLeg.rotation = 0;
self.velocityY = 0;
self.velocityX = 0;
self.isGrounded = false;
self.jumpPower = -35;
self.gravity = 1.2;
self.speed = 12;
self.animationTime = 0;
self.lastVelocityX = 0;
self.animateWalk = function () {
if (Math.abs(self.velocityX) > 0.5) {
// Walking animation
self.animationTime += 0.3;
var walkCycle = Math.sin(self.animationTime);
// Animate legs
tween(self.leftLeg, {
rotation: walkCycle * 0.5
}, {
duration: 100,
easing: tween.linear
});
tween(self.rightLeg, {
rotation: -walkCycle * 0.5
}, {
duration: 100,
easing: tween.linear
});
// Animate arms opposite to legs
tween(self.leftArm, {
rotation: -walkCycle * 0.3 + 0.2
}, {
duration: 100,
easing: tween.linear
});
tween(self.rightArm, {
rotation: walkCycle * 0.3 - 0.2
}, {
duration: 100,
easing: tween.linear
});
} else {
// Idle position
tween(self.leftArm, {
rotation: 0.2
}, {
duration: 300,
easing: tween.easeOut
});
tween(self.rightArm, {
rotation: -0.2
}, {
duration: 300,
easing: tween.easeOut
});
tween(self.leftLeg, {
rotation: 0
}, {
duration: 300,
easing: tween.easeOut
});
tween(self.rightLeg, {
rotation: 0
}, {
duration: 300,
easing: tween.easeOut
});
}
};
self.animateJump = function () {
// Jump animation - arms up, legs bent
tween(self.leftArm, {
rotation: -1.2
}, {
duration: 200,
easing: tween.easeOut
});
tween(self.rightArm, {
rotation: 1.2
}, {
duration: 200,
easing: tween.easeOut
});
tween(self.leftLeg, {
rotation: 0.8
}, {
duration: 200,
easing: tween.easeOut
});
tween(self.rightLeg, {
rotation: -0.8
}, {
duration: 200,
easing: tween.easeOut
});
};
self.update = function () {
// Apply gravity
self.velocityY += self.gravity;
// Apply velocity
self.x += self.velocityX;
self.y += self.velocityY;
// Reduce horizontal velocity (friction)
self.velocityX *= 0.85;
// Animation logic
if (!self.isGrounded) {
// In air - keep jump pose
} else if (Math.abs(self.velocityX) !== Math.abs(self.lastVelocityX)) {
// Velocity changed, update animation
self.animateWalk();
}
self.lastVelocityX = self.velocityX;
// Ground collision
if (self.y >= groundY) {
var wasInAir = !self.isGrounded;
self.y = groundY;
self.velocityY = 0;
self.isGrounded = true;
// Landing animation
if (wasInAir) {
self.animateWalk();
}
}
};
self.jump = function () {
if (self.isGrounded) {
self.velocityY = self.jumpPower;
self.isGrounded = false;
self.animateJump();
LK.getSound('jump').play();
}
};
self.moveLeft = function () {
self.velocityX = -self.speed;
};
self.moveRight = function () {
self.velocityX = self.speed;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
var currentLevel = 1;
var maxLevels = 10;
var groundY = 2500;
var player;
var obstacles = [];
var enemies = [];
var finishFlag;
var isGameActive = true;
var lives = 3;
var clouds = [];
var boss;
var projectiles = [];
var bossHealthBar;
var bossHealthBarBg;
var currentDifficulty = 'medium'; // Default difficulty
var difficultyButtons = [];
var difficultyContainer;
// Create background clouds
function createClouds() {
for (var i = 0; i < 8; i++) {
var cloudX = Math.random() * 2400 - 200; // Spread across wider area
var cloudY = Math.random() * 800 + 200; // Y between 200 and 1000
var cloud = new Cloud(cloudX, cloudY);
clouds.push(cloud);
game.addChild(cloud);
}
}
// Create difficulty selection bar
function createDifficultyBar() {
// Create container for difficulty bar
difficultyContainer = new Container();
difficultyContainer.x = 120;
difficultyContainer.y = 2600; // Bottom left area
game.addChild(difficultyContainer);
// Create difficulty label
var difficultyLabel = new Text2('DIFFICULTY:', {
size: 28,
fill: 0x000000
});
difficultyLabel.anchor.set(0, 0.5);
difficultyLabel.x = 0;
difficultyLabel.y = -60;
difficultyContainer.addChild(difficultyLabel);
// Create difficulty buttons
var difficulties = ['easy', 'medium', 'hard'];
var buttonSpacing = 220;
for (var i = 0; i < difficulties.length; i++) {
var button = new DifficultyButton(difficulties[i], i * buttonSpacing, 0);
difficultyButtons.push(button);
difficultyContainer.addChild(button);
}
}
// Apply difficulty settings to game
function applyDifficultySettings() {
if (currentDifficulty === 'easy') {
// Easy mode - slower enemies, more lives, lower jump required
for (var i = 0; i < enemies.length; i++) {
enemies[i].chaseSpeed = 2.5;
enemies[i].patrolSpeed = 1.5;
}
if (player) {
player.jumpPower = -38; // Higher jump
player.speed = 14; // Faster movement
}
} else if (currentDifficulty === 'medium') {
// Medium mode - default settings
for (var i = 0; i < enemies.length; i++) {
enemies[i].chaseSpeed = 4.0;
enemies[i].patrolSpeed = 2.0;
}
if (player) {
player.jumpPower = -35;
player.speed = 12;
}
} else if (currentDifficulty === 'hard') {
// Hard mode - faster enemies, lower jump, slower movement
for (var i = 0; i < enemies.length; i++) {
enemies[i].chaseSpeed = 5.5;
enemies[i].patrolSpeed = 2.8;
}
if (player) {
player.jumpPower = -32; // Lower jump
player.speed = 10; // Slower movement
}
}
}
// UI Elements
var levelText = new Text2('Level 1', {
size: 80,
fill: 0x000000
});
levelText.anchor.set(0.5, 0);
LK.gui.top.addChild(levelText);
var livesText = new Text2('Lives: 3', {
size: 60,
fill: 0xFF0000
});
livesText.anchor.set(1, 0);
LK.gui.topRight.addChild(livesText);
// Create ground platforms
function createGround() {
for (var i = 0; i < 15; i++) {
var groundPiece = LK.getAsset('ground', {
anchorX: 0,
anchorY: 1.0
});
groundPiece.x = i * 300;
groundPiece.y = groundY;
game.addChild(groundPiece);
}
}
// Level configurations
var levelConfigs = [
// Level 1 - Simple spikes
{
obstacles: [{
type: 'spike',
x: 600,
y: groundY
}, {
type: 'spike',
x: 1200,
y: groundY
}],
finish: 1800
},
// Level 2 - More spikes
{
obstacles: [{
type: 'spike',
x: 500,
y: groundY
}, {
type: 'spike',
x: 800,
y: groundY
}, {
type: 'spike',
x: 1100,
y: groundY
}],
finish: 1600
},
// Level 3 - Moving platform with enemy
{
obstacles: [{
type: 'movingPlatform',
x: 700,
y: groundY - 200
}, {
type: 'spike',
x: 1400,
y: groundY
}],
enemies: [{
x: 1000,
y: groundY,
patrolRange: 100
}],
finish: 1800
},
// Level 4 - Multiple moving platforms
{
obstacles: [{
type: 'movingPlatform',
x: 500,
y: groundY - 150
}, {
type: 'movingPlatform',
x: 1000,
y: groundY - 250
}],
finish: 1600
},
// Level 5 - Mixed obstacles with enemies
{
obstacles: [{
type: 'spike',
x: 400,
y: groundY
}, {
type: 'movingPlatform',
x: 700,
y: groundY - 180
}, {
type: 'spike',
x: 1200,
y: groundY
}],
enemies: [{
x: 600,
y: groundY,
patrolRange: 80
}, {
x: 1400,
y: groundY,
patrolRange: 120
}],
finish: 1800
},
// Level 6 - Dense spikes
{
obstacles: [{
type: 'spike',
x: 400,
y: groundY
}, {
type: 'spike',
x: 500,
y: groundY
}, {
type: 'spike',
x: 700,
y: groundY
}, {
type: 'spike',
x: 800,
y: groundY
}],
finish: 1200
},
// Level 7 - Fast moving platforms
{
obstacles: [{
type: 'movingPlatform',
x: 500,
y: groundY - 200
}, {
type: 'movingPlatform',
x: 900,
y: groundY - 150
}, {
type: 'spike',
x: 1300,
y: groundY
}],
finish: 1600
},
// Level 8 - High platforms
{
obstacles: [{
type: 'movingPlatform',
x: 400,
y: groundY - 300
}, {
type: 'movingPlatform',
x: 800,
y: groundY - 400
}, {
type: 'spike',
x: 1200,
y: groundY
}],
finish: 1500
},
// Level 9 - Complex pattern
{
obstacles: [{
type: 'spike',
x: 350,
y: groundY
}, {
type: 'movingPlatform',
x: 600,
y: groundY - 250
}, {
type: 'spike',
x: 900,
y: groundY
}, {
type: 'movingPlatform',
x: 1200,
y: groundY - 180
}],
finish: 1600
},
// Level 10 - Boss battle
{
obstacles: [{
type: 'spike',
x: 300,
y: groundY
}, {
type: 'spike',
x: 400,
y: groundY
}],
boss: {
x: 1500,
y: groundY
},
finish: 1800
}];
function initializeLevel(level) {
// Clear existing obstacles
for (var i = obstacles.length - 1; i >= 0; i--) {
obstacles[i].destroy();
obstacles.splice(i, 1);
}
// Clear existing enemies
for (var k = enemies.length - 1; k >= 0; k--) {
enemies[k].destroy();
enemies.splice(k, 1);
}
// Clear existing projectiles
for (var p = projectiles.length - 1; p >= 0; p--) {
projectiles[p].destroy();
projectiles.splice(p, 1);
}
// Clear boss
if (boss) {
boss.destroy();
boss = null;
}
// Clear boss health bar
if (bossHealthBar) {
bossHealthBar.destroy();
bossHealthBar = null;
}
if (bossHealthBarBg) {
bossHealthBarBg.destroy();
bossHealthBarBg = null;
}
if (finishFlag) {
finishFlag.destroy();
}
// Create new obstacles based on level config
var config = levelConfigs[level - 1];
for (var j = 0; j < config.obstacles.length; j++) {
var obstacleConfig = config.obstacles[j];
var obstacle = new Obstacle(obstacleConfig.type, obstacleConfig.x, obstacleConfig.y);
if (obstacleConfig.type === 'movingPlatform' && level >= 7) {
obstacle.speed = 3; // Faster platforms in later levels
}
obstacles.push(obstacle);
game.addChild(obstacle);
}
// Create enemies if they exist in config
if (config.enemies) {
for (var m = 0; m < config.enemies.length; m++) {
var enemyConfig = config.enemies[m];
var enemy = new EnemyStickFigure(enemyConfig.x, enemyConfig.y, enemyConfig.patrolRange);
enemies.push(enemy);
game.addChild(enemy);
}
}
// Create boss if level 10
if (level === 10 && config.boss) {
boss = new BossStickFigure(config.boss.x, config.boss.y);
game.addChild(boss);
// Create boss health bar background
bossHealthBarBg = LK.getAsset('ground', {
anchorX: 0.5,
anchorY: 0.5
});
bossHealthBarBg.width = 600;
bossHealthBarBg.height = 30;
bossHealthBarBg.x = 2048 / 2;
bossHealthBarBg.y = 150;
bossHealthBarBg.tint = 0x333333;
game.addChild(bossHealthBarBg);
// Create boss health bar
bossHealthBar = LK.getAsset('ground', {
anchorX: 0,
anchorY: 0.5
});
bossHealthBar.width = 594;
bossHealthBar.height = 24;
bossHealthBar.x = 2048 / 2 - 297;
bossHealthBar.y = 150;
bossHealthBar.tint = 0xff0000;
game.addChild(bossHealthBar);
}
// Create finish flag
finishFlag = new FinishFlag(config.finish, groundY);
game.addChild(finishFlag);
// Reset player position
player.x = 200;
player.y = groundY;
player.velocityX = 0;
player.velocityY = 0;
player.isGrounded = true;
// Update UI
levelText.setText('Level ' + level);
livesText.setText('Lives: ' + lives);
isGameActive = true;
// Apply difficulty settings
applyDifficultySettings();
}
function resetLevel() {
lives--;
livesText.setText('Lives: ' + lives);
if (lives <= 0) {
LK.showGameOver();
return;
}
// Flash screen red
LK.effects.flashScreen(0xff0000, 500);
// Reset player position after a short delay
LK.setTimeout(function () {
player.x = 200;
player.y = groundY;
player.velocityX = 0;
player.velocityY = 0;
player.isGrounded = true;
isGameActive = true;
}, 500);
}
function completeLevel() {
LK.getSound('levelComplete').play();
LK.effects.flashScreen(0x00ff00, 800);
if (currentLevel >= maxLevels) {
// Game completed
LK.setTimeout(function () {
LK.showYouWin();
}, 800);
} else {
currentLevel++;
LK.setTimeout(function () {
initializeLevel(currentLevel);
}, 800);
}
}
// Initialize game
createClouds();
createGround();
createDifficultyBar();
player = new StickFigure();
game.addChild(player);
initializeLevel(currentLevel);
// Game controls
game.down = function (x, y, obj) {
if (isGameActive) {
player.jump();
}
};
var dragStartX = 0;
var isDragging = false;
game.move = function (x, y, obj) {
if (isGameActive && isDragging) {
var deltaX = x - dragStartX;
if (deltaX < -50) {
player.moveLeft();
} else if (deltaX > 50) {
player.moveRight();
}
} else if (isGameActive) {
dragStartX = x;
isDragging = true;
}
};
game.up = function (x, y, obj) {
isDragging = false;
};
// Game update loop
game.update = function () {
if (!isGameActive) return;
// Check obstacle collisions
for (var i = 0; i < obstacles.length; i++) {
var obstacle = obstacles[i];
if (obstacle.obstacleType === 'spike') {
if (player.intersects(obstacle)) {
LK.getSound('death').play();
isGameActive = false;
resetLevel();
return;
}
} else if (obstacle.obstacleType === 'movingPlatform') {
// Simple platform collision - if player is above platform
if (player.intersects(obstacle) && player.velocityY >= 0 && player.y - 60 <= obstacle.y - 15) {
player.y = obstacle.y - 15;
player.velocityY = 0;
player.isGrounded = true;
}
}
}
// Check enemy collisions
for (var j = 0; j < enemies.length; j++) {
var enemy = enemies[j];
if (player.intersects(enemy)) {
LK.getSound('death').play();
isGameActive = false;
resetLevel();
return;
}
}
// Boss battle mechanics for level 10
if (boss) {
// Boss throws projectiles at player
if (LK.ticks % 120 === 0) {
// Every 2 seconds
var projectile = new Projectile(boss.x, boss.y - 100, player.x, player.y);
projectiles.push(projectile);
game.addChild(projectile);
}
// Update projectiles
for (var pr = projectiles.length - 1; pr >= 0; pr--) {
var proj = projectiles[pr];
// Check if projectile hits player
if (player.intersects(proj)) {
LK.getSound('death').play();
isGameActive = false;
resetLevel();
proj.destroy();
projectiles.splice(pr, 1);
return;
}
// Remove projectiles that go off screen
if (proj.x < -50 || proj.x > 2098 || proj.y < -50 || proj.y > groundY + 100) {
proj.destroy();
projectiles.splice(pr, 1);
}
}
// Check if player throws at boss (when player is near boss)
var distanceToBoss = Math.abs(player.x - boss.x);
if (distanceToBoss < 150) {
// Damage boss
if (boss.lastHealth === undefined) boss.lastHealth = boss.health;
if (boss.lastHealth === boss.health && LK.ticks % 60 === 0) {
boss.health -= 10;
// Update health bar
var healthPercent = boss.health / boss.maxHealth;
bossHealthBar.width = 594 * healthPercent;
// Flash boss red when hit
tween(boss, {
tint: 0xff4444
}, {
duration: 200,
onFinish: function onFinish() {
tween(boss, {
tint: 0xffffff
}, {
duration: 200
});
}
});
}
boss.lastHealth = boss.health;
// Check if boss is defeated
if (boss.health <= 0) {
boss.destroy();
boss = null;
// Hide health bars
if (bossHealthBar) {
bossHealthBar.destroy();
bossHealthBar = null;
}
if (bossHealthBarBg) {
bossHealthBarBg.destroy();
bossHealthBarBg = null;
}
// Complete level
isGameActive = false;
completeLevel();
return;
}
}
}
// Check finish flag collision
if (finishFlag && player.intersects(finishFlag)) {
isGameActive = false;
completeLevel();
}
// Keep player on screen
if (player.x < 0) {
player.x = 0;
player.velocityX = 0;
}
if (player.x > 2048) {
player.x = 2048;
player.velocityX = 0;
}
// Check if player fell off screen
if (player.y > groundY + 200) {
LK.getSound('death').play();
isGameActive = false;
resetLevel();
}
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var BossStickFigure = Container.expand(function (x, y) {
var self = Container.call(this);
// Create red boss body parts - scaled up to make boss bigger
self.head = self.attachAsset('bossHead', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
});
self.body = self.attachAsset('bossBody', {
anchorX: 0.5,
anchorY: 0,
scaleX: 1.5,
scaleY: 1.5
});
self.leftArm = self.attachAsset('bossArm', {
anchorX: 0.5,
anchorY: 0,
scaleX: 1.5,
scaleY: 1.5
});
self.rightArm = self.attachAsset('bossArm', {
anchorX: 0.5,
anchorY: 0,
scaleX: 1.5,
scaleY: 1.5
});
self.leftLeg = self.attachAsset('bossLeg', {
anchorX: 0.5,
anchorY: 0,
scaleX: 1.5,
scaleY: 1.5
});
self.rightLeg = self.attachAsset('bossLeg', {
anchorX: 0.5,
anchorY: 0,
scaleX: 1.5,
scaleY: 1.5
});
// Create horns - scaled up to match boss size
self.leftHorn = self.attachAsset('bossHorn', {
anchorX: 0.5,
anchorY: 1,
scaleX: 1.5,
scaleY: 1.5
});
self.rightHorn = self.attachAsset('bossHorn', {
anchorX: 0.5,
anchorY: 1,
scaleX: 1.5,
scaleY: 1.5
});
// Position body parts - adjusted for larger scale
self.head.x = 0;
self.head.y = -200;
self.body.x = 0;
self.body.y = -165;
self.leftArm.x = -30;
self.leftArm.y = -145;
self.rightArm.x = 30;
self.rightArm.y = -145;
self.leftLeg.x = -18;
self.leftLeg.y = -55;
self.rightLeg.x = 18;
self.rightLeg.y = -55;
// Position horns on head - adjusted for larger scale
self.leftHorn.x = -22;
self.leftHorn.y = -215;
self.rightHorn.x = 22;
self.rightHorn.y = -215;
// Rotate horns to look like triangular horns
self.leftHorn.rotation = -0.3;
self.rightHorn.rotation = 0.3;
self.x = x;
self.y = y;
self.health = 100;
self.maxHealth = 100;
self.lastHealth = 100;
return self;
});
var Cloud = Container.expand(function (x, y) {
var self = Container.call(this);
var graphics = self.attachAsset('cloud', {
anchorX: 0.5,
anchorY: 0.5
});
self.x = x;
self.y = y;
self.speed = Math.random() * 0.5 + 0.2; // Random speed between 0.2 and 0.7
self.alpha = Math.random() * 0.4 + 0.3; // Random opacity between 0.3 and 0.7
// Random scale for variety
var scale = Math.random() * 0.8 + 0.6; // Scale between 0.6 and 1.4
graphics.scaleX = scale;
graphics.scaleY = scale * 0.7; // Make clouds flatter
self.update = function () {
self.x += self.speed;
// Reset cloud position when it goes off screen
if (self.x > 2200) {
self.x = -200;
self.y = Math.random() * 800 + 200; // Random Y between 200 and 1000
self.speed = Math.random() * 0.5 + 0.2;
}
};
return self;
});
var DifficultyButton = Container.expand(function (difficulty, x, y) {
var self = Container.call(this);
self.difficulty = difficulty;
self.isSelected = difficulty === currentDifficulty;
// Create button background
self.background = self.attachAsset(self.isSelected ? 'selectedDifficultyButton' : 'difficultyButton', {
anchorX: 0.5,
anchorY: 0.5
});
// Create button text
self.text = new Text2(difficulty.toUpperCase(), {
size: 32,
fill: 0xffffff
});
self.text.anchor.set(0.5, 0.5);
self.addChild(self.text);
self.x = x;
self.y = y;
self.setSelected = function (selected) {
self.isSelected = selected;
self.removeChild(self.background);
self.background = self.attachAsset(self.isSelected ? 'selectedDifficultyButton' : 'difficultyButton', {
anchorX: 0.5,
anchorY: 0.5
});
// Move text to front
self.removeChild(self.text);
self.addChild(self.text);
};
self.down = function (x, y, obj) {
// Update difficulty
currentDifficulty = self.difficulty;
// Update all buttons' selected state
for (var i = 0; i < difficultyButtons.length; i++) {
difficultyButtons[i].setSelected(difficultyButtons[i].difficulty === currentDifficulty);
}
// Apply difficulty changes to current level
applyDifficultySettings();
};
return self;
});
var EnemyStickFigure = Container.expand(function (x, y, patrolRange) {
var self = Container.call(this);
// Create red body parts
self.head = self.attachAsset('enemyHead', {
anchorX: 0.5,
anchorY: 0.5
});
self.body = self.attachAsset('enemyBody', {
anchorX: 0.5,
anchorY: 0
});
self.leftArm = self.attachAsset('enemyArm', {
anchorX: 0.5,
anchorY: 0
});
self.rightArm = self.attachAsset('enemyArm', {
anchorX: 0.5,
anchorY: 0
});
self.leftLeg = self.attachAsset('enemyLeg', {
anchorX: 0.5,
anchorY: 0
});
self.rightLeg = self.attachAsset('enemyLeg', {
anchorX: 0.5,
anchorY: 0
});
// Position body parts
self.head.x = 0;
self.head.y = -105;
self.body.x = 0;
self.body.y = -90;
self.leftArm.x = -12;
self.leftArm.y = -75;
self.rightArm.x = 12;
self.rightArm.y = -75;
self.leftLeg.x = -8;
self.leftLeg.y = -30;
self.rightLeg.x = 8;
self.rightLeg.y = -30;
// Set initial rotations
self.leftArm.rotation = 0.3;
self.rightArm.rotation = -0.3;
self.x = x;
self.y = y;
self.startX = x;
self.patrolRange = patrolRange || 150;
self.speed = 2.0;
self.direction = 1;
self.animationTime = 0;
self.state = 'patrol'; // 'patrol', 'chase', 'returning'
self.detectionRange = 300; // How far enemy can see player
self.chaseSpeed = 4.0; // Speed when chasing
self.patrolSpeed = 2.0; // Speed when patrolling
self.lastPlayerX = 0; // Track last known player position
self.returnTimer = 0; // Timer for returning to patrol
self.animateWalk = function () {
self.animationTime += 0.2;
var walkCycle = Math.sin(self.animationTime);
// Animate legs
tween(self.leftLeg, {
rotation: walkCycle * 0.4
}, {
duration: 150,
easing: tween.linear
});
tween(self.rightLeg, {
rotation: -walkCycle * 0.4
}, {
duration: 150,
easing: tween.linear
});
// Animate arms
tween(self.leftArm, {
rotation: -walkCycle * 0.2 + 0.3
}, {
duration: 150,
easing: tween.linear
});
tween(self.rightArm, {
rotation: walkCycle * 0.2 - 0.3
}, {
duration: 150,
easing: tween.linear
});
};
self.update = function () {
// Get distance to player
var distanceToPlayer = Math.abs(player.x - self.x);
var playerOnMovingPlatform = false;
// Check if player is on a moving platform
for (var p = 0; p < obstacles.length; p++) {
if (obstacles[p].obstacleType === 'movingPlatform') {
if (player.intersects(obstacles[p]) && player.velocityY >= 0 && player.y - 60 <= obstacles[p].y - 15) {
playerOnMovingPlatform = true;
break;
}
}
}
// State machine for enemy behavior
if (self.state === 'patrol') {
// Check if player is in detection range and not on moving platform
if (distanceToPlayer <= self.detectionRange && !playerOnMovingPlatform) {
self.state = 'chase';
self.lastPlayerX = player.x;
} else {
// Normal patrol movement
self.x += self.direction * self.patrolSpeed;
// Check patrol bounds
if (self.x > self.startX + self.patrolRange) {
self.direction = -1;
} else if (self.x < self.startX - self.patrolRange) {
self.direction = 1;
}
}
} else if (self.state === 'chase') {
// Chase the player
if (distanceToPlayer > self.detectionRange * 1.5 || playerOnMovingPlatform) {
// Player too far or on moving platform - start returning
self.state = 'returning';
self.returnTimer = 60; // Return for 1 second at 60fps
} else {
// Move towards player
if (player.x > self.x) {
self.direction = 1;
} else {
self.direction = -1;
}
self.x += self.direction * self.chaseSpeed;
self.lastPlayerX = player.x;
}
} else if (self.state === 'returning') {
// Return to patrol area
self.returnTimer--;
if (self.returnTimer <= 0) {
self.state = 'patrol';
} else {
// Move back towards patrol center
if (self.startX > self.x) {
self.direction = 1;
} else if (self.startX < self.x) {
self.direction = -1;
}
self.x += self.direction * self.patrolSpeed;
}
}
// Animate walking
self.animateWalk();
};
return self;
});
var FinishFlag = Container.expand(function (x, y) {
var self = Container.call(this);
var graphics = self.attachAsset('finishFlag', {
anchorX: 0.5,
anchorY: 1.0
});
self.x = x;
self.y = y;
return self;
});
var Obstacle = Container.expand(function (type, x, y) {
var self = Container.call(this);
self.obstacleType = type;
if (type === 'spike') {
var graphics = self.attachAsset('spike', {
anchorX: 0.5,
anchorY: 1.0
});
} else if (type === 'movingPlatform') {
var graphics = self.attachAsset('movingPlatform', {
anchorX: 0.5,
anchorY: 0.5
});
self.direction = 1;
self.speed = 2;
self.startX = x;
self.range = 200;
}
self.x = x;
self.y = y;
self.update = function () {
if (self.obstacleType === 'movingPlatform') {
self.x += self.direction * self.speed;
if (self.x > self.startX + self.range || self.x < self.startX - self.range) {
self.direction *= -1;
}
}
};
return self;
});
var Projectile = Container.expand(function (x, y, targetX, targetY) {
var self = Container.call(this);
var graphics = self.attachAsset('projectile', {
anchorX: 0.5,
anchorY: 0.5
});
self.x = x;
self.y = y;
// Calculate direction to target
var deltaX = targetX - x;
var deltaY = targetY - y;
var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
self.velocityX = deltaX / distance * 8;
self.velocityY = deltaY / distance * 8;
self.update = function () {
self.x += self.velocityX;
self.y += self.velocityY;
};
return self;
});
var StickFigure = Container.expand(function () {
var self = Container.call(this);
// Create body parts
self.head = self.attachAsset('stickFigureHead', {
anchorX: 0.5,
anchorY: 0.5
});
self.body = self.attachAsset('stickFigureBody', {
anchorX: 0.5,
anchorY: 0
});
self.leftArm = self.attachAsset('stickFigureArm', {
anchorX: 0.5,
anchorY: 0
});
self.rightArm = self.attachAsset('stickFigureArm', {
anchorX: 0.5,
anchorY: 0
});
self.leftLeg = self.attachAsset('stickFigureLeg', {
anchorX: 0.5,
anchorY: 0
});
self.rightLeg = self.attachAsset('stickFigureLeg', {
anchorX: 0.5,
anchorY: 0
});
// Position body parts
self.head.x = 0;
self.head.y = -105;
self.body.x = 0;
self.body.y = -90;
self.leftArm.x = -12;
self.leftArm.y = -75;
self.rightArm.x = 12;
self.rightArm.y = -75;
self.leftLeg.x = -8;
self.leftLeg.y = -30;
self.rightLeg.x = 8;
self.rightLeg.y = -30;
// Set initial rotations
self.leftArm.rotation = 0.2;
self.rightArm.rotation = -0.2;
self.leftLeg.rotation = 0;
self.rightLeg.rotation = 0;
self.velocityY = 0;
self.velocityX = 0;
self.isGrounded = false;
self.jumpPower = -35;
self.gravity = 1.2;
self.speed = 12;
self.animationTime = 0;
self.lastVelocityX = 0;
self.animateWalk = function () {
if (Math.abs(self.velocityX) > 0.5) {
// Walking animation
self.animationTime += 0.3;
var walkCycle = Math.sin(self.animationTime);
// Animate legs
tween(self.leftLeg, {
rotation: walkCycle * 0.5
}, {
duration: 100,
easing: tween.linear
});
tween(self.rightLeg, {
rotation: -walkCycle * 0.5
}, {
duration: 100,
easing: tween.linear
});
// Animate arms opposite to legs
tween(self.leftArm, {
rotation: -walkCycle * 0.3 + 0.2
}, {
duration: 100,
easing: tween.linear
});
tween(self.rightArm, {
rotation: walkCycle * 0.3 - 0.2
}, {
duration: 100,
easing: tween.linear
});
} else {
// Idle position
tween(self.leftArm, {
rotation: 0.2
}, {
duration: 300,
easing: tween.easeOut
});
tween(self.rightArm, {
rotation: -0.2
}, {
duration: 300,
easing: tween.easeOut
});
tween(self.leftLeg, {
rotation: 0
}, {
duration: 300,
easing: tween.easeOut
});
tween(self.rightLeg, {
rotation: 0
}, {
duration: 300,
easing: tween.easeOut
});
}
};
self.animateJump = function () {
// Jump animation - arms up, legs bent
tween(self.leftArm, {
rotation: -1.2
}, {
duration: 200,
easing: tween.easeOut
});
tween(self.rightArm, {
rotation: 1.2
}, {
duration: 200,
easing: tween.easeOut
});
tween(self.leftLeg, {
rotation: 0.8
}, {
duration: 200,
easing: tween.easeOut
});
tween(self.rightLeg, {
rotation: -0.8
}, {
duration: 200,
easing: tween.easeOut
});
};
self.update = function () {
// Apply gravity
self.velocityY += self.gravity;
// Apply velocity
self.x += self.velocityX;
self.y += self.velocityY;
// Reduce horizontal velocity (friction)
self.velocityX *= 0.85;
// Animation logic
if (!self.isGrounded) {
// In air - keep jump pose
} else if (Math.abs(self.velocityX) !== Math.abs(self.lastVelocityX)) {
// Velocity changed, update animation
self.animateWalk();
}
self.lastVelocityX = self.velocityX;
// Ground collision
if (self.y >= groundY) {
var wasInAir = !self.isGrounded;
self.y = groundY;
self.velocityY = 0;
self.isGrounded = true;
// Landing animation
if (wasInAir) {
self.animateWalk();
}
}
};
self.jump = function () {
if (self.isGrounded) {
self.velocityY = self.jumpPower;
self.isGrounded = false;
self.animateJump();
LK.getSound('jump').play();
}
};
self.moveLeft = function () {
self.velocityX = -self.speed;
};
self.moveRight = function () {
self.velocityX = self.speed;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
var currentLevel = 1;
var maxLevels = 10;
var groundY = 2500;
var player;
var obstacles = [];
var enemies = [];
var finishFlag;
var isGameActive = true;
var lives = 3;
var clouds = [];
var boss;
var projectiles = [];
var bossHealthBar;
var bossHealthBarBg;
var currentDifficulty = 'medium'; // Default difficulty
var difficultyButtons = [];
var difficultyContainer;
// Create background clouds
function createClouds() {
for (var i = 0; i < 8; i++) {
var cloudX = Math.random() * 2400 - 200; // Spread across wider area
var cloudY = Math.random() * 800 + 200; // Y between 200 and 1000
var cloud = new Cloud(cloudX, cloudY);
clouds.push(cloud);
game.addChild(cloud);
}
}
// Create difficulty selection bar
function createDifficultyBar() {
// Create container for difficulty bar
difficultyContainer = new Container();
difficultyContainer.x = 120;
difficultyContainer.y = 2600; // Bottom left area
game.addChild(difficultyContainer);
// Create difficulty label
var difficultyLabel = new Text2('DIFFICULTY:', {
size: 28,
fill: 0x000000
});
difficultyLabel.anchor.set(0, 0.5);
difficultyLabel.x = 0;
difficultyLabel.y = -60;
difficultyContainer.addChild(difficultyLabel);
// Create difficulty buttons
var difficulties = ['easy', 'medium', 'hard'];
var buttonSpacing = 220;
for (var i = 0; i < difficulties.length; i++) {
var button = new DifficultyButton(difficulties[i], i * buttonSpacing, 0);
difficultyButtons.push(button);
difficultyContainer.addChild(button);
}
}
// Apply difficulty settings to game
function applyDifficultySettings() {
if (currentDifficulty === 'easy') {
// Easy mode - slower enemies, more lives, lower jump required
for (var i = 0; i < enemies.length; i++) {
enemies[i].chaseSpeed = 2.5;
enemies[i].patrolSpeed = 1.5;
}
if (player) {
player.jumpPower = -38; // Higher jump
player.speed = 14; // Faster movement
}
} else if (currentDifficulty === 'medium') {
// Medium mode - default settings
for (var i = 0; i < enemies.length; i++) {
enemies[i].chaseSpeed = 4.0;
enemies[i].patrolSpeed = 2.0;
}
if (player) {
player.jumpPower = -35;
player.speed = 12;
}
} else if (currentDifficulty === 'hard') {
// Hard mode - faster enemies, lower jump, slower movement
for (var i = 0; i < enemies.length; i++) {
enemies[i].chaseSpeed = 5.5;
enemies[i].patrolSpeed = 2.8;
}
if (player) {
player.jumpPower = -32; // Lower jump
player.speed = 10; // Slower movement
}
}
}
// UI Elements
var levelText = new Text2('Level 1', {
size: 80,
fill: 0x000000
});
levelText.anchor.set(0.5, 0);
LK.gui.top.addChild(levelText);
var livesText = new Text2('Lives: 3', {
size: 60,
fill: 0xFF0000
});
livesText.anchor.set(1, 0);
LK.gui.topRight.addChild(livesText);
// Create ground platforms
function createGround() {
for (var i = 0; i < 15; i++) {
var groundPiece = LK.getAsset('ground', {
anchorX: 0,
anchorY: 1.0
});
groundPiece.x = i * 300;
groundPiece.y = groundY;
game.addChild(groundPiece);
}
}
// Level configurations
var levelConfigs = [
// Level 1 - Simple spikes
{
obstacles: [{
type: 'spike',
x: 600,
y: groundY
}, {
type: 'spike',
x: 1200,
y: groundY
}],
finish: 1800
},
// Level 2 - More spikes
{
obstacles: [{
type: 'spike',
x: 500,
y: groundY
}, {
type: 'spike',
x: 800,
y: groundY
}, {
type: 'spike',
x: 1100,
y: groundY
}],
finish: 1600
},
// Level 3 - Moving platform with enemy
{
obstacles: [{
type: 'movingPlatform',
x: 700,
y: groundY - 200
}, {
type: 'spike',
x: 1400,
y: groundY
}],
enemies: [{
x: 1000,
y: groundY,
patrolRange: 100
}],
finish: 1800
},
// Level 4 - Multiple moving platforms
{
obstacles: [{
type: 'movingPlatform',
x: 500,
y: groundY - 150
}, {
type: 'movingPlatform',
x: 1000,
y: groundY - 250
}],
finish: 1600
},
// Level 5 - Mixed obstacles with enemies
{
obstacles: [{
type: 'spike',
x: 400,
y: groundY
}, {
type: 'movingPlatform',
x: 700,
y: groundY - 180
}, {
type: 'spike',
x: 1200,
y: groundY
}],
enemies: [{
x: 600,
y: groundY,
patrolRange: 80
}, {
x: 1400,
y: groundY,
patrolRange: 120
}],
finish: 1800
},
// Level 6 - Dense spikes
{
obstacles: [{
type: 'spike',
x: 400,
y: groundY
}, {
type: 'spike',
x: 500,
y: groundY
}, {
type: 'spike',
x: 700,
y: groundY
}, {
type: 'spike',
x: 800,
y: groundY
}],
finish: 1200
},
// Level 7 - Fast moving platforms
{
obstacles: [{
type: 'movingPlatform',
x: 500,
y: groundY - 200
}, {
type: 'movingPlatform',
x: 900,
y: groundY - 150
}, {
type: 'spike',
x: 1300,
y: groundY
}],
finish: 1600
},
// Level 8 - High platforms
{
obstacles: [{
type: 'movingPlatform',
x: 400,
y: groundY - 300
}, {
type: 'movingPlatform',
x: 800,
y: groundY - 400
}, {
type: 'spike',
x: 1200,
y: groundY
}],
finish: 1500
},
// Level 9 - Complex pattern
{
obstacles: [{
type: 'spike',
x: 350,
y: groundY
}, {
type: 'movingPlatform',
x: 600,
y: groundY - 250
}, {
type: 'spike',
x: 900,
y: groundY
}, {
type: 'movingPlatform',
x: 1200,
y: groundY - 180
}],
finish: 1600
},
// Level 10 - Boss battle
{
obstacles: [{
type: 'spike',
x: 300,
y: groundY
}, {
type: 'spike',
x: 400,
y: groundY
}],
boss: {
x: 1500,
y: groundY
},
finish: 1800
}];
function initializeLevel(level) {
// Clear existing obstacles
for (var i = obstacles.length - 1; i >= 0; i--) {
obstacles[i].destroy();
obstacles.splice(i, 1);
}
// Clear existing enemies
for (var k = enemies.length - 1; k >= 0; k--) {
enemies[k].destroy();
enemies.splice(k, 1);
}
// Clear existing projectiles
for (var p = projectiles.length - 1; p >= 0; p--) {
projectiles[p].destroy();
projectiles.splice(p, 1);
}
// Clear boss
if (boss) {
boss.destroy();
boss = null;
}
// Clear boss health bar
if (bossHealthBar) {
bossHealthBar.destroy();
bossHealthBar = null;
}
if (bossHealthBarBg) {
bossHealthBarBg.destroy();
bossHealthBarBg = null;
}
if (finishFlag) {
finishFlag.destroy();
}
// Create new obstacles based on level config
var config = levelConfigs[level - 1];
for (var j = 0; j < config.obstacles.length; j++) {
var obstacleConfig = config.obstacles[j];
var obstacle = new Obstacle(obstacleConfig.type, obstacleConfig.x, obstacleConfig.y);
if (obstacleConfig.type === 'movingPlatform' && level >= 7) {
obstacle.speed = 3; // Faster platforms in later levels
}
obstacles.push(obstacle);
game.addChild(obstacle);
}
// Create enemies if they exist in config
if (config.enemies) {
for (var m = 0; m < config.enemies.length; m++) {
var enemyConfig = config.enemies[m];
var enemy = new EnemyStickFigure(enemyConfig.x, enemyConfig.y, enemyConfig.patrolRange);
enemies.push(enemy);
game.addChild(enemy);
}
}
// Create boss if level 10
if (level === 10 && config.boss) {
boss = new BossStickFigure(config.boss.x, config.boss.y);
game.addChild(boss);
// Create boss health bar background
bossHealthBarBg = LK.getAsset('ground', {
anchorX: 0.5,
anchorY: 0.5
});
bossHealthBarBg.width = 600;
bossHealthBarBg.height = 30;
bossHealthBarBg.x = 2048 / 2;
bossHealthBarBg.y = 150;
bossHealthBarBg.tint = 0x333333;
game.addChild(bossHealthBarBg);
// Create boss health bar
bossHealthBar = LK.getAsset('ground', {
anchorX: 0,
anchorY: 0.5
});
bossHealthBar.width = 594;
bossHealthBar.height = 24;
bossHealthBar.x = 2048 / 2 - 297;
bossHealthBar.y = 150;
bossHealthBar.tint = 0xff0000;
game.addChild(bossHealthBar);
}
// Create finish flag
finishFlag = new FinishFlag(config.finish, groundY);
game.addChild(finishFlag);
// Reset player position
player.x = 200;
player.y = groundY;
player.velocityX = 0;
player.velocityY = 0;
player.isGrounded = true;
// Update UI
levelText.setText('Level ' + level);
livesText.setText('Lives: ' + lives);
isGameActive = true;
// Apply difficulty settings
applyDifficultySettings();
}
function resetLevel() {
lives--;
livesText.setText('Lives: ' + lives);
if (lives <= 0) {
LK.showGameOver();
return;
}
// Flash screen red
LK.effects.flashScreen(0xff0000, 500);
// Reset player position after a short delay
LK.setTimeout(function () {
player.x = 200;
player.y = groundY;
player.velocityX = 0;
player.velocityY = 0;
player.isGrounded = true;
isGameActive = true;
}, 500);
}
function completeLevel() {
LK.getSound('levelComplete').play();
LK.effects.flashScreen(0x00ff00, 800);
if (currentLevel >= maxLevels) {
// Game completed
LK.setTimeout(function () {
LK.showYouWin();
}, 800);
} else {
currentLevel++;
LK.setTimeout(function () {
initializeLevel(currentLevel);
}, 800);
}
}
// Initialize game
createClouds();
createGround();
createDifficultyBar();
player = new StickFigure();
game.addChild(player);
initializeLevel(currentLevel);
// Game controls
game.down = function (x, y, obj) {
if (isGameActive) {
player.jump();
}
};
var dragStartX = 0;
var isDragging = false;
game.move = function (x, y, obj) {
if (isGameActive && isDragging) {
var deltaX = x - dragStartX;
if (deltaX < -50) {
player.moveLeft();
} else if (deltaX > 50) {
player.moveRight();
}
} else if (isGameActive) {
dragStartX = x;
isDragging = true;
}
};
game.up = function (x, y, obj) {
isDragging = false;
};
// Game update loop
game.update = function () {
if (!isGameActive) return;
// Check obstacle collisions
for (var i = 0; i < obstacles.length; i++) {
var obstacle = obstacles[i];
if (obstacle.obstacleType === 'spike') {
if (player.intersects(obstacle)) {
LK.getSound('death').play();
isGameActive = false;
resetLevel();
return;
}
} else if (obstacle.obstacleType === 'movingPlatform') {
// Simple platform collision - if player is above platform
if (player.intersects(obstacle) && player.velocityY >= 0 && player.y - 60 <= obstacle.y - 15) {
player.y = obstacle.y - 15;
player.velocityY = 0;
player.isGrounded = true;
}
}
}
// Check enemy collisions
for (var j = 0; j < enemies.length; j++) {
var enemy = enemies[j];
if (player.intersects(enemy)) {
LK.getSound('death').play();
isGameActive = false;
resetLevel();
return;
}
}
// Boss battle mechanics for level 10
if (boss) {
// Boss throws projectiles at player
if (LK.ticks % 120 === 0) {
// Every 2 seconds
var projectile = new Projectile(boss.x, boss.y - 100, player.x, player.y);
projectiles.push(projectile);
game.addChild(projectile);
}
// Update projectiles
for (var pr = projectiles.length - 1; pr >= 0; pr--) {
var proj = projectiles[pr];
// Check if projectile hits player
if (player.intersects(proj)) {
LK.getSound('death').play();
isGameActive = false;
resetLevel();
proj.destroy();
projectiles.splice(pr, 1);
return;
}
// Remove projectiles that go off screen
if (proj.x < -50 || proj.x > 2098 || proj.y < -50 || proj.y > groundY + 100) {
proj.destroy();
projectiles.splice(pr, 1);
}
}
// Check if player throws at boss (when player is near boss)
var distanceToBoss = Math.abs(player.x - boss.x);
if (distanceToBoss < 150) {
// Damage boss
if (boss.lastHealth === undefined) boss.lastHealth = boss.health;
if (boss.lastHealth === boss.health && LK.ticks % 60 === 0) {
boss.health -= 10;
// Update health bar
var healthPercent = boss.health / boss.maxHealth;
bossHealthBar.width = 594 * healthPercent;
// Flash boss red when hit
tween(boss, {
tint: 0xff4444
}, {
duration: 200,
onFinish: function onFinish() {
tween(boss, {
tint: 0xffffff
}, {
duration: 200
});
}
});
}
boss.lastHealth = boss.health;
// Check if boss is defeated
if (boss.health <= 0) {
boss.destroy();
boss = null;
// Hide health bars
if (bossHealthBar) {
bossHealthBar.destroy();
bossHealthBar = null;
}
if (bossHealthBarBg) {
bossHealthBarBg.destroy();
bossHealthBarBg = null;
}
// Complete level
isGameActive = false;
completeLevel();
return;
}
}
}
// Check finish flag collision
if (finishFlag && player.intersects(finishFlag)) {
isGameActive = false;
completeLevel();
}
// Keep player on screen
if (player.x < 0) {
player.x = 0;
player.velocityX = 0;
}
if (player.x > 2048) {
player.x = 2048;
player.velocityX = 0;
}
// Check if player fell off screen
if (player.y > groundY + 200) {
LK.getSound('death').play();
isGameActive = false;
resetLevel();
}
};