/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
currentLevel: 1,
unlockedLevels: 1,
musicVolume: 1,
soundVolume: 1,
highScore: 0,
lastCompletedLevel: 0,
coins: 0,
selectedSkin: "default",
ownedSkins: ["default"],
selectedEnemySkin: "default",
ownedEnemySkins: ["default"],
selectedBossSkin: "default",
ownedBossSkins: ["default"],
selectedFlyingSkin: "default",
ownedFlyingSkins: ["default"],
selectedVoiceSkin: "default",
ownedVoiceSkins: ["default"]
});
/****
* Classes
****/
var Arrow = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('arrow', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocityX = 0;
self.velocityY = 0;
self.lifetime = 240; // 4 seconds at 60fps
self.damage = 20;
self.update = function () {
// Homing behavior - track nearest enemy
var nearestEnemy = null;
var nearestDistance = Infinity;
// Find nearest enemy
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < nearestDistance) {
nearestDistance = distance;
nearestEnemy = enemy;
}
}
// Adjust velocity towards nearest enemy if found
if (nearestEnemy && nearestDistance > 50) {
var dx = nearestEnemy.x - self.x;
var dy = nearestEnemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Normalize direction vector
var dirX = dx / distance;
var dirY = dy / distance;
// Homing strength (how aggressively it turns)
var homingStrength = 0.3;
var arrowSpeed = 12;
// Blend current velocity with target direction using tween for smooth turning
self.velocityX += (dirX * arrowSpeed - self.velocityX) * homingStrength;
self.velocityY += (dirY * arrowSpeed - self.velocityY) * homingStrength;
// Maintain consistent speed
var currentSpeed = Math.sqrt(self.velocityX * self.velocityX + self.velocityY * self.velocityY);
if (currentSpeed > 0) {
self.velocityX = self.velocityX / currentSpeed * arrowSpeed;
self.velocityY = self.velocityY / currentSpeed * arrowSpeed;
}
}
self.x += self.velocityX;
self.y += self.velocityY;
self.lifetime--;
// Rotate arrow to match trajectory
if (self.velocityX !== 0) {
graphics.rotation = Math.atan2(self.velocityY, self.velocityX);
}
// Calculate distance traveled from start position
if (self.startX === undefined) {
self.startX = self.x;
self.startY = self.y;
}
var distanceTraveled = Math.sqrt(Math.pow(self.x - self.startX, 2) + Math.pow(self.y - self.startY, 2));
var maxRange = 400; // Short range limit
// Remove if lifetime expired, off screen, or exceeded range
if (self.lifetime <= 0 || self.x < -50 || self.x > 2098 || self.y > 2100 || distanceTraveled > maxRange) {
self.destroy();
}
};
return self;
});
var Boss = Container.expand(function () {
var self = Container.call(this);
// Apply selected boss skin
var skinColor = storage.selectedBossSkin || 'default';
var bossSkinColors = {
'default': {
main: 0x800080,
accent: 0x9932CC
},
'crimson': {
main: 0xDC143C,
accent: 0xFF6347
},
'shadow': {
main: 0x2F2F2F,
accent: 0x696969
},
'golden': {
main: 0xFFD700,
accent: 0xFFA500
},
'emerald': {
main: 0x50C878,
accent: 0x32CD32
},
'cyber': {
main: 0x00CED1,
accent: 0x00FFFF
}
};
var currentSkin = bossSkinColors[skinColor] || bossSkinColors['default'];
var graphics = self.attachAsset('boss', {
anchorX: 0.5,
anchorY: 1.0,
tint: currentSkin.main
});
// Health bar
var healthBarBg = self.attachAsset('platform', {
width: 160,
height: 20,
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -220,
tint: 0x000000
});
var healthBarFill = self.attachAsset('platform', {
width: 156,
height: 16,
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -220,
tint: currentSkin.accent || 0xFF0000
});
self.health = 150;
self.maxHealth = 150;
self.velocityX = 0;
self.velocityY = 0;
self.onGround = false;
self.speed = 3;
self.direction = 1;
self.attackCooldown = 0;
self.animationTick = 0;
self.phase = 1; // Boss has different phases
self.epicMusicTriggered = false;
self.update = function () {
// Apply gravity
if (!self.onGround) {
self.velocityY += 0.8;
}
// Enhanced Boss AI - different behavior based on health with range detection
var distanceToPlayer = Math.abs(self.x - player.x);
var verticalDistance = Math.abs(self.y - player.y);
var healthPercent = self.health / self.maxHealth;
var attackRange = healthPercent > 0.5 ? 250 : 350; // Longer range in phase 2
var aggressiveRange = healthPercent > 0.5 ? 120 : 180;
if (healthPercent > 0.5) {
// Phase 1: Enhanced chase and attack with range detection
if (distanceToPlayer < attackRange && distanceToPlayer > aggressiveRange) {
// Pursuit mode - faster movement when player detected
var pursuitSpeed = self.speed * 1.3;
if (player.x > self.x) {
self.direction = 1;
self.velocityX = pursuitSpeed;
} else {
self.direction = -1;
self.velocityX = -pursuitSpeed;
}
// Boss can jump to platforms to reach player
if (player.y < self.y - 100 && self.onGround && Math.random() < 0.02) {
// Find platform in direction of player
var targetPlatform = null;
var targetDirection = player.x > self.x ? 1 : -1;
for (var p = 0; p < platforms.length; p++) {
var platform = platforms[p];
var platformInDirection = targetDirection > 0 ? platform.x > self.x : platform.x < self.x;
var platformDistance = Math.abs(platform.x - self.x);
if (platformInDirection && platform.y < self.y && platform.y > player.y - 100 && platformDistance < 400) {
targetPlatform = platform;
break;
}
}
if (targetPlatform) {
self.velocityY = -20; // Powerful boss jump
self.velocityX = targetDirection * (self.speed + 3);
self.onGround = false;
LK.getSound('boss_attack').play(); // Use unique boss attack sound for boss jump
}
}
} else {
self.velocityX = 0;
if (self.attackCooldown <= 0) {
self.groundSlam();
self.attackCooldown = 120;
}
}
} else {
// Phase 2: Faster, more aggressive - trigger epic music transition
if (!self.epicMusicTriggered) {
self.epicMusicTriggered = true;
// Play boss music with higher intensity for final phase
LK.playMusic('boss_music', {
fade: {
start: storage.musicVolume,
end: storage.musicVolume * 1.2,
duration: 500
}
});
}
self.speed = 4;
if (distanceToPlayer < attackRange && distanceToPlayer > aggressiveRange) {
// Enhanced pursuit in phase 2 with speed boost
var phase2Speed = self.speed * 1.5;
if (player.x > self.x) {
self.direction = 1;
self.velocityX = phase2Speed;
} else {
self.direction = -1;
self.velocityX = -phase2Speed;
}
// Highly aggressive platform jumping and pursuit in phase 2
if (self.onGround && (verticalDistance > 60 || Math.random() < 0.06)) {
// Find best platform for tactical advantage
var bestPlatform = null;
var bestScore = Infinity;
for (var p = 0; p < platforms.length; p++) {
var platform = platforms[p];
var platformDistance = Math.abs(platform.x - self.x);
var platformToPlayerDistance = Math.abs(platform.x - player.x);
var tacticalScore = platformDistance + platformToPlayerDistance * 0.3;
if (platform.y < self.y && platform.y > player.y - 120 && platformDistance < 500) {
if (tacticalScore < bestScore) {
bestScore = tacticalScore;
bestPlatform = platform;
}
}
}
if (bestPlatform) {
// Powerful strategic jump towards best platform
var jumpDirection = bestPlatform.x > self.x ? 1 : -1;
self.velocityY = -24; // Even more powerful jump
self.velocityX = jumpDirection * (self.speed + 5);
self.onGround = false;
LK.getSound('boss_attack').play();
} else {
// Direct pursuit jump if no platforms available
var targetDirection = player.x > self.x ? 1 : -1;
self.velocityY = -22;
self.velocityX = targetDirection * (self.speed + 4);
self.onGround = false;
LK.getSound('boss_attack').play();
}
// Create screen shake effect for dramatic boss jump
tween(game, {
x: game.x + (Math.random() - 0.5) * 20
}, {
duration: 100,
onFinish: function onFinish() {
tween(game, {
x: 0
}, {
duration: 100
});
}
});
}
} else {
self.velocityX = 0;
if (self.attackCooldown <= 0) {
self.multiAttack();
self.attackCooldown = 180;
}
}
}
// Apply velocity
self.x += self.velocityX;
self.y += self.velocityY;
self.onGround = false;
// Update cooldowns
if (self.attackCooldown > 0) {
self.attackCooldown--;
}
self.animationTick++;
// Face direction
graphics.scaleX = self.direction > 0 ? 1 : -1;
// Breathing animation
var breathCycle = Math.sin(self.animationTick * 0.05);
graphics.scaleY = 1 + breathCycle * 0.05;
};
self.groundSlam = function () {
// Ground slam attack
tween(graphics, {
scaleY: 0.8
}, {
duration: 200,
onFinish: function onFinish() {
tween(graphics, {
scaleY: 1.2
}, {
duration: 100,
onFinish: function onFinish() {
tween(graphics, {
scaleY: 1
}, {
duration: 200
});
// Damage player if close
if (Math.abs(self.x - player.x) < 120) {
player.takeDamage(20);
player.velocityX += (player.x > self.x ? 1 : -1) * 15;
player.velocityY = -10;
}
}
});
}
});
LK.getSound('boss_attack').play();
};
self.multiAttack = function () {
// Multiple projectiles in different directions
for (var i = 0; i < 5; i++) {
var bullet = new EnemyBullet();
bullet.x = self.x;
bullet.y = self.y - 100;
var angle = (i - 2) * 0.5; // Spread shots
bullet.velocityX = Math.cos(angle) * 8 * self.direction;
bullet.velocityY = Math.sin(angle) * 8 - 2;
enemyBullets.push(bullet);
game.addChild(bullet);
}
LK.getSound('boss_attack').play();
};
self.takeDamage = function (damage) {
self.health -= damage;
// Update health bar
var healthPercent = Math.max(0, self.health / self.maxHealth);
healthBarFill.width = 156 * healthPercent;
// Flash effect
tween(graphics, {
tint: 0xFFFFFF
}, {
duration: 150,
onFinish: function onFinish() {
tween(graphics, {
tint: 0x800080
}, {
duration: 150
});
}
});
LK.getSound('enemy_hit').play();
if (self.health <= 0) {
LK.getSound('enemy_death').play();
self.destroy();
return true;
}
return false;
};
return self;
});
var EnemyBullet = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('enemyBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocityX = 0;
self.velocityY = 0;
self.lifetime = 180;
self.update = function () {
self.x += self.velocityX;
self.y += self.velocityY;
self.lifetime--;
// Calculate distance traveled from start position
if (self.startX === undefined) {
self.startX = self.x;
self.startY = self.y;
}
var distanceTraveled = Math.sqrt(Math.pow(self.x - self.startX, 2) + Math.pow(self.y - self.startY, 2));
var maxRange = 300; // Short range limit for enemy bullets
// Remove if lifetime expired, off screen, or exceeded range
if (self.lifetime <= 0 || self.x < -50 || self.x > 2098 || self.y > 2800 || self.y < -100 || distanceTraveled > maxRange) {
self.destroy();
}
};
return self;
});
var FireBoss = Container.expand(function () {
var self = Container.call(this);
// Apply selected boss skin for fire boss
var skinColor = storage.selectedBossSkin || 'default';
var fireBossSkinColors = {
'default': {
main: 0xFF4500,
flame: 0xFF6347
},
'crimson': {
main: 0xDC143C,
flame: 0xFF1493
},
'shadow': {
main: 0x8B008B,
flame: 0xFF00FF
},
'golden': {
main: 0xFFD700,
flame: 0xFFA500
},
'emerald': {
main: 0x32CD32,
flame: 0x00FF00
},
'cyber': {
main: 0x00CED1,
flame: 0x00BFFF
}
};
var currentSkin = fireBossSkinColors[skinColor] || fireBossSkinColors['default'];
var graphics = self.attachAsset('boss', {
anchorX: 0.5,
anchorY: 1.0,
tint: currentSkin.main
});
// Health bar
var healthBarBg = self.attachAsset('platform', {
width: 160,
height: 20,
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -220,
tint: 0x000000
});
var healthBarFill = self.attachAsset('platform', {
width: 156,
height: 16,
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -220,
tint: currentSkin.flame || 0xFF6347
});
self.health = 250;
self.maxHealth = 250;
self.velocityX = 0;
self.velocityY = 0;
self.onGround = false;
self.speed = 2;
self.direction = 1;
self.attackCooldown = 0;
self.chargeAttackCooldown = 0;
self.animationTick = 0;
self.update = function () {
// Apply gravity
if (!self.onGround) {
self.velocityY += 0.8;
}
var distanceToPlayer = Math.abs(self.x - player.x);
var healthPercent = self.health / self.maxHealth;
// Charge attack
if (self.chargeAttackCooldown <= 0 && distanceToPlayer < 400) {
self.chargeAttack();
self.chargeAttackCooldown = 400;
}
// Fire rain attack
if (self.attackCooldown <= 0) {
self.fireRain();
self.attackCooldown = healthPercent > 0.5 ? 180 : 120;
}
// Slower but powerful movement
if (player.x > self.x) {
self.direction = 1;
self.velocityX = self.speed;
} else {
self.direction = -1;
self.velocityX = -self.speed;
}
// Apply velocity
self.x += self.velocityX;
self.y += self.velocityY;
self.onGround = false;
// Update cooldowns
if (self.attackCooldown > 0) {
self.attackCooldown--;
}
if (self.chargeAttackCooldown > 0) {
self.chargeAttackCooldown--;
}
self.animationTick++;
// Fire glow effect
var glowIntensity = 0.8 + Math.sin(self.animationTick * 0.15) * 0.2;
graphics.scaleY = glowIntensity;
graphics.scaleX = self.direction > 0 ? glowIntensity : -glowIntensity;
};
self.chargeAttack = function () {
// Powerful charge towards player
var chargeDirection = player.x > self.x ? 1 : -1;
self.velocityX = chargeDirection * 15;
self.velocityY = -5;
// Visual effect
tween(graphics, {
tint: 0xFFFF00
}, {
duration: 300,
onFinish: function onFinish() {
tween(graphics, {
tint: 0xFF4500
}, {
duration: 200
});
}
});
LK.getSound('fire_boss_attack').play();
};
self.fireRain = function () {
// Create multiple fire projectiles falling from above
for (var i = 0; i < 5; i++) {
var bullet = new EnemyBullet();
bullet.x = player.x + (i - 2) * 100 + Math.random() * 50 - 25;
bullet.y = player.y - 400;
bullet.velocityX = Math.random() * 2 - 1;
bullet.velocityY = 8;
// Make fire bullets orange/red
bullet.tint = 0xFF6347;
enemyBullets.push(bullet);
game.addChild(bullet);
}
LK.getSound('fire_boss_attack').play();
};
self.takeDamage = function (damage) {
self.health -= damage;
var healthPercent = Math.max(0, self.health / self.maxHealth);
healthBarFill.width = 156 * healthPercent;
// Flash effect
tween(graphics, {
tint: 0xFFFFFF
}, {
duration: 150,
onFinish: function onFinish() {
tween(graphics, {
tint: 0xFF4500
}, {
duration: 150
});
}
});
LK.getSound('enemy_hit').play();
if (self.health <= 0) {
LK.getSound('enemy_death').play();
self.destroy();
return true;
}
return false;
};
return self;
});
var FlyingEnemy = Container.expand(function () {
var self = Container.call(this);
// Create flying enemy body parts with skin-specific assets
var skinColor = storage.selectedFlyingSkin || 'default';
var flyingSkinAssetMap = {
'default': {
body: 'flying_default_body',
wing: 'enemy_limb',
tint: 0x8B4513
},
'black': {
body: 'flying_black_body',
wing: 'flying_black_wing',
tint: 0x2f2f2f
},
'silver': {
body: 'flying_silver_body',
wing: 'flying_silver_wing',
tint: 0xc0c0c0
},
'golden': {
body: 'flying_golden_body',
wing: 'flying_golden_wing',
tint: 0xffd700
},
'red': {
body: 'flying_red_body',
wing: 'flying_red_wing',
tint: 0xff4500
},
'blue': {
body: 'flying_blue_body',
wing: 'flying_blue_wing',
tint: 0x1e90ff
}
};
var currentSkinAssets = flyingSkinAssetMap[skinColor] || flyingSkinAssetMap['default'];
var body = self.attachAsset(currentSkinAssets.body, {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 0,
width: 40,
height: 40,
tint: currentSkinAssets.tint
});
var leftWing = self.attachAsset(currentSkinAssets.wing, {
anchorX: 0.5,
anchorY: 0.5,
x: -25,
y: 0,
width: 20,
height: 8
});
var rightWing = self.attachAsset(currentSkinAssets.wing, {
anchorX: 0.5,
anchorY: 0.5,
x: 25,
y: 0,
width: 20,
height: 8
});
// Health bar
var healthBarBg = self.attachAsset('platform', {
width: 60,
height: 8,
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -35,
tint: 0x000000
});
var healthBarFill = self.attachAsset('platform', {
width: 56,
height: 6,
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -35,
tint: 0x00FF00
});
self.health = 30;
self.maxHealth = 30;
self.speed = 2;
self.direction = 1;
self.attackRange = 120;
self.attackCooldown = 0;
self.animationTick = 0;
self.floatOffset = 0;
self.shootCooldown = 0;
self.update = function () {
// Floating movement
self.floatOffset += 0.1;
self.y += Math.sin(self.floatOffset) * 0.5;
// Wing flapping animation
var flapSpeed = 0.3;
var flapCycle = Math.sin(self.animationTick * flapSpeed);
leftWing.rotation = flapCycle * 0.8;
rightWing.rotation = -flapCycle * 0.8;
leftWing.y = Math.sin(self.animationTick * flapSpeed * 2) * 2;
rightWing.y = Math.sin(self.animationTick * flapSpeed * 2) * 2;
// Enhanced AI behavior - chase player and shoot with range detection
var distanceToPlayer = Math.abs(self.x - player.x);
var verticalDistance = Math.abs(self.y - player.y);
var attackRange = 400; // Flying enemies have longer detection range
var aggressiveRange = 200; // Close range for aggressive behavior
if (distanceToPlayer < attackRange && verticalDistance < 200) {
// Enhanced chase behavior with speed adjustment based on range
var isInAggressiveRange = distanceToPlayer < aggressiveRange;
var chaseSpeed = isInAggressiveRange ? self.speed * 1.8 : self.speed * 1.2;
// Chase player
if (player.x > self.x) {
self.direction = 1;
self.x += chaseSpeed;
} else {
self.direction = -1;
self.x -= chaseSpeed;
}
// Vertical pursuit - move towards player's Y position more aggressively
if (Math.abs(player.y - self.y) > 30) {
if (player.y > self.y) {
self.y += chaseSpeed * 0.7;
} else {
self.y -= chaseSpeed * 0.7;
}
}
// Strategic platform landing when pursuing player
if (Math.random() < 0.015 || isInAggressiveRange && Math.random() < 0.03) {
// Higher chance to land on platforms when in aggressive range
var nearestPlatform = null;
var nearestDistance = Infinity;
var bestStrategicPlatform = null;
var bestStrategicValue = Infinity;
for (var p = 0; p < platforms.length; p++) {
var platform = platforms[p];
var platformDistance = Math.sqrt(Math.pow(platform.x - self.x, 2) + Math.pow(platform.y - self.y, 2));
var platformToPlayerDistance = Math.abs(platform.x - player.x);
// Calculate strategic value (closer to player is better)
var strategicValue = platformDistance + platformToPlayerDistance;
if (platformDistance < 200) {
if (platformDistance < nearestDistance) {
nearestDistance = platformDistance;
nearestPlatform = platform;
}
if (strategicValue < bestStrategicValue && platformToPlayerDistance < 150) {
bestStrategicValue = strategicValue;
bestStrategicPlatform = platform;
}
}
}
// Prefer strategic platform over nearest if available
var targetPlatform = bestStrategicPlatform || nearestPlatform;
if (targetPlatform) {
// Aggressive dive towards platform
var dx = targetPlatform.x - self.x;
var dy = targetPlatform.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
self.x += dx / distance * (chaseSpeed + 1);
self.y += dy / distance * (chaseSpeed + 0.8);
}
}
// Shoot projectiles at player
if (self.shootCooldown <= 0 && distanceToPlayer < 200) {
self.shootAtPlayer();
self.shootCooldown = 90; // 1.5 seconds
}
} else {
// Patrol movement
self.x += self.speed * self.direction;
if (self.x < 50 || self.x > 1998) {
self.direction *= -1;
}
// Occasionally move towards platforms while patrolling
if (Math.random() < 0.003) {
// Random platform seeking
var randomPlatform = platforms[Math.floor(Math.random() * platforms.length)];
if (randomPlatform && Math.abs(randomPlatform.x - self.x) < 300) {
var dx = randomPlatform.x - self.x;
var dy = randomPlatform.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 50) {
// Don't get too close
self.x += dx / distance * self.speed * 0.5;
self.y += dy / distance * self.speed * 0.3;
}
}
}
}
// Update cooldowns
if (self.shootCooldown > 0) {
self.shootCooldown--;
}
self.animationTick++;
// Face direction
if (self.direction > 0) {
body.scaleX = 1;
leftWing.scaleX = 1;
rightWing.scaleX = 1;
} else {
body.scaleX = -1;
leftWing.scaleX = -1;
rightWing.scaleX = -1;
}
};
self.shootAtPlayer = function () {
var bullet = new EnemyBullet();
bullet.x = self.x;
bullet.y = self.y;
// Calculate direction to player
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
bullet.velocityX = dx / distance * 6;
bullet.velocityY = dy / distance * 6;
enemyBullets.push(bullet);
game.addChild(bullet);
LK.getSound('attack').play();
};
self.takeDamage = function (damage) {
self.health -= damage;
// Update health bar
var healthPercent = Math.max(0, self.health / self.maxHealth);
healthBarFill.width = 56 * healthPercent;
if (healthPercent > 0.6) {
healthBarFill.tint = 0x00FF00;
} else if (healthPercent > 0.3) {
healthBarFill.tint = 0xFFFF00;
} else {
healthBarFill.tint = 0xFF0000;
}
// Flash effect
var originalTint = body.tint; // Store original skin color
tween(body, {
tint: 0xFFFFFF
}, {
duration: 100,
onFinish: function onFinish() {
tween(body, {
tint: originalTint // Restore original skin color
}, {
duration: 100
});
}
});
LK.getSound('enemy_hit').play();
if (self.health <= 0) {
LK.getSound('enemy_death').play();
self.destroy();
return true;
}
return false;
};
return self;
});
var Platform = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('platform', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
var Projectile = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('projectile', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocityX = 0;
self.velocityY = 0;
self.lifetime = 180; // 3 seconds at 60fps
self.update = function () {
self.x += self.velocityX;
self.y += self.velocityY;
self.lifetime--;
// Calculate distance traveled from start position
if (self.startX === undefined) {
self.startX = self.x;
self.startY = self.y;
}
var distanceTraveled = Math.sqrt(Math.pow(self.x - self.startX, 2) + Math.pow(self.y - self.startY, 2));
var maxRange = 350; // Short range limit for projectiles
// Remove if lifetime expired, off screen, or exceeded range
if (self.lifetime <= 0 || self.x < -50 || self.x > 2098 || self.y > 2800 || distanceTraveled > maxRange) {
self.destroy();
}
};
return self;
});
var ShadowBoss = Container.expand(function () {
var self = Container.call(this);
// Apply selected boss skin for shadow boss
var skinColor = storage.selectedBossSkin || 'default';
var shadowBossSkinColors = {
'default': {
main: 0x2F2F2F,
glow: 0x8A2BE2
},
'crimson': {
main: 0x8B0000,
glow: 0xFF0000
},
'shadow': {
main: 0x1C1C1C,
glow: 0x4B0082
},
'golden': {
main: 0xB8860B,
glow: 0xFFD700
},
'emerald': {
main: 0x006400,
glow: 0x00FF00
},
'cyber': {
main: 0x008B8B,
glow: 0x00FFFF
}
};
var currentSkin = shadowBossSkinColors[skinColor] || shadowBossSkinColors['default'];
var graphics = self.attachAsset('boss', {
anchorX: 0.5,
anchorY: 1.0,
tint: currentSkin.main
});
// Health bar
var healthBarBg = self.attachAsset('platform', {
width: 160,
height: 20,
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -220,
tint: 0x000000
});
var healthBarFill = self.attachAsset('platform', {
width: 156,
height: 16,
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -220,
tint: currentSkin.glow || 0x8A2BE2
});
self.health = 200;
self.maxHealth = 200;
self.velocityX = 0;
self.velocityY = 0;
self.onGround = false;
self.speed = 4;
self.direction = 1;
self.attackCooldown = 0;
self.teleportCooldown = 0;
self.animationTick = 0;
self.phase = 1;
self.update = function () {
// Apply gravity
if (!self.onGround) {
self.velocityY += 0.8;
}
var distanceToPlayer = Math.abs(self.x - player.x);
var healthPercent = self.health / self.maxHealth;
// Teleport ability
if (self.teleportCooldown <= 0 && distanceToPlayer > 300) {
self.teleportToPlayer();
self.teleportCooldown = 300;
}
// Shadow projectile attack
if (self.attackCooldown <= 0) {
self.shadowBlast();
self.attackCooldown = healthPercent > 0.5 ? 150 : 100;
}
// Movement
if (player.x > self.x) {
self.direction = 1;
self.velocityX = self.speed;
} else {
self.direction = -1;
self.velocityX = -self.speed;
}
// Apply velocity
self.x += self.velocityX;
self.y += self.velocityY;
self.onGround = false;
// Update cooldowns
if (self.attackCooldown > 0) {
self.attackCooldown--;
}
if (self.teleportCooldown > 0) {
self.teleportCooldown--;
}
self.animationTick++;
// Shadow flickering effect
graphics.alpha = 0.7 + Math.sin(self.animationTick * 0.1) * 0.3;
graphics.scaleX = self.direction > 0 ? 1 : -1;
};
self.teleportToPlayer = function () {
// Fade out
tween(graphics, {
alpha: 0
}, {
duration: 200,
onFinish: function onFinish() {
// Teleport behind player
self.x = player.x + (Math.random() > 0.5 ? 200 : -200);
self.y = player.y;
// Fade in
tween(graphics, {
alpha: 0.7
}, {
duration: 200
});
}
});
};
self.shadowBlast = function () {
for (var i = 0; i < 3; i++) {
var bullet = new EnemyBullet();
bullet.x = self.x;
bullet.y = self.y - 100;
var angle = (i - 1) * 0.8;
bullet.velocityX = Math.cos(angle) * 6 * self.direction;
bullet.velocityY = Math.sin(angle) * 6 - 3;
// Make shadow bullets darker
bullet.tint = 0x4B0082;
enemyBullets.push(bullet);
game.addChild(bullet);
}
LK.getSound('shadow_boss_attack').play();
};
self.takeDamage = function (damage) {
self.health -= damage;
var healthPercent = Math.max(0, self.health / self.maxHealth);
healthBarFill.width = 156 * healthPercent;
// Flash effect
tween(graphics, {
tint: 0xFFFFFF
}, {
duration: 150,
onFinish: function onFinish() {
tween(graphics, {
tint: 0x2F2F2F
}, {
duration: 150
});
}
});
LK.getSound('enemy_hit').play();
if (self.health <= 0) {
LK.getSound('enemy_death').play();
self.destroy();
return true;
}
return false;
};
return self;
});
var Stickman = Container.expand(function () {
var self = Container.call(this);
// Get selected skin and determine asset and tint
var selectedSkin = storage.selectedSkin || 'default';
var skinAssetMap = {
'default': {
asset: 'warrior',
tint: 0xFFFFFF
},
'red': {
asset: 'warrior_red',
tint: 0xFF4444
},
'blue': {
asset: 'warrior_blue',
tint: 0x4444FF
},
'green': {
asset: 'warrior_green',
tint: 0x44FF44
},
'purple': {
asset: 'warrior_purple',
tint: 0x8844FF
},
'gold': {
asset: 'warrior_gold',
tint: 0xFFD700
},
'orange': {
asset: 'warrior_orange',
tint: 0xFF8844
},
'cyan': {
asset: 'warrior_cyan',
tint: 0x44FFFF
},
'magenta': {
asset: 'warrior_magenta',
tint: 0xFF44FF
},
'silver': {
asset: 'warrior_silver',
tint: 0xC0C0C0
},
'lime': {
asset: 'warrior_lime',
tint: 0x88FF44
},
'bronze': {
asset: 'warrior_bronze',
tint: 0xCD7F32
}
};
var skinConfig = skinAssetMap[selectedSkin] || skinAssetMap['default'];
// Create detailed warrior with body parts for enhanced animations using selected skin
var warriorBody = self.attachAsset(skinConfig.asset, {
anchorX: 0.5,
anchorY: 1.0,
x: 0,
y: 0,
tint: skinConfig.tint
});
// Create separate limbs for detailed animation
var leftArm = self.attachAsset('enemy_limb', {
anchorX: 0.5,
anchorY: 0,
x: -15,
y: -80,
tint: 0x8B4513
});
var rightArm = self.attachAsset('enemy_limb', {
anchorX: 0.5,
anchorY: 0,
x: 15,
y: -80,
tint: 0x8B4513
});
var leftLeg = self.attachAsset('enemy_limb', {
anchorX: 0.5,
anchorY: 0,
x: -8,
y: -40,
height: 40,
tint: 0x654321
});
var rightLeg = self.attachAsset('enemy_limb', {
anchorX: 0.5,
anchorY: 0,
x: 8,
y: -40,
height: 40,
tint: 0x654321
});
// No sword - warrior fights with hands
// Movement properties
self.velocityX = 0;
self.velocityY = 0;
self.onGround = false;
self.speed = 8;
self.jumpPower = -18;
self.health = 100;
self.maxHealth = 100;
self.facingRight = true;
// Combat properties
self.canAttack = true;
self.attackCooldown = 0;
self.lastAttackTime = 0;
// Ammunition properties
self.maxAmmo = 5;
self.currentAmmo = 5;
self.reloadTime = 180; // 3 seconds at 60fps
self.timeSinceLastShot = 0;
// Animation properties
self.animationTick = 0;
self.isAttacking = false;
self.isJumping = false;
self.wasOnGround = true;
self.update = function () {
// Apply gravity
if (!self.onGround) {
self.velocityY += 0.8;
}
// Apply velocity
self.x += self.velocityX;
self.y += self.velocityY;
// Apply friction
self.velocityX *= 0.85;
// Reset ground detection
self.onGround = false;
// Reset double jump when touching ground later in collision detection
// Update attack cooldown
if (self.attackCooldown > 0) {
self.attackCooldown--;
}
// Update ammunition reload system
self.timeSinceLastShot++;
if (self.currentAmmo < self.maxAmmo && self.timeSinceLastShot >= self.reloadTime) {
self.currentAmmo++;
self.timeSinceLastShot = 0;
// Update ammunition display when reloading
if (ammoText) {
ammoText.setText('Arrows: ' + self.currentAmmo + '/' + self.maxAmmo);
ammoText.tint = self.currentAmmo > 0 ? 0xFFFFFF : 0xFF4444;
}
}
// Animation updates
self.animationTick++;
// Check if jumping state changed
if (!self.onGround && self.wasOnGround) {
self.isJumping = true;
}
if (self.onGround && !self.wasOnGround) {
self.isJumping = false;
}
self.wasOnGround = self.onGround;
// Handle enhanced animations with detailed warrior body parts and sword movements
if (self.isAttacking) {
// Attack animation is handled in attack method - keep sword position
} else if (self.isJumping || !self.onGround) {
// Enhanced jump animation with dynamic rotation and detailed limb movement
var jumpPhase = self.velocityY < 0 ? 0 : 1; // 0 for going up, 1 for falling
if (jumpPhase === 0) {
// Going up - dynamic backward tilt based on jump velocity
var tiltAmount = Math.min(Math.abs(self.velocityY) * 0.02, 0.4);
warriorBody.rotation = -tiltAmount;
// Slight scale animation for jump power
warriorBody.scaleY = 1.1 - Math.abs(self.velocityY) * 0.005;
// Detailed leg positioning during upward jump - legs bent for power
leftLeg.rotation = -0.3;
rightLeg.rotation = -0.2;
leftLeg.y = -35;
rightLeg.y = -35;
// Arm positioning during jump - spread for balance
leftArm.rotation = -0.4;
rightArm.rotation = 0.2;
// No sword - hands positioned during jump for balance
} else {
// Falling down - forward tilt increases with fall speed
var fallTilt = Math.min(self.velocityY * 0.01, 0.3);
warriorBody.rotation = fallTilt;
// Slight stretch when falling fast
warriorBody.scaleY = 1 + self.velocityY * 0.002;
// Detailed leg positioning during fall - preparing for landing
leftLeg.rotation = 0.2;
rightLeg.rotation = 0.1;
leftLeg.y = -38;
rightLeg.y = -38;
// Arm positioning for landing preparation
leftArm.rotation = -0.2;
rightArm.rotation = 0.3;
// No sword - hands positioned for landing
// Add landing preparation animation when close to ground
if (self.velocityY > 8) {
tween(warriorBody, {
scaleY: 0.95
}, {
duration: 100,
easing: tween.easeOut
});
tween(leftLeg, {
rotation: 0.4,
y: -42
}, {
duration: 100,
easing: tween.easeOut
});
tween(rightLeg, {
rotation: 0.3,
y: -42
}, {
duration: 100,
easing: tween.easeOut
});
}
}
} else if (Math.abs(self.velocityX) > 0.1) {
// Enhanced walking/running animation with detailed warrior body parts and realistic limb movement
var walkSpeed = Math.abs(self.velocityX) > 4 ? 0.4 : 0.3; // Faster animation for running
var walkCycle = Math.sin(self.animationTick * walkSpeed);
var walkCycleDouble = Math.sin(self.animationTick * walkSpeed * 2);
var walkCycleOffset = Math.sin(self.animationTick * walkSpeed + Math.PI);
// Dynamic rotation based on movement speed
var speedFactor = Math.min(Math.abs(self.velocityX) / self.speed, 1);
var isRunning = Math.abs(self.velocityX) > 4;
warriorBody.rotation = walkCycle * (isRunning ? 0.12 : 0.08) * speedFactor;
// Vertical bob with speed-based intensity - more pronounced when running
warriorBody.y = Math.abs(walkCycleDouble) * (isRunning ? 6 : 4) * speedFactor;
// Subtle scale animation for dynamic feel
warriorBody.scaleY = 1 - Math.abs(walkCycleDouble) * (isRunning ? 0.03 : 0.02) * speedFactor;
// Slight horizontal sway
warriorBody.x = walkCycle * (isRunning ? 3 : 2) * speedFactor;
// Detailed leg animation - alternating steps with realistic movement
var leftLegCycle = Math.sin(self.animationTick * walkSpeed);
var rightLegCycle = Math.sin(self.animationTick * walkSpeed + Math.PI);
// Left leg movement
leftLeg.rotation = leftLegCycle * (isRunning ? 0.6 : 0.4);
leftLeg.y = -40 + Math.abs(leftLegCycle) * (isRunning ? 8 : 5);
// Right leg movement (opposite phase)
rightLeg.rotation = rightLegCycle * (isRunning ? 0.6 : 0.4);
rightLeg.y = -40 + Math.abs(rightLegCycle) * (isRunning ? 8 : 5);
// Detailed arm animation - natural swinging motion opposite to legs
leftArm.rotation = rightLegCycle * (isRunning ? 0.5 : 0.3);
leftArm.y = -80 + Math.abs(rightLegCycle) * (isRunning ? 4 : 2);
rightArm.rotation = leftLegCycle * (isRunning ? 0.3 : 0.2); // Right arm holds sword, less movement
rightArm.y = -80 + Math.abs(leftLegCycle) * (isRunning ? 3 : 1);
// Both arms swing naturally during movement
// Add realistic stride animation using tween for smoother transitions
if (Math.floor(self.animationTick * walkSpeed) !== Math.floor((self.animationTick - 1) * walkSpeed)) {
// Trigger on each step cycle for enhanced leg animation
var stepDirection = leftLegCycle > 0 ? 1 : -1;
tween(warriorBody, {
scaleY: isRunning ? 0.96 : 0.98
}, {
duration: isRunning ? 80 : 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(warriorBody, {
scaleY: isRunning ? 1.04 : 1.02
}, {
duration: isRunning ? 80 : 100,
easing: tween.easeIn
});
}
});
}
// Add slight lean forward when walking/running
var leanDirection = self.facingRight ? 1 : -1;
warriorBody.rotation += leanDirection * speedFactor * (isRunning ? 0.08 : 0.05);
} else {
// Enhanced idle animation with breathing effect and detailed body part movement
var breathCycle = Math.sin(self.animationTick * 0.05);
var idleCycle = Math.sin(self.animationTick * 0.03);
var weightShiftCycle = Math.sin(self.animationTick * 0.02);
warriorBody.rotation = breathCycle * 0.01;
warriorBody.y = breathCycle * 1;
warriorBody.scaleY = 1 + breathCycle * 0.01;
warriorBody.x = 0;
// Detailed idle leg positioning with subtle weight shifting
leftLeg.rotation = weightShiftCycle * 0.08;
rightLeg.rotation = -weightShiftCycle * 0.06;
leftLeg.y = -40 + Math.abs(idleCycle) * 1;
rightLeg.y = -40 + Math.abs(weightShiftCycle) * 1;
// Detailed idle arm positioning with breathing
leftArm.rotation = breathCycle * 0.03;
leftArm.y = -80 + breathCycle * 0.5;
rightArm.rotation = breathCycle * 0.02; // Right arm holds sword
rightArm.y = -80 + breathCycle * 0.3;
// Arms in natural idle position with breathing
// Add periodic subtle repositioning animation
if (self.animationTick % 180 === 0) {
// Every 3 seconds - subtle weight shift
var shiftDirection = Math.random() > 0.5 ? 1 : -1;
tween(leftLeg, {
rotation: shiftDirection * 0.1
}, {
duration: 300,
easing: tween.easeInOut
});
tween(rightLeg, {
rotation: -shiftDirection * 0.08
}, {
duration: 300,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(leftLeg, {
rotation: 0
}, {
duration: 500,
easing: tween.easeOut
});
tween(rightLeg, {
rotation: 0
}, {
duration: 500,
easing: tween.easeOut
});
}
});
}
}
// Face direction with smooth transition for all body parts
if (self.facingRight) {
warriorBody.scaleX = 1;
leftArm.scaleX = 1;
rightArm.scaleX = 1;
leftLeg.scaleX = 1;
rightLeg.scaleX = 1;
} else {
warriorBody.scaleX = -1;
leftArm.scaleX = -1;
rightArm.scaleX = -1;
leftLeg.scaleX = -1;
rightLeg.scaleX = -1;
}
// Keep player in bounds for horizontal layout
if (self.x < 30) {
self.x = 30;
}
if (self.x > 2018) {
self.x = 2018;
}
// Reset skew if character is not moving or attacking
if (Math.abs(self.velocityX) < 0.1 && !self.isAttacking && !self.isJumping) {
// Smoothly reset skew values
if (Math.abs(warriorBody.skewX) > 0.001) {
warriorBody.skewX *= 0.9;
}
if (Math.abs(warriorBody.skewY) > 0.001) {
warriorBody.skewY *= 0.9;
}
}
};
self.moveLeft = function () {
self.velocityX = -self.speed;
if (self.facingRight) {
// Add quick turn animation when changing direction
self.facingRight = false;
tween(warriorBody, {
scaleX: -1.2,
skewX: 0.1
}, {
duration: 100,
onFinish: function onFinish() {
tween(warriorBody, {
scaleX: -1,
skewX: 0
}, {
duration: 100
});
}
});
// No sword position changes needed
} else {
self.facingRight = false;
}
// Add quick leg push animation for movement start
tween(warriorBody, {
skewY: -0.05
}, {
duration: 50,
onFinish: function onFinish() {
tween(warriorBody, {
skewY: 0
}, {
duration: 100
});
}
});
};
self.moveRight = function () {
self.velocityX = self.speed;
if (!self.facingRight) {
// Add quick turn animation when changing direction
self.facingRight = true;
tween(warriorBody, {
scaleX: 1.2,
skewX: -0.1
}, {
duration: 100,
onFinish: function onFinish() {
tween(warriorBody, {
scaleX: 1,
skewX: 0
}, {
duration: 100
});
}
});
// No sword position changes needed
} else {
self.facingRight = true;
}
// Add quick leg push animation for movement start
tween(warriorBody, {
skewY: 0.05
}, {
duration: 50,
onFinish: function onFinish() {
tween(warriorBody, {
skewY: 0
}, {
duration: 100
});
}
});
};
self.jump = function () {
console.log("Jump called! onGround:", self.onGround, "velocityY:", self.velocityY);
if (self.onGround || Math.abs(self.velocityY) < 2) {
// First jump with squash animation
self.velocityY = self.jumpPower;
self.onGround = false;
LK.getSound('jump').play();
// Enhanced squash and stretch animation for jump with sword movement
tween(warriorBody, {
scaleY: 0.7,
scaleX: self.facingRight ? 1.3 : -1.3
}, {
duration: 100,
onFinish: function onFinish() {
tween(warriorBody, {
scaleY: 1.2,
scaleX: self.facingRight ? 0.9 : -0.9
}, {
duration: 150,
onFinish: function onFinish() {
tween(warriorBody, {
scaleY: 1,
scaleX: self.facingRight ? 1 : -1
}, {
duration: 200
});
}
});
}
});
// Arms raised during jump for balance
tween(leftArm, {
y: -85,
rotation: -0.4
}, {
duration: 100,
onFinish: function onFinish() {
tween(leftArm, {
y: -80,
rotation: 0
}, {
duration: 300
});
}
});
console.log("Jump executed! New velocityY:", self.velocityY);
} else if (self.canDoubleJump && !self.hasUsedDoubleJump) {
// Double jump with spin animation
self.velocityY = self.jumpPower * 0.8;
self.hasUsedDoubleJump = true;
self.canDoubleJump = false;
LK.getSound('jump').play();
// Enhanced spin animation for double jump with sword trail effect
var startRotation = warriorBody.rotation;
tween(warriorBody, {
rotation: startRotation + (self.facingRight ? Math.PI * 2 : -Math.PI * 2)
}, {
duration: 400,
onFinish: function onFinish() {
warriorBody.rotation = 0;
}
});
// Arms spinning during double jump
tween(leftArm, {
rotation: leftArm.rotation + (self.facingRight ? Math.PI * 2 : -Math.PI * 2)
}, {
duration: 400,
onFinish: function onFinish() {
leftArm.rotation = 0;
}
});
tween(rightArm, {
rotation: rightArm.rotation + (self.facingRight ? Math.PI * 2 : -Math.PI * 2)
}, {
duration: 400,
onFinish: function onFinish() {
rightArm.rotation = 0;
}
});
console.log("Double jump executed!");
} else {
console.log("Cannot jump - not on ground and no double jump available");
}
};
self.attack = function () {
if (self.attackCooldown <= 0) {
self.attackCooldown = 30;
self.isAttacking = true;
LK.getSound('attack').play();
// Hand-to-hand combat - punch animation
var originalWarriorRotation = warriorBody.rotation;
// Wind up phase - pull right arm back for powerful punch
tween(rightArm, {
rotation: -0.8,
x: self.facingRight ? 5 : -5,
y: -75
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
// Powerful punch forward
tween(rightArm, {
rotation: 0.6,
x: self.facingRight ? 25 : -25,
y: -80
}, {
duration: 200,
easing: tween.easeIn,
onFinish: function onFinish() {
// Recovery - return arm to normal position
tween(rightArm, {
rotation: 0,
x: self.facingRight ? 15 : -15,
y: -80
}, {
duration: 250,
easing: tween.easeInOut,
onFinish: function onFinish() {
self.isAttacking = false;
}
});
}
});
// Warrior body movement during punch
tween(warriorBody, {
rotation: originalWarriorRotation + (self.facingRight ? 0.2 : -0.2),
skewY: self.facingRight ? 0.1 : -0.1
}, {
duration: 150,
onFinish: function onFinish() {
tween(warriorBody, {
rotation: originalWarriorRotation - (self.facingRight ? 0.1 : -0.1),
skewY: self.facingRight ? -0.05 : 0.05
}, {
duration: 200,
onFinish: function onFinish() {
tween(warriorBody, {
rotation: originalWarriorRotation,
skewY: 0
}, {
duration: 250
});
}
});
}
});
}
});
// Add warrior body lean and step forward during punch
LK.setTimeout(function () {
// Dynamic body movement during attack
tween(warriorBody, {
scaleX: self.facingRight ? 1.1 : -1.1,
x: self.facingRight ? 8 : -8
}, {
duration: 100,
onFinish: function onFinish() {
tween(warriorBody, {
scaleX: self.facingRight ? 1 : -1,
x: 0
}, {
duration: 150
});
}
});
}, 150);
// Check for enemy hits during forward punch
LK.setTimeout(function () {
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
// Calculate punch position based on warrior's facing direction and arm extension
var punchReach = 80; // Increased reach for better hit detection
var punchX = self.x + (self.facingRight ? punchReach : -punchReach);
var punchY = self.y - 60; // Adjusted height to match enemy center
// Calculate distance from punch position to enemy
var distanceToEnemy = Math.abs(punchX - enemy.x);
var verticalDistance = Math.abs(punchY - enemy.y);
// Improved hit-box - larger rectangular area in front of warrior
var hitBoxWidth = 70; // Increased width of punch hit area
var hitBoxHeight = 80; // Increased height of punch hit area
if (distanceToEnemy < hitBoxWidth && verticalDistance < hitBoxHeight) {
// Additional check: enemy must be in front of warrior
var enemyInFront = self.facingRight ? enemy.x > self.x : enemy.x < self.x;
if (enemyInFront) {
if (enemy.takeDamage(25)) {
// Enemy damaged - check if destroyed
enemies.splice(i, 1);
LK.setScore(LK.getScore() + 100);
storage.coins += 5; // Reward coins for melee kills
scoreText.setText('Score: ' + LK.getScore());
}
// Enhanced knockback effect based on punch direction
var knockbackDirection = self.facingRight ? 1 : -1;
enemy.velocityX += knockbackDirection * 10;
enemy.velocityY = -4; // Slightly stronger upward knockback
}
}
}
}, 120);
}
};
self.shootArrow = function () {
if (self.attackCooldown <= 0 && self.currentAmmo > 0) {
self.attackCooldown = 20; // Shorter cooldown for ranged attacks
self.currentAmmo--; // Consume ammunition
self.timeSinceLastShot = 0; // Reset reload timer
LK.getSound('bow_shoot').play();
// Update ammunition display immediately
if (ammoText) {
ammoText.setText('Arrows: ' + self.currentAmmo + '/' + self.maxAmmo);
ammoText.tint = self.currentAmmo > 0 ? 0xFFFFFF : 0xFF4444;
}
// Create arrow
var arrow = new Arrow();
arrow.x = self.x + (self.facingRight ? 40 : -40);
arrow.y = self.y - 80;
// Set arrow velocity based on facing direction
var arrowSpeed = 12;
arrow.velocityX = self.facingRight ? arrowSpeed : -arrowSpeed;
arrow.velocityY = 0; // Straight horizontal trajectory
// Add arrow to game
arrows.push(arrow);
game.addChild(arrow);
// Bow shooting animation - pull left arm back then forward
var originalLeftArmX = leftArm.x;
var originalLeftArmY = leftArm.y;
var originalLeftArmRotation = leftArm.rotation;
// Pull back animation (drawing the bow)
tween(leftArm, {
rotation: -0.5,
x: self.facingRight ? -20 : 20,
y: -85
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
// Release animation (shooting the arrow)
tween(leftArm, {
rotation: 0.3,
x: self.facingRight ? -10 : 10,
y: -75
}, {
duration: 150,
easing: tween.easeIn,
onFinish: function onFinish() {
// Return to normal position
tween(leftArm, {
rotation: originalLeftArmRotation,
x: originalLeftArmX,
y: originalLeftArmY
}, {
duration: 200,
easing: tween.easeInOut
});
}
});
}
});
// Slight body lean during bow shot
var originalWarriorRotation = warriorBody.rotation;
tween(warriorBody, {
rotation: originalWarriorRotation + (self.facingRight ? -0.1 : 0.1),
x: self.facingRight ? -5 : 5
}, {
duration: 100,
onFinish: function onFinish() {
tween(warriorBody, {
rotation: originalWarriorRotation,
x: 0
}, {
duration: 200
});
}
});
}
};
self.takeDamage = function (damage) {
self.health -= damage;
LK.getSound('hit').play();
// Update health bar if it exists
if (healthText && healthText.healthBarFill) {
var healthPercent = Math.max(0, self.health / self.maxHealth);
healthText.healthBarFill.width = 210 * healthPercent;
healthText.healthBarFill.tint = self.health < 30 ? 0xFF0000 : 0x00FF00;
}
// Enhanced damage flash effect on warrior and sword
var originalSkinTint = skinConfig.tint; // Store the original skin tint
tween(warriorBody, {
tint: 0xFF0066
}, {
duration: 150,
onFinish: function onFinish() {
tween(warriorBody, {
tint: originalSkinTint // Restore original skin tint instead of white
}, {
duration: 150
});
}
});
// Flash arms as well
tween(leftArm, {
tint: 0xFF0066
}, {
duration: 150,
onFinish: function onFinish() {
tween(leftArm, {
tint: 0x8B4513
}, {
duration: 150
});
}
});
tween(rightArm, {
tint: 0xFF0066
}, {
duration: 150,
onFinish: function onFinish() {
tween(rightArm, {
tint: 0x8B4513
}, {
duration: 150
});
}
});
if (self.health <= 0) {
LK.showGameOver();
}
};
return self;
});
var StickmanEnemy = Container.expand(function () {
var self = Container.call(this);
// Apply selected enemy skin with specific assets
var skinColor = storage.selectedEnemySkin || 'default';
var skinAssetMap = {
'default': {
head: 'enemy_head',
body: 'enemy_body',
limb: 'enemy_limb',
sword: 'enemy_sword'
},
'dark': {
head: 'enemy_dark_head',
body: 'enemy_dark_body',
limb: 'enemy_dark_limb',
sword: 'enemy_dark_sword'
},
'green': {
head: 'enemy_green_head',
body: 'enemy_green_body',
limb: 'enemy_green_limb',
sword: 'enemy_green_sword'
},
'purple': {
head: 'enemy_purple_head',
body: 'enemy_purple_body',
limb: 'enemy_purple_limb',
sword: 'enemy_purple_sword'
},
'orange': {
head: 'enemy_orange_head',
body: 'enemy_orange_body',
limb: 'enemy_orange_limb',
sword: 'enemy_orange_sword'
},
'blue': {
head: 'enemy_blue_head',
body: 'enemy_blue_body',
limb: 'enemy_blue_limb',
sword: 'enemy_blue_sword'
}
};
var currentSkinAssets = skinAssetMap[skinColor] || skinAssetMap['default'];
// Create stickman body parts with skin-specific assets
var head = self.attachAsset(currentSkinAssets.head, {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -65
});
var body = self.attachAsset(currentSkinAssets.body, {
anchorX: 0.5,
anchorY: 0,
x: 0,
y: -50
});
var leftArm = self.attachAsset(currentSkinAssets.limb, {
anchorX: 0.5,
anchorY: 0,
x: -10,
y: -40
});
var rightArm = self.attachAsset(currentSkinAssets.limb, {
anchorX: 0.5,
anchorY: 0,
x: 10,
y: -40
});
var leftLeg = self.attachAsset(currentSkinAssets.limb, {
anchorX: 0.5,
anchorY: 0,
x: -5,
y: -20
});
var rightLeg = self.attachAsset(currentSkinAssets.limb, {
anchorX: 0.5,
anchorY: 0,
x: 5,
y: -20
});
var sword = self.attachAsset(currentSkinAssets.sword, {
anchorX: 0.5,
anchorY: 1,
x: 15,
y: -30
});
self.velocityX = 0;
self.velocityY = 0;
self.health = 50;
self.maxHealth = 50;
// Create health bar background
var healthBarBg = self.attachAsset('platform', {
width: 60,
height: 8,
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -90,
tint: 0x000000
});
// Create health bar fill
var healthBarFill = self.attachAsset('platform', {
width: 56,
height: 6,
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -90,
tint: 0x00FF00
});
self.speed = 1.5;
self.direction = 1;
self.onGround = false;
self.attackRange = 80;
self.attackCooldown = 0;
self.animationTick = 0;
self.isAttacking = false;
self.lastPlayerDistance = 999;
self.update = function () {
// Apply gravity
if (!self.onGround) {
self.velocityY += 0.8;
}
// AI behavior - chase player if close enough with enhanced range detection
var distanceToPlayer = Math.abs(self.x - player.x);
var verticalDistance = Math.abs(self.y - player.y);
var attackRange = 300; // Increased detection range
var aggressiveRange = 150; // Close range for aggressive behavior
if (distanceToPlayer < attackRange && verticalDistance < 150) {
// Enhanced chase behavior with speed boost when close
var isInAggressiveRange = distanceToPlayer < aggressiveRange;
var chaseSpeed = isInAggressiveRange ? self.speed * 1.5 : self.speed;
// Chase player
if (player.x > self.x) {
self.direction = 1;
self.velocityX = chaseSpeed;
} else {
self.direction = -1;
self.velocityX = -chaseSpeed;
}
// Aggressive platform jumping when pursuing player
if (self.onGround && (verticalDistance > 60 || Math.abs(player.y - self.y) > 50)) {
// Look for platforms to reach player more aggressively
var nearestPlatform = null;
var nearestDistance = Infinity;
var targetDirection = player.x > self.x ? 1 : -1;
// Check all platforms for strategic positioning
for (var p = 0; p < platforms.length; p++) {
var platform = platforms[p];
var platformDistance = Math.abs(platform.x - self.x);
var platformToPlayerDistance = Math.abs(platform.x - player.x);
// Prefer platforms that are closer to player or provide better positioning
var strategicValue = platformDistance + platformToPlayerDistance * 0.5;
if (platform.y < self.y && platform.y > player.y - 100 && platformDistance < 400) {
if (strategicValue < nearestDistance) {
nearestDistance = strategicValue;
nearestPlatform = platform;
}
}
}
// Jump towards the platform or directly towards player
if (nearestPlatform) {
// Calculate jump direction towards platform
var jumpDirection = nearestPlatform.x > self.x ? 1 : -1;
self.velocityY = -16; // Stronger jump for pursuit
self.velocityX = jumpDirection * (self.speed + 3); // Extra horizontal velocity
self.onGround = false;
LK.getSound('jump').play();
} else if (verticalDistance > 100) {
// Direct jump towards player if no platforms available
self.velocityY = -14;
self.velocityX = targetDirection * (self.speed + 2);
self.onGround = false;
LK.getSound('jump').play();
}
}
// Attack if in range
if (distanceToPlayer < self.attackRange && self.attackCooldown <= 0) {
self.attackPlayer();
}
} else {
// Simple patrol movement
self.velocityX = self.speed * self.direction;
// Random jump towards platforms while patrolling
if (self.onGround && Math.random() < 0.005) {
// 0.5% chance per frame when on ground
// Look for platforms to jump to
var targetPlatform = null;
var patrolDirection = self.direction;
for (var p = 0; p < platforms.length; p++) {
var platform = platforms[p];
var platformDistance = Math.abs(platform.x - self.x);
var platformInDirection = patrolDirection > 0 ? platform.x > self.x : platform.x < self.x;
if (platformInDirection && platform.y < self.y && platformDistance < 200 && platformDistance > 50) {
targetPlatform = platform;
break;
}
}
if (targetPlatform) {
self.velocityY = -12; // Smaller jump for patrol
self.velocityX = patrolDirection * (self.speed + 1);
self.onGround = false;
}
}
}
// Apply velocity
self.x += self.velocityX;
self.y += self.velocityY;
// Reset ground detection
self.onGround = false;
// Reverse direction at edges
if (self.x < 50 || self.x > 1998) {
self.direction *= -1;
}
// Update attack cooldown
if (self.attackCooldown > 0) {
self.attackCooldown--;
}
// Animation
self.animationTick++;
if (!self.isAttacking) {
// Walking animation with more realistic movement
var walkSpeed = Math.abs(self.velocityX) > 0.1 ? 0.25 : 0.1;
var walkCycle = Math.sin(self.animationTick * walkSpeed);
var walkCycleOffset = Math.sin(self.animationTick * walkSpeed + Math.PI);
// Leg animation - alternate walking
leftLeg.rotation = walkCycle * 0.4;
rightLeg.rotation = walkCycleOffset * 0.4;
// Arm animation - opposite to legs (natural walking)
leftArm.rotation = walkCycleOffset * 0.3;
rightArm.rotation = walkCycle * 0.3;
// Body bob animation when walking
if (Math.abs(self.velocityX) > 0.1) {
body.y = -50 + Math.abs(Math.sin(self.animationTick * walkSpeed * 2)) * 2;
head.y = -65 + Math.abs(Math.sin(self.animationTick * walkSpeed * 2)) * 2;
} else {
// Return to normal position when not walking
body.y = -50;
head.y = -65;
}
}
// Face direction
if (self.direction > 0) {
head.scaleX = 1;
body.scaleX = 1;
leftArm.scaleX = 1;
rightArm.scaleX = 1;
leftLeg.scaleX = 1;
rightLeg.scaleX = 1;
sword.scaleX = 1;
sword.x = 15;
} else {
head.scaleX = -1;
body.scaleX = -1;
leftArm.scaleX = -1;
rightArm.scaleX = -1;
leftLeg.scaleX = -1;
rightLeg.scaleX = -1;
sword.scaleX = -1;
sword.x = -15;
}
self.lastPlayerDistance = distanceToPlayer;
};
self.attackPlayer = function () {
if (self.attackCooldown <= 0) {
self.attackCooldown = 120; // 2 seconds at 60fps
self.isAttacking = true;
// Sword attack animation - swing from back to front
tween(sword, {
rotation: -1.8
}, {
duration: 150,
onFinish: function onFinish() {
// Swing forward
tween(sword, {
rotation: 0.8
}, {
duration: 200,
onFinish: function onFinish() {
// Return to normal position
tween(sword, {
rotation: 0
}, {
duration: 250,
onFinish: function onFinish() {
self.isAttacking = false;
}
});
}
});
// Check if player is hit during forward swing (after 150ms delay)
LK.setTimeout(function () {
var distanceToPlayer = Math.abs(self.x - player.x);
if (distanceToPlayer < self.attackRange) {
player.takeDamage(10);
// Knockback effect
var knockbackDirection = player.x > self.x ? 1 : -1;
player.velocityX += knockbackDirection * 8;
}
}, 150);
}
});
}
};
self.takeDamage = function (damage) {
self.health -= damage;
// Update health bar
var healthPercent = Math.max(0, self.health / self.maxHealth);
healthBarFill.width = 56 * healthPercent;
// Change health bar color based on health
if (healthPercent > 0.6) {
healthBarFill.tint = 0x00FF00; // Green
} else if (healthPercent > 0.3) {
healthBarFill.tint = 0xFFFF00; // Yellow
} else {
healthBarFill.tint = 0xFF0000; // Red
}
// Damage flash effect on all body parts
var bodyParts = [head, body, leftArm, rightArm, leftLeg, rightLeg];
for (var i = 0; i < bodyParts.length; i++) {
var part = bodyParts[i];
tween(part, {
tint: 0xFFFFFF
}, {
duration: 100,
onFinish: function onFinish() {
tween(part, {
tint: 0xFF0000
}, {
duration: 100
});
}
});
}
if (self.health <= 0) {
self.destroy();
return true;
}
return false;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x001122,
// Dark digital blue background
width: 2732,
// Optimized for mobile landscape
height: 2048 // Optimized for mobile landscape
});
/****
* Game Code
****/
// Shadow Lord boss attack sound
// Fire Demon boss attack sound
// Purple Giant boss attack sound
// Load current level from storage
// Game state management
// StickmanEnemy skin variations
// FlyingEnemy skin variations
if (storage.currentLevel) {
currentLevel = storage.currentLevel;
}
var gameState = 'menu'; // 'menu', 'mapSelect', 'settings', 'playing', 'shop'
var shopContainer;
var currentShopCategory = 'guardior'; // Global variable for shop category state
var currentLevel = 1;
var enemyBullets = [];
// Input state variables
var leftPressed = false;
var rightPressed = false;
var currentTouchId = null;
// Level progression system - 3 levels + 1 boss, repeating
function getCurrentLevelConfig() {
var levelIndex = (currentLevel - 1) % 4;
var cycleNumber = Math.floor((currentLevel - 1) / 4);
var isBossLevel = levelIndex === 3;
if (isBossLevel) {
return getBossLevel(cycleNumber);
} else {
return getRegularLevel(levelIndex, cycleNumber);
}
}
function getRegularLevel(levelIndex, cycleNumber) {
var baseConfigs = [
// Level 1 theme - Forest Plains with detailed environment
{
name: "Forest Plains",
backgroundColor: 0x1a4d1a,
// Deeper forest green
musicTrack: 'menu_music',
basePlatforms: [{
x: 400,
y: 1800,
type: 'wooden',
// Wooden log platforms
tint: 0x8B4513
}, {
x: 800,
y: 1600,
type: 'stone',
tint: 0x696969
}, {
x: 1200,
y: 1700,
type: 'wooden',
tint: 0x8B4513
}, {
x: 1600,
y: 1500,
type: 'stone',
tint: 0x696969
}, {
x: 1900,
y: 1800,
type: 'wooden',
tint: 0x8B4513
}, {
x: 600,
y: 1450,
type: 'moss_covered',
tint: 0x556B2F
}, {
x: 1000,
y: 1350,
type: 'fallen_log',
tint: 0x654321
}, {
x: 1750,
y: 1400,
type: 'stone_slab',
tint: 0x708090
}],
decorations: [{
type: 'tree',
x: 300,
y: 1900,
tint: 0x228B22
}, {
type: 'tree',
x: 700,
y: 1900,
tint: 0x32CD32
}, {
type: 'tree',
x: 1100,
y: 1900,
tint: 0x228B22
}, {
type: 'tree',
x: 1500,
y: 1900,
tint: 0x32CD32
}, {
type: 'tree',
x: 1800,
y: 1900,
tint: 0x2E8B57
}, {
type: 'tree',
x: 200,
y: 1900,
tint: 0x006400
}, {
type: 'bush',
x: 450,
y: 1880,
tint: 0x006400
}, {
type: 'bush',
x: 850,
y: 1880,
tint: 0x228B22
}, {
type: 'bush',
x: 1250,
y: 1880,
tint: 0x32CD32
}, {
type: 'bush',
x: 1650,
y: 1880,
tint: 0x2E8B57
}, {
type: 'bush',
x: 750,
y: 1850,
tint: 0x3CB371
}, {
type: 'rock',
x: 1050,
y: 1920,
tint: 0x696969
}, {
type: 'rock',
x: 1750,
y: 1920,
tint: 0x808080
}, {
type: 'rock',
x: 350,
y: 1920,
tint: 0x778899
}, {
type: 'rock',
x: 1350,
y: 1920,
tint: 0x2F4F4F
}, {
type: 'flower_patch',
x: 500,
y: 1870,
tint: 0xFF69B4
}, {
type: 'flower_patch',
x: 900,
y: 1870,
tint: 0xFFB6C1
}, {
type: 'flower_patch',
x: 1300,
y: 1870,
tint: 0xFF1493
}, {
type: 'mushroom',
x: 650,
y: 1890,
tint: 0xFF6347
}, {
type: 'mushroom',
x: 1150,
y: 1890,
tint: 0xFF4500
}, {
type: 'mushroom',
x: 1550,
y: 1890,
tint: 0xDC143C
}, {
type: 'fallen_branch',
x: 550,
y: 1910,
tint: 0x8B4513
}, {
type: 'fallen_branch',
x: 950,
y: 1910,
tint: 0xA0522D
}, {
type: 'fallen_branch',
x: 1450,
y: 1910,
tint: 0x654321
}, {
type: 'ivy_patch',
x: 800,
y: 1550,
tint: 0x228B22
}, {
type: 'ivy_patch',
x: 1200,
y: 1650,
tint: 0x32CD32
}, {
type: 'vine_hanging',
x: 1000,
y: 1300,
tint: 0x6B8E23
}, {
type: 'vine_hanging',
x: 1600,
y: 1450,
tint: 0x9ACD32
}, {
type: 'bird_nest',
x: 400,
y: 1750,
tint: 0x8B4513
}, {
type: 'bird_nest',
x: 1700,
y: 1750,
tint: 0xA0522D
}, {
type: 'forest_shrine',
x: 1000,
y: 1850,
tint: 0x708090
}, {
type: 'wooden_sign',
x: 250,
y: 1850,
tint: 0x8B4513
}],
baseEnemies: [{
type: 'stickman',
x: 900,
y: 1550
}, {
type: 'stickman',
x: 1400,
y: 1650
}, {
type: 'flying',
x: 1200,
y: 1400
}]
},
// Level 2 theme - Sky Temple with floating elements
{
name: "Sky Temple",
backgroundColor: 0x1e3a8a,
// Deep sky blue
musicTrack: 'menu_music',
basePlatforms: [{
x: 300,
y: 1700,
type: 'crystal',
tint: 0x87CEEB
}, {
x: 600,
y: 1500,
type: 'marble',
tint: 0xF5F5DC
}, {
x: 900,
y: 1300,
type: 'crystal',
tint: 0x87CEEB
}, {
x: 1300,
y: 1200,
type: 'marble',
tint: 0xF5F5DC
}, {
x: 1700,
y: 1400,
type: 'crystal',
tint: 0x87CEEB
}, {
x: 2000,
y: 1600,
type: 'marble',
tint: 0xF5F5DC
}, {
x: 450,
y: 1350,
type: 'floating_crystal',
tint: 0x00CED1
}, {
x: 750,
y: 1150,
type: 'sky_marble',
tint: 0xE6E6FA
}, {
x: 1050,
y: 1050,
type: 'ethereal_platform',
tint: 0xB0E0E6
}, {
x: 1450,
y: 1350,
type: 'celestial_stone',
tint: 0x87CEFA
}],
decorations: [{
type: 'cloud',
x: 200,
y: 1000,
tint: 0xFFFFFF
}, {
type: 'cloud',
x: 800,
y: 800,
tint: 0xF0F8FF
}, {
type: 'cloud',
x: 1400,
y: 900,
tint: 0xFFFFFF
}, {
type: 'cloud',
x: 1800,
y: 700,
tint: 0xF5F5F5
}, {
type: 'cloud',
x: 500,
y: 600,
tint: 0xFFFAFA
}, {
type: 'cloud',
x: 1100,
y: 500,
tint: 0xF8F8FF
}, {
type: 'pillar',
x: 400,
y: 1750,
tint: 0xDDDDDD
}, {
type: 'pillar',
x: 1200,
y: 1550,
tint: 0xDDDDDD
}, {
type: 'pillar',
x: 1800,
y: 1650,
tint: 0xDDDDDD
}, {
type: 'pillar',
x: 700,
y: 1450,
tint: 0xE0E0E0
}, {
type: 'pillar',
x: 1500,
y: 1150,
tint: 0xD3D3D3
}, {
type: 'crystal',
x: 500,
y: 1450,
tint: 0x00FFFF
}, {
type: 'crystal',
x: 1100,
y: 1250,
tint: 0x00FFFF
}, {
type: 'crystal',
x: 350,
y: 1600,
tint: 0x40E0D0
}, {
type: 'crystal',
x: 1650,
y: 1300,
tint: 0x48D1CC
}, {
type: 'floating_shrine',
x: 900,
y: 1100,
tint: 0xB0C4DE
}, {
type: 'wind_chime',
x: 600,
y: 1300,
tint: 0xFFD700
}, {
type: 'wind_chime',
x: 1300,
y: 1000,
tint: 0xFFA500
}, {
type: 'celestial_orb',
x: 750,
y: 950,
tint: 0xDDA0DD
}, {
type: 'celestial_orb',
x: 1150,
y: 850,
tint: 0xEE82EE
}, {
type: 'celestial_orb',
x: 1550,
y: 1050,
tint: 0xDA70D6
}, {
type: 'sky_rune',
x: 250,
y: 1600,
tint: 0x9370DB
}, {
type: 'sky_rune',
x: 1950,
y: 1500,
tint: 0x8A2BE2
}, {
type: 'ethereal_gateway',
x: 1000,
y: 800,
tint: 0x6495ED
}, {
type: 'starlight_pool',
x: 800,
y: 1400,
tint: 0x87CEEB
}, {
type: 'starlight_pool',
x: 1400,
y: 1100,
tint: 0x87CEFA
}, {
type: 'divine_statue',
x: 600,
y: 1200,
tint: 0xF0F8FF
}, {
type: 'divine_statue',
x: 1600,
y: 1200,
tint: 0xE6E6FA
}, {
type: 'floating_lotus',
x: 450,
y: 1250,
tint: 0xFFB6C1
}, {
type: 'floating_lotus',
x: 1350,
y: 950,
tint: 0xFFC0CB
}],
baseEnemies: [{
type: 'flying',
x: 500,
y: 1400
}, {
type: 'stickman',
x: 1000,
y: 1250
}, {
type: 'flying',
x: 1500,
y: 1300
}, {
type: 'flying',
x: 800,
y: 1100
}]
},
// Level 3 theme - Desert Ruins with ancient structures
{
name: "Desert Ruins",
backgroundColor: 0x8B4513,
// Desert brown
musicTrack: 'menu_music',
basePlatforms: [{
x: 200,
y: 1900,
type: 'sandstone',
tint: 0xF4A460
}, {
x: 500,
y: 1700,
type: 'brick',
tint: 0xCD853F
}, {
x: 800,
y: 1400,
type: 'sandstone',
tint: 0xF4A460
}, {
x: 1200,
y: 1600,
type: 'brick',
tint: 0xCD853F
}, {
x: 1550,
y: 1300,
type: 'sandstone',
tint: 0xF4A460
}, {
x: 1900,
y: 1700,
type: 'brick',
tint: 0xCD853F
}, {
x: 650,
y: 1500,
type: 'ancient_stone',
tint: 0xBDB76B
}, {
x: 1050,
y: 1200,
type: 'weathered_brick',
tint: 0xD2691E
}, {
x: 1750,
y: 1450,
type: 'carved_platform',
tint: 0xBC8F8F
}],
decorations: [{
type: 'pyramid',
x: 150,
y: 1950,
tint: 0xDEB887
}, {
type: 'pyramid',
x: 1950,
y: 1950,
tint: 0xDEB887
}, {
type: 'pyramid',
x: 1000,
y: 1950,
tint: 0xD2B48C
}, {
type: 'column',
x: 400,
y: 1850,
tint: 0xD2B48C
}, {
type: 'column',
x: 900,
y: 1650,
tint: 0xD2B48C
}, {
type: 'column',
x: 1400,
y: 1750,
tint: 0xD2B48C
}, {
type: 'column',
x: 700,
y: 1550,
tint: 0xDDD8C4
}, {
type: 'column',
x: 1700,
y: 1550,
tint: 0xE6E0D4
}, {
type: 'obelisk',
x: 600,
y: 1800,
tint: 0xA0522D
}, {
type: 'obelisk',
x: 1600,
y: 1600,
tint: 0xA0522D
}, {
type: 'obelisk',
x: 300,
y: 1850,
tint: 0x8B4513
}, {
type: 'cactus',
x: 350,
y: 1920,
tint: 0x228B22
}, {
type: 'cactus',
x: 1750,
y: 1920,
tint: 0x228B22
}, {
type: 'cactus',
x: 850,
y: 1920,
tint: 0x2E8B57
}, {
type: 'cactus',
x: 1350,
y: 1920,
tint: 0x6B8E23
}, {
type: 'ancient_tomb',
x: 500,
y: 1850,
tint: 0x8B7355
}, {
type: 'ancient_tomb',
x: 1500,
y: 1750,
tint: 0x8B7D6B
}, {
type: 'hieroglyph_wall',
x: 250,
y: 1800,
tint: 0xDEB887
}, {
type: 'hieroglyph_wall',
x: 1850,
y: 1650,
tint: 0xD2B48C
}, {
type: 'sphinx_statue',
x: 800,
y: 1850,
tint: 0xF5DEB3
}, {
type: 'scarab_carving',
x: 450,
y: 1650,
tint: 0xDAA520
}, {
type: 'scarab_carving',
x: 1250,
y: 1550,
tint: 0xFFD700
}, {
type: 'ancient_vase',
x: 550,
y: 1680,
tint: 0xCD853F
}, {
type: 'ancient_vase',
x: 1150,
y: 1580,
tint: 0xD2691E
}, {
type: 'sand_dune',
x: 200,
y: 1900,
tint: 0xF5DEB3
}, {
type: 'sand_dune',
x: 600,
y: 1900,
tint: 0xF4A460
}, {
type: 'sand_dune',
x: 1000,
y: 1900,
tint: 0xDEB887
}, {
type: 'sand_dune',
x: 1400,
y: 1900,
tint: 0xD2B48C
}, {
type: 'sand_dune',
x: 1800,
y: 1900,
tint: 0xF5DEB3
}, {
type: 'temple_entrance',
x: 1100,
y: 1500,
tint: 0x8B7355
}, {
type: 'ankh_symbol',
x: 750,
y: 1350,
tint: 0xDAA520
}, {
type: 'ankh_symbol',
x: 1450,
y: 1250,
tint: 0xFFD700
}, {
type: 'desert_gem',
x: 650,
y: 1450,
tint: 0x32CD32
}, {
type: 'desert_gem',
x: 1350,
y: 1150,
tint: 0x00CED1
}],
baseEnemies: [{
type: 'stickman',
x: 600,
y: 1650
}, {
type: 'flying',
x: 1000,
y: 1300
}, {
type: 'stickman',
x: 1400,
y: 1250
}, {
type: 'flying',
x: 1750,
y: 1600
}, {
type: 'stickman',
x: 800,
y: 1350
}]
}];
var config = baseConfigs[levelIndex];
var scaledConfig = {
name: config.name + " " + (cycleNumber + 1),
backgroundColor: config.backgroundColor,
musicTrack: config.musicTrack,
platforms: [],
enemies: [],
decorations: []
};
// Scale platforms and add variety with enhanced details
for (var i = 0; i < config.basePlatforms.length; i++) {
var platform = config.basePlatforms[i];
scaledConfig.platforms.push({
x: platform.x + (cycleNumber * 50 - 25),
y: platform.y - cycleNumber * 30,
type: platform.type,
tint: platform.tint,
width: 200 + cycleNumber * 20,
// Larger platforms in higher cycles
height: 40 + cycleNumber * 5
});
}
// Add more detailed platforms for higher cycles
if (cycleNumber > 0) {
scaledConfig.platforms.push({
x: 250 + cycleNumber * 100,
y: 2350 - cycleNumber * 40,
type: 'enhanced',
tint: 0x666666,
width: 250,
height: 50
});
scaledConfig.platforms.push({
x: 1750 - cycleNumber * 100,
y: 2150 - cycleNumber * 20,
type: 'enhanced',
tint: 0x666666,
width: 250,
height: 50
});
}
// Scale and enhance decorations
if (config.decorations) {
for (var i = 0; i < config.decorations.length; i++) {
var decoration = config.decorations[i];
scaledConfig.decorations.push({
type: decoration.type,
x: decoration.x + (cycleNumber * 30 - 15),
y: decoration.y - cycleNumber * 20,
tint: decoration.tint,
scale: 1 + cycleNumber * 0.2 // Bigger decorations in higher cycles
});
}
// Add cycle-specific decorations
for (var i = 0; i < cycleNumber; i++) {
scaledConfig.decorations.push({
type: 'treasure',
x: 400 + i * 600,
y: 1950 - i * 100,
tint: 0xFFD700,
scale: 0.8
});
}
}
// Scale enemies and add more for difficulty
for (var i = 0; i < config.baseEnemies.length; i++) {
var enemy = config.baseEnemies[i];
scaledConfig.enemies.push({
type: enemy.type,
x: enemy.x + (cycleNumber * 30 - 15),
y: enemy.y - cycleNumber * 30
});
}
// Add extra enemies for higher cycles
var extraEnemies = Math.min(cycleNumber, 3);
for (var i = 0; i < extraEnemies; i++) {
var enemyType = Math.random() < 0.6 ? 'stickman' : 'flying';
scaledConfig.enemies.push({
type: enemyType,
x: 300 + i * 400 + Math.random() * 200,
y: 2300 - Math.random() * 200
});
}
return scaledConfig;
}
function getBossLevel(cycleNumber) {
var bossTypes = [
// Boss 1 - Purple Giant's Detailed Lair
{
name: "Purple Giant's Lair",
backgroundColor: 0x4a0e4e,
// Darker, more ominous purple
musicTrack: 'boss_music',
bossType: 'boss',
platforms: [{
x: 600,
y: 1700,
type: 'obsidian',
tint: 0x2F2F2F,
width: 280,
height: 60
}, {
x: 1024,
y: 1800,
type: 'throne',
tint: 0x800080,
width: 350,
height: 80
}, {
x: 1600,
y: 1700,
type: 'obsidian',
tint: 0x2F2F2F,
width: 280,
height: 60
}],
decorations: [{
type: 'statue',
x: 300,
y: 1900,
tint: 0x483D8B,
scale: 2.0
}, {
type: 'statue',
x: 1800,
y: 1900,
tint: 0x483D8B,
scale: 2.0
}, {
type: 'statue',
x: 700,
y: 1900,
tint: 0x4B0082,
scale: 1.8
}, {
type: 'statue',
x: 1400,
y: 1900,
tint: 0x6A5ACD,
scale: 1.8
}, {
type: 'torch',
x: 500,
y: 1600,
tint: 0xFF4500,
scale: 1.5
}, {
type: 'torch',
x: 1500,
y: 1600,
tint: 0xFF4500,
scale: 1.5
}, {
type: 'torch',
x: 800,
y: 1500,
tint: 0xFF6347,
scale: 1.3
}, {
type: 'torch',
x: 1200,
y: 1500,
tint: 0xFF6347,
scale: 1.3
}, {
type: 'torch',
x: 400,
y: 1800,
tint: 0xDC143C,
scale: 1.2
}, {
type: 'torch',
x: 1600,
y: 1800,
tint: 0xDC143C,
scale: 1.2
}, {
type: 'skull',
x: 200,
y: 1950,
tint: 0xF5F5DC,
scale: 1.2
}, {
type: 'skull',
x: 1900,
y: 1950,
tint: 0xF5F5DC,
scale: 1.2
}, {
type: 'skull',
x: 600,
y: 1950,
tint: 0xDDD8C4,
scale: 1.0
}, {
type: 'skull',
x: 1000,
y: 1950,
tint: 0xE6E0D4,
scale: 1.0
}, {
type: 'skull',
x: 1400,
y: 1950,
tint: 0xDDD8C4,
scale: 1.0
}, {
type: 'banner',
x: 1024,
y: 1200,
tint: 0x8B008B,
scale: 3.0
}, {
type: 'banner',
x: 600,
y: 1350,
tint: 0x9932CC,
scale: 2.0
}, {
type: 'banner',
x: 1400,
y: 1350,
tint: 0x9932CC,
scale: 2.0
}, {
type: 'dark_crystal',
x: 450,
y: 1750,
tint: 0x8B008B,
scale: 1.5
}, {
type: 'dark_crystal',
x: 1550,
y: 1750,
tint: 0x8B008B,
scale: 1.5
}, {
type: 'evil_altar',
x: 850,
y: 1800,
tint: 0x2F2F2F,
scale: 1.8
}, {
type: 'evil_altar',
x: 1200,
y: 1800,
tint: 0x2F2F2F,
scale: 1.8
}, {
type: 'bone_pile',
x: 350,
y: 1920,
tint: 0xF5F5DC,
scale: 1.3
}, {
type: 'bone_pile',
x: 750,
y: 1920,
tint: 0xF5F5DC,
scale: 1.3
}, {
type: 'bone_pile',
x: 1150,
y: 1920,
tint: 0xF5F5DC,
scale: 1.3
}, {
type: 'bone_pile',
x: 1650,
y: 1920,
tint: 0xF5F5DC,
scale: 1.3
}, {
type: 'dark_throne',
x: 1024,
y: 1750,
tint: 0x2F2F2F,
scale: 2.5
}, {
type: 'purple_orb',
x: 300,
y: 1700,
tint: 0x9370DB,
scale: 1.2
}, {
type: 'purple_orb',
x: 1700,
y: 1700,
tint: 0x9370DB,
scale: 1.2
}, {
type: 'sacrificial_circle',
x: 1024,
y: 1900,
tint: 0x8B0000,
scale: 3.5
}],
minions: [{
type: 'stickman',
x: 700,
y: 1650
}, {
type: 'stickman',
x: 1500,
y: 1650
}]
},
// Boss 2 - Shadow Lord's Enhanced Domain
{
name: "Shadow Lord's Domain",
backgroundColor: 0x0f0f0f,
// Almost black for shadow realm
musicTrack: 'boss_music',
bossType: 'shadowBoss',
platforms: [{
x: 400,
y: 1600,
type: 'shadow',
tint: 0x1C1C1C,
width: 240,
height: 50
}, {
x: 800,
y: 1400,
type: 'void',
tint: 0x000000,
width: 260,
height: 55
}, {
x: 1200,
y: 1500,
type: 'shadow',
tint: 0x1C1C1C,
width: 240,
height: 50
}, {
x: 1600,
y: 1300,
type: 'void',
tint: 0x000000,
width: 260,
height: 55
}, {
x: 1900,
y: 1700,
type: 'shadow',
tint: 0x1C1C1C,
width: 240,
height: 50
}],
decorations: [{
type: 'portal',
x: 200,
y: 1800,
tint: 0x8A2BE2,
scale: 1.8
}, {
type: 'portal',
x: 1900,
y: 1800,
tint: 0x8A2BE2,
scale: 1.8
}, {
type: 'crystal',
x: 600,
y: 1500,
tint: 0x4B0082,
scale: 1.4
}, {
type: 'crystal',
x: 1400,
y: 1200,
tint: 0x4B0082,
scale: 1.4
}, {
type: 'rune',
x: 300,
y: 1950,
tint: 0x9932CC,
scale: 1.0
}, {
type: 'rune',
x: 700,
y: 1950,
tint: 0x9932CC,
scale: 1.0
}, {
type: 'rune',
x: 1100,
y: 1950,
tint: 0x9932CC,
scale: 1.0
}, {
type: 'rune',
x: 1500,
y: 1950,
tint: 0x9932CC,
scale: 1.0
}, {
type: 'shadowspire',
x: 1024,
y: 1000,
tint: 0x2F2F2F,
scale: 4.0
}],
minions: [{
type: 'flying',
x: 600,
y: 1300
}, {
type: 'flying',
x: 1400,
y: 1200
}, {
type: 'stickman',
x: 1000,
y: 1350
}]
},
// Boss 3 - Fire Demon's Enhanced Inferno
{
name: "Fire Demon's Inferno",
backgroundColor: 0x8B0000,
// Deep fire red
musicTrack: 'boss_music',
bossType: 'fireBoss',
platforms: [{
x: 500,
y: 1800,
type: 'lava',
tint: 0xFF6347,
width: 300,
height: 70
}, {
x: 900,
y: 1600,
type: 'molten',
tint: 0xFF4500,
width: 280,
height: 60
}, {
x: 1300,
y: 1400,
type: 'lava',
tint: 0xFF6347,
width: 300,
height: 70
}, {
x: 1700,
y: 1700,
type: 'molten',
tint: 0xFF4500,
width: 280,
height: 60
}],
decorations: [{
type: 'volcano',
x: 150,
y: 1950,
tint: 0x8B0000,
scale: 2.5
}, {
type: 'volcano',
x: 1950,
y: 1950,
tint: 0x8B0000,
scale: 2.5
}, {
type: 'lavafall',
x: 300,
y: 1000,
tint: 0xFF4500,
scale: 3.0
}, {
type: 'lavafall',
x: 1750,
y: 1000,
tint: 0xFF4500,
scale: 3.0
}, {
type: 'firecrystal',
x: 600,
y: 1700,
tint: 0xFF0000,
scale: 1.6
}, {
type: 'firecrystal',
x: 1200,
y: 1300,
tint: 0xFF0000,
scale: 1.6
}, {
type: 'firecrystal',
x: 1600,
y: 1600,
tint: 0xFF0000,
scale: 1.6
}, {
type: 'brazier',
x: 400,
y: 1850,
tint: 0xFFD700,
scale: 1.3
}, {
type: 'brazier',
x: 1100,
y: 1650,
tint: 0xFFD700,
scale: 1.3
}, {
type: 'brazier',
x: 1800,
y: 1750,
tint: 0xFFD700,
scale: 1.3
}, {
type: 'infernospire',
x: 1024,
y: 800,
tint: 0xFF4500,
scale: 5.0
}],
minions: [{
type: 'flying',
x: 700,
y: 1500
}, {
type: 'stickman',
x: 1100,
y: 1350
}, {
type: 'flying',
x: 1500,
y: 1600
}, {
type: 'stickman',
x: 1900,
y: 1650
}]
}];
var bossIndex = cycleNumber % bossTypes.length;
var bossConfig = bossTypes[bossIndex];
// Enhanced boss level with detailed environment
var enhancedConfig = {
name: bossConfig.name + " " + (cycleNumber + 1),
backgroundColor: bossConfig.backgroundColor,
musicTrack: bossConfig.musicTrack,
platforms: [],
enemies: [{
type: bossConfig.bossType,
x: 1024,
y: 2450
}].concat(bossConfig.minions),
decorations: []
};
// Enhanced platforms with cycle scaling
for (var i = 0; i < bossConfig.platforms.length; i++) {
var platform = bossConfig.platforms[i];
enhancedConfig.platforms.push({
x: platform.x,
y: platform.y - cycleNumber * 15,
// Slightly higher for more challenge
type: platform.type,
tint: platform.tint,
width: platform.width + cycleNumber * 10,
// Larger platforms
height: platform.height + cycleNumber * 5
});
}
// Enhanced decorations with cycle scaling
if (bossConfig.decorations) {
for (var i = 0; i < bossConfig.decorations.length; i++) {
var decoration = bossConfig.decorations[i];
enhancedConfig.decorations.push({
type: decoration.type,
x: decoration.x,
y: decoration.y - cycleNumber * 10,
tint: decoration.tint,
scale: decoration.scale + cycleNumber * 0.1 // Grander decorations
});
}
// Add cycle-specific enhancements
for (var i = 0; i < cycleNumber; i++) {
// Add power crystals that make the boss stronger
enhancedConfig.decorations.push({
type: 'powercrystal',
x: 300 + i * 700,
y: 1200 - i * 50,
tint: 0xFFD700,
scale: 1.5 + i * 0.2
});
}
}
return enhancedConfig;
}
// Game arrays
var platforms = [];
var enemies = [];
var projectiles = [];
var arrows = [];
// UI Elements
var menuContainer, mapSelectContainer, settingsContainer;
// Game objects (will be created when starting game)
var ground, player, staminaBarBackground, staminaBar;
function createMenu() {
menuContainer = new Container();
game.addChild(menuContainer);
// Background decorative elements
// Create background warrior silhouettes
for (var i = 0; i < 8; i++) {
var bgWarrior = LK.getAsset('warrior', {
width: 60,
height: 70,
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.1,
tint: 0x444444
});
bgWarrior.x = 200 + i * 200 + Math.random() * 100;
bgWarrior.y = 800 + Math.random() * 400;
bgWarrior.rotation = Math.random() * Math.PI * 2;
menuContainer.addChild(bgWarrior);
}
// Animated floating swords
for (var i = 0; i < 5; i++) {
var bgSword = LK.getAsset('sword', {
width: 40,
height: 40,
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.15,
tint: 0x666666
});
bgSword.x = 300 + i * 300 + Math.random() * 100;
bgSword.y = 600 + Math.random() * 300;
bgSword.startRotation = Math.random() * Math.PI * 2;
bgSword.rotationSpeed = (Math.random() - 0.5) * 0.02;
menuContainer.addChild(bgSword);
// Animate floating swords
tween(bgSword, {
y: bgSword.y - 50,
alpha: 0.05
}, {
duration: 3000 + Math.random() * 2000,
easing: tween.easeInOut,
repeat: -1,
yoyo: true
});
}
// Decorative border elements
var topBorder = LK.getAsset('platform', {
width: 2048,
height: 8,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFD700
});
topBorder.x = 1024;
topBorder.y = 100;
menuContainer.addChild(topBorder);
var bottomBorder = LK.getAsset('platform', {
width: 2048,
height: 8,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFD700
});
bottomBorder.x = 1024;
bottomBorder.y = 1300;
menuContainer.addChild(bottomBorder);
// Title with enhanced styling
var titleShadow = new Text2('CubikWarrior: Choque de Titanes', {
size: 70,
fill: 0x000000
});
titleShadow.anchor.set(0.5, 0.5);
titleShadow.x = 1028;
titleShadow.y = 404;
menuContainer.addChild(titleShadow);
var title = new Text2('CubikWarrior: Choque de Titanes', {
size: 70,
fill: 0xFFD700
});
title.anchor.set(0.5, 0.5);
title.x = 1024;
title.y = 400;
menuContainer.addChild(title);
// Subtitle
var subtitle = new Text2('EPIC BATTLES AWAIT', {
size: 28,
fill: 0xCCCCCC
});
subtitle.anchor.set(0.5, 0.5);
subtitle.x = 1024;
subtitle.y = 480;
menuContainer.addChild(subtitle);
// Animated title glow effect
var glowCycle = 0;
var titleGlowInterval = LK.setInterval(function () {
glowCycle += 0.05;
var glow = 0.8 + Math.sin(glowCycle) * 0.2;
title.alpha = glow;
}, 50);
// Play button with enhanced styling - larger for Android phones
var playButtonShadow = LK.getAsset('platform', {
width: 408,
height: 128,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x000000
});
playButtonShadow.x = 1028;
playButtonShadow.y = 604;
menuContainer.addChild(playButtonShadow);
var playButton = LK.getAsset('platform', {
width: 400,
height: 120,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x4444FF
});
playButton.x = 1024;
playButton.y = 600;
playButton.interactive = true;
playButton.buttonMode = true;
menuContainer.addChild(playButton);
var playButtonBorder = LK.getAsset('platform', {
width: 408,
height: 128,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFD700,
alpha: 0.3
});
playButtonBorder.x = 1024;
playButtonBorder.y = 600;
menuContainer.addChild(playButtonBorder);
var playText = new Text2('PLAY', {
size: 45,
fill: 0xFFFFFF
});
playText.anchor.set(0.5, 0.5);
playText.x = playButton.x;
playText.y = playButton.y;
menuContainer.addChild(playText);
// Add button glow animation
var playButtonGlow = 0;
var playGlowInterval = LK.setInterval(function () {
playButtonGlow += 0.03;
var glowAlpha = 0.3 + Math.sin(playButtonGlow) * 0.1;
playButtonBorder.alpha = glowAlpha;
}, 50);
playButton.down = function () {
LK.getSound('button_click').play();
// Always start at level 1 for the Play button
currentLevel = 1;
storage.currentLevel = currentLevel;
gameState = 'mapSelect';
menuContainer.visible = false;
createMapSelect();
};
// Settings button with enhanced detailed styling - optimized for mobile
// Multi-layered shadow system for depth
var settingsButtonDeepShadow = LK.getAsset('platform', {
width: 418,
height: 138,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x000000,
alpha: 0.6
});
settingsButtonDeepShadow.x = 1032;
settingsButtonDeepShadow.y = 788;
menuContainer.addChild(settingsButtonDeepShadow);
var settingsButtonShadow = LK.getAsset('platform', {
width: 412,
height: 132,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x222222,
alpha: 0.8
});
settingsButtonShadow.x = 1028;
settingsButtonShadow.y = 784;
menuContainer.addChild(settingsButtonShadow);
// Main settings button with gradient-like effect using multiple layers
var settingsButtonBase = LK.getAsset('platform', {
width: 400,
height: 120,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x2d7a2d
});
settingsButtonBase.x = 1024;
settingsButtonBase.y = 780;
menuContainer.addChild(settingsButtonBase);
var settingsButton = LK.getAsset('platform', {
width: 390,
height: 110,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x44FF44
});
settingsButton.x = 1024;
settingsButton.y = 780;
settingsButton.interactive = true;
settingsButton.buttonMode = true;
menuContainer.addChild(settingsButton);
// Detailed border system with multiple accent layers
var settingsButtonOuterBorder = LK.getAsset('platform', {
width: 416,
height: 136,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x88FF88,
alpha: 0.4
});
settingsButtonOuterBorder.x = 1024;
settingsButtonOuterBorder.y = 780;
menuContainer.addChild(settingsButtonOuterBorder);
var settingsButtonInnerBorder = LK.getAsset('platform', {
width: 408,
height: 128,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xAAFFAA,
alpha: 0.2
});
settingsButtonInnerBorder.x = 1024;
settingsButtonInnerBorder.y = 780;
menuContainer.addChild(settingsButtonInnerBorder);
// Detailed corner accents for enhanced visual appeal
var settingsCornerAccents = [];
for (var i = 0; i < 4; i++) {
var corner = LK.getAsset('platform', {
width: 20,
height: 20,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFD700,
alpha: 0.7
});
var offsetX = i % 2 === 0 ? -180 : 180;
var offsetY = i < 2 ? -40 : 40;
corner.x = 1024 + offsetX;
corner.y = 780 + offsetY;
menuContainer.addChild(corner);
settingsCornerAccents.push(corner);
}
// Enhanced gear icon for settings with detailed design
var settingsGearBase = LK.getAsset('platform', {
width: 40,
height: 40,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFFFFF,
alpha: 0.9
});
settingsGearBase.x = 950;
settingsGearBase.y = 780;
menuContainer.addChild(settingsGearBase);
// Gear teeth details
for (var i = 0; i < 8; i++) {
var tooth = LK.getAsset('platform', {
width: 8,
height: 12,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xCCCCCC,
alpha: 0.8
});
var angle = i / 8 * Math.PI * 2;
tooth.x = 950 + Math.cos(angle) * 18;
tooth.y = 780 + Math.sin(angle) * 18;
tooth.rotation = angle;
menuContainer.addChild(tooth);
}
// Central gear hub
var settingsGearCenter = LK.getAsset('platform', {
width: 16,
height: 16,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x888888,
alpha: 0.9
});
settingsGearCenter.x = 950;
settingsGearCenter.y = 780;
menuContainer.addChild(settingsGearCenter);
// Enhanced settings text with shadow and styling
var settingsTextShadow = new Text2('SETTINGS', {
size: 45,
fill: 0x000000
});
settingsTextShadow.anchor.set(0.5, 0.5);
settingsTextShadow.x = 1026;
settingsTextShadow.y = 782;
menuContainer.addChild(settingsTextShadow);
var settingsText = new Text2('SETTINGS', {
size: 45,
fill: 0xFFFFFF
});
settingsText.anchor.set(0.5, 0.5);
settingsText.x = settingsButton.x;
settingsText.y = settingsButton.y;
menuContainer.addChild(settingsText);
// Detailed icon indicators for settings categories
var volumeIcon = LK.getAsset('platform', {
width: 24,
height: 24,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFD700,
alpha: 0.7
});
volumeIcon.x = 1080;
volumeIcon.y = 765;
menuContainer.addChild(volumeIcon);
var controlsIcon = LK.getAsset('platform', {
width: 20,
height: 20,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFD700,
alpha: 0.7
});
controlsIcon.x = 1080;
controlsIcon.y = 795;
menuContainer.addChild(controlsIcon);
// Enhanced button animation and interaction system
var settingsAnimationInterval;
var settingsButtonElements = [settingsButton, settingsButtonBase, settingsButtonOuterBorder, settingsButtonInnerBorder, settingsGearBase, settingsGearCenter];
// Continuous subtle animation for enhanced appeal
var settingsAnimCycle = 0;
settingsAnimationInterval = LK.setInterval(function () {
settingsAnimCycle += 0.02;
var pulseEffect = 0.95 + Math.sin(settingsAnimCycle) * 0.05;
// Pulse the main button slightly
settingsButton.scaleX = pulseEffect;
settingsButton.scaleY = pulseEffect;
// Rotate the gear elements
settingsGearBase.rotation += 0.01;
settingsGearCenter.rotation -= 0.015;
// Animate corner accents
for (var i = 0; i < settingsCornerAccents.length; i++) {
var corner = settingsCornerAccents[i];
var cornerCycle = settingsAnimCycle + i * Math.PI / 2;
corner.alpha = 0.5 + Math.sin(cornerCycle * 2) * 0.3;
}
// Animate border glow
var glowAlpha = 0.3 + Math.sin(settingsAnimCycle * 1.5) * 0.15;
settingsButtonOuterBorder.alpha = glowAlpha;
settingsButtonInnerBorder.alpha = glowAlpha * 0.7;
}, 50);
// Enhanced button interaction with detailed feedback
settingsButton.down = function () {
LK.getSound('button_click').play();
// Detailed press animation with multiple elements
tween(settingsButton, {
scaleX: 0.95,
scaleY: 0.95,
alpha: 0.9
}, {
duration: 100,
onFinish: function onFinish() {
tween(settingsButton, {
scaleX: 1.05,
scaleY: 1.05,
alpha: 1.0
}, {
duration: 150,
onFinish: function onFinish() {
tween(settingsButton, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100
});
}
});
}
});
// Enhanced text flash effect
tween(settingsText, {
tint: 0x44FF44,
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 100,
onFinish: function onFinish() {
tween(settingsText, {
tint: 0xFFFFFF,
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200
});
}
});
// Enhanced gear spin effect on press
tween(settingsGearBase, {
rotation: settingsGearBase.rotation + Math.PI
}, {
duration: 400,
easing: tween.easeOut
});
// Animate corner accents on press
for (var i = 0; i < settingsCornerAccents.length; i++) {
var corner = settingsCornerAccents[i];
tween(corner, {
scaleX: 1.5,
scaleY: 1.5,
alpha: 1.0
}, {
duration: 200,
onFinish: function onFinish() {
tween(corner, {
scaleX: 1.0,
scaleY: 1.0,
alpha: 0.7
}, {
duration: 300
});
}
});
}
// Navigate to settings
gameState = 'settings';
menuContainer.visible = false;
createSettings();
};
// Shop button with enhanced styling - repositioned for better layout
var shopButtonShadow = LK.getAsset('platform', {
width: 308,
height: 88,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x000000
});
shopButtonShadow.x = 604; // Better positioning
shopButtonShadow.y = 704;
menuContainer.addChild(shopButtonShadow);
var shopButton = LK.getAsset('platform', {
width: 300,
height: 80,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFD700
});
shopButton.x = 600; // Better positioning
shopButton.y = 700;
shopButton.interactive = true;
shopButton.buttonMode = true;
menuContainer.addChild(shopButton);
var shopButtonBorder = LK.getAsset('platform', {
width: 308,
height: 88,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFFF88,
alpha: 0.4
});
shopButtonBorder.x = 600;
shopButtonBorder.y = 700;
menuContainer.addChild(shopButtonBorder);
var shopText = new Text2('SHOP', {
size: 36,
fill: 0x000000
});
shopText.anchor.set(0.5, 0.5);
shopText.x = shopButton.x;
shopText.y = shopButton.y;
menuContainer.addChild(shopText);
// Add map select button for better navigation
var mapButtonShadow = LK.getAsset('platform', {
width: 308,
height: 88,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x000000
});
mapButtonShadow.x = 1444;
mapButtonShadow.y = 704;
menuContainer.addChild(mapButtonShadow);
var mapButton = LK.getAsset('platform', {
width: 300,
height: 80,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFF8844
});
mapButton.x = 1440;
mapButton.y = 700;
mapButton.interactive = true;
mapButton.buttonMode = true;
menuContainer.addChild(mapButton);
var mapButtonBorder = LK.getAsset('platform', {
width: 308,
height: 88,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFAA66,
alpha: 0.4
});
mapButtonBorder.x = 1440;
mapButtonBorder.y = 700;
menuContainer.addChild(mapButtonBorder);
var mapText = new Text2('LEVELS', {
size: 32,
fill: 0xFFFFFF
});
mapText.anchor.set(0.5, 0.5);
mapText.x = mapButton.x;
mapText.y = mapButton.y;
menuContainer.addChild(mapText);
mapButton.down = function () {
LK.getSound('button_click').play();
gameState = 'mapSelect';
menuContainer.visible = false;
createMapSelect();
};
shopButton.down = function () {
LK.getSound('button_click').play();
gameState = 'shop';
menuContainer.visible = false;
createShop();
};
// Statistics panel background
var statsPanel = LK.getAsset('platform', {
width: 600,
height: 280,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x1a1a1a,
alpha: 0.8
});
statsPanel.x = 1024;
statsPanel.y = 1000;
menuContainer.addChild(statsPanel);
// Statistics title
var statsTitle = new Text2('STATISTICS', {
size: 36,
fill: 0xFFD700
});
statsTitle.anchor.set(0.5, 0.5);
statsTitle.x = 1024;
statsTitle.y = 880;
menuContainer.addChild(statsTitle);
// High score display with enhanced styling
var highScoreLabel = new Text2('HIGH SCORE', {
size: 24,
fill: 0xCCCCCC
});
highScoreLabel.anchor.set(0.5, 0.5);
highScoreLabel.x = 1024;
highScoreLabel.y = 920;
menuContainer.addChild(highScoreLabel);
var highScoreText = new Text2(storage.highScore.toString(), {
size: 32,
fill: 0xFFD700
});
highScoreText.anchor.set(0.5, 0.5);
highScoreText.x = 1024;
highScoreText.y = 950;
menuContainer.addChild(highScoreText);
// Levels completed display
var levelsLabel = new Text2('LEVELS UNLOCKED', {
size: 24,
fill: 0xCCCCCC
});
levelsLabel.anchor.set(0.5, 0.5);
levelsLabel.x = 1024;
levelsLabel.y = 990;
menuContainer.addChild(levelsLabel);
var levelsText = new Text2(storage.unlockedLevels.toString(), {
size: 32,
fill: 0x44FF44
});
levelsText.anchor.set(0.5, 0.5);
levelsText.x = 1024;
levelsText.y = 1020;
menuContainer.addChild(levelsText);
// Coins display
var coinsLabel = new Text2('COINS EARNED', {
size: 24,
fill: 0xCCCCCC
});
coinsLabel.anchor.set(0.5, 0.5);
coinsLabel.x = 1024;
coinsLabel.y = 1060;
menuContainer.addChild(coinsLabel);
var coinsText = new Text2(storage.coins.toString(), {
size: 32,
fill: 0xFFD700
});
coinsText.anchor.set(0.5, 0.5);
coinsText.x = 1024;
coinsText.y = 1090;
menuContainer.addChild(coinsText);
// Current skin display
var skinLabel = new Text2('CURRENT SKIN', {
size: 24,
fill: 0xCCCCCC
});
skinLabel.anchor.set(0.5, 0.5);
skinLabel.x = 1024;
skinLabel.y = 1130;
menuContainer.addChild(skinLabel);
var skinName = storage.selectedSkin.charAt(0).toUpperCase() + storage.selectedSkin.slice(1);
var skinText = new Text2(skinName, {
size: 28,
fill: 0x8844FF
});
skinText.anchor.set(0.5, 0.5);
skinText.x = 1024;
skinText.y = 1160;
menuContainer.addChild(skinText);
// Version and credits
var versionText = new Text2('v1.0 - Made with LK Engine', {
size: 20,
fill: 0x666666
});
versionText.anchor.set(0.5, 0.5);
versionText.x = 1024;
versionText.y = 1220;
menuContainer.addChild(versionText);
// Animated background particles
for (var i = 0; i < 15; i++) {
var particle = LK.getAsset('bullet', {
width: 4,
height: 4,
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.3,
tint: 0xFFD700
});
particle.x = Math.random() * 2048;
particle.y = Math.random() * 1400;
particle.velocityX = (Math.random() - 0.5) * 2;
particle.velocityY = (Math.random() - 0.5) * 2;
menuContainer.addChild(particle);
// Animate particles
var _animateParticle = function animateParticle(p) {
tween(p, {
x: p.x + p.velocityX * 100,
y: p.y + p.velocityY * 100,
alpha: 0.1
}, {
duration: 2000 + Math.random() * 3000,
easing: tween.easeInOut,
onFinish: function onFinish() {
p.x = Math.random() * 2048;
p.y = Math.random() * 1400;
p.alpha = 0.3;
_animateParticle(p);
}
});
};
_animateParticle(particle);
}
// Animated menu background warrior showcase
var showcaseWarrior = LK.getAsset('warrior', {
width: 200,
height: 240,
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.4,
tint: 0x4444FF
});
showcaseWarrior.x = 1600;
showcaseWarrior.y = 700;
menuContainer.addChild(showcaseWarrior);
// Animate showcase warrior
var _breatheAnimation = function breatheAnimation() {
tween(showcaseWarrior, {
scaleY: 1.05,
y: showcaseWarrior.y - 10
}, {
duration: 2000,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(showcaseWarrior, {
scaleY: 1.0,
y: showcaseWarrior.y + 10
}, {
duration: 2000,
easing: tween.easeInOut,
onFinish: _breatheAnimation
});
}
});
};
_breatheAnimation();
}
function createMapSelect() {
// Hide all other containers first
if (menuContainer) {
menuContainer.visible = false;
}
if (settingsContainer) {
settingsContainer.visible = false;
}
if (mapSelectContainer) {
mapSelectContainer.destroy();
}
mapSelectContainer = new Container();
game.addChild(mapSelectContainer);
// Enhanced background decorations with animated elements
for (var i = 0; i < 15; i++) {
var bgElement = LK.getAsset('platform', {
width: 8,
height: 8,
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.1,
tint: 0x4444FF
});
bgElement.x = Math.random() * 2048;
bgElement.y = Math.random() * 1200 + 200;
mapSelectContainer.addChild(bgElement);
// Animate background elements
tween(bgElement, {
y: bgElement.y - 50,
alpha: 0.05
}, {
duration: 4000 + Math.random() * 2000,
easing: tween.easeInOut,
repeat: -1,
yoyo: true
});
}
// Decorative border frame with enhanced styling
var topBorder = LK.getAsset('platform', {
width: 1800,
height: 12,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFD700
});
topBorder.x = 1024;
topBorder.y = 150;
mapSelectContainer.addChild(topBorder);
var bottomBorder = LK.getAsset('platform', {
width: 1800,
height: 12,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFD700
});
bottomBorder.x = 1024;
bottomBorder.y = 1100;
mapSelectContainer.addChild(bottomBorder);
// Enhanced title with shadow and glow effects
var titleShadow = new Text2('LEVEL SELECTOR', {
size: 66,
fill: 0x000000
});
titleShadow.anchor.set(0.5, 0.5);
titleShadow.x = 1028;
titleShadow.y = 254;
mapSelectContainer.addChild(titleShadow);
var title = new Text2('LEVEL SELECTOR', {
size: 62,
fill: 0xFFD700
});
title.anchor.set(0.5, 0.5);
title.x = 1024;
title.y = 250;
mapSelectContainer.addChild(title);
// Animated title glow effect
var titleGlowCycle = 0;
var titleGlowInterval = LK.setInterval(function () {
titleGlowCycle += 0.04;
var glow = 0.9 + Math.sin(titleGlowCycle) * 0.1;
title.alpha = glow;
}, 60);
// Enhanced progress panel with detailed statistics
var progressPanelBg = LK.getAsset('platform', {
width: 800,
height: 120,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x1a1a1a,
alpha: 0.8
});
progressPanelBg.x = 1024;
progressPanelBg.y = 360;
mapSelectContainer.addChild(progressPanelBg);
var progressPanelBorder = LK.getAsset('platform', {
width: 808,
height: 128,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x44FF44,
alpha: 0.3
});
progressPanelBorder.x = 1024;
progressPanelBorder.y = 360;
mapSelectContainer.addChild(progressPanelBorder);
// Detailed progress information
var progressTitle = new Text2('CAMPAIGN PROGRESS', {
size: 28,
fill: 0xFFD700
});
progressTitle.anchor.set(0.5, 0.5);
progressTitle.x = 1024;
progressTitle.y = 330;
mapSelectContainer.addChild(progressTitle);
var progressText = new Text2('Levels Unlocked: ' + storage.unlockedLevels + ' | High Score: ' + storage.highScore, {
size: 24,
fill: 0xFFFFFF
});
progressText.anchor.set(0.5, 0.5);
progressText.x = 1024;
progressText.y = 360;
mapSelectContainer.addChild(progressText);
var coinsText = new Text2('Coins Earned: ' + storage.coins + ' | Last Completed: Level ' + storage.lastCompletedLevel, {
size: 24,
fill: 0xCCCCCC
});
coinsText.anchor.set(0.5, 0.5);
coinsText.x = 1024;
coinsText.y = 390;
mapSelectContainer.addChild(coinsText);
// Enhanced current level display with detailed preview card
var levelCardBg = LK.getAsset('platform', {
width: 900,
height: 400,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x2a2a2a,
alpha: 0.9
});
levelCardBg.x = 1024;
levelCardBg.y = 650;
mapSelectContainer.addChild(levelCardBg);
var levelCardBorder = LK.getAsset('platform', {
width: 908,
height: 408,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x4444FF,
alpha: 0.4
});
levelCardBorder.x = 1024;
levelCardBorder.y = 650;
mapSelectContainer.addChild(levelCardBorder);
// Current level header
var levelHeader = new Text2('SELECTED LEVEL: ' + currentLevel, {
size: 36,
fill: 0xFFD700
});
levelHeader.anchor.set(0.5, 0.5);
levelHeader.x = 1024;
levelHeader.y = 490;
mapSelectContainer.addChild(levelHeader);
// Check if current level is unlocked
var isLevelUnlocked = currentLevel <= storage.unlockedLevels;
if (isLevelUnlocked) {
// Enhanced level preview for unlocked levels
var previewConfig = getCurrentLevelConfig();
// Level name with enhanced styling
var levelNameShadow = new Text2(previewConfig.name, {
size: 34,
fill: 0x000000
});
levelNameShadow.anchor.set(0.5, 0.5);
levelNameShadow.x = 1026;
levelNameShadow.y = 542;
mapSelectContainer.addChild(levelNameShadow);
var levelName = new Text2(previewConfig.name, {
size: 32,
fill: 0xFFFFFF
});
levelName.anchor.set(0.5, 0.5);
levelName.x = 1024;
levelName.y = 540;
mapSelectContainer.addChild(levelName);
// Enhanced level type indicator with detailed classification
var isBossLevel = (currentLevel - 1) % 4 === 3;
var cycleNumber = Math.floor((currentLevel - 1) / 4) + 1;
var levelType = isBossLevel ? 'BOSS BATTLE' : 'EXPLORATION LEVEL';
var difficultyText = 'Cycle ' + cycleNumber + (isBossLevel ? ' - Final Challenge' : ' - Stage ' + ((currentLevel - 1) % 4 + 1));
var typeIndicatorBg = LK.getAsset('platform', {
width: 300,
height: 60,
anchorX: 0.5,
anchorY: 0.5,
tint: isBossLevel ? 0x8B0000 : 0x006400
});
typeIndicatorBg.x = 1024;
typeIndicatorBg.y = 590;
mapSelectContainer.addChild(typeIndicatorBg);
var typeText = new Text2(levelType, {
size: 26,
fill: 0xFFFFFF
});
typeText.anchor.set(0.5, 0.5);
typeText.x = 1024;
typeText.y = 590;
mapSelectContainer.addChild(typeText);
var difficultyIndicator = new Text2(difficultyText, {
size: 20,
fill: 0xCCCCCC
});
difficultyIndicator.anchor.set(0.5, 0.5);
difficultyIndicator.x = 1024;
difficultyIndicator.y = 620;
mapSelectContainer.addChild(difficultyIndicator);
// Enhanced level preview with environmental elements
var previewAreaBg = LK.getAsset('platform', {
width: 800,
height: 120,
anchorX: 0.5,
anchorY: 0.5,
tint: previewConfig.backgroundColor || 0x333333,
alpha: 0.3
});
previewAreaBg.x = 1024;
previewAreaBg.y = 690;
mapSelectContainer.addChild(previewAreaBg);
// Level characteristics display
var characteristicsText = new Text2('Environment: ' + previewConfig.name.split(' ')[0] + ' | Enemies: ' + previewConfig.enemies.length + ' | Platforms: ' + previewConfig.platforms.length, {
size: 18,
fill: 0xFFFFFF
});
characteristicsText.anchor.set(0.5, 0.5);
characteristicsText.x = 1024;
characteristicsText.y = 680;
mapSelectContainer.addChild(characteristicsText);
// Special features indicator
var specialFeatures = [];
if (isBossLevel) {
specialFeatures.push('Epic Boss Fight');
}
if (cycleNumber > 1) {
specialFeatures.push('Enhanced Difficulty');
}
if (previewConfig.decorations && previewConfig.decorations.length > 5) {
specialFeatures.push('Rich Environment');
}
if (previewConfig.enemies.length > 3) {
specialFeatures.push('Multiple Enemies');
}
if (specialFeatures.length > 0) {
var featuresText = new Text2('Features: ' + specialFeatures.join(' • '), {
size: 16,
fill: 0xFFD700
});
featuresText.anchor.set(0.5, 0.5);
featuresText.x = 1024;
featuresText.y = 710;
mapSelectContainer.addChild(featuresText);
}
// Enhanced preview miniatures with enemy and platform icons
var miniatureContainer = new Container();
mapSelectContainer.addChild(miniatureContainer);
// Create mini platforms
for (var i = 0; i < Math.min(previewConfig.platforms.length, 5); i++) {
var miniPlatform = LK.getAsset('platform', {
width: 40,
height: 8,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x666666,
alpha: 0.8
});
miniPlatform.x = 700 + i * 50;
miniPlatform.y = 750;
miniatureContainer.addChild(miniPlatform);
}
// Create mini enemies
for (var i = 0; i < Math.min(previewConfig.enemies.length, 4); i++) {
var enemyType = previewConfig.enemies[i].type;
var enemyColor = enemyType === 'boss' ? 0x800080 : enemyType === 'flying' ? 0x8B4513 : 0xFF0000;
var miniEnemy = LK.getAsset('platform', {
width: 12,
height: 16,
anchorX: 0.5,
anchorY: 0.5,
tint: enemyColor
});
miniEnemy.x = 720 + i * 60;
miniEnemy.y = 730;
miniatureContainer.addChild(miniEnemy);
}
// Rewards preview
var rewardsBg = LK.getAsset('platform', {
width: 400,
height: 40,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x1a4d1a,
alpha: 0.6
});
rewardsBg.x = 1024;
rewardsBg.y = 780;
mapSelectContainer.addChild(rewardsBg);
var baseReward = isBossLevel ? 25 : 15;
var bonusCoins = cycleNumber * 5;
var totalReward = baseReward + bonusCoins;
var rewardsText = new Text2('Completion Reward: ' + totalReward + ' coins (' + baseReward + ' base + ' + bonusCoins + ' cycle bonus)', {
size: 18,
fill: 0x44FF44
});
rewardsText.anchor.set(0.5, 0.5);
rewardsText.x = 1024;
rewardsText.y = 780;
mapSelectContainer.addChild(rewardsText);
} else {
// Enhanced locked level display
var lockedCardBg = LK.getAsset('platform', {
width: 600,
height: 200,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x444444,
alpha: 0.7
});
lockedCardBg.x = 1024;
lockedCardBg.y = 650;
mapSelectContainer.addChild(lockedCardBg);
var lockedBorder = LK.getAsset('platform', {
width: 608,
height: 208,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFF4444,
alpha: 0.5
});
lockedBorder.x = 1024;
lockedBorder.y = 650;
mapSelectContainer.addChild(lockedBorder);
// Enhanced lock icon
var lockShadow = LK.getAsset('lock', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0x000000,
scaleX: 2.2,
scaleY: 2.2,
alpha: 0.5
});
lockShadow.x = 1026;
lockShadow.y = 612;
mapSelectContainer.addChild(lockShadow);
var lockGraphic = LK.getAsset('lock', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0x888888,
scaleX: 2,
scaleY: 2
});
lockGraphic.x = 1024;
lockGraphic.y = 610;
mapSelectContainer.addChild(lockGraphic);
// Enhanced locked message
var lockedTitle = new Text2('LEVEL LOCKED', {
size: 36,
fill: 0xFF4444
});
lockedTitle.anchor.set(0.5, 0.5);
lockedTitle.x = 1024;
lockedTitle.y = 550;
mapSelectContainer.addChild(lockedTitle);
// Show unlock requirement with better styling
var requirementBg = LK.getAsset('platform', {
width: 500,
height: 50,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x2a2a2a,
alpha: 0.8
});
requirementBg.x = 1024;
requirementBg.y = 700;
mapSelectContainer.addChild(requirementBg);
var requirementText = new Text2('Complete Level ' + (currentLevel - 1) + ' to unlock this level', {
size: 22,
fill: 0xFFFFFF
});
requirementText.anchor.set(0.5, 0.5);
requirementText.x = 1024;
requirementText.y = 700;
mapSelectContainer.addChild(requirementText);
// Show level preview hint
var hintText = new Text2('Unlock to discover: ' + ((currentLevel - 1) % 4 === 3 ? 'Epic Boss Battle' : 'New Challenges'), {
size: 18,
fill: 0xCCCCCC
});
hintText.anchor.set(0.5, 0.5);
hintText.x = 1024;
hintText.y = 730;
mapSelectContainer.addChild(hintText);
// Animate lock with breathing effect
var lockAnimCycle = 0;
var lockAnimInterval = LK.setInterval(function () {
lockAnimCycle += 0.05;
var breathe = 1 + Math.sin(lockAnimCycle) * 0.1;
lockGraphic.scaleX = 2 * breathe;
lockGraphic.scaleY = 2 * breathe;
}, 50);
}
// Enhanced play button with better styling and animation
var playButtonShadow = LK.getAsset('platform', {
width: 368,
height: 118,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x000000,
alpha: 0.4
});
playButtonShadow.x = 1028;
playButtonShadow.y = 864;
mapSelectContainer.addChild(playButtonShadow);
var playButton = LK.getAsset('platform', {
width: 360,
height: 110,
anchorX: 0.5,
anchorY: 0.5,
tint: isLevelUnlocked ? getCurrentLevelConfig().backgroundColor || 0x4444FF : 0x666666
});
playButton.x = 1024;
playButton.y = 860;
playButton.interactive = isLevelUnlocked;
playButton.buttonMode = isLevelUnlocked;
mapSelectContainer.addChild(playButton);
var playButtonBorder = LK.getAsset('platform', {
width: 368,
height: 118,
anchorX: 0.5,
anchorY: 0.5,
tint: isLevelUnlocked ? 0x88FF88 : 0x888888,
alpha: isLevelUnlocked ? 0.5 : 0.2
});
playButtonBorder.x = 1024;
playButtonBorder.y = 860;
mapSelectContainer.addChild(playButtonBorder);
var playText = new Text2(isLevelUnlocked ? 'ENTER LEVEL ' + currentLevel : 'LOCKED', {
size: 32,
fill: isLevelUnlocked ? 0xFFFFFF : 0x888888
});
playText.anchor.set(0.5, 0.5);
playText.x = playButton.x;
playText.y = playButton.y;
mapSelectContainer.addChild(playText);
// Add animated glow effect for unlocked levels
if (isLevelUnlocked) {
var playGlowCycle = 0;
var playGlowInterval = LK.setInterval(function () {
playGlowCycle += 0.04;
var glow = 0.5 + Math.sin(playGlowCycle) * 0.2;
playButtonBorder.alpha = glow;
}, 60);
playButton.down = function () {
LK.getSound('button_click').play();
// Enhanced button press animation
tween(playButton, {
scaleX: 0.95,
scaleY: 0.95
}, {
duration: 100,
onFinish: function onFinish() {
tween(playButton, {
scaleX: 1.05,
scaleY: 1.05
}, {
duration: 150,
onFinish: function onFinish() {
tween(playButton, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100
});
startGame();
}
});
}
});
};
}
// Enhanced level navigation with detailed styling
var navigationContainer = new Container();
mapSelectContainer.addChild(navigationContainer);
// Navigation background panel
var navPanelBg = LK.getAsset('platform', {
width: 800,
height: 80,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x1a1a1a,
alpha: 0.7
});
navPanelBg.x = 1024;
navPanelBg.y = 950;
navigationContainer.addChild(navPanelBg);
// Previous level button (enhanced)
if (currentLevel > 1) {
var prevButtonShadow = LK.getAsset('platform', {
width: 188,
height: 68,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x000000,
alpha: 0.3
});
prevButtonShadow.x = 704;
prevButtonShadow.y = 954;
navigationContainer.addChild(prevButtonShadow);
var prevButton = LK.getAsset('platform', {
width: 180,
height: 60,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x4444FF
});
prevButton.x = 700;
prevButton.y = 950;
prevButton.interactive = true;
prevButton.buttonMode = true;
navigationContainer.addChild(prevButton);
var prevButtonBorder = LK.getAsset('platform', {
width: 188,
height: 68,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x8888FF,
alpha: 0.4
});
prevButtonBorder.x = 700;
prevButtonBorder.y = 950;
navigationContainer.addChild(prevButtonBorder);
var prevIcon = new Text2('◀', {
size: 24,
fill: 0xFFFFFF
});
prevIcon.anchor.set(0.5, 0.5);
prevIcon.x = 680;
prevIcon.y = 950;
navigationContainer.addChild(prevIcon);
var prevText = new Text2('PREV', {
size: 20,
fill: 0xFFFFFF
});
prevText.anchor.set(0.5, 0.5);
prevText.x = 720;
prevText.y = 950;
navigationContainer.addChild(prevText);
prevButton.down = function () {
LK.getSound('button_click').play();
tween(prevButton, {
alpha: 0.8
}, {
duration: 100,
onFinish: function onFinish() {
tween(prevButton, {
alpha: 1.0
}, {
duration: 100
});
}
});
currentLevel = Math.max(1, currentLevel - 1);
storage.currentLevel = currentLevel;
mapSelectContainer.visible = false;
createMapSelect();
};
}
// Next level button (enhanced, only if unlocked)
if (currentLevel < storage.unlockedLevels) {
var nextButtonShadow = LK.getAsset('platform', {
width: 188,
height: 68,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x000000,
alpha: 0.3
});
nextButtonShadow.x = 1344;
nextButtonShadow.y = 954;
navigationContainer.addChild(nextButtonShadow);
var nextButton = LK.getAsset('platform', {
width: 180,
height: 60,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x4444FF
});
nextButton.x = 1340;
nextButton.y = 950;
nextButton.interactive = true;
nextButton.buttonMode = true;
navigationContainer.addChild(nextButton);
var nextButtonBorder = LK.getAsset('platform', {
width: 188,
height: 68,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x8888FF,
alpha: 0.4
});
nextButtonBorder.x = 1340;
nextButtonBorder.y = 950;
navigationContainer.addChild(nextButtonBorder);
var nextIcon = new Text2('▶', {
size: 24,
fill: 0xFFFFFF
});
nextIcon.anchor.set(0.5, 0.5);
nextIcon.x = 1360;
nextIcon.y = 950;
navigationContainer.addChild(nextIcon);
var nextText = new Text2('NEXT', {
size: 20,
fill: 0xFFFFFF
});
nextText.anchor.set(0.5, 0.5);
nextText.x = 1320;
nextText.y = 950;
navigationContainer.addChild(nextText);
nextButton.down = function () {
LK.getSound('button_click').play();
tween(nextButton, {
alpha: 0.8
}, {
duration: 100,
onFinish: function onFinish() {
tween(nextButton, {
alpha: 1.0
}, {
duration: 100
});
}
});
currentLevel++;
storage.currentLevel = currentLevel;
mapSelectContainer.visible = false;
createMapSelect();
};
}
// Level counter in navigation
var levelCounter = new Text2(currentLevel + ' / ' + storage.unlockedLevels, {
size: 24,
fill: 0xFFD700
});
levelCounter.anchor.set(0.5, 0.5);
levelCounter.x = 1024;
levelCounter.y = 950;
navigationContainer.addChild(levelCounter);
// Quick jump to first/last level buttons
if (storage.unlockedLevels > 3) {
// Jump to first level
var firstLevelButton = LK.getAsset('platform', {
width: 60,
height: 40,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x666666,
alpha: 0.7
});
firstLevelButton.x = 600;
firstLevelButton.y = 950;
firstLevelButton.interactive = currentLevel > 1;
firstLevelButton.buttonMode = currentLevel > 1;
navigationContainer.addChild(firstLevelButton);
var firstLevelText = new Text2('1', {
size: 18,
fill: currentLevel > 1 ? 0xFFFFFF : 0x888888
});
firstLevelText.anchor.set(0.5, 0.5);
firstLevelText.x = 600;
firstLevelText.y = 950;
navigationContainer.addChild(firstLevelText);
if (currentLevel > 1) {
firstLevelButton.down = function () {
LK.getSound('button_click').play();
currentLevel = 1;
storage.currentLevel = currentLevel;
mapSelectContainer.visible = false;
createMapSelect();
};
}
// Jump to latest unlocked level
var lastLevelButton = LK.getAsset('platform', {
width: 80,
height: 40,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x666666,
alpha: 0.7
});
lastLevelButton.x = 1440;
lastLevelButton.y = 950;
lastLevelButton.interactive = currentLevel < storage.unlockedLevels;
lastLevelButton.buttonMode = currentLevel < storage.unlockedLevels;
navigationContainer.addChild(lastLevelButton);
var lastLevelText = new Text2('MAX', {
size: 16,
fill: currentLevel < storage.unlockedLevels ? 0xFFFFFF : 0x888888
});
lastLevelText.anchor.set(0.5, 0.5);
lastLevelText.x = 1440;
lastLevelText.y = 950;
navigationContainer.addChild(lastLevelText);
if (currentLevel < storage.unlockedLevels) {
lastLevelButton.down = function () {
LK.getSound('button_click').play();
currentLevel = storage.unlockedLevels;
storage.currentLevel = currentLevel;
mapSelectContainer.visible = false;
createMapSelect();
};
}
}
// Enhanced bottom navigation panel
var bottomNavBg = LK.getAsset('platform', {
width: 1600,
height: 100,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x1a1a1a,
alpha: 0.8
});
bottomNavBg.x = 1024;
bottomNavBg.y = 1050;
mapSelectContainer.addChild(bottomNavBg);
var bottomNavBorder = LK.getAsset('platform', {
width: 1608,
height: 108,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFD700,
alpha: 0.3
});
bottomNavBorder.x = 1024;
bottomNavBorder.y = 1050;
mapSelectContainer.addChild(bottomNavBorder);
// Enhanced back button with better styling
var backButtonShadow = LK.getAsset('platform', {
width: 248,
height: 78,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x000000,
alpha: 0.4
});
backButtonShadow.x = 1028;
backButtonShadow.y = 1054;
mapSelectContainer.addChild(backButtonShadow);
var backButton = LK.getAsset('platform', {
width: 240,
height: 70,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFF4444
});
backButton.x = 1024;
backButton.y = 1050;
backButton.interactive = true;
backButton.buttonMode = true;
mapSelectContainer.addChild(backButton);
var backButtonBorder = LK.getAsset('platform', {
width: 248,
height: 78,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFF8888,
alpha: 0.4
});
backButtonBorder.x = 1024;
backButtonBorder.y = 1050;
mapSelectContainer.addChild(backButtonBorder);
var backIcon = new Text2('◀', {
size: 24,
fill: 0xFFFFFF
});
backIcon.anchor.set(0.5, 0.5);
backIcon.x = 1000;
backIcon.y = 1050;
mapSelectContainer.addChild(backIcon);
var backText = new Text2('MAIN MENU', {
size: 24,
fill: 0xFFFFFF
});
backText.anchor.set(0.5, 0.5);
backText.x = 1040;
backText.y = 1050;
mapSelectContainer.addChild(backText);
// Add pulsing animation to back button
var backGlowCycle = 0;
var backGlowInterval = LK.setInterval(function () {
backGlowCycle += 0.03;
var glow = 0.4 + Math.sin(backGlowCycle) * 0.1;
backButtonBorder.alpha = glow;
}, 60);
backButton.down = function () {
LK.getSound('button_click').play();
// Enhanced back button animation
tween(backButton, {
scaleX: 0.9,
scaleY: 0.9,
alpha: 0.8
}, {
duration: 100,
onFinish: function onFinish() {
tween(backButton, {
scaleX: 1.1,
scaleY: 1.1,
alpha: 1.0
}, {
duration: 150,
onFinish: function onFinish() {
tween(backButton, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100,
onFinish: function onFinish() {
gameState = 'menu';
if (mapSelectContainer) {
mapSelectContainer.destroy();
}
if (shopContainer) {
shopContainer.visible = false;
}
if (!menuContainer) {
createMenu();
}
menuContainer.visible = true;
}
});
}
});
}
});
};
// Additional quick access buttons
// Shop button
var shopQuickButton = LK.getAsset('platform', {
width: 160,
height: 60,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFD700,
alpha: 0.8
});
shopQuickButton.x = 700;
shopQuickButton.y = 1050;
shopQuickButton.interactive = true;
shopQuickButton.buttonMode = true;
mapSelectContainer.addChild(shopQuickButton);
var shopQuickText = new Text2('SHOP', {
size: 20,
fill: 0x000000
});
shopQuickText.anchor.set(0.5, 0.5);
shopQuickText.x = 700;
shopQuickText.y = 1050;
mapSelectContainer.addChild(shopQuickText);
shopQuickButton.down = function () {
LK.getSound('button_click').play();
gameState = 'shop';
if (mapSelectContainer) {
mapSelectContainer.destroy();
}
if (!shopContainer) {
createShop();
}
};
// Settings button
var settingsQuickButton = LK.getAsset('platform', {
width: 160,
height: 60,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x44FF44,
alpha: 0.8
});
settingsQuickButton.x = 1348;
settingsQuickButton.y = 1050;
settingsQuickButton.interactive = true;
settingsQuickButton.buttonMode = true;
mapSelectContainer.addChild(settingsQuickButton);
var settingsQuickText = new Text2('SETTINGS', {
size: 18,
fill: 0xFFFFFF
});
settingsQuickText.anchor.set(0.5, 0.5);
settingsQuickText.x = 1348;
settingsQuickText.y = 1050;
mapSelectContainer.addChild(settingsQuickText);
settingsQuickButton.down = function () {
LK.getSound('button_click').play();
gameState = 'settings';
if (mapSelectContainer) {
mapSelectContainer.destroy();
}
createSettings();
};
// Level completion status indicator
var completionStatusBg = LK.getAsset('platform', {
width: 300,
height: 30,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x2a2a2a,
alpha: 0.6
});
completionStatusBg.x = 1024;
completionStatusBg.y = 1100;
mapSelectContainer.addChild(completionStatusBg);
var completionPercentage = Math.round(storage.lastCompletedLevel / storage.unlockedLevels * 100);
var completionText = new Text2('Campaign Progress: ' + completionPercentage + '% Complete', {
size: 16,
fill: completionPercentage >= 100 ? 0x44FF44 : completionPercentage >= 50 ? 0xFFD700 : 0xFFFFFF
});
completionText.anchor.set(0.5, 0.5);
completionText.x = 1024;
completionText.y = 1100;
mapSelectContainer.addChild(completionText);
}
function createShop() {
// Hide all other containers first
if (menuContainer) {
menuContainer.visible = false;
}
if (mapSelectContainer) {
mapSelectContainer.visible = false;
}
if (settingsContainer) {
settingsContainer.visible = false;
}
if (shopContainer) {
shopContainer.destroy();
}
shopContainer = new Container();
game.addChild(shopContainer);
// Enhanced background decorations
for (var i = 0; i < 12; i++) {
var bgDecor = LK.getAsset('warrior', {
width: 40,
height: 50,
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.05,
tint: 0x333333
});
bgDecor.x = 100 + i * 150 + Math.random() * 80;
bgDecor.y = 300 + Math.random() * 800;
bgDecor.rotation = Math.random() * Math.PI * 2;
shopContainer.addChild(bgDecor);
}
// Decorative border frame
var topBorder = LK.getAsset('platform', {
width: 1900,
height: 12,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFD700
});
topBorder.x = 1024;
topBorder.y = 120;
shopContainer.addChild(topBorder);
var bottomBorder = LK.getAsset('platform', {
width: 1900,
height: 12,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFD700
});
bottomBorder.x = 1024;
bottomBorder.y = 1150;
shopContainer.addChild(bottomBorder);
// Left and right decorative borders
var leftBorder = LK.getAsset('platform', {
width: 12,
height: 1000,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFD700
});
leftBorder.x = 80;
leftBorder.y = 635;
shopContainer.addChild(leftBorder);
var rightBorder = LK.getAsset('platform', {
width: 12,
height: 1000,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFD700
});
rightBorder.x = 1968;
rightBorder.y = 635;
shopContainer.addChild(rightBorder);
// Title - dynamic based on current category with enhanced styling
var categoryTitles = {
guardior: 'GUARDIOR SHOP',
enemies: 'ENEMY SKINS',
bosses: 'BOSS SKINS',
flying: 'FLYING ENEMY SKINS',
voces: 'VOICE SKINS'
};
// Title shadow for depth
var titleShadow = new Text2(categoryTitles[currentShopCategory] || 'SHOP', {
size: 64,
fill: 0x000000
});
titleShadow.anchor.set(0.5, 0.5);
titleShadow.x = 1028;
titleShadow.y = 204;
shopContainer.addChild(titleShadow);
var title = new Text2(categoryTitles[currentShopCategory] || 'SHOP', {
size: 60,
fill: 0xFFD700
});
title.anchor.set(0.5, 0.5);
title.x = 1024;
title.y = 200;
shopContainer.addChild(title);
// Animated title glow effect
var titleGlowCycle = 0;
var titleGlowInterval = LK.setInterval(function () {
titleGlowCycle += 0.03;
var glow = 0.9 + Math.sin(titleGlowCycle) * 0.1;
title.alpha = glow;
}, 60);
// Enhanced coins display with icon and styling
var coinsBg = LK.getAsset('platform', {
width: 400,
height: 80,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x1a1a1a,
alpha: 0.8
});
coinsBg.x = 1024;
coinsBg.y = 280;
shopContainer.addChild(coinsBg);
var coinsBorder = LK.getAsset('platform', {
width: 408,
height: 88,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFD700,
alpha: 0.3
});
coinsBorder.x = 1024;
coinsBorder.y = 280;
shopContainer.addChild(coinsBorder);
// Coin icon
var coinIcon = LK.getAsset('platform', {
width: 32,
height: 32,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFD700
});
coinIcon.x = 900;
coinIcon.y = 280;
shopContainer.addChild(coinIcon);
var coinsText = new Text2('Coins: ' + storage.coins, {
size: 42,
fill: 0xFFD700
});
coinsText.anchor.set(0.5, 0.5);
coinsText.x = 1024;
coinsText.y = 280;
shopContainer.addChild(coinsText);
// Animated coin counter effect
var coinsGlowCycle = 0;
var coinsGlowInterval = LK.setInterval(function () {
coinsGlowCycle += 0.05;
var glow = 0.8 + Math.sin(coinsGlowCycle) * 0.2;
coinIcon.alpha = glow;
coinsBorder.alpha = 0.3 + Math.sin(coinsGlowCycle * 1.2) * 0.1;
}, 50);
// Shop category tabs with enhanced styling - use global variable to maintain state
if (typeof currentShopCategory === 'undefined') {
var currentShopCategory = 'guardior'; // Initialize if not already set
}
// Tab container background
var tabsBackground = LK.getAsset('platform', {
width: 900,
height: 120,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x1a1a1a,
alpha: 0.7
});
tabsBackground.x = 1024;
tabsBackground.y = 360;
shopContainer.addChild(tabsBackground);
// Enhanced tab styling with shadows and borders
var tabData = [{
key: 'guardior',
text: 'GUARDIOR',
x: 450,
width: 180
}, {
key: 'enemies',
text: 'ENEMIES',
x: 650,
width: 160
}, {
key: 'bosses',
text: 'BOSSES',
x: 830,
width: 140
}, {
key: 'flying',
text: 'FLYING',
x: 990,
width: 120
}, {
key: 'voces',
text: 'VOCES',
x: 1130,
width: 120
}];
var tabButtons = {};
var tabTexts = {};
for (var t = 0; t < tabData.length; t++) {
var tab = tabData[t];
var isActive = currentShopCategory === tab.key;
// Tab shadow
var tabShadow = LK.getAsset('platform', {
width: tab.width + 8,
height: 68,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x000000,
alpha: 0.5
});
tabShadow.x = tab.x + 3;
tabShadow.y = 363;
shopContainer.addChild(tabShadow);
// Tab background
var tabButton = LK.getAsset('platform', {
width: tab.width,
height: 60,
anchorX: 0.5,
anchorY: 0.5,
tint: isActive ? 0x44FF44 : 0x555555
});
tabButton.x = tab.x;
tabButton.y = 360;
tabButton.interactive = true;
tabButton.buttonMode = true;
shopContainer.addChild(tabButton);
// Tab border glow for active tab
if (isActive) {
var tabGlow = LK.getAsset('platform', {
width: tab.width + 8,
height: 68,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x88FF88,
alpha: 0.4
});
tabGlow.x = tab.x;
tabGlow.y = 360;
shopContainer.addChild(tabGlow);
}
// Tab text
var tabText = new Text2(tab.text, {
size: tab.width > 150 ? 24 : 20,
fill: isActive ? 0x000000 : 0xFFFFFF
});
tabText.anchor.set(0.5, 0.5);
tabText.x = tab.x;
tabText.y = 360;
shopContainer.addChild(tabText);
// Store references for event handlers
tabButtons[tab.key] = tabButton;
tabTexts[tab.key] = tabText;
// Add hover effects
(function (button, text, key, originalTint) {
button.down = function () {
LK.getSound('button_click').play();
currentShopCategory = key;
createShop();
};
})(tabButton, tabText, tab.key, isActive ? 0x44FF44 : 0x555555);
}
// Create legacy tab variables for compatibility with existing event handlers
var guardiorTab = tabButtons.guardior;
var enemyTab = tabButtons.enemies;
var bossTab = tabButtons.bosses;
var flyingTab = tabButtons.flying;
var voicesTab = tabButtons.voces;
// Tab event handlers
guardiorTab.down = function () {
LK.getSound('button_click').play();
currentShopCategory = 'guardior';
createShop();
};
enemyTab.down = function () {
LK.getSound('button_click').play();
currentShopCategory = 'enemies';
createShop();
};
bossTab.down = function () {
LK.getSound('button_click').play();
currentShopCategory = 'bosses';
createShop();
};
flyingTab.down = function () {
LK.getSound('button_click').play();
currentShopCategory = 'flying';
createShop();
};
voicesTab.down = function () {
LK.getSound('button_click').play();
currentShopCategory = 'voces';
createShop();
};
// Define available skins first
var skins = [{
id: 'default',
name: 'Classic Guardior',
price: 0,
color: 0xFFFFFF,
description: 'The original warrior'
}, {
id: 'red',
name: 'Fire Warrior',
price: 100,
color: 0xFF4444,
description: 'Blazing red armor'
}, {
id: 'blue',
name: 'Ice Knight',
price: 150,
color: 0x4444FF,
description: 'Frozen blue steel'
}, {
id: 'green',
name: 'Forest Guardian',
price: 200,
color: 0x44FF44,
description: 'Nature\'s protector'
}, {
id: 'purple',
name: 'Shadow Lord',
price: 300,
color: 0x8844FF,
description: 'Master of darkness'
}, {
id: 'gold',
name: 'Golden Hero',
price: 500,
color: 0xFFD700,
description: 'Legendary champion'
}, {
id: 'orange',
name: 'Sunset Warrior',
price: 120,
color: 0xFF8844,
description: 'Strength of dusk'
}, {
id: 'cyan',
name: 'Ocean Guardian',
price: 180,
color: 0x44FFFF,
description: 'Master of tides'
}, {
id: 'magenta',
name: 'Mystic Knight',
price: 250,
color: 0xFF44FF,
description: 'Arcane protector'
}, {
id: 'silver',
name: 'Steel Champion',
price: 350,
color: 0xC0C0C0,
description: 'Unbreakable will'
}, {
id: 'lime',
name: 'Toxic Avenger',
price: 280,
color: 0x88FF44,
description: 'Venomous fighter'
}, {
id: 'bronze',
name: 'Ancient Warrior',
price: 400,
color: 0xCD7F32,
description: 'Timeless legend'
}];
// Define skin categories
var skinCategories = {
guardior: skins,
enemies: [{
id: 'default',
name: 'Red Warrior',
price: 0,
color: 0xFF0000,
description: 'Standard enemy'
}, {
id: 'dark',
name: 'Shadow Fighter',
price: 80,
color: 0x444444,
description: 'Dark assassin'
}, {
id: 'green',
name: 'Forest Bandit',
price: 120,
color: 0x228B22,
description: 'Woodland raider'
}, {
id: 'purple',
name: 'Void Warrior',
price: 150,
color: 0x8B008B,
description: 'Corrupted fighter'
}, {
id: 'orange',
name: 'Fire Soldier',
price: 100,
color: 0xFF6347,
description: 'Burning berserker'
}, {
id: 'blue',
name: 'Ice Guardian',
price: 140,
color: 0x4169E1,
description: 'Frozen sentinel'
}],
bosses: [{
id: 'default',
name: 'Purple Giant',
price: 0,
color: 0x800080,
description: 'Original boss'
}, {
id: 'crimson',
name: 'Crimson Overlord',
price: 200,
color: 0xDC143C,
description: 'Blood tyrant'
}, {
id: 'shadow',
name: 'Dark Emperor',
price: 300,
color: 0x2F2F2F,
description: 'Shadow master'
}, {
id: 'golden',
name: 'Golden Titan',
price: 400,
color: 0xFFD700,
description: 'Legendary ruler'
}, {
id: 'emerald',
name: 'Emerald Colossus',
price: 350,
color: 0x50C878,
description: 'Nature\'s wrath'
}, {
id: 'cyber',
name: 'Cyber Destroyer',
price: 450,
color: 0x00CED1,
description: 'Tech nightmare'
}, {
id: 'inferno',
name: 'Inferno Lord',
price: 500,
color: 0xFF4500,
description: 'Master of flames'
}, {
id: 'frost',
name: 'Frost Monarch',
price: 480,
color: 0x87CEEB,
description: 'Ruler of ice'
}, {
id: 'void',
name: 'Void Emperor',
price: 520,
color: 0x1C1C1C,
description: 'Lord of nothingness'
}],
flying: [{
id: 'default',
name: 'Brown Flyer',
price: 0,
color: 0x8B4513,
description: 'Standard flying enemy'
}, {
id: 'black',
name: 'Night Flyer',
price: 90,
color: 0x2F2F2F,
description: 'Shadow wings'
}, {
id: 'silver',
name: 'Steel Wing',
price: 130,
color: 0xC0C0C0,
description: 'Metal predator'
}, {
id: 'golden',
name: 'Golden Eagle',
price: 180,
color: 0xFFD700,
description: 'Sky sovereign'
}, {
id: 'red',
name: 'Fire Bird',
price: 110,
color: 0xFF4500,
description: 'Burning flyer'
}, {
id: 'blue',
name: 'Storm Wing',
price: 160,
color: 0x1E90FF,
description: 'Lightning fast'
}, {
id: 'toxic',
name: 'Toxic Wasp',
price: 140,
color: 0x9ACD32,
description: 'Poisonous hunter'
}, {
id: 'crystal',
name: 'Crystal Flyer',
price: 200,
color: 0xE6E6FA,
description: 'Crystalline predator'
}, {
id: 'shadow',
name: 'Shadow Bat',
price: 170,
color: 0x404040,
description: 'Darkness incarnate'
}],
voces: [{
id: 'default',
name: 'Classic Voice',
price: 0,
color: 0xFFFFFF,
description: 'Original warrior voice'
}, {
id: 'deep',
name: 'Deep Voice',
price: 80,
color: 0x4169E1,
description: 'Commanding tone'
}, {
id: 'heroic',
name: 'Heroic Voice',
price: 120,
color: 0xFFD700,
description: 'Noble warrior'
}, {
id: 'mysterious',
name: 'Mysterious Voice',
price: 150,
color: 0x8B008B,
description: 'Enigmatic whispers'
}, {
id: 'robotic',
name: 'Robotic Voice',
price: 100,
color: 0x00CED1,
description: 'Cyber warrior'
}, {
id: 'ancient',
name: 'Ancient Voice',
price: 180,
color: 0xCD7F32,
description: 'Wise elder'
}]
};
var currentSkins = skinCategories[currentShopCategory];
var storageKeys = {
guardior: {
selected: 'selectedSkin',
owned: 'ownedSkins'
},
enemies: {
selected: 'selectedEnemySkin',
owned: 'ownedEnemySkins'
},
bosses: {
selected: 'selectedBossSkin',
owned: 'ownedBossSkins'
},
flying: {
selected: 'selectedFlyingSkin',
owned: 'ownedFlyingSkins'
},
voces: {
selected: 'selectedVoiceSkin',
owned: 'ownedVoiceSkins'
}
};
// Create organized skins display container with proper bounds
var skinsDisplayArea = new Container();
shopContainer.addChild(skinsDisplayArea);
// Create background area for skins display
var skinsAreaBg = LK.getAsset('platform', {
width: 1600,
height: 600,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x1a1a1a,
alpha: 0.3
});
skinsAreaBg.x = 1024;
skinsAreaBg.y = 700;
skinsDisplayArea.addChild(skinsAreaBg);
// Create skins grid container with proper organization
var skinsGrid = new Container();
skinsDisplayArea.addChild(skinsGrid);
// Enhanced grid layout with better organization
var itemsPerRow = 4; // Better fit for screen width
var itemWidth = 220; // Slightly smaller for better fit
var itemHeight = 180; // Compact height
var spacingX = 60;
var spacingY = 40;
var startX = 300; // Start position for grid
var startY = 500;
var maxRows = 3; // Limit visible rows
// Calculate grid bounds for container organization
var gridWidth = itemsPerRow * (itemWidth + spacingX) - spacingX;
var gridHeight = maxRows * (itemHeight + spacingY) - spacingY;
// Center the grid within the display area
var gridStartX = 1024 - gridWidth / 2 + itemWidth / 2;
var gridStartY = 550;
for (var i = 0; i < currentSkins.length; i++) {
var skin = currentSkins[i];
var row = Math.floor(i / itemsPerRow);
var col = i % itemsPerRow;
var itemX = gridStartX + col * (itemWidth + spacingX);
var itemY = gridStartY + row * (itemHeight + spacingY);
// Only show skins that fit in visible area
if (row >= maxRows) {
continue; // Skip items that don't fit in visible area
}
var isOwned = storage[storageKeys[currentShopCategory].owned].indexOf(skin.id) !== -1;
var isEquipped = storage[storageKeys[currentShopCategory].selected] === skin.id;
// Create individual skin container for better organization
var skinItemContainer = new Container();
skinsGrid.addChild(skinItemContainer);
// Enhanced skin preview background with shadow and depth
var skinShadow = LK.getAsset('platform', {
width: itemWidth + 8,
height: itemHeight + 8,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x000000,
alpha: 0.4
});
skinShadow.x = itemX + 4;
skinShadow.y = itemY + 4;
skinItemContainer.addChild(skinShadow);
// Main skin background with enhanced colors and better organization
var bgColor = isEquipped ? 0x44FF44 : isOwned ? 0x4444FF : 0x555555;
var skinBg = LK.getAsset('platform', {
width: itemWidth,
height: itemHeight,
anchorX: 0.5,
anchorY: 0.5,
tint: bgColor
});
skinBg.x = itemX;
skinBg.y = itemY;
skinBg.interactive = true;
skinBg.buttonMode = true;
skinItemContainer.addChild(skinBg);
// Enhanced border for special states with better visual hierarchy
if (isEquipped) {
var equippedBorder = LK.getAsset('platform', {
width: itemWidth + 12,
height: itemHeight + 12,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x88FF88,
alpha: 0.8
});
equippedBorder.x = itemX;
equippedBorder.y = itemY;
skinItemContainer.addChild(equippedBorder);
// Add equipped indicator
var equippedIcon = new Text2('★', {
size: 24,
fill: 0x00FF00
});
equippedIcon.anchor.set(0.5, 0.5);
equippedIcon.x = itemX + itemWidth / 2 - 20;
equippedIcon.y = itemY - itemHeight / 2 + 20;
skinItemContainer.addChild(equippedIcon);
} else if (isOwned) {
var ownedBorder = LK.getAsset('platform', {
width: itemWidth + 8,
height: itemHeight + 8,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x8888FF,
alpha: 0.6
});
ownedBorder.x = itemX;
ownedBorder.y = itemY;
skinItemContainer.addChild(ownedBorder);
// Add owned indicator
var ownedIcon = new Text2('✓', {
size: 20,
fill: 0xFFD700
});
ownedIcon.anchor.set(0.5, 0.5);
ownedIcon.x = itemX + itemWidth / 2 - 20;
ownedIcon.y = itemY - itemHeight / 2 + 20;
skinItemContainer.addChild(ownedIcon);
}
// Inner content area with better organization
var contentBg = LK.getAsset('platform', {
width: itemWidth - 20,
height: itemHeight - 20,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x2a2a2a,
alpha: 0.9
});
contentBg.x = itemX;
contentBg.y = itemY;
skinItemContainer.addChild(contentBg);
// Enhanced skin preview with category-appropriate assets
var previewAssets = {
guardior: 'warrior',
enemies: 'enemy_body',
bosses: 'boss',
flying: 'enemy_body',
voces: 'warrior'
};
var previewSize = currentShopCategory === 'bosses' ? {
w: 70,
h: 80
} : {
w: 60,
h: 70
};
var skinPreview = LK.getAsset(previewAssets[currentShopCategory], {
width: previewSize.w,
height: previewSize.h,
anchorX: 0.5,
anchorY: 0.5,
tint: skin.color
});
skinPreview.x = itemX;
skinPreview.y = itemY - 25;
skinItemContainer.addChild(skinPreview);
// Skin name with better sizing and organization
var skinName = new Text2(skin.name, {
size: 18,
fill: 0xFFFFFF
});
skinName.anchor.set(0.5, 0.5);
skinName.x = itemX;
skinName.y = itemY + 20;
skinItemContainer.addChild(skinName);
// Enhanced description text with better fit
var skinDesc = new Text2(skin.description, {
size: 14,
fill: 0xCCCCCC
});
skinDesc.anchor.set(0.5, 0.5);
skinDesc.x = itemX;
skinDesc.y = itemY + 40;
skinItemContainer.addChild(skinDesc);
// Price or status with enhanced styling and better organization
var statusText;
if (isOwned) {
if (isEquipped) {
statusText = new Text2('EQUIPPED', {
size: 16,
fill: 0x00FF00
});
} else {
statusText = new Text2('OWNED', {
size: 16,
fill: 0xFFD700
});
}
} else {
var canAfford = storage.coins >= skin.price;
statusText = new Text2(skin.price + ' COINS', {
size: 16,
fill: canAfford ? 0xFFFFFF : 0xFF4444
});
// Add coin icon for price display with better positioning
if (!isOwned) {
var priceIcon = LK.getAsset('platform', {
width: 16,
height: 16,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFD700
});
priceIcon.x = itemX - 30;
priceIcon.y = itemY + 60;
skinItemContainer.addChild(priceIcon);
}
}
statusText.anchor.set(0.5, 0.5);
statusText.x = itemX;
statusText.y = itemY + 60;
skinItemContainer.addChild(statusText);
// Add rarity indicator for expensive items with better organization
if (skin.price >= 300) {
var rarityBadge = LK.getAsset('platform', {
width: 35,
height: 18,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFD700
});
rarityBadge.x = itemX - itemWidth / 2 + 25;
rarityBadge.y = itemY - itemHeight / 2 + 15;
skinItemContainer.addChild(rarityBadge);
var rarityText = new Text2('RARE', {
size: 10,
fill: 0x000000
});
rarityText.anchor.set(0.5, 0.5);
rarityText.x = rarityBadge.x;
rarityText.y = rarityBadge.y;
skinItemContainer.addChild(rarityText);
}
// Create organized click handler with proper scope
(function (skinData, background, container) {
background.down = function () {
LK.getSound('button_click').play();
var owned = storage[storageKeys[currentShopCategory].owned].indexOf(skinData.id) !== -1;
if (owned) {
// Equip the skin
storage[storageKeys[currentShopCategory].selected] = skinData.id;
// Refresh the shop display
shopContainer.visible = false;
createShop();
} else if (storage.coins >= skinData.price) {
// Purchase the skin
storage.coins -= skinData.price;
storage[storageKeys[currentShopCategory].owned].push(skinData.id);
storage[storageKeys[currentShopCategory].selected] = skinData.id;
// Refresh the shop display
shopContainer.visible = false;
createShop();
} else {
// Not enough coins - flash red with better feedback
tween(background, {
tint: 0xFF0000
}, {
duration: 200,
onFinish: function onFinish() {
tween(background, {
tint: bgColor
}, {
duration: 200
});
}
});
// Shake the container for better feedback
tween(container, {
x: container.x + 10
}, {
duration: 50,
onFinish: function onFinish() {
tween(container, {
x: container.x - 20
}, {
duration: 50,
onFinish: function onFinish() {
tween(container, {
x: container.x + 10
}, {
duration: 50
});
}
});
}
});
}
};
})(skin, skinBg, skinItemContainer);
}
// Add navigation indicators if there are more skins than can be displayed
var totalRows = Math.ceil(currentSkins.length / itemsPerRow);
if (totalRows > maxRows) {
// Add scroll indicator
var scrollIndicator = new Text2('More skins available - ' + (currentSkins.length - maxRows * itemsPerRow) + ' more', {
size: 24,
fill: 0xFFD700
});
scrollIndicator.anchor.set(0.5, 0.5);
scrollIndicator.x = 1024;
scrollIndicator.y = gridStartY + maxRows * (itemHeight + spacingY) + 30;
skinsDisplayArea.addChild(scrollIndicator);
// Add blinking effect to scroll indicator
var scrollBlinkCycle = 0;
var scrollBlinkInterval = LK.setInterval(function () {
scrollBlinkCycle += 0.05;
var alpha = 0.5 + Math.sin(scrollBlinkCycle) * 0.5;
scrollIndicator.alpha = alpha;
}, 50);
}
// Add category-specific organization message
var organizationMessage = new Text2('Organized by: ' + (currentShopCategory === 'guardior' ? 'Hero Skins' : currentShopCategory === 'enemies' ? 'Enemy Variations' : currentShopCategory === 'bosses' ? 'Boss Themes' : currentShopCategory === 'flying' ? 'Flying Units' : 'Voice Packs'), {
size: 20,
fill: 0xCCCCCC
});
organizationMessage.anchor.set(0.5, 0.5);
organizationMessage.x = 1024;
organizationMessage.y = 460;
skinsDisplayArea.addChild(organizationMessage);
// Enhanced back button with styling - positioned for organized layout
var backButtonShadow = LK.getAsset('platform', {
width: 228,
height: 78,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x000000,
alpha: 0.5
});
backButtonShadow.x = 1028;
backButtonShadow.y = 1064; // Positioned below organized skins area
shopContainer.addChild(backButtonShadow);
var backButton = LK.getAsset('platform', {
width: 220,
height: 70,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFF4444
});
backButton.x = 1024;
backButton.y = 1060; // Positioned below organized skins area
backButton.interactive = true;
backButton.buttonMode = true;
shopContainer.addChild(backButton);
var backButtonBorder = LK.getAsset('platform', {
width: 228,
height: 78,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFF8888,
alpha: 0.4
});
backButtonBorder.x = 1024;
backButtonBorder.y = 1200;
shopContainer.addChild(backButtonBorder);
var backText = new Text2('BACK TO MENU', {
size: 28,
fill: 0xFFFFFF
});
backText.anchor.set(0.5, 0.5);
backText.x = backButton.x;
backText.y = backButton.y;
shopContainer.addChild(backText);
// Add button hover effect
var backButtonGlow = 0;
var backGlowInterval = LK.setInterval(function () {
backButtonGlow += 0.04;
var glowAlpha = 0.4 + Math.sin(backButtonGlow) * 0.1;
backButtonBorder.alpha = glowAlpha;
}, 60);
backButton.down = function () {
LK.getSound('button_click').play();
gameState = 'menu';
if (shopContainer) {
shopContainer.destroy();
}
if (!menuContainer) {
createMenu();
}
menuContainer.visible = true;
};
}
function createSettings() {
// Hide all other containers first
if (menuContainer) {
menuContainer.visible = false;
}
if (mapSelectContainer) {
mapSelectContainer.visible = false;
}
if (settingsContainer) {
settingsContainer.destroy();
}
settingsContainer = new Container();
game.addChild(settingsContainer);
// Enhanced background decorations with animated particles
for (var i = 0; i < 20; i++) {
var bgParticle = LK.getAsset('platform', {
width: 6,
height: 6,
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.2,
tint: 0x44FF44
});
bgParticle.x = Math.random() * 2048;
bgParticle.y = Math.random() * 1400 + 200;
settingsContainer.addChild(bgParticle);
// Animate particles with subtle movement
tween(bgParticle, {
y: bgParticle.y - 100,
alpha: 0.05
}, {
duration: 5000 + Math.random() * 3000,
easing: tween.easeInOut,
repeat: -1,
yoyo: true
});
}
// Enhanced decorative frame with better styling
var topBorder = LK.getAsset('platform', {
width: 1800,
height: 15,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x44FF44
});
topBorder.x = 1024;
topBorder.y = 150;
settingsContainer.addChild(topBorder);
var bottomBorder = LK.getAsset('platform', {
width: 1800,
height: 15,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x44FF44
});
bottomBorder.x = 1024;
bottomBorder.y = 1150;
settingsContainer.addChild(bottomBorder);
// Enhanced title with shadow and glow
var titleShadow = new Text2('SETTINGS & OPTIONS', {
size: 66,
fill: 0x000000
});
titleShadow.anchor.set(0.5, 0.5);
titleShadow.x = 1028;
titleShadow.y = 254;
settingsContainer.addChild(titleShadow);
var title = new Text2('SETTINGS & OPTIONS', {
size: 62,
fill: 0x44FF44
});
title.anchor.set(0.5, 0.5);
title.x = 1024;
title.y = 250;
settingsContainer.addChild(title);
// Animated title glow effect
var titleGlowCycle = 0;
var titleGlowInterval = LK.setInterval(function () {
titleGlowCycle += 0.03;
var glow = 0.9 + Math.sin(titleGlowCycle) * 0.1;
title.alpha = glow;
}, 60);
// Initialize storage defaults for new settings
if (storage.graphicsQuality === undefined) {
storage.graphicsQuality = 'high';
}
if (storage.particleEffects === undefined) {
storage.particleEffects = true;
}
if (storage.screenShake === undefined) {
storage.screenShake = true;
}
if (storage.autoSave === undefined) {
storage.autoSave = true;
}
if (storage.showFPS === undefined) {
storage.showFPS = false;
}
if (storage.controlSensitivity === undefined) {
storage.controlSensitivity = 1.0;
}
if (storage.hapticFeedback === undefined) {
storage.hapticFeedback = true;
}
if (storage.colorBlindMode === undefined) {
storage.colorBlindMode = false;
}
// Settings categories container with organized layout
var settingsMainContainer = new Container();
settingsContainer.addChild(settingsMainContainer);
// AUDIO SETTINGS SECTION
var audioSectionBg = LK.getAsset('platform', {
width: 900,
height: 180,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x1a1a1a,
alpha: 0.8
});
audioSectionBg.x = 1024;
audioSectionBg.y = 400;
settingsMainContainer.addChild(audioSectionBg);
var audioSectionBorder = LK.getAsset('platform', {
width: 908,
height: 188,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x44FF44,
alpha: 0.3
});
audioSectionBorder.x = 1024;
audioSectionBorder.y = 400;
settingsMainContainer.addChild(audioSectionBorder);
var audioTitle = new Text2('AUDIO SETTINGS', {
size: 32,
fill: 0x44FF44
});
audioTitle.anchor.set(0.5, 0.5);
audioTitle.x = 1024;
audioTitle.y = 340;
settingsMainContainer.addChild(audioTitle);
// Music volume with enhanced controls
var musicLabel = new Text2('Music Volume: ' + Math.round(storage.musicVolume * 100) + '%', {
size: 28,
fill: 0xFFFFFF
});
musicLabel.anchor.set(0.5, 0.5);
musicLabel.x = 1024;
musicLabel.y = 375;
settingsMainContainer.addChild(musicLabel);
var musicDown = LK.getAsset('platform', {
width: 70,
height: 50,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFF4444
});
musicDown.x = 650;
musicDown.y = 375;
musicDown.interactive = true;
musicDown.buttonMode = true;
settingsMainContainer.addChild(musicDown);
var musicDownText = new Text2('-', {
size: 35,
fill: 0xFFFFFF
});
musicDownText.anchor.set(0.5, 0.5);
musicDownText.x = musicDown.x;
musicDownText.y = musicDown.y;
settingsMainContainer.addChild(musicDownText);
var musicUp = LK.getAsset('platform', {
width: 70,
height: 50,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x44FF44
});
musicUp.x = 1398;
musicUp.y = 375;
musicUp.interactive = true;
musicUp.buttonMode = true;
settingsMainContainer.addChild(musicUp);
var musicUpText = new Text2('+', {
size: 35,
fill: 0xFFFFFF
});
musicUpText.anchor.set(0.5, 0.5);
musicUpText.x = musicUp.x;
musicUpText.y = musicUp.y;
settingsMainContainer.addChild(musicUpText);
// Enhanced music volume bar
var musicVolumeBg = LK.getAsset('platform', {
width: 300,
height: 15,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x333333
});
musicVolumeBg.x = 1024;
musicVolumeBg.y = 405;
settingsMainContainer.addChild(musicVolumeBg);
var musicVolumeFill = LK.getAsset('platform', {
width: 290 * storage.musicVolume,
height: 10,
anchorX: 0,
anchorY: 0.5,
tint: 0x44FF44
});
musicVolumeFill.x = 879; // Start position for left-aligned fill
musicVolumeFill.y = 405;
settingsMainContainer.addChild(musicVolumeFill);
musicDown.down = function () {
storage.musicVolume = Math.max(0, storage.musicVolume - 0.1);
musicLabel.setText('Music Volume: ' + Math.round(storage.musicVolume * 100) + '%');
musicVolumeFill.width = 290 * storage.musicVolume;
LK.getSound('button_click').play();
// Apply volume change immediately
LK.playMusic('menu_music', {
volume: storage.musicVolume
});
};
musicUp.down = function () {
storage.musicVolume = Math.min(1, storage.musicVolume + 0.1);
musicLabel.setText('Music Volume: ' + Math.round(storage.musicVolume * 100) + '%');
musicVolumeFill.width = 290 * storage.musicVolume;
LK.getSound('button_click').play();
// Apply volume change immediately
LK.playMusic('menu_music', {
volume: storage.musicVolume
});
};
// Sound volume with enhanced controls
var soundLabel = new Text2('Sound Volume: ' + Math.round(storage.soundVolume * 100) + '%', {
size: 28,
fill: 0xFFFFFF
});
soundLabel.anchor.set(0.5, 0.5);
soundLabel.x = 1024;
soundLabel.y = 440;
settingsMainContainer.addChild(soundLabel);
var soundDown = LK.getAsset('platform', {
width: 70,
height: 50,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFF4444
});
soundDown.x = 650;
soundDown.y = 440;
soundDown.interactive = true;
soundDown.buttonMode = true;
settingsMainContainer.addChild(soundDown);
var soundDownText = new Text2('-', {
size: 35,
fill: 0xFFFFFF
});
soundDownText.anchor.set(0.5, 0.5);
soundDownText.x = soundDown.x;
soundDownText.y = soundDown.y;
settingsMainContainer.addChild(soundDownText);
var soundUp = LK.getAsset('platform', {
width: 70,
height: 50,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x44FF44
});
soundUp.x = 1398;
soundUp.y = 440;
soundUp.interactive = true;
soundUp.buttonMode = true;
settingsMainContainer.addChild(soundUp);
var soundUpText = new Text2('+', {
size: 35,
fill: 0xFFFFFF
});
soundUpText.anchor.set(0.5, 0.5);
soundUpText.x = soundUp.x;
soundUpText.y = soundUp.y;
settingsMainContainer.addChild(soundUpText);
// Enhanced sound volume bar
var soundVolumeBg = LK.getAsset('platform', {
width: 300,
height: 15,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x333333
});
soundVolumeBg.x = 1024;
soundVolumeBg.y = 470;
settingsMainContainer.addChild(soundVolumeBg);
var soundVolumeFill = LK.getAsset('platform', {
width: 290 * storage.soundVolume,
height: 10,
anchorX: 0,
anchorY: 0.5,
tint: 0xFF8844
});
soundVolumeFill.x = 879;
soundVolumeFill.y = 470;
settingsMainContainer.addChild(soundVolumeFill);
soundDown.down = function () {
storage.soundVolume = Math.max(0, storage.soundVolume - 0.1);
soundLabel.setText('Sound Volume: ' + Math.round(storage.soundVolume * 100) + '%');
soundVolumeFill.width = 290 * storage.soundVolume;
LK.getSound('button_click').play();
};
soundUp.down = function () {
storage.soundVolume = Math.min(1, storage.soundVolume + 0.1);
soundLabel.setText('Sound Volume: ' + Math.round(storage.soundVolume * 100) + '%');
soundVolumeFill.width = 290 * storage.soundVolume;
LK.getSound('button_click').play();
};
// GRAPHICS SETTINGS SECTION
var graphicsSectionBg = LK.getAsset('platform', {
width: 900,
height: 200,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x1a1a1a,
alpha: 0.8
});
graphicsSectionBg.x = 1024;
graphicsSectionBg.y = 580;
settingsMainContainer.addChild(graphicsSectionBg);
var graphicsSectionBorder = LK.getAsset('platform', {
width: 908,
height: 208,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x4444FF,
alpha: 0.3
});
graphicsSectionBorder.x = 1024;
graphicsSectionBorder.y = 580;
settingsMainContainer.addChild(graphicsSectionBorder);
var graphicsTitle = new Text2('GRAPHICS & PERFORMANCE', {
size: 32,
fill: 0x4444FF
});
graphicsTitle.anchor.set(0.5, 0.5);
graphicsTitle.x = 1024;
graphicsTitle.y = 520;
settingsMainContainer.addChild(graphicsTitle);
// Graphics Quality Setting
var qualityLabel = new Text2('Graphics Quality: ' + storage.graphicsQuality.toUpperCase(), {
size: 26,
fill: 0xFFFFFF
});
qualityLabel.anchor.set(0.5, 0.5);
qualityLabel.x = 1024;
qualityLabel.y = 555;
settingsMainContainer.addChild(qualityLabel);
var qualityDown = LK.getAsset('platform', {
width: 80,
height: 45,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFF4444
});
qualityDown.x = 700;
qualityDown.y = 555;
qualityDown.interactive = true;
qualityDown.buttonMode = true;
settingsMainContainer.addChild(qualityDown);
var qualityDownText = new Text2('◀', {
size: 28,
fill: 0xFFFFFF
});
qualityDownText.anchor.set(0.5, 0.5);
qualityDownText.x = qualityDown.x;
qualityDownText.y = qualityDown.y;
settingsMainContainer.addChild(qualityDownText);
var qualityUp = LK.getAsset('platform', {
width: 80,
height: 45,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x44FF44
});
qualityUp.x = 1348;
qualityUp.y = 555;
qualityUp.interactive = true;
qualityUp.buttonMode = true;
settingsMainContainer.addChild(qualityUp);
var qualityUpText = new Text2('▶', {
size: 28,
fill: 0xFFFFFF
});
qualityUpText.anchor.set(0.5, 0.5);
qualityUpText.x = qualityUp.x;
qualityUpText.y = qualityUp.y;
settingsMainContainer.addChild(qualityUpText);
var qualityOptions = ['low', 'medium', 'high', 'ultra'];
var currentQualityIndex = qualityOptions.indexOf(storage.graphicsQuality);
qualityDown.down = function () {
currentQualityIndex = Math.max(0, currentQualityIndex - 1);
storage.graphicsQuality = qualityOptions[currentQualityIndex];
qualityLabel.setText('Graphics Quality: ' + storage.graphicsQuality.toUpperCase());
LK.getSound('button_click').play();
};
qualityUp.down = function () {
currentQualityIndex = Math.min(qualityOptions.length - 1, currentQualityIndex + 1);
storage.graphicsQuality = qualityOptions[currentQualityIndex];
qualityLabel.setText('Graphics Quality: ' + storage.graphicsQuality.toUpperCase());
LK.getSound('button_click').play();
};
// Particle Effects Toggle
var particleLabel = new Text2('Particle Effects: ' + (storage.particleEffects ? 'ON' : 'OFF'), {
size: 24,
fill: 0xFFFFFF
});
particleLabel.anchor.set(0.5, 0.5);
particleLabel.x = 800;
particleLabel.y = 590;
settingsMainContainer.addChild(particleLabel);
var particleToggle = LK.getAsset('platform', {
width: 100,
height: 40,
anchorX: 0.5,
anchorY: 0.5,
tint: storage.particleEffects ? 0x44FF44 : 0x666666
});
particleToggle.x = 1100;
particleToggle.y = 590;
particleToggle.interactive = true;
particleToggle.buttonMode = true;
settingsMainContainer.addChild(particleToggle);
var particleToggleText = new Text2(storage.particleEffects ? 'ON' : 'OFF', {
size: 20,
fill: 0xFFFFFF
});
particleToggleText.anchor.set(0.5, 0.5);
particleToggleText.x = particleToggle.x;
particleToggleText.y = particleToggle.y;
settingsMainContainer.addChild(particleToggleText);
particleToggle.down = function () {
storage.particleEffects = !storage.particleEffects;
particleLabel.setText('Particle Effects: ' + (storage.particleEffects ? 'ON' : 'OFF'));
particleToggleText.setText(storage.particleEffects ? 'ON' : 'OFF');
particleToggle.tint = storage.particleEffects ? 0x44FF44 : 0x666666;
LK.getSound('button_click').play();
};
// Screen Shake Toggle
var shakeLabel = new Text2('Screen Shake: ' + (storage.screenShake ? 'ON' : 'OFF'), {
size: 24,
fill: 0xFFFFFF
});
shakeLabel.anchor.set(0.5, 0.5);
shakeLabel.x = 800;
shakeLabel.y = 625;
settingsMainContainer.addChild(shakeLabel);
var shakeToggle = LK.getAsset('platform', {
width: 100,
height: 40,
anchorX: 0.5,
anchorY: 0.5,
tint: storage.screenShake ? 0x44FF44 : 0x666666
});
shakeToggle.x = 1100;
shakeToggle.y = 625;
shakeToggle.interactive = true;
shakeToggle.buttonMode = true;
settingsMainContainer.addChild(shakeToggle);
var shakeToggleText = new Text2(storage.screenShake ? 'ON' : 'OFF', {
size: 20,
fill: 0xFFFFFF
});
shakeToggleText.anchor.set(0.5, 0.5);
shakeToggleText.x = shakeToggle.x;
shakeToggleText.y = shakeToggle.y;
settingsMainContainer.addChild(shakeToggleText);
shakeToggle.down = function () {
storage.screenShake = !storage.screenShake;
shakeLabel.setText('Screen Shake: ' + (storage.screenShake ? 'ON' : 'OFF'));
shakeToggleText.setText(storage.screenShake ? 'ON' : 'OFF');
shakeToggle.tint = storage.screenShake ? 0x44FF44 : 0x666666;
LK.getSound('button_click').play();
};
// GAMEPLAY SETTINGS SECTION
var gameplaySectionBg = LK.getAsset('platform', {
width: 900,
height: 200,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x1a1a1a,
alpha: 0.8
});
gameplaySectionBg.x = 1024;
gameplaySectionBg.y = 760;
settingsMainContainer.addChild(gameplaySectionBg);
var gameplaySectionBorder = LK.getAsset('platform', {
width: 908,
height: 208,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFD700,
alpha: 0.3
});
gameplaySectionBorder.x = 1024;
gameplaySectionBorder.y = 760;
settingsMainContainer.addChild(gameplaySectionBorder);
var gameplayTitle = new Text2('GAMEPLAY OPTIONS', {
size: 32,
fill: 0xFFD700
});
gameplayTitle.anchor.set(0.5, 0.5);
gameplayTitle.x = 1024;
gameplayTitle.y = 700;
settingsMainContainer.addChild(gameplayTitle);
// Control Sensitivity Setting
var sensitivityLabel = new Text2('Control Sensitivity: ' + Math.round(storage.controlSensitivity * 100) + '%', {
size: 26,
fill: 0xFFFFFF
});
sensitivityLabel.anchor.set(0.5, 0.5);
sensitivityLabel.x = 1024;
sensitivityLabel.y = 735;
settingsMainContainer.addChild(sensitivityLabel);
var sensitivityDown = LK.getAsset('platform', {
width: 70,
height: 50,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFF4444
});
sensitivityDown.x = 650;
sensitivityDown.y = 735;
sensitivityDown.interactive = true;
sensitivityDown.buttonMode = true;
settingsMainContainer.addChild(sensitivityDown);
var sensitivityDownText = new Text2('-', {
size: 35,
fill: 0xFFFFFF
});
sensitivityDownText.anchor.set(0.5, 0.5);
sensitivityDownText.x = sensitivityDown.x;
sensitivityDownText.y = sensitivityDown.y;
settingsMainContainer.addChild(sensitivityDownText);
var sensitivityUp = LK.getAsset('platform', {
width: 70,
height: 50,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x44FF44
});
sensitivityUp.x = 1398;
sensitivityUp.y = 735;
sensitivityUp.interactive = true;
sensitivityUp.buttonMode = true;
settingsMainContainer.addChild(sensitivityUp);
var sensitivityUpText = new Text2('+', {
size: 35,
fill: 0xFFFFFF
});
sensitivityUpText.anchor.set(0.5, 0.5);
sensitivityUpText.x = sensitivityUp.x;
sensitivityUpText.y = sensitivityUp.y;
settingsMainContainer.addChild(sensitivityUpText);
sensitivityDown.down = function () {
storage.controlSensitivity = Math.max(0.5, storage.controlSensitivity - 0.1);
sensitivityLabel.setText('Control Sensitivity: ' + Math.round(storage.controlSensitivity * 100) + '%');
LK.getSound('button_click').play();
};
sensitivityUp.down = function () {
storage.controlSensitivity = Math.min(2.0, storage.controlSensitivity + 0.1);
sensitivityLabel.setText('Control Sensitivity: ' + Math.round(storage.controlSensitivity * 100) + '%');
LK.getSound('button_click').play();
};
// Auto-Save Toggle
var autoSaveLabel = new Text2('Auto-Save: ' + (storage.autoSave ? 'ON' : 'OFF'), {
size: 24,
fill: 0xFFFFFF
});
autoSaveLabel.anchor.set(0.5, 0.5);
autoSaveLabel.x = 800;
autoSaveLabel.y = 770;
settingsMainContainer.addChild(autoSaveLabel);
var autoSaveToggle = LK.getAsset('platform', {
width: 100,
height: 40,
anchorX: 0.5,
anchorY: 0.5,
tint: storage.autoSave ? 0x44FF44 : 0x666666
});
autoSaveToggle.x = 1100;
autoSaveToggle.y = 770;
autoSaveToggle.interactive = true;
autoSaveToggle.buttonMode = true;
settingsMainContainer.addChild(autoSaveToggle);
var autoSaveToggleText = new Text2(storage.autoSave ? 'ON' : 'OFF', {
size: 20,
fill: 0xFFFFFF
});
autoSaveToggleText.anchor.set(0.5, 0.5);
autoSaveToggleText.x = autoSaveToggle.x;
autoSaveToggleText.y = autoSaveToggle.y;
settingsMainContainer.addChild(autoSaveToggleText);
autoSaveToggle.down = function () {
storage.autoSave = !storage.autoSave;
autoSaveLabel.setText('Auto-Save: ' + (storage.autoSave ? 'ON' : 'OFF'));
autoSaveToggleText.setText(storage.autoSave ? 'ON' : 'OFF');
autoSaveToggle.tint = storage.autoSave ? 0x44FF44 : 0x666666;
LK.getSound('button_click').play();
};
// Haptic Feedback Toggle
var hapticLabel = new Text2('Haptic Feedback: ' + (storage.hapticFeedback ? 'ON' : 'OFF'), {
size: 24,
fill: 0xFFFFFF
});
hapticLabel.anchor.set(0.5, 0.5);
hapticLabel.x = 800;
hapticLabel.y = 805;
settingsMainContainer.addChild(hapticLabel);
var hapticToggle = LK.getAsset('platform', {
width: 100,
height: 40,
anchorX: 0.5,
anchorY: 0.5,
tint: storage.hapticFeedback ? 0x44FF44 : 0x666666
});
hapticToggle.x = 1100;
hapticToggle.y = 805;
hapticToggle.interactive = true;
hapticToggle.buttonMode = true;
settingsMainContainer.addChild(hapticToggle);
var hapticToggleText = new Text2(storage.hapticFeedback ? 'ON' : 'OFF', {
size: 20,
fill: 0xFFFFFF
});
hapticToggleText.anchor.set(0.5, 0.5);
hapticToggleText.x = hapticToggle.x;
hapticToggleText.y = hapticToggle.y;
settingsMainContainer.addChild(hapticToggleText);
hapticToggle.down = function () {
storage.hapticFeedback = !storage.hapticFeedback;
hapticLabel.setText('Haptic Feedback: ' + (storage.hapticFeedback ? 'ON' : 'OFF'));
hapticToggleText.setText(storage.hapticFeedback ? 'ON' : 'OFF');
hapticToggle.tint = storage.hapticFeedback ? 0x44FF44 : 0x666666;
LK.getSound('button_click').play();
};
// ACCESSIBILITY SETTINGS SECTION
var accessibilitySectionBg = LK.getAsset('platform', {
width: 900,
height: 140,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x1a1a1a,
alpha: 0.8
});
accessibilitySectionBg.x = 1024;
accessibilitySectionBg.y = 910;
settingsMainContainer.addChild(accessibilitySectionBg);
var accessibilitySectionBorder = LK.getAsset('platform', {
width: 908,
height: 148,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFF44FF,
alpha: 0.3
});
accessibilitySectionBorder.x = 1024;
accessibilitySectionBorder.y = 910;
settingsMainContainer.addChild(accessibilitySectionBorder);
var accessibilityTitle = new Text2('ACCESSIBILITY', {
size: 32,
fill: 0xFF44FF
});
accessibilityTitle.anchor.set(0.5, 0.5);
accessibilityTitle.x = 1024;
accessibilityTitle.y = 860;
settingsMainContainer.addChild(accessibilityTitle);
// Color Blind Mode Toggle
var colorBlindLabel = new Text2('Color Blind Mode: ' + (storage.colorBlindMode ? 'ON' : 'OFF'), {
size: 24,
fill: 0xFFFFFF
});
colorBlindLabel.anchor.set(0.5, 0.5);
colorBlindLabel.x = 800;
colorBlindLabel.y = 895;
settingsMainContainer.addChild(colorBlindLabel);
var colorBlindToggle = LK.getAsset('platform', {
width: 100,
height: 40,
anchorX: 0.5,
anchorY: 0.5,
tint: storage.colorBlindMode ? 0x44FF44 : 0x666666
});
colorBlindToggle.x = 1100;
colorBlindToggle.y = 895;
colorBlindToggle.interactive = true;
colorBlindToggle.buttonMode = true;
settingsMainContainer.addChild(colorBlindToggle);
var colorBlindToggleText = new Text2(storage.colorBlindMode ? 'ON' : 'OFF', {
size: 20,
fill: 0xFFFFFF
});
colorBlindToggleText.anchor.set(0.5, 0.5);
colorBlindToggleText.x = colorBlindToggle.x;
colorBlindToggleText.y = colorBlindToggle.y;
settingsMainContainer.addChild(colorBlindToggleText);
colorBlindToggle.down = function () {
storage.colorBlindMode = !storage.colorBlindMode;
colorBlindLabel.setText('Color Blind Mode: ' + (storage.colorBlindMode ? 'ON' : 'OFF'));
colorBlindToggleText.setText(storage.colorBlindMode ? 'ON' : 'OFF');
colorBlindToggle.tint = storage.colorBlindMode ? 0x44FF44 : 0x666666;
LK.getSound('button_click').play();
};
// Show FPS Toggle
var fpsLabel = new Text2('Show FPS: ' + (storage.showFPS ? 'ON' : 'OFF'), {
size: 24,
fill: 0xFFFFFF
});
fpsLabel.anchor.set(0.5, 0.5);
fpsLabel.x = 800;
fpsLabel.y = 930;
settingsMainContainer.addChild(fpsLabel);
var fpsToggle = LK.getAsset('platform', {
width: 100,
height: 40,
anchorX: 0.5,
anchorY: 0.5,
tint: storage.showFPS ? 0x44FF44 : 0x666666
});
fpsToggle.x = 1100;
fpsToggle.y = 930;
fpsToggle.interactive = true;
fpsToggle.buttonMode = true;
settingsMainContainer.addChild(fpsToggle);
var fpsToggleText = new Text2(storage.showFPS ? 'ON' : 'OFF', {
size: 20,
fill: 0xFFFFFF
});
fpsToggleText.anchor.set(0.5, 0.5);
fpsToggleText.x = fpsToggle.x;
fpsToggleText.y = fpsToggle.y;
settingsMainContainer.addChild(fpsToggleText);
fpsToggle.down = function () {
storage.showFPS = !storage.showFPS;
fpsLabel.setText('Show FPS: ' + (storage.showFPS ? 'ON' : 'OFF'));
fpsToggleText.setText(storage.showFPS ? 'ON' : 'OFF');
fpsToggle.tint = storage.showFPS ? 0x44FF44 : 0x666666;
LK.getSound('button_click').play();
};
// Enhanced bottom navigation panel
var bottomNavBg = LK.getAsset('platform', {
width: 1200,
height: 100,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x1a1a1a,
alpha: 0.8
});
bottomNavBg.x = 1024;
bottomNavBg.y = 1050;
settingsContainer.addChild(bottomNavBg);
var bottomNavBorder = LK.getAsset('platform', {
width: 1208,
height: 108,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x44FF44,
alpha: 0.3
});
bottomNavBorder.x = 1024;
bottomNavBorder.y = 1050;
settingsContainer.addChild(bottomNavBorder);
// Enhanced reset to defaults button
var resetButton = LK.getAsset('platform', {
width: 250,
height: 70,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFF8844
});
resetButton.x = 700;
resetButton.y = 1050;
resetButton.interactive = true;
resetButton.buttonMode = true;
settingsContainer.addChild(resetButton);
var resetText = new Text2('RESET DEFAULTS', {
size: 24,
fill: 0xFFFFFF
});
resetText.anchor.set(0.5, 0.5);
resetText.x = resetButton.x;
resetText.y = resetButton.y;
settingsContainer.addChild(resetText);
resetButton.down = function () {
LK.getSound('button_click').play();
// Reset all settings to defaults
storage.musicVolume = 1.0;
storage.soundVolume = 1.0;
storage.graphicsQuality = 'high';
storage.particleEffects = true;
storage.screenShake = true;
storage.autoSave = true;
storage.showFPS = false;
storage.controlSensitivity = 1.0;
storage.hapticFeedback = true;
storage.colorBlindMode = false;
// Recreate settings menu to reflect changes
settingsContainer.visible = false;
createSettings();
};
// Enhanced back button
var backButton = LK.getAsset('platform', {
width: 250,
height: 70,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFF4444
});
backButton.x = 1348;
backButton.y = 1050;
backButton.interactive = true;
backButton.buttonMode = true;
settingsContainer.addChild(backButton);
var backButtonBorder = LK.getAsset('platform', {
width: 258,
height: 78,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFF8888,
alpha: 0.4
});
backButtonBorder.x = 1348;
backButtonBorder.y = 1050;
settingsContainer.addChild(backButtonBorder);
var backText = new Text2('BACK TO MENU', {
size: 24,
fill: 0xFFFFFF
});
backText.anchor.set(0.5, 0.5);
backText.x = backButton.x;
backText.y = backButton.y;
settingsContainer.addChild(backText);
// Add pulsing animation to back button
var backGlowCycle = 0;
var backGlowInterval = LK.setInterval(function () {
backGlowCycle += 0.03;
var glow = 0.4 + Math.sin(backGlowCycle) * 0.1;
backButtonBorder.alpha = glow;
}, 60);
backButton.down = function () {
LK.getSound('button_click').play();
// Enhanced back button animation
tween(backButton, {
scaleX: 0.9,
scaleY: 0.9,
alpha: 0.8
}, {
duration: 100,
onFinish: function onFinish() {
tween(backButton, {
scaleX: 1.1,
scaleY: 1.1,
alpha: 1.0
}, {
duration: 150,
onFinish: function onFinish() {
tween(backButton, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100,
onFinish: function onFinish() {
gameState = 'menu';
if (settingsContainer) {
settingsContainer.destroy();
}
if (shopContainer) {
shopContainer.visible = false;
}
if (!menuContainer) {
createMenu();
}
menuContainer.visible = true;
}
});
}
});
}
});
};
// Add floating information panel
var infoPanel = LK.getAsset('platform', {
width: 500,
height: 60,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x2a2a2a,
alpha: 0.6
});
infoPanel.x = 1024;
infoPanel.y = 320;
settingsContainer.addChild(infoPanel);
var infoText = new Text2('Settings are automatically saved', {
size: 20,
fill: 0xCCCCCC
});
infoText.anchor.set(0.5, 0.5);
infoText.x = 1024;
infoText.y = 320;
settingsContainer.addChild(infoText);
// Add animated info icon
var infoIcon = LK.getAsset('platform', {
width: 20,
height: 20,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x44FF44
});
infoIcon.x = 750;
infoIcon.y = 320;
settingsContainer.addChild(infoIcon);
// Animate info icon with pulsing effect
var infoGlowCycle = 0;
var infoGlowInterval = LK.setInterval(function () {
infoGlowCycle += 0.05;
var glow = 0.8 + Math.sin(infoGlowCycle) * 0.2;
infoIcon.alpha = glow;
}, 50);
}
function startGame() {
// Check if level is unlocked before starting
if (currentLevel > storage.unlockedLevels) {
// Level is locked, return to map select
LK.getSound('button_click').play();
return;
}
gameState = 'playing';
// Hide all menu containers to prevent text overlap
if (menuContainer) {
menuContainer.visible = false;
}
if (mapSelectContainer) {
mapSelectContainer.visible = false;
}
if (settingsContainer) {
settingsContainer.visible = false;
}
// Get current level configuration
var levelConfig = getCurrentLevelConfig();
// Set background color for current level
game.setBackgroundColor(levelConfig.backgroundColor);
// Create ground
ground = game.addChild(LK.getAsset('ground', {
anchorX: 0.5,
anchorY: 1.0,
x: 1024,
y: 2048
}));
// Create platforms based on current level with enhanced styling
platforms = [];
var platformData = levelConfig.platforms;
for (var i = 0; i < platformData.length; i++) {
var platform = new Platform();
platform.x = platformData[i].x;
platform.y = platformData[i].y;
// Apply enhanced platform styling if available
if (platformData[i].type && platformData[i].tint) {
platform.children[0].tint = platformData[i].tint;
}
if (platformData[i].width) {
platform.children[0].width = platformData[i].width;
}
if (platformData[i].height) {
platform.children[0].height = platformData[i].height;
}
platforms.push(platform);
game.addChild(platform);
}
// Create detailed environmental decorations
if (levelConfig.decorations) {
for (var i = 0; i < levelConfig.decorations.length; i++) {
var decoration = levelConfig.decorations[i];
var decorAsset;
// Create different decoration types with appropriate assets
switch (decoration.type) {
case 'tree':
case 'bush':
case 'rock':
case 'cactus':
case 'flower_patch':
case 'mushroom':
case 'fallen_branch':
case 'ivy_patch':
case 'vine_hanging':
case 'bird_nest':
case 'forest_shrine':
case 'wooden_sign':
decorAsset = LK.getAsset('platform', {
width: decoration.type === 'tree' ? 60 : decoration.type === 'bush' ? 40 : decoration.type === 'flower_patch' ? 35 : decoration.type === 'mushroom' ? 20 : decoration.type === 'fallen_branch' ? 50 : decoration.type === 'ivy_patch' ? 45 : decoration.type === 'vine_hanging' ? 15 : decoration.type === 'bird_nest' ? 25 : decoration.type === 'forest_shrine' ? 80 : decoration.type === 'wooden_sign' ? 40 : 30,
height: decoration.type === 'tree' ? 120 : decoration.type === 'bush' ? 30 : decoration.type === 'flower_patch' ? 15 : decoration.type === 'mushroom' ? 25 : decoration.type === 'fallen_branch' ? 12 : decoration.type === 'ivy_patch' ? 35 : decoration.type === 'vine_hanging' ? 60 : decoration.type === 'bird_nest' ? 15 : decoration.type === 'forest_shrine' ? 100 : decoration.type === 'wooden_sign' ? 60 : 25,
anchorX: 0.5,
anchorY: 1.0,
tint: decoration.tint,
alpha: 0.8
});
break;
case 'cloud':
case 'floating_shrine':
case 'wind_chime':
case 'celestial_orb':
case 'sky_rune':
case 'ethereal_gateway':
case 'starlight_pool':
case 'divine_statue':
case 'floating_lotus':
decorAsset = LK.getAsset('platform', {
width: decoration.type === 'cloud' ? 100 : decoration.type === 'floating_shrine' ? 120 : decoration.type === 'wind_chime' ? 30 : decoration.type === 'celestial_orb' ? 40 : decoration.type === 'sky_rune' ? 50 : decoration.type === 'ethereal_gateway' ? 150 : decoration.type === 'starlight_pool' ? 80 : decoration.type === 'divine_statue' ? 60 : decoration.type === 'floating_lotus' ? 35 : 100,
height: decoration.type === 'cloud' ? 40 : decoration.type === 'floating_shrine' ? 80 : decoration.type === 'wind_chime' ? 50 : decoration.type === 'celestial_orb' ? 40 : decoration.type === 'sky_rune' ? 60 : decoration.type === 'ethereal_gateway' ? 200 : decoration.type === 'starlight_pool' ? 30 : decoration.type === 'divine_statue' ? 120 : decoration.type === 'floating_lotus' ? 25 : 40,
anchorX: 0.5,
anchorY: 0.5,
tint: decoration.tint,
alpha: 0.6
});
break;
case 'pillar':
case 'column':
case 'obelisk':
decorAsset = LK.getAsset('platform', {
width: decoration.type === 'obelisk' ? 25 : 35,
height: decoration.type === 'obelisk' ? 100 : 80,
anchorX: 0.5,
anchorY: 1.0,
tint: decoration.tint,
alpha: 0.9
});
break;
case 'pyramid':
case 'ancient_tomb':
case 'hieroglyph_wall':
case 'sphinx_statue':
case 'scarab_carving':
case 'ancient_vase':
case 'sand_dune':
case 'temple_entrance':
case 'ankh_symbol':
case 'desert_gem':
decorAsset = LK.getAsset('platform', {
width: decoration.type === 'pyramid' ? 80 : decoration.type === 'ancient_tomb' ? 100 : decoration.type === 'hieroglyph_wall' ? 120 : decoration.type === 'sphinx_statue' ? 150 : decoration.type === 'scarab_carving' ? 40 : decoration.type === 'ancient_vase' ? 35 : decoration.type === 'sand_dune' ? 200 : decoration.type === 'temple_entrance' ? 180 : decoration.type === 'ankh_symbol' ? 30 : decoration.type === 'desert_gem' ? 25 : 80,
height: decoration.type === 'pyramid' ? 60 : decoration.type === 'ancient_tomb' ? 80 : decoration.type === 'hieroglyph_wall' ? 100 : decoration.type === 'sphinx_statue' ? 100 : decoration.type === 'scarab_carving' ? 35 : decoration.type === 'ancient_vase' ? 50 : decoration.type === 'sand_dune' ? 40 : decoration.type === 'temple_entrance' ? 150 : decoration.type === 'ankh_symbol' ? 45 : decoration.type === 'desert_gem' ? 30 : 60,
anchorX: 0.5,
anchorY: 1.0,
tint: decoration.tint,
alpha: 0.8
});
break;
case 'crystal':
case 'firecrystal':
decorAsset = LK.getAsset('platform', {
width: 20,
height: 40,
anchorX: 0.5,
anchorY: 1.0,
tint: decoration.tint,
alpha: 0.7
});
break;
case 'statue':
case 'torch':
case 'brazier':
decorAsset = LK.getAsset('platform', {
width: decoration.type === 'statue' ? 40 : 15,
height: decoration.type === 'statue' ? 80 : 50,
anchorX: 0.5,
anchorY: 1.0,
tint: decoration.tint,
alpha: 0.8
});
break;
case 'skull':
case 'rune':
decorAsset = LK.getAsset('platform', {
width: 25,
height: 20,
anchorX: 0.5,
anchorY: 1.0,
tint: decoration.tint,
alpha: 0.7
});
break;
case 'portal':
decorAsset = LK.getAsset('platform', {
width: 60,
height: 100,
anchorX: 0.5,
anchorY: 1.0,
tint: decoration.tint,
alpha: 0.5
});
break;
case 'volcano':
case 'shadowspire':
case 'infernospire':
decorAsset = LK.getAsset('platform', {
width: decoration.type === 'volcano' ? 100 : 40,
height: decoration.type === 'volcano' ? 150 : 200,
anchorX: 0.5,
anchorY: 1.0,
tint: decoration.tint,
alpha: 0.6
});
break;
case 'lavafall':
decorAsset = LK.getAsset('platform', {
width: 30,
height: 400,
anchorX: 0.5,
anchorY: 0.0,
tint: decoration.tint,
alpha: 0.4
});
break;
case 'banner':
case 'dark_crystal':
case 'evil_altar':
case 'bone_pile':
case 'dark_throne':
case 'purple_orb':
case 'sacrificial_circle':
decorAsset = LK.getAsset('platform', {
width: decoration.type === 'banner' ? 80 : decoration.type === 'dark_crystal' ? 50 : decoration.type === 'evil_altar' ? 100 : decoration.type === 'bone_pile' ? 60 : decoration.type === 'dark_throne' ? 120 : decoration.type === 'purple_orb' ? 35 : decoration.type === 'sacrificial_circle' ? 200 : 80,
height: decoration.type === 'banner' ? 120 : decoration.type === 'dark_crystal' ? 80 : decoration.type === 'evil_altar' ? 60 : decoration.type === 'bone_pile' ? 40 : decoration.type === 'dark_throne' ? 150 : decoration.type === 'purple_orb' ? 35 : decoration.type === 'sacrificial_circle' ? 20 : 120,
anchorX: 0.5,
anchorY: decoration.type === 'banner' ? 0.0 : 1.0,
tint: decoration.tint,
alpha: 0.7
});
break;
case 'treasure':
case 'powercrystal':
decorAsset = LK.getAsset('platform', {
width: 30,
height: 25,
anchorX: 0.5,
anchorY: 1.0,
tint: decoration.tint,
alpha: 0.8
});
break;
default:
decorAsset = LK.getAsset('platform', {
width: 30,
height: 30,
anchorX: 0.5,
anchorY: 1.0,
tint: decoration.tint || 0x888888,
alpha: 0.6
});
}
decorAsset.x = decoration.x;
decorAsset.y = decoration.y;
if (decoration.scale) {
decorAsset.scaleX = decoration.scale;
decorAsset.scaleY = decoration.scale;
}
game.addChild(decorAsset);
// Add atmospheric effects for certain decorations
if (decoration.type === 'torch' || decoration.type === 'brazier') {
// Add flickering animation
var originalTint = decorAsset.tint;
var flickerCycle = 0;
var flickerInterval = LK.setInterval(function () {
flickerCycle += 0.1;
var flicker = 0.8 + Math.sin(flickerCycle) * 0.2;
decorAsset.alpha = flicker;
}, 100);
}
if (decoration.type === 'crystal' || decoration.type === 'firecrystal' || decoration.type === 'powercrystal') {
// Add glowing animation
var glowCycle = 0;
var glowInterval = LK.setInterval(function () {
glowCycle += 0.05;
var glow = 0.7 + Math.sin(glowCycle) * 0.3;
decorAsset.alpha = glow;
}, 80);
}
if (decoration.type === 'cloud') {
// Add floating animation
var floatOffset = Math.random() * Math.PI * 2;
var originalY = decorAsset.y;
var floatInterval = LK.setInterval(function () {
floatOffset += 0.02;
decorAsset.y = originalY + Math.sin(floatOffset) * 10;
}, 50);
}
}
}
// Create player
player = new Stickman();
player.x = 200; // Start from left side for horizontal progression
player.y = 1900;
player.canDoubleJump = true;
player.hasUsedDoubleJump = false;
// Apply selected skin
var skinColors = {
'default': 0xFFFFFF,
'red': 0xFF4444,
'blue': 0x4444FF,
'green': 0x44FF44,
'purple': 0x8844FF,
'gold': 0xFFD700
};
if (skinColors[storage.selectedSkin]) {
// Apply tint to all player body parts
player.children.forEach(function (child) {
if (child.tint !== undefined) {
child.tint = skinColors[storage.selectedSkin];
}
});
}
game.addChild(player);
// Create stamina bar
staminaBarBackground = LK.getAsset('platform', {
width: 120,
height: 20,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x000000
});
game.addChild(staminaBarBackground);
staminaBar = LK.getAsset('platform', {
width: 110,
height: 14,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFFFFF
});
game.addChild(staminaBar);
// Clear arrows array
arrows = [];
// Create enemies based on current level
enemies = [];
var enemyData = levelConfig.enemies;
// Create enemies with automatically applied skins from class constructors
for (var i = 0; i < enemyData.length; i++) {
var enemy;
switch (enemyData[i].type) {
case 'stickman':
enemy = new StickmanEnemy();
break;
case 'flying':
enemy = new FlyingEnemy();
break;
case 'boss':
enemy = new Boss();
break;
case 'shadowBoss':
enemy = new ShadowBoss();
break;
case 'fireBoss':
enemy = new FireBoss();
break;
}
enemy.x = enemyData[i].x;
enemy.y = enemyData[i].y;
enemies.push(enemy);
game.addChild(enemy);
}
// Play level-specific music with configurable volume
var currentMusicTrack = levelConfig.musicTrack;
LK.playMusic(currentMusicTrack, {
fade: {
start: 0,
end: storage.musicVolume,
duration: 1000
}
});
// Clear any existing GUI elements first to prevent overlap
if (healthText && healthText.parent) {
healthText.destroy();
}
if (scoreText && scoreText.parent) {
scoreText.destroy();
}
if (ammoText && ammoText.parent) {
ammoText.destroy();
}
if (pauseButton && pauseButton.parent) {
pauseButton.destroy();
}
// Clear existing control buttons to prevent overlap
if (leftButton && leftButton.parent) {
leftButton.destroy();
}
if (rightButton && rightButton.parent) {
rightButton.destroy();
}
if (jumpButton && jumpButton.parent) {
jumpButton.destroy();
}
if (attackButton && attackButton.parent) {
attackButton.destroy();
}
if (bowButton && bowButton.parent) {
bowButton.destroy();
}
// Clear all GUI children to ensure clean state
while (LK.gui.children.length > 0) {
LK.gui.children[0].destroy();
}
// Show game UI
createGameUI();
// Create game controls for mobile interaction
createGameControls();
}
function createGameUI() {
// UI Elements - optimized for Android phone readability
healthText = new Text2('Health: 100', {
size: 50,
fill: 0x00FF00
});
healthText.anchor.set(0, 0);
LK.gui.left.addChild(healthText);
healthText.y = 150; // Position below top-left menu area
// Health bar background
var healthBarBg = LK.getAsset('platform', {
width: 220,
height: 25,
anchorX: 0,
anchorY: 0,
tint: 0x000000
});
healthBarBg.x = 20;
healthBarBg.y = 200;
LK.gui.addChild(healthBarBg);
// Health bar fill
var healthBarFill = LK.getAsset('platform', {
width: 210,
height: 20,
anchorX: 0,
anchorY: 0,
tint: 0x00FF00
});
healthBarFill.x = 25;
healthBarFill.y = 202.5;
LK.gui.addChild(healthBarFill);
// Store references for updating
healthText.healthBarFill = healthBarFill;
scoreText = new Text2('Score: 0', {
size: 50,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
scoreText.y = 50;
// Pause button - positioned in top-right, below the platform menu icon
pauseButton = LK.getAsset('platform', {
width: 120,
height: 80,
anchorX: 1.0,
anchorY: 0.0,
tint: 0x666666
});
pauseButton.x = LK.gui.right.x - 20;
pauseButton.y = 150; // Below the top-left menu area
pauseButton.interactive = true;
pauseButton.buttonMode = true;
LK.gui.addChild(pauseButton);
var pauseText = new Text2('PAUSE', {
size: 28,
fill: 0xFFFFFF
});
pauseText.anchor.set(0.5, 0.5);
pauseText.x = pauseButton.x - pauseButton.width / 2;
pauseText.y = pauseButton.y + pauseButton.height / 2;
LK.gui.addChild(pauseText);
pauseButton.down = function () {
LK.getSound('button_click').play();
showPauseMenu();
};
// Level display - larger text for Android
var levelConfig = getCurrentLevelConfig();
var levelText = new Text2('Level: ' + currentLevel, {
size: 45,
fill: 0xFFD700
});
levelText.anchor.set(1, 0);
levelText.x = LK.gui.right.x - 30;
levelText.y = 230;
LK.gui.addChild(levelText);
// Level name display - larger text for Android
var levelNameText = new Text2(levelConfig.name, {
size: 35,
fill: 0xFFD700
});
levelNameText.anchor.set(1, 0);
levelNameText.x = LK.gui.right.x - 30;
levelNameText.y = 290;
LK.gui.addChild(levelNameText);
// Boss level indicator - larger text for Android
if ((currentLevel - 1) % 4 === 3) {
var bossText = new Text2('BOSS FIGHT!', {
size: 35,
fill: 0xFF4444
});
bossText.anchor.set(1, 0);
bossText.x = LK.gui.right.x - 30;
bossText.y = 340;
LK.gui.addChild(bossText);
}
// Ammunition display - larger text for Android
ammoText = new Text2('Arrows: 5/5', {
size: 50,
fill: 0xFFFFFF
});
ammoText.anchor.set(0, 0);
LK.gui.left.addChild(ammoText);
ammoText.y = 220; // Position below health text
}
// Global UI variables
var healthText, scoreText, ammoText, pauseButton;
var pauseMenuContainer;
var gamePaused = false;
function showPauseMenu() {
if (gamePaused) {
return;
} // Prevent multiple pause menus
gamePaused = true;
// Create pause menu container
pauseMenuContainer = new Container();
game.addChild(pauseMenuContainer);
// Dark overlay
var overlay = LK.getAsset('platform', {
width: 2732,
height: 2048,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x000000,
alpha: 0.7
});
overlay.x = 1366;
overlay.y = 1024;
pauseMenuContainer.addChild(overlay);
// Pause menu background
var menuBg = LK.getAsset('platform', {
width: 600,
height: 800,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x222222
});
menuBg.x = 1366;
menuBg.y = 1024;
pauseMenuContainer.addChild(menuBg);
// Pause title
var pauseTitle = new Text2('GAME PAUSED', {
size: 60,
fill: 0xFFFFFF
});
pauseTitle.anchor.set(0.5, 0.5);
pauseTitle.x = 1366;
pauseTitle.y = 700;
pauseMenuContainer.addChild(pauseTitle);
// Resume button
var resumeButton = LK.getAsset('platform', {
width: 400,
height: 100,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x44FF44
});
resumeButton.x = 1366;
resumeButton.y = 850;
resumeButton.interactive = true;
resumeButton.buttonMode = true;
pauseMenuContainer.addChild(resumeButton);
var resumeText = new Text2('RESUME', {
size: 40,
fill: 0xFFFFFF
});
resumeText.anchor.set(0.5, 0.5);
resumeText.x = resumeButton.x;
resumeText.y = resumeButton.y;
pauseMenuContainer.addChild(resumeText);
resumeButton.down = function () {
LK.getSound('button_click').play();
hidePauseMenu();
};
// Settings button
var pauseSettingsButton = LK.getAsset('platform', {
width: 400,
height: 100,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x4444FF
});
pauseSettingsButton.x = 1366;
pauseSettingsButton.y = 1000;
pauseSettingsButton.interactive = true;
pauseSettingsButton.buttonMode = true;
pauseMenuContainer.addChild(pauseSettingsButton);
var pauseSettingsText = new Text2('SETTINGS', {
size: 40,
fill: 0xFFFFFF
});
pauseSettingsText.anchor.set(0.5, 0.5);
pauseSettingsText.x = pauseSettingsButton.x;
pauseSettingsText.y = pauseSettingsButton.y;
pauseMenuContainer.addChild(pauseSettingsText);
pauseSettingsButton.down = function () {
LK.getSound('button_click').play();
hidePauseMenu();
showPauseSettings();
};
// Main menu button
var mainMenuButton = LK.getAsset('platform', {
width: 400,
height: 100,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFF4444
});
mainMenuButton.x = 1366;
mainMenuButton.y = 1150;
mainMenuButton.interactive = true;
mainMenuButton.buttonMode = true;
pauseMenuContainer.addChild(mainMenuButton);
var mainMenuText = new Text2('MAIN MENU', {
size: 40,
fill: 0xFFFFFF
});
mainMenuText.anchor.set(0.5, 0.5);
mainMenuText.x = mainMenuButton.x;
mainMenuText.y = mainMenuButton.y;
pauseMenuContainer.addChild(mainMenuText);
mainMenuButton.down = function () {
LK.getSound('button_click').play();
returnToMainMenu();
};
}
function hidePauseMenu() {
if (pauseMenuContainer) {
pauseMenuContainer.destroy();
pauseMenuContainer = null;
}
gamePaused = false;
}
function showPauseSettings() {
// Create pause settings container
var pauseSettingsContainer = new Container();
game.addChild(pauseSettingsContainer);
// Dark overlay
var overlay = LK.getAsset('platform', {
width: 2732,
height: 2048,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x000000,
alpha: 0.7
});
overlay.x = 1366;
overlay.y = 1024;
pauseSettingsContainer.addChild(overlay);
// Settings menu background
var settingsBg = LK.getAsset('platform', {
width: 700,
height: 900,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x222222
});
settingsBg.x = 1366;
settingsBg.y = 1024;
pauseSettingsContainer.addChild(settingsBg);
// Settings title
var settingsTitle = new Text2('SETTINGS', {
size: 60,
fill: 0xFFFFFF
});
settingsTitle.anchor.set(0.5, 0.5);
settingsTitle.x = 1366;
settingsTitle.y = 650;
pauseSettingsContainer.addChild(settingsTitle);
// Music volume
var musicLabel = new Text2('Music Volume: ' + Math.round(storage.musicVolume * 100) + '%', {
size: 40,
fill: 0xFFFFFF
});
musicLabel.anchor.set(0.5, 0.5);
musicLabel.x = 1366;
musicLabel.y = 800;
pauseSettingsContainer.addChild(musicLabel);
var musicDown = LK.getAsset('platform', {
width: 80,
height: 80,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFF4444
});
musicDown.x = 1150;
musicDown.y = 850;
musicDown.interactive = true;
musicDown.buttonMode = true;
pauseSettingsContainer.addChild(musicDown);
var musicDownText = new Text2('-', {
size: 50,
fill: 0xFFFFFF
});
musicDownText.anchor.set(0.5, 0.5);
musicDownText.x = musicDown.x;
musicDownText.y = musicDown.y;
pauseSettingsContainer.addChild(musicDownText);
var musicUp = LK.getAsset('platform', {
width: 80,
height: 80,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x44FF44
});
musicUp.x = 1582;
musicUp.y = 850;
musicUp.interactive = true;
musicUp.buttonMode = true;
pauseSettingsContainer.addChild(musicUp);
var musicUpText = new Text2('+', {
size: 50,
fill: 0xFFFFFF
});
musicUpText.anchor.set(0.5, 0.5);
musicUpText.x = musicUp.x;
musicUpText.y = musicUp.y;
pauseSettingsContainer.addChild(musicUpText);
musicDown.down = function () {
storage.musicVolume = Math.max(0, storage.musicVolume - 0.1);
musicLabel.setText('Music Volume: ' + Math.round(storage.musicVolume * 100) + '%');
LK.getSound('button_click').play();
};
musicUp.down = function () {
storage.musicVolume = Math.min(1, storage.musicVolume + 0.1);
musicLabel.setText('Music Volume: ' + Math.round(storage.musicVolume * 100) + '%');
LK.getSound('button_click').play();
};
// Sound volume
var soundLabel = new Text2('Sound Volume: ' + Math.round(storage.soundVolume * 100) + '%', {
size: 40,
fill: 0xFFFFFF
});
soundLabel.anchor.set(0.5, 0.5);
soundLabel.x = 1366;
soundLabel.y = 1000;
pauseSettingsContainer.addChild(soundLabel);
var soundDown = LK.getAsset('platform', {
width: 80,
height: 80,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFF4444
});
soundDown.x = 1150;
soundDown.y = 1050;
soundDown.interactive = true;
soundDown.buttonMode = true;
pauseSettingsContainer.addChild(soundDown);
var soundDownText = new Text2('-', {
size: 50,
fill: 0xFFFFFF
});
soundDownText.anchor.set(0.5, 0.5);
soundDownText.x = soundDown.x;
soundDownText.y = soundDown.y;
pauseSettingsContainer.addChild(soundDownText);
var soundUp = LK.getAsset('platform', {
width: 80,
height: 80,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x44FF44
});
soundUp.x = 1582;
soundUp.y = 1050;
soundUp.interactive = true;
soundUp.buttonMode = true;
pauseSettingsContainer.addChild(soundUp);
var soundUpText = new Text2('+', {
size: 50,
fill: 0xFFFFFF
});
soundUpText.anchor.set(0.5, 0.5);
soundUpText.x = soundUp.x;
soundUpText.y = soundUp.y;
pauseSettingsContainer.addChild(soundUpText);
soundDown.down = function () {
storage.soundVolume = Math.max(0, storage.soundVolume - 0.1);
soundLabel.setText('Sound Volume: ' + Math.round(storage.soundVolume * 100) + '%');
LK.getSound('button_click').play();
};
soundUp.down = function () {
storage.soundVolume = Math.min(1, storage.soundVolume + 0.1);
soundLabel.setText('Sound Volume: ' + Math.round(storage.soundVolume * 100) + '%');
LK.getSound('button_click').play();
};
// Back button
var backButton = LK.getAsset('platform', {
width: 300,
height: 80,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFF4444
});
backButton.x = 1366;
backButton.y = 1250;
backButton.interactive = true;
backButton.buttonMode = true;
pauseSettingsContainer.addChild(backButton);
var backText = new Text2('BACK', {
size: 40,
fill: 0xFFFFFF
});
backText.anchor.set(0.5, 0.5);
backText.x = backButton.x;
backText.y = backButton.y;
pauseSettingsContainer.addChild(backText);
backButton.down = function () {
LK.getSound('button_click').play();
pauseSettingsContainer.destroy();
showPauseMenu();
};
}
function returnToMainMenu() {
// Clean up current game
hidePauseMenu();
// Clear GUI elements first to prevent overlap
if (healthText && healthText.parent) {
healthText.destroy();
}
if (scoreText && scoreText.parent) {
scoreText.destroy();
}
if (ammoText && ammoText.parent) {
ammoText.destroy();
}
if (pauseButton && pauseButton.parent) {
pauseButton.destroy();
}
// Clear control buttons if they exist
if (leftButton && leftButton.parent) {
leftButton.destroy();
}
if (rightButton && rightButton.parent) {
rightButton.destroy();
}
if (jumpButton && jumpButton.parent) {
jumpButton.destroy();
}
if (attackButton && attackButton.parent) {
attackButton.destroy();
}
if (bowButton && bowButton.parent) {
bowButton.destroy();
}
// Clear any GUI children that might be lingering
while (LK.gui.children.length > 0) {
LK.gui.children[0].destroy();
}
// Reset control variables
leftButton = null;
rightButton = null;
jumpButton = null;
attackButton = null;
bowButton = null;
// Clean up game objects
for (var i = game.children.length - 1; i >= 0; i--) {
var child = game.children[i];
if (child !== menuContainer && child !== mapSelectContainer && child !== settingsContainer) {
child.destroy();
}
}
// Clear game arrays
platforms = [];
enemies = [];
arrows = [];
projectiles = [];
enemyBullets = [];
// Reset global UI variables
healthText = null;
scoreText = null;
ammoText = null;
pauseButton = null;
// Reset game state
gameState = 'menu';
gamePaused = false;
// Show menu and play menu music
if (menuContainer) {
menuContainer.visible = true;
} else {
createMenu();
}
// Reset camera position
game.x = 0;
game.y = 0;
// Play menu music
LK.playMusic('menu_music', {
volume: storage.musicVolume || 0.6
});
}
// Unlock cinematic function
function showUnlockCinematic(newLevel, callback) {
// Create cinematic container
var cinematicContainer = new Container();
game.addChild(cinematicContainer);
// Dark overlay
var overlay = LK.getAsset('platform', {
width: 2048,
height: 2732,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x000000,
alpha: 0.8
});
overlay.x = 1024;
overlay.y = 1366;
cinematicContainer.addChild(overlay);
// Level unlock text
var unlockText = new Text2('LEVEL ' + newLevel + ' UNLOCKED!', {
size: 60,
fill: 0xFFD700
});
unlockText.anchor.set(0.5, 0.5);
unlockText.x = 1024;
unlockText.y = 1100;
unlockText.alpha = 0;
cinematicContainer.addChild(unlockText);
// Create pixel-style lock
var lockGraphic = LK.getAsset('lock', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0x666666,
scaleX: 3,
scaleY: 3
});
lockGraphic.x = 1024;
lockGraphic.y = 1366;
cinematicContainer.addChild(lockGraphic);
// Create pixel-style key
var keyGraphic = LK.getAsset('key', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFD700,
scaleX: 2,
scaleY: 2
});
keyGraphic.x = 600; // Start from left side
keyGraphic.y = 1366;
cinematicContainer.addChild(keyGraphic);
// Animation sequence
LK.setTimeout(function () {
// Fade in text
tween(unlockText, {
alpha: 1
}, {
duration: 500
});
}, 200);
// Key moves toward lock
LK.setTimeout(function () {
tween(keyGraphic, {
x: 950,
// Move close to lock
rotation: Math.PI * 2 // Spinning effect
}, {
duration: 1000,
easing: tween.easeInOut
});
}, 500);
// Key enters lock with unlock effect
LK.setTimeout(function () {
// Key enters lock
tween(keyGraphic, {
x: 1024,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 300,
easing: tween.easeIn,
onFinish: function onFinish() {
// Lock opens with flash effect
tween(lockGraphic, {
tint: 0xFFFFFF,
scaleX: 4,
scaleY: 4,
alpha: 0
}, {
duration: 400,
easing: tween.easeOut
});
// Key disappears with glow
tween(keyGraphic, {
tint: 0xFFFFFF,
scaleX: 3,
scaleY: 3,
alpha: 0
}, {
duration: 400,
easing: tween.easeOut
});
// Text grows and glows
tween(unlockText, {
scaleX: 1.5,
scaleY: 1.5,
tint: 0xFFFFFF
}, {
duration: 400,
easing: tween.easeOut
});
}
});
}, 1500);
// Clean up and continue
LK.setTimeout(function () {
tween(cinematicContainer, {
alpha: 0
}, {
duration: 800,
onFinish: function onFinish() {
cinematicContainer.destroy();
if (callback) {
callback();
}
}
});
}, 3000);
}
function createGameControls() {
// Mobile Controls UI - Optimized for Android phones with larger touch targets
// Movement area background - larger for easier touch detection
var movementArea = LK.getAsset('platform', {
width: 350,
height: 320,
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.2,
tint: 0x333333
});
movementArea.x = 180;
movementArea.y = LK.gui.bottom.y - 160;
LK.gui.addChild(movementArea);
// Left movement button - larger for Android phones
leftButton = LK.getAsset('platform', {
width: 150,
height: 150,
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.8,
tint: 0x4444FF
});
leftButton.x = 120;
leftButton.y = LK.gui.bottom.y - 160;
leftButton.interactive = true;
leftButton.buttonMode = true;
LK.gui.addChild(leftButton);
var leftIcon = new Text2('<', {
size: 70,
fill: 0xFFFFFF
});
leftIcon.anchor.set(0.5, 0.5);
leftIcon.x = leftButton.x;
leftIcon.y = leftButton.y;
LK.gui.addChild(leftIcon);
// Right movement button - larger for Android phones
rightButton = LK.getAsset('platform', {
width: 150,
height: 150,
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.8,
tint: 0x4444FF
});
rightButton.x = 240;
rightButton.y = LK.gui.bottom.y - 160;
rightButton.interactive = true;
rightButton.buttonMode = true;
LK.gui.addChild(rightButton);
var rightIcon = new Text2('>', {
size: 70,
fill: 0xFFFFFF
});
rightIcon.anchor.set(0.5, 0.5);
rightIcon.x = rightButton.x;
rightIcon.y = rightButton.y;
LK.gui.addChild(rightIcon);
// Action buttons on the right side - optimized for Android thumb reach
// Jump button - largest and most accessible for Android phones
jumpButton = LK.getAsset('platform', {
width: 180,
height: 180,
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.8,
tint: 0x44FF44
});
jumpButton.x = LK.gui.right.x - 120;
jumpButton.y = LK.gui.bottom.y - 120;
jumpButton.interactive = true;
jumpButton.buttonMode = true;
LK.gui.addChild(jumpButton);
var jumpLabel = new Text2('JUMP', {
size: 32,
fill: 0xFFFFFF
});
jumpLabel.anchor.set(0.5, 0.5);
jumpLabel.x = jumpButton.x;
jumpLabel.y = jumpButton.y;
LK.gui.addChild(jumpLabel);
// Attack button - positioned for comfortable Android thumb reach
attackButton = LK.getAsset('platform', {
width: 160,
height: 160,
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.8,
tint: 0xFF4444
});
attackButton.x = LK.gui.right.x - 300;
attackButton.y = LK.gui.bottom.y - 120;
attackButton.interactive = true;
attackButton.buttonMode = true;
LK.gui.addChild(attackButton);
var attackLabel = new Text2('ATK', {
size: 30,
fill: 0xFFFFFF
});
attackLabel.anchor.set(0.5, 0.5);
attackLabel.x = attackButton.x;
attackLabel.y = attackButton.y;
LK.gui.addChild(attackLabel);
// Bow button - positioned higher for Android ergonomics
bowButton = LK.getAsset('platform', {
width: 140,
height: 140,
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.8,
tint: 0xFF8844
});
bowButton.x = LK.gui.right.x - 210;
bowButton.y = LK.gui.bottom.y - 280;
bowButton.interactive = true;
bowButton.buttonMode = true;
LK.gui.addChild(bowButton);
var bowLabel = new Text2('BOW', {
size: 26,
fill: 0xFFFFFF
});
bowLabel.anchor.set(0.5, 0.5);
bowLabel.x = bowButton.x;
bowLabel.y = bowButton.y;
LK.gui.addChild(bowLabel);
setupControlEvents();
}
// Global control variables
var leftButton, rightButton, jumpButton, attackButton, bowButton;
// Collision detection function
function checkCollisions(obj, platforms) {
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
if (obj.intersects(platform)) {
// Landing on top of platform
if (obj.velocityY > 0 && obj.y - 40 < platform.y) {
obj.y = platform.y - 40;
obj.velocityY = 0;
obj.onGround = true;
// Reset double jump when landing on platforms
if (obj === player) {
obj.canDoubleJump = true;
obj.hasUsedDoubleJump = false;
}
}
}
}
// Ground collision
if (obj.y > 1948) {
obj.y = 1948;
obj.velocityY = 0;
obj.onGround = true;
// Reset double jump when landing on ground
if (obj === player) {
obj.canDoubleJump = true;
obj.hasUsedDoubleJump = false;
}
}
}
function setupControlEvents() {
// Input handling - variables moved to global scope
game.down = function (x, y, obj) {
// Fallback touch handling for areas outside buttons
};
game.up = function (x, y, obj) {
// Fallback touch release handling
};
// Input state variables already declared in global scope
// Control event handlers - enhanced feedback for Android
leftButton.down = function (x, y, obj) {
leftPressed = true;
currentTouchId = 'left';
// Enhanced visual feedback for Android - simulates haptic feedback
tween(leftButton, {
alpha: 1.0,
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 80
});
LK.getSound('button_click').play();
};
leftButton.up = function (x, y, obj) {
leftPressed = false;
if (currentTouchId === 'left') {
currentTouchId = null;
}
tween(leftButton, {
alpha: 0.8,
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 120
});
};
rightButton.down = function (x, y, obj) {
rightPressed = true;
currentTouchId = 'right';
tween(rightButton, {
alpha: 0.9
}, {
duration: 100
});
LK.getSound('button_click').play();
};
rightButton.up = function (x, y, obj) {
rightPressed = false;
if (currentTouchId === 'right') {
currentTouchId = null;
}
tween(rightButton, {
alpha: 0.6
}, {
duration: 100
});
};
jumpButton.down = function (x, y, obj) {
player.jump();
tween(jumpButton, {
alpha: 0.9
}, {
duration: 100
});
};
jumpButton.up = function (x, y, obj) {
tween(jumpButton, {
alpha: 0.6
}, {
duration: 100
});
};
attackButton.down = function (x, y, obj) {
player.attack();
tween(attackButton, {
alpha: 0.9
}, {
duration: 100
});
};
attackButton.up = function (x, y, obj) {
tween(attackButton, {
alpha: 0.6
}, {
duration: 100
});
};
bowButton.down = function (x, y, obj) {
if (player.currentAmmo > 0) {
player.shootArrow();
tween(bowButton, {
alpha: 0.9
}, {
duration: 100
});
} else {
// Visual feedback for no ammo
tween(bowButton, {
tint: 0xFF0000
}, {
duration: 200,
onFinish: function onFinish() {
tween(bowButton, {
tint: 0xFF8844
}, {
duration: 200
});
}
});
}
};
bowButton.up = function (x, y, obj) {
tween(bowButton, {
alpha: 0.6
}, {
duration: 100
});
};
}
// Initialize menu system
LK.playMusic('menu_music', {
volume: storage.musicVolume || 0.6
});
createMenu();
game.update = function () {
if (gameState !== 'playing' || gamePaused) {
return; // Don't update game logic if not playing or paused
}
// Handle input
if (leftPressed) {
player.moveLeft();
}
if (rightPressed) {
player.moveRight();
}
// Check collisions for player
checkCollisions(player, platforms);
// Check collisions for enemies
for (var i = 0; i < enemies.length; i++) {
checkCollisions(enemies[i], platforms);
}
// Update arrows and check enemy hits
for (var i = arrows.length - 1; i >= 0; i--) {
var arrow = arrows[i];
// Check if arrow hits enemies
for (var j = enemies.length - 1; j >= 0; j--) {
var enemy = enemies[j];
if (arrow.intersects(enemy)) {
if (enemy.takeDamage(arrow.damage)) {
// Enemy destroyed
enemies.splice(j, 1);
LK.setScore(LK.getScore() + 150); // More points for ranged kills
storage.coins += 5; // Reward coins for defeating enemies
scoreText.setText('Score: ' + LK.getScore());
}
// Remove arrow
arrow.destroy();
arrows.splice(i, 1);
break;
}
}
// Remove destroyed arrows
if (arrow.parent === null) {
arrows.splice(i, 1);
}
}
// Update projectiles and check enemy hits
for (var i = projectiles.length - 1; i >= 0; i--) {
var projectile = projectiles[i];
// Check if projectile hits enemies
for (var j = enemies.length - 1; j >= 0; j--) {
var enemy = enemies[j];
if (projectile.intersects(enemy)) {
if (enemy.takeDamage(25)) {
// Enemy destroyed
enemies.splice(j, 1);
LK.setScore(LK.getScore() + 100);
storage.coins += 5; // Reward coins for defeating enemies
scoreText.setText('Score: ' + LK.getScore());
}
// Remove projectile
projectile.destroy();
projectiles.splice(i, 1);
break;
}
}
// Remove destroyed projectiles
if (projectile.parent === null) {
projectiles.splice(i, 1);
}
}
// Update enemy bullets and check player hits
for (var i = enemyBullets.length - 1; i >= 0; i--) {
var bullet = enemyBullets[i];
// Check if bullet hits player
if (bullet.intersects(player)) {
player.takeDamage(10);
bullet.destroy();
enemyBullets.splice(i, 1);
continue;
}
// Remove destroyed bullets
if (bullet.parent === null) {
enemyBullets.splice(i, 1);
}
}
// Check player-enemy collisions
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
if (player.intersects(enemy)) {
// Simple knockback and damage
var dx = player.x - enemy.x;
player.velocityX += dx > 0 ? 5 : -5;
player.takeDamage(1);
// Update health display
healthText.setText('Health: ' + Math.max(0, player.health));
healthText.tint = player.health < 30 ? 0xFF0000 : 0x00FF00;
// Update health bar
if (healthText.healthBarFill) {
var healthPercent = Math.max(0, player.health / player.maxHealth);
healthText.healthBarFill.width = 210 * healthPercent;
healthText.healthBarFill.tint = player.health < 30 ? 0xFF0000 : 0x00FF00;
}
}
}
// Win condition - defeat all enemies
if (enemies.length === 0) {
var returnToMainMenu = function returnToMainMenu() {
// Clean up current level more carefully
for (var i = game.children.length - 1; i >= 0; i--) {
var child = game.children[i];
// Don't destroy menu containers
if (child !== menuContainer && child !== mapSelectContainer && child !== settingsContainer) {
child.destroy();
}
}
// Clear arrays
platforms = [];
enemies = [];
arrows = [];
projectiles = [];
enemyBullets = [];
// Reset camera position
game.x = 0;
game.y = 0;
// Change game state to main menu
gameState = 'menu';
gamePaused = false;
// Show main menu and play menu music
if (menuContainer) {
menuContainer.visible = true;
} else {
createMenu();
}
LK.playMusic('menu_music', {
volume: storage.musicVolume || 0.6
});
};
// Update high score
if (LK.getScore() > storage.highScore) {
storage.highScore = LK.getScore();
}
// Award bonus coins for level completion
var levelBonus = 10; // 10 coins for completing any level
storage.coins += levelBonus;
var completedLevel = currentLevel;
var shouldShowUnlock = false;
// Mark this level as completed
storage.lastCompletedLevel = completedLevel;
// Unlock the next level
var nextLevel = currentLevel + 1;
if (nextLevel > storage.unlockedLevels) {
storage.unlockedLevels = nextLevel;
shouldShowUnlock = true;
}
// Reset player health to full when leveling up
player.health = player.maxHealth;
healthText.setText('Health: ' + player.health);
healthText.tint = 0x00FF00;
// Reset current level to 1 for main menu (Play button will advance to next uncompleted level)
currentLevel = 1;
storage.currentLevel = currentLevel;
// Create completion screen overlay
var completionOverlay = LK.getAsset('platform', {
width: 2732,
height: 2048,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x000000,
alpha: 0.8
});
completionOverlay.x = 1366;
completionOverlay.y = 1024;
game.addChild(completionOverlay);
// Create completion message background
var completionBg = LK.getAsset('platform', {
width: 800,
height: 400,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x222222
});
completionBg.x = 1366;
completionBg.y = 1024;
game.addChild(completionBg);
// Show level complete message with enhanced styling
var levelComplete = new Text2('NIVEL ' + completedLevel + ' COMPLETADO', {
size: 60,
fill: 0xFFD700
});
levelComplete.anchor.set(0.5, 0.5);
levelComplete.x = 1366;
levelComplete.y = 950;
levelComplete.alpha = 0;
game.addChild(levelComplete);
// Success message
var successMessage = new Text2('¡Excelente trabajo!', {
size: 40,
fill: 0x00FF00
});
successMessage.anchor.set(0.5, 0.5);
successMessage.x = 1366;
successMessage.y = 1050;
successMessage.alpha = 0;
game.addChild(successMessage);
// Main menu message
var selectorText = new Text2('Regresando al menú principal...', {
size: 35,
fill: 0xFFFFFF
});
selectorText.anchor.set(0.5, 0.5);
selectorText.x = 1366;
selectorText.y = 1150;
selectorText.alpha = 0;
game.addChild(selectorText);
// Animate completion screen entrance
tween(levelComplete, {
alpha: 1,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 600,
easing: tween.easeOut
});
// Animate success message
LK.setTimeout(function () {
tween(successMessage, {
alpha: 1
}, {
duration: 400,
easing: tween.easeOut
});
}, 400);
// Animate selector text
LK.setTimeout(function () {
tween(selectorText, {
alpha: 1
}, {
duration: 400,
easing: tween.easeOut
});
}, 800);
// Return to main menu after 3 seconds
LK.setTimeout(function () {
// Clean up completion screen elements first
if (completionOverlay && completionOverlay.parent) {
completionOverlay.destroy();
}
if (completionBg && completionBg.parent) {
completionBg.destroy();
}
if (levelComplete && levelComplete.parent) {
levelComplete.destroy();
}
if (successMessage && successMessage.parent) {
successMessage.destroy();
}
if (selectorText && selectorText.parent) {
selectorText.destroy();
}
if (shouldShowUnlock) {
// Show unlock cinematic for new level
showUnlockCinematic(nextLevel, function () {
// Return to main menu after cinematic
returnToMainMenu();
});
} else {
// Return to main menu immediately
returnToMainMenu();
}
}, 3000);
}
// Update stamina bar position and appearance - moved higher up
staminaBarBackground.x = player.x;
staminaBarBackground.y = player.y - 130;
staminaBar.x = player.x;
staminaBar.y = player.y - 130;
// Update stamina bar color based on double jump availability
if (player.canDoubleJump && !player.hasUsedDoubleJump) {
staminaBar.tint = 0x00FF00; // Bright green when available
} else {
staminaBar.tint = 0x444444; // Dark gray when used
}
// Update bow button appearance based on ammunition
if (bowButton) {
bowButton.alpha = player.currentAmmo > 0 ? 0.6 : 0.3;
bowButton.tint = player.currentAmmo > 0 ? 0xFF8844 : 0x666666;
}
// Horizontal camera follow player with smooth movement
var targetX = Math.max(-1024, Math.min(0, -(player.x - 1024)));
var targetY = Math.max(-500, Math.min(0, -(player.y - 1024)));
game.x += (targetX - game.x) * 0.08;
game.y += (targetY - game.y) * 0.06;
// Sound volume is now controlled through storage and applied during initialization
};
// Controls will be created when entering levels via startGame() /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
currentLevel: 1,
unlockedLevels: 1,
musicVolume: 1,
soundVolume: 1,
highScore: 0,
lastCompletedLevel: 0,
coins: 0,
selectedSkin: "default",
ownedSkins: ["default"],
selectedEnemySkin: "default",
ownedEnemySkins: ["default"],
selectedBossSkin: "default",
ownedBossSkins: ["default"],
selectedFlyingSkin: "default",
ownedFlyingSkins: ["default"],
selectedVoiceSkin: "default",
ownedVoiceSkins: ["default"]
});
/****
* Classes
****/
var Arrow = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('arrow', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocityX = 0;
self.velocityY = 0;
self.lifetime = 240; // 4 seconds at 60fps
self.damage = 20;
self.update = function () {
// Homing behavior - track nearest enemy
var nearestEnemy = null;
var nearestDistance = Infinity;
// Find nearest enemy
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < nearestDistance) {
nearestDistance = distance;
nearestEnemy = enemy;
}
}
// Adjust velocity towards nearest enemy if found
if (nearestEnemy && nearestDistance > 50) {
var dx = nearestEnemy.x - self.x;
var dy = nearestEnemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Normalize direction vector
var dirX = dx / distance;
var dirY = dy / distance;
// Homing strength (how aggressively it turns)
var homingStrength = 0.3;
var arrowSpeed = 12;
// Blend current velocity with target direction using tween for smooth turning
self.velocityX += (dirX * arrowSpeed - self.velocityX) * homingStrength;
self.velocityY += (dirY * arrowSpeed - self.velocityY) * homingStrength;
// Maintain consistent speed
var currentSpeed = Math.sqrt(self.velocityX * self.velocityX + self.velocityY * self.velocityY);
if (currentSpeed > 0) {
self.velocityX = self.velocityX / currentSpeed * arrowSpeed;
self.velocityY = self.velocityY / currentSpeed * arrowSpeed;
}
}
self.x += self.velocityX;
self.y += self.velocityY;
self.lifetime--;
// Rotate arrow to match trajectory
if (self.velocityX !== 0) {
graphics.rotation = Math.atan2(self.velocityY, self.velocityX);
}
// Calculate distance traveled from start position
if (self.startX === undefined) {
self.startX = self.x;
self.startY = self.y;
}
var distanceTraveled = Math.sqrt(Math.pow(self.x - self.startX, 2) + Math.pow(self.y - self.startY, 2));
var maxRange = 400; // Short range limit
// Remove if lifetime expired, off screen, or exceeded range
if (self.lifetime <= 0 || self.x < -50 || self.x > 2098 || self.y > 2100 || distanceTraveled > maxRange) {
self.destroy();
}
};
return self;
});
var Boss = Container.expand(function () {
var self = Container.call(this);
// Apply selected boss skin
var skinColor = storage.selectedBossSkin || 'default';
var bossSkinColors = {
'default': {
main: 0x800080,
accent: 0x9932CC
},
'crimson': {
main: 0xDC143C,
accent: 0xFF6347
},
'shadow': {
main: 0x2F2F2F,
accent: 0x696969
},
'golden': {
main: 0xFFD700,
accent: 0xFFA500
},
'emerald': {
main: 0x50C878,
accent: 0x32CD32
},
'cyber': {
main: 0x00CED1,
accent: 0x00FFFF
}
};
var currentSkin = bossSkinColors[skinColor] || bossSkinColors['default'];
var graphics = self.attachAsset('boss', {
anchorX: 0.5,
anchorY: 1.0,
tint: currentSkin.main
});
// Health bar
var healthBarBg = self.attachAsset('platform', {
width: 160,
height: 20,
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -220,
tint: 0x000000
});
var healthBarFill = self.attachAsset('platform', {
width: 156,
height: 16,
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -220,
tint: currentSkin.accent || 0xFF0000
});
self.health = 150;
self.maxHealth = 150;
self.velocityX = 0;
self.velocityY = 0;
self.onGround = false;
self.speed = 3;
self.direction = 1;
self.attackCooldown = 0;
self.animationTick = 0;
self.phase = 1; // Boss has different phases
self.epicMusicTriggered = false;
self.update = function () {
// Apply gravity
if (!self.onGround) {
self.velocityY += 0.8;
}
// Enhanced Boss AI - different behavior based on health with range detection
var distanceToPlayer = Math.abs(self.x - player.x);
var verticalDistance = Math.abs(self.y - player.y);
var healthPercent = self.health / self.maxHealth;
var attackRange = healthPercent > 0.5 ? 250 : 350; // Longer range in phase 2
var aggressiveRange = healthPercent > 0.5 ? 120 : 180;
if (healthPercent > 0.5) {
// Phase 1: Enhanced chase and attack with range detection
if (distanceToPlayer < attackRange && distanceToPlayer > aggressiveRange) {
// Pursuit mode - faster movement when player detected
var pursuitSpeed = self.speed * 1.3;
if (player.x > self.x) {
self.direction = 1;
self.velocityX = pursuitSpeed;
} else {
self.direction = -1;
self.velocityX = -pursuitSpeed;
}
// Boss can jump to platforms to reach player
if (player.y < self.y - 100 && self.onGround && Math.random() < 0.02) {
// Find platform in direction of player
var targetPlatform = null;
var targetDirection = player.x > self.x ? 1 : -1;
for (var p = 0; p < platforms.length; p++) {
var platform = platforms[p];
var platformInDirection = targetDirection > 0 ? platform.x > self.x : platform.x < self.x;
var platformDistance = Math.abs(platform.x - self.x);
if (platformInDirection && platform.y < self.y && platform.y > player.y - 100 && platformDistance < 400) {
targetPlatform = platform;
break;
}
}
if (targetPlatform) {
self.velocityY = -20; // Powerful boss jump
self.velocityX = targetDirection * (self.speed + 3);
self.onGround = false;
LK.getSound('boss_attack').play(); // Use unique boss attack sound for boss jump
}
}
} else {
self.velocityX = 0;
if (self.attackCooldown <= 0) {
self.groundSlam();
self.attackCooldown = 120;
}
}
} else {
// Phase 2: Faster, more aggressive - trigger epic music transition
if (!self.epicMusicTriggered) {
self.epicMusicTriggered = true;
// Play boss music with higher intensity for final phase
LK.playMusic('boss_music', {
fade: {
start: storage.musicVolume,
end: storage.musicVolume * 1.2,
duration: 500
}
});
}
self.speed = 4;
if (distanceToPlayer < attackRange && distanceToPlayer > aggressiveRange) {
// Enhanced pursuit in phase 2 with speed boost
var phase2Speed = self.speed * 1.5;
if (player.x > self.x) {
self.direction = 1;
self.velocityX = phase2Speed;
} else {
self.direction = -1;
self.velocityX = -phase2Speed;
}
// Highly aggressive platform jumping and pursuit in phase 2
if (self.onGround && (verticalDistance > 60 || Math.random() < 0.06)) {
// Find best platform for tactical advantage
var bestPlatform = null;
var bestScore = Infinity;
for (var p = 0; p < platforms.length; p++) {
var platform = platforms[p];
var platformDistance = Math.abs(platform.x - self.x);
var platformToPlayerDistance = Math.abs(platform.x - player.x);
var tacticalScore = platformDistance + platformToPlayerDistance * 0.3;
if (platform.y < self.y && platform.y > player.y - 120 && platformDistance < 500) {
if (tacticalScore < bestScore) {
bestScore = tacticalScore;
bestPlatform = platform;
}
}
}
if (bestPlatform) {
// Powerful strategic jump towards best platform
var jumpDirection = bestPlatform.x > self.x ? 1 : -1;
self.velocityY = -24; // Even more powerful jump
self.velocityX = jumpDirection * (self.speed + 5);
self.onGround = false;
LK.getSound('boss_attack').play();
} else {
// Direct pursuit jump if no platforms available
var targetDirection = player.x > self.x ? 1 : -1;
self.velocityY = -22;
self.velocityX = targetDirection * (self.speed + 4);
self.onGround = false;
LK.getSound('boss_attack').play();
}
// Create screen shake effect for dramatic boss jump
tween(game, {
x: game.x + (Math.random() - 0.5) * 20
}, {
duration: 100,
onFinish: function onFinish() {
tween(game, {
x: 0
}, {
duration: 100
});
}
});
}
} else {
self.velocityX = 0;
if (self.attackCooldown <= 0) {
self.multiAttack();
self.attackCooldown = 180;
}
}
}
// Apply velocity
self.x += self.velocityX;
self.y += self.velocityY;
self.onGround = false;
// Update cooldowns
if (self.attackCooldown > 0) {
self.attackCooldown--;
}
self.animationTick++;
// Face direction
graphics.scaleX = self.direction > 0 ? 1 : -1;
// Breathing animation
var breathCycle = Math.sin(self.animationTick * 0.05);
graphics.scaleY = 1 + breathCycle * 0.05;
};
self.groundSlam = function () {
// Ground slam attack
tween(graphics, {
scaleY: 0.8
}, {
duration: 200,
onFinish: function onFinish() {
tween(graphics, {
scaleY: 1.2
}, {
duration: 100,
onFinish: function onFinish() {
tween(graphics, {
scaleY: 1
}, {
duration: 200
});
// Damage player if close
if (Math.abs(self.x - player.x) < 120) {
player.takeDamage(20);
player.velocityX += (player.x > self.x ? 1 : -1) * 15;
player.velocityY = -10;
}
}
});
}
});
LK.getSound('boss_attack').play();
};
self.multiAttack = function () {
// Multiple projectiles in different directions
for (var i = 0; i < 5; i++) {
var bullet = new EnemyBullet();
bullet.x = self.x;
bullet.y = self.y - 100;
var angle = (i - 2) * 0.5; // Spread shots
bullet.velocityX = Math.cos(angle) * 8 * self.direction;
bullet.velocityY = Math.sin(angle) * 8 - 2;
enemyBullets.push(bullet);
game.addChild(bullet);
}
LK.getSound('boss_attack').play();
};
self.takeDamage = function (damage) {
self.health -= damage;
// Update health bar
var healthPercent = Math.max(0, self.health / self.maxHealth);
healthBarFill.width = 156 * healthPercent;
// Flash effect
tween(graphics, {
tint: 0xFFFFFF
}, {
duration: 150,
onFinish: function onFinish() {
tween(graphics, {
tint: 0x800080
}, {
duration: 150
});
}
});
LK.getSound('enemy_hit').play();
if (self.health <= 0) {
LK.getSound('enemy_death').play();
self.destroy();
return true;
}
return false;
};
return self;
});
var EnemyBullet = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('enemyBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocityX = 0;
self.velocityY = 0;
self.lifetime = 180;
self.update = function () {
self.x += self.velocityX;
self.y += self.velocityY;
self.lifetime--;
// Calculate distance traveled from start position
if (self.startX === undefined) {
self.startX = self.x;
self.startY = self.y;
}
var distanceTraveled = Math.sqrt(Math.pow(self.x - self.startX, 2) + Math.pow(self.y - self.startY, 2));
var maxRange = 300; // Short range limit for enemy bullets
// Remove if lifetime expired, off screen, or exceeded range
if (self.lifetime <= 0 || self.x < -50 || self.x > 2098 || self.y > 2800 || self.y < -100 || distanceTraveled > maxRange) {
self.destroy();
}
};
return self;
});
var FireBoss = Container.expand(function () {
var self = Container.call(this);
// Apply selected boss skin for fire boss
var skinColor = storage.selectedBossSkin || 'default';
var fireBossSkinColors = {
'default': {
main: 0xFF4500,
flame: 0xFF6347
},
'crimson': {
main: 0xDC143C,
flame: 0xFF1493
},
'shadow': {
main: 0x8B008B,
flame: 0xFF00FF
},
'golden': {
main: 0xFFD700,
flame: 0xFFA500
},
'emerald': {
main: 0x32CD32,
flame: 0x00FF00
},
'cyber': {
main: 0x00CED1,
flame: 0x00BFFF
}
};
var currentSkin = fireBossSkinColors[skinColor] || fireBossSkinColors['default'];
var graphics = self.attachAsset('boss', {
anchorX: 0.5,
anchorY: 1.0,
tint: currentSkin.main
});
// Health bar
var healthBarBg = self.attachAsset('platform', {
width: 160,
height: 20,
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -220,
tint: 0x000000
});
var healthBarFill = self.attachAsset('platform', {
width: 156,
height: 16,
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -220,
tint: currentSkin.flame || 0xFF6347
});
self.health = 250;
self.maxHealth = 250;
self.velocityX = 0;
self.velocityY = 0;
self.onGround = false;
self.speed = 2;
self.direction = 1;
self.attackCooldown = 0;
self.chargeAttackCooldown = 0;
self.animationTick = 0;
self.update = function () {
// Apply gravity
if (!self.onGround) {
self.velocityY += 0.8;
}
var distanceToPlayer = Math.abs(self.x - player.x);
var healthPercent = self.health / self.maxHealth;
// Charge attack
if (self.chargeAttackCooldown <= 0 && distanceToPlayer < 400) {
self.chargeAttack();
self.chargeAttackCooldown = 400;
}
// Fire rain attack
if (self.attackCooldown <= 0) {
self.fireRain();
self.attackCooldown = healthPercent > 0.5 ? 180 : 120;
}
// Slower but powerful movement
if (player.x > self.x) {
self.direction = 1;
self.velocityX = self.speed;
} else {
self.direction = -1;
self.velocityX = -self.speed;
}
// Apply velocity
self.x += self.velocityX;
self.y += self.velocityY;
self.onGround = false;
// Update cooldowns
if (self.attackCooldown > 0) {
self.attackCooldown--;
}
if (self.chargeAttackCooldown > 0) {
self.chargeAttackCooldown--;
}
self.animationTick++;
// Fire glow effect
var glowIntensity = 0.8 + Math.sin(self.animationTick * 0.15) * 0.2;
graphics.scaleY = glowIntensity;
graphics.scaleX = self.direction > 0 ? glowIntensity : -glowIntensity;
};
self.chargeAttack = function () {
// Powerful charge towards player
var chargeDirection = player.x > self.x ? 1 : -1;
self.velocityX = chargeDirection * 15;
self.velocityY = -5;
// Visual effect
tween(graphics, {
tint: 0xFFFF00
}, {
duration: 300,
onFinish: function onFinish() {
tween(graphics, {
tint: 0xFF4500
}, {
duration: 200
});
}
});
LK.getSound('fire_boss_attack').play();
};
self.fireRain = function () {
// Create multiple fire projectiles falling from above
for (var i = 0; i < 5; i++) {
var bullet = new EnemyBullet();
bullet.x = player.x + (i - 2) * 100 + Math.random() * 50 - 25;
bullet.y = player.y - 400;
bullet.velocityX = Math.random() * 2 - 1;
bullet.velocityY = 8;
// Make fire bullets orange/red
bullet.tint = 0xFF6347;
enemyBullets.push(bullet);
game.addChild(bullet);
}
LK.getSound('fire_boss_attack').play();
};
self.takeDamage = function (damage) {
self.health -= damage;
var healthPercent = Math.max(0, self.health / self.maxHealth);
healthBarFill.width = 156 * healthPercent;
// Flash effect
tween(graphics, {
tint: 0xFFFFFF
}, {
duration: 150,
onFinish: function onFinish() {
tween(graphics, {
tint: 0xFF4500
}, {
duration: 150
});
}
});
LK.getSound('enemy_hit').play();
if (self.health <= 0) {
LK.getSound('enemy_death').play();
self.destroy();
return true;
}
return false;
};
return self;
});
var FlyingEnemy = Container.expand(function () {
var self = Container.call(this);
// Create flying enemy body parts with skin-specific assets
var skinColor = storage.selectedFlyingSkin || 'default';
var flyingSkinAssetMap = {
'default': {
body: 'flying_default_body',
wing: 'enemy_limb',
tint: 0x8B4513
},
'black': {
body: 'flying_black_body',
wing: 'flying_black_wing',
tint: 0x2f2f2f
},
'silver': {
body: 'flying_silver_body',
wing: 'flying_silver_wing',
tint: 0xc0c0c0
},
'golden': {
body: 'flying_golden_body',
wing: 'flying_golden_wing',
tint: 0xffd700
},
'red': {
body: 'flying_red_body',
wing: 'flying_red_wing',
tint: 0xff4500
},
'blue': {
body: 'flying_blue_body',
wing: 'flying_blue_wing',
tint: 0x1e90ff
}
};
var currentSkinAssets = flyingSkinAssetMap[skinColor] || flyingSkinAssetMap['default'];
var body = self.attachAsset(currentSkinAssets.body, {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 0,
width: 40,
height: 40,
tint: currentSkinAssets.tint
});
var leftWing = self.attachAsset(currentSkinAssets.wing, {
anchorX: 0.5,
anchorY: 0.5,
x: -25,
y: 0,
width: 20,
height: 8
});
var rightWing = self.attachAsset(currentSkinAssets.wing, {
anchorX: 0.5,
anchorY: 0.5,
x: 25,
y: 0,
width: 20,
height: 8
});
// Health bar
var healthBarBg = self.attachAsset('platform', {
width: 60,
height: 8,
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -35,
tint: 0x000000
});
var healthBarFill = self.attachAsset('platform', {
width: 56,
height: 6,
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -35,
tint: 0x00FF00
});
self.health = 30;
self.maxHealth = 30;
self.speed = 2;
self.direction = 1;
self.attackRange = 120;
self.attackCooldown = 0;
self.animationTick = 0;
self.floatOffset = 0;
self.shootCooldown = 0;
self.update = function () {
// Floating movement
self.floatOffset += 0.1;
self.y += Math.sin(self.floatOffset) * 0.5;
// Wing flapping animation
var flapSpeed = 0.3;
var flapCycle = Math.sin(self.animationTick * flapSpeed);
leftWing.rotation = flapCycle * 0.8;
rightWing.rotation = -flapCycle * 0.8;
leftWing.y = Math.sin(self.animationTick * flapSpeed * 2) * 2;
rightWing.y = Math.sin(self.animationTick * flapSpeed * 2) * 2;
// Enhanced AI behavior - chase player and shoot with range detection
var distanceToPlayer = Math.abs(self.x - player.x);
var verticalDistance = Math.abs(self.y - player.y);
var attackRange = 400; // Flying enemies have longer detection range
var aggressiveRange = 200; // Close range for aggressive behavior
if (distanceToPlayer < attackRange && verticalDistance < 200) {
// Enhanced chase behavior with speed adjustment based on range
var isInAggressiveRange = distanceToPlayer < aggressiveRange;
var chaseSpeed = isInAggressiveRange ? self.speed * 1.8 : self.speed * 1.2;
// Chase player
if (player.x > self.x) {
self.direction = 1;
self.x += chaseSpeed;
} else {
self.direction = -1;
self.x -= chaseSpeed;
}
// Vertical pursuit - move towards player's Y position more aggressively
if (Math.abs(player.y - self.y) > 30) {
if (player.y > self.y) {
self.y += chaseSpeed * 0.7;
} else {
self.y -= chaseSpeed * 0.7;
}
}
// Strategic platform landing when pursuing player
if (Math.random() < 0.015 || isInAggressiveRange && Math.random() < 0.03) {
// Higher chance to land on platforms when in aggressive range
var nearestPlatform = null;
var nearestDistance = Infinity;
var bestStrategicPlatform = null;
var bestStrategicValue = Infinity;
for (var p = 0; p < platforms.length; p++) {
var platform = platforms[p];
var platformDistance = Math.sqrt(Math.pow(platform.x - self.x, 2) + Math.pow(platform.y - self.y, 2));
var platformToPlayerDistance = Math.abs(platform.x - player.x);
// Calculate strategic value (closer to player is better)
var strategicValue = platformDistance + platformToPlayerDistance;
if (platformDistance < 200) {
if (platformDistance < nearestDistance) {
nearestDistance = platformDistance;
nearestPlatform = platform;
}
if (strategicValue < bestStrategicValue && platformToPlayerDistance < 150) {
bestStrategicValue = strategicValue;
bestStrategicPlatform = platform;
}
}
}
// Prefer strategic platform over nearest if available
var targetPlatform = bestStrategicPlatform || nearestPlatform;
if (targetPlatform) {
// Aggressive dive towards platform
var dx = targetPlatform.x - self.x;
var dy = targetPlatform.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
self.x += dx / distance * (chaseSpeed + 1);
self.y += dy / distance * (chaseSpeed + 0.8);
}
}
// Shoot projectiles at player
if (self.shootCooldown <= 0 && distanceToPlayer < 200) {
self.shootAtPlayer();
self.shootCooldown = 90; // 1.5 seconds
}
} else {
// Patrol movement
self.x += self.speed * self.direction;
if (self.x < 50 || self.x > 1998) {
self.direction *= -1;
}
// Occasionally move towards platforms while patrolling
if (Math.random() < 0.003) {
// Random platform seeking
var randomPlatform = platforms[Math.floor(Math.random() * platforms.length)];
if (randomPlatform && Math.abs(randomPlatform.x - self.x) < 300) {
var dx = randomPlatform.x - self.x;
var dy = randomPlatform.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 50) {
// Don't get too close
self.x += dx / distance * self.speed * 0.5;
self.y += dy / distance * self.speed * 0.3;
}
}
}
}
// Update cooldowns
if (self.shootCooldown > 0) {
self.shootCooldown--;
}
self.animationTick++;
// Face direction
if (self.direction > 0) {
body.scaleX = 1;
leftWing.scaleX = 1;
rightWing.scaleX = 1;
} else {
body.scaleX = -1;
leftWing.scaleX = -1;
rightWing.scaleX = -1;
}
};
self.shootAtPlayer = function () {
var bullet = new EnemyBullet();
bullet.x = self.x;
bullet.y = self.y;
// Calculate direction to player
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
bullet.velocityX = dx / distance * 6;
bullet.velocityY = dy / distance * 6;
enemyBullets.push(bullet);
game.addChild(bullet);
LK.getSound('attack').play();
};
self.takeDamage = function (damage) {
self.health -= damage;
// Update health bar
var healthPercent = Math.max(0, self.health / self.maxHealth);
healthBarFill.width = 56 * healthPercent;
if (healthPercent > 0.6) {
healthBarFill.tint = 0x00FF00;
} else if (healthPercent > 0.3) {
healthBarFill.tint = 0xFFFF00;
} else {
healthBarFill.tint = 0xFF0000;
}
// Flash effect
var originalTint = body.tint; // Store original skin color
tween(body, {
tint: 0xFFFFFF
}, {
duration: 100,
onFinish: function onFinish() {
tween(body, {
tint: originalTint // Restore original skin color
}, {
duration: 100
});
}
});
LK.getSound('enemy_hit').play();
if (self.health <= 0) {
LK.getSound('enemy_death').play();
self.destroy();
return true;
}
return false;
};
return self;
});
var Platform = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('platform', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
var Projectile = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('projectile', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocityX = 0;
self.velocityY = 0;
self.lifetime = 180; // 3 seconds at 60fps
self.update = function () {
self.x += self.velocityX;
self.y += self.velocityY;
self.lifetime--;
// Calculate distance traveled from start position
if (self.startX === undefined) {
self.startX = self.x;
self.startY = self.y;
}
var distanceTraveled = Math.sqrt(Math.pow(self.x - self.startX, 2) + Math.pow(self.y - self.startY, 2));
var maxRange = 350; // Short range limit for projectiles
// Remove if lifetime expired, off screen, or exceeded range
if (self.lifetime <= 0 || self.x < -50 || self.x > 2098 || self.y > 2800 || distanceTraveled > maxRange) {
self.destroy();
}
};
return self;
});
var ShadowBoss = Container.expand(function () {
var self = Container.call(this);
// Apply selected boss skin for shadow boss
var skinColor = storage.selectedBossSkin || 'default';
var shadowBossSkinColors = {
'default': {
main: 0x2F2F2F,
glow: 0x8A2BE2
},
'crimson': {
main: 0x8B0000,
glow: 0xFF0000
},
'shadow': {
main: 0x1C1C1C,
glow: 0x4B0082
},
'golden': {
main: 0xB8860B,
glow: 0xFFD700
},
'emerald': {
main: 0x006400,
glow: 0x00FF00
},
'cyber': {
main: 0x008B8B,
glow: 0x00FFFF
}
};
var currentSkin = shadowBossSkinColors[skinColor] || shadowBossSkinColors['default'];
var graphics = self.attachAsset('boss', {
anchorX: 0.5,
anchorY: 1.0,
tint: currentSkin.main
});
// Health bar
var healthBarBg = self.attachAsset('platform', {
width: 160,
height: 20,
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -220,
tint: 0x000000
});
var healthBarFill = self.attachAsset('platform', {
width: 156,
height: 16,
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -220,
tint: currentSkin.glow || 0x8A2BE2
});
self.health = 200;
self.maxHealth = 200;
self.velocityX = 0;
self.velocityY = 0;
self.onGround = false;
self.speed = 4;
self.direction = 1;
self.attackCooldown = 0;
self.teleportCooldown = 0;
self.animationTick = 0;
self.phase = 1;
self.update = function () {
// Apply gravity
if (!self.onGround) {
self.velocityY += 0.8;
}
var distanceToPlayer = Math.abs(self.x - player.x);
var healthPercent = self.health / self.maxHealth;
// Teleport ability
if (self.teleportCooldown <= 0 && distanceToPlayer > 300) {
self.teleportToPlayer();
self.teleportCooldown = 300;
}
// Shadow projectile attack
if (self.attackCooldown <= 0) {
self.shadowBlast();
self.attackCooldown = healthPercent > 0.5 ? 150 : 100;
}
// Movement
if (player.x > self.x) {
self.direction = 1;
self.velocityX = self.speed;
} else {
self.direction = -1;
self.velocityX = -self.speed;
}
// Apply velocity
self.x += self.velocityX;
self.y += self.velocityY;
self.onGround = false;
// Update cooldowns
if (self.attackCooldown > 0) {
self.attackCooldown--;
}
if (self.teleportCooldown > 0) {
self.teleportCooldown--;
}
self.animationTick++;
// Shadow flickering effect
graphics.alpha = 0.7 + Math.sin(self.animationTick * 0.1) * 0.3;
graphics.scaleX = self.direction > 0 ? 1 : -1;
};
self.teleportToPlayer = function () {
// Fade out
tween(graphics, {
alpha: 0
}, {
duration: 200,
onFinish: function onFinish() {
// Teleport behind player
self.x = player.x + (Math.random() > 0.5 ? 200 : -200);
self.y = player.y;
// Fade in
tween(graphics, {
alpha: 0.7
}, {
duration: 200
});
}
});
};
self.shadowBlast = function () {
for (var i = 0; i < 3; i++) {
var bullet = new EnemyBullet();
bullet.x = self.x;
bullet.y = self.y - 100;
var angle = (i - 1) * 0.8;
bullet.velocityX = Math.cos(angle) * 6 * self.direction;
bullet.velocityY = Math.sin(angle) * 6 - 3;
// Make shadow bullets darker
bullet.tint = 0x4B0082;
enemyBullets.push(bullet);
game.addChild(bullet);
}
LK.getSound('shadow_boss_attack').play();
};
self.takeDamage = function (damage) {
self.health -= damage;
var healthPercent = Math.max(0, self.health / self.maxHealth);
healthBarFill.width = 156 * healthPercent;
// Flash effect
tween(graphics, {
tint: 0xFFFFFF
}, {
duration: 150,
onFinish: function onFinish() {
tween(graphics, {
tint: 0x2F2F2F
}, {
duration: 150
});
}
});
LK.getSound('enemy_hit').play();
if (self.health <= 0) {
LK.getSound('enemy_death').play();
self.destroy();
return true;
}
return false;
};
return self;
});
var Stickman = Container.expand(function () {
var self = Container.call(this);
// Get selected skin and determine asset and tint
var selectedSkin = storage.selectedSkin || 'default';
var skinAssetMap = {
'default': {
asset: 'warrior',
tint: 0xFFFFFF
},
'red': {
asset: 'warrior_red',
tint: 0xFF4444
},
'blue': {
asset: 'warrior_blue',
tint: 0x4444FF
},
'green': {
asset: 'warrior_green',
tint: 0x44FF44
},
'purple': {
asset: 'warrior_purple',
tint: 0x8844FF
},
'gold': {
asset: 'warrior_gold',
tint: 0xFFD700
},
'orange': {
asset: 'warrior_orange',
tint: 0xFF8844
},
'cyan': {
asset: 'warrior_cyan',
tint: 0x44FFFF
},
'magenta': {
asset: 'warrior_magenta',
tint: 0xFF44FF
},
'silver': {
asset: 'warrior_silver',
tint: 0xC0C0C0
},
'lime': {
asset: 'warrior_lime',
tint: 0x88FF44
},
'bronze': {
asset: 'warrior_bronze',
tint: 0xCD7F32
}
};
var skinConfig = skinAssetMap[selectedSkin] || skinAssetMap['default'];
// Create detailed warrior with body parts for enhanced animations using selected skin
var warriorBody = self.attachAsset(skinConfig.asset, {
anchorX: 0.5,
anchorY: 1.0,
x: 0,
y: 0,
tint: skinConfig.tint
});
// Create separate limbs for detailed animation
var leftArm = self.attachAsset('enemy_limb', {
anchorX: 0.5,
anchorY: 0,
x: -15,
y: -80,
tint: 0x8B4513
});
var rightArm = self.attachAsset('enemy_limb', {
anchorX: 0.5,
anchorY: 0,
x: 15,
y: -80,
tint: 0x8B4513
});
var leftLeg = self.attachAsset('enemy_limb', {
anchorX: 0.5,
anchorY: 0,
x: -8,
y: -40,
height: 40,
tint: 0x654321
});
var rightLeg = self.attachAsset('enemy_limb', {
anchorX: 0.5,
anchorY: 0,
x: 8,
y: -40,
height: 40,
tint: 0x654321
});
// No sword - warrior fights with hands
// Movement properties
self.velocityX = 0;
self.velocityY = 0;
self.onGround = false;
self.speed = 8;
self.jumpPower = -18;
self.health = 100;
self.maxHealth = 100;
self.facingRight = true;
// Combat properties
self.canAttack = true;
self.attackCooldown = 0;
self.lastAttackTime = 0;
// Ammunition properties
self.maxAmmo = 5;
self.currentAmmo = 5;
self.reloadTime = 180; // 3 seconds at 60fps
self.timeSinceLastShot = 0;
// Animation properties
self.animationTick = 0;
self.isAttacking = false;
self.isJumping = false;
self.wasOnGround = true;
self.update = function () {
// Apply gravity
if (!self.onGround) {
self.velocityY += 0.8;
}
// Apply velocity
self.x += self.velocityX;
self.y += self.velocityY;
// Apply friction
self.velocityX *= 0.85;
// Reset ground detection
self.onGround = false;
// Reset double jump when touching ground later in collision detection
// Update attack cooldown
if (self.attackCooldown > 0) {
self.attackCooldown--;
}
// Update ammunition reload system
self.timeSinceLastShot++;
if (self.currentAmmo < self.maxAmmo && self.timeSinceLastShot >= self.reloadTime) {
self.currentAmmo++;
self.timeSinceLastShot = 0;
// Update ammunition display when reloading
if (ammoText) {
ammoText.setText('Arrows: ' + self.currentAmmo + '/' + self.maxAmmo);
ammoText.tint = self.currentAmmo > 0 ? 0xFFFFFF : 0xFF4444;
}
}
// Animation updates
self.animationTick++;
// Check if jumping state changed
if (!self.onGround && self.wasOnGround) {
self.isJumping = true;
}
if (self.onGround && !self.wasOnGround) {
self.isJumping = false;
}
self.wasOnGround = self.onGround;
// Handle enhanced animations with detailed warrior body parts and sword movements
if (self.isAttacking) {
// Attack animation is handled in attack method - keep sword position
} else if (self.isJumping || !self.onGround) {
// Enhanced jump animation with dynamic rotation and detailed limb movement
var jumpPhase = self.velocityY < 0 ? 0 : 1; // 0 for going up, 1 for falling
if (jumpPhase === 0) {
// Going up - dynamic backward tilt based on jump velocity
var tiltAmount = Math.min(Math.abs(self.velocityY) * 0.02, 0.4);
warriorBody.rotation = -tiltAmount;
// Slight scale animation for jump power
warriorBody.scaleY = 1.1 - Math.abs(self.velocityY) * 0.005;
// Detailed leg positioning during upward jump - legs bent for power
leftLeg.rotation = -0.3;
rightLeg.rotation = -0.2;
leftLeg.y = -35;
rightLeg.y = -35;
// Arm positioning during jump - spread for balance
leftArm.rotation = -0.4;
rightArm.rotation = 0.2;
// No sword - hands positioned during jump for balance
} else {
// Falling down - forward tilt increases with fall speed
var fallTilt = Math.min(self.velocityY * 0.01, 0.3);
warriorBody.rotation = fallTilt;
// Slight stretch when falling fast
warriorBody.scaleY = 1 + self.velocityY * 0.002;
// Detailed leg positioning during fall - preparing for landing
leftLeg.rotation = 0.2;
rightLeg.rotation = 0.1;
leftLeg.y = -38;
rightLeg.y = -38;
// Arm positioning for landing preparation
leftArm.rotation = -0.2;
rightArm.rotation = 0.3;
// No sword - hands positioned for landing
// Add landing preparation animation when close to ground
if (self.velocityY > 8) {
tween(warriorBody, {
scaleY: 0.95
}, {
duration: 100,
easing: tween.easeOut
});
tween(leftLeg, {
rotation: 0.4,
y: -42
}, {
duration: 100,
easing: tween.easeOut
});
tween(rightLeg, {
rotation: 0.3,
y: -42
}, {
duration: 100,
easing: tween.easeOut
});
}
}
} else if (Math.abs(self.velocityX) > 0.1) {
// Enhanced walking/running animation with detailed warrior body parts and realistic limb movement
var walkSpeed = Math.abs(self.velocityX) > 4 ? 0.4 : 0.3; // Faster animation for running
var walkCycle = Math.sin(self.animationTick * walkSpeed);
var walkCycleDouble = Math.sin(self.animationTick * walkSpeed * 2);
var walkCycleOffset = Math.sin(self.animationTick * walkSpeed + Math.PI);
// Dynamic rotation based on movement speed
var speedFactor = Math.min(Math.abs(self.velocityX) / self.speed, 1);
var isRunning = Math.abs(self.velocityX) > 4;
warriorBody.rotation = walkCycle * (isRunning ? 0.12 : 0.08) * speedFactor;
// Vertical bob with speed-based intensity - more pronounced when running
warriorBody.y = Math.abs(walkCycleDouble) * (isRunning ? 6 : 4) * speedFactor;
// Subtle scale animation for dynamic feel
warriorBody.scaleY = 1 - Math.abs(walkCycleDouble) * (isRunning ? 0.03 : 0.02) * speedFactor;
// Slight horizontal sway
warriorBody.x = walkCycle * (isRunning ? 3 : 2) * speedFactor;
// Detailed leg animation - alternating steps with realistic movement
var leftLegCycle = Math.sin(self.animationTick * walkSpeed);
var rightLegCycle = Math.sin(self.animationTick * walkSpeed + Math.PI);
// Left leg movement
leftLeg.rotation = leftLegCycle * (isRunning ? 0.6 : 0.4);
leftLeg.y = -40 + Math.abs(leftLegCycle) * (isRunning ? 8 : 5);
// Right leg movement (opposite phase)
rightLeg.rotation = rightLegCycle * (isRunning ? 0.6 : 0.4);
rightLeg.y = -40 + Math.abs(rightLegCycle) * (isRunning ? 8 : 5);
// Detailed arm animation - natural swinging motion opposite to legs
leftArm.rotation = rightLegCycle * (isRunning ? 0.5 : 0.3);
leftArm.y = -80 + Math.abs(rightLegCycle) * (isRunning ? 4 : 2);
rightArm.rotation = leftLegCycle * (isRunning ? 0.3 : 0.2); // Right arm holds sword, less movement
rightArm.y = -80 + Math.abs(leftLegCycle) * (isRunning ? 3 : 1);
// Both arms swing naturally during movement
// Add realistic stride animation using tween for smoother transitions
if (Math.floor(self.animationTick * walkSpeed) !== Math.floor((self.animationTick - 1) * walkSpeed)) {
// Trigger on each step cycle for enhanced leg animation
var stepDirection = leftLegCycle > 0 ? 1 : -1;
tween(warriorBody, {
scaleY: isRunning ? 0.96 : 0.98
}, {
duration: isRunning ? 80 : 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(warriorBody, {
scaleY: isRunning ? 1.04 : 1.02
}, {
duration: isRunning ? 80 : 100,
easing: tween.easeIn
});
}
});
}
// Add slight lean forward when walking/running
var leanDirection = self.facingRight ? 1 : -1;
warriorBody.rotation += leanDirection * speedFactor * (isRunning ? 0.08 : 0.05);
} else {
// Enhanced idle animation with breathing effect and detailed body part movement
var breathCycle = Math.sin(self.animationTick * 0.05);
var idleCycle = Math.sin(self.animationTick * 0.03);
var weightShiftCycle = Math.sin(self.animationTick * 0.02);
warriorBody.rotation = breathCycle * 0.01;
warriorBody.y = breathCycle * 1;
warriorBody.scaleY = 1 + breathCycle * 0.01;
warriorBody.x = 0;
// Detailed idle leg positioning with subtle weight shifting
leftLeg.rotation = weightShiftCycle * 0.08;
rightLeg.rotation = -weightShiftCycle * 0.06;
leftLeg.y = -40 + Math.abs(idleCycle) * 1;
rightLeg.y = -40 + Math.abs(weightShiftCycle) * 1;
// Detailed idle arm positioning with breathing
leftArm.rotation = breathCycle * 0.03;
leftArm.y = -80 + breathCycle * 0.5;
rightArm.rotation = breathCycle * 0.02; // Right arm holds sword
rightArm.y = -80 + breathCycle * 0.3;
// Arms in natural idle position with breathing
// Add periodic subtle repositioning animation
if (self.animationTick % 180 === 0) {
// Every 3 seconds - subtle weight shift
var shiftDirection = Math.random() > 0.5 ? 1 : -1;
tween(leftLeg, {
rotation: shiftDirection * 0.1
}, {
duration: 300,
easing: tween.easeInOut
});
tween(rightLeg, {
rotation: -shiftDirection * 0.08
}, {
duration: 300,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(leftLeg, {
rotation: 0
}, {
duration: 500,
easing: tween.easeOut
});
tween(rightLeg, {
rotation: 0
}, {
duration: 500,
easing: tween.easeOut
});
}
});
}
}
// Face direction with smooth transition for all body parts
if (self.facingRight) {
warriorBody.scaleX = 1;
leftArm.scaleX = 1;
rightArm.scaleX = 1;
leftLeg.scaleX = 1;
rightLeg.scaleX = 1;
} else {
warriorBody.scaleX = -1;
leftArm.scaleX = -1;
rightArm.scaleX = -1;
leftLeg.scaleX = -1;
rightLeg.scaleX = -1;
}
// Keep player in bounds for horizontal layout
if (self.x < 30) {
self.x = 30;
}
if (self.x > 2018) {
self.x = 2018;
}
// Reset skew if character is not moving or attacking
if (Math.abs(self.velocityX) < 0.1 && !self.isAttacking && !self.isJumping) {
// Smoothly reset skew values
if (Math.abs(warriorBody.skewX) > 0.001) {
warriorBody.skewX *= 0.9;
}
if (Math.abs(warriorBody.skewY) > 0.001) {
warriorBody.skewY *= 0.9;
}
}
};
self.moveLeft = function () {
self.velocityX = -self.speed;
if (self.facingRight) {
// Add quick turn animation when changing direction
self.facingRight = false;
tween(warriorBody, {
scaleX: -1.2,
skewX: 0.1
}, {
duration: 100,
onFinish: function onFinish() {
tween(warriorBody, {
scaleX: -1,
skewX: 0
}, {
duration: 100
});
}
});
// No sword position changes needed
} else {
self.facingRight = false;
}
// Add quick leg push animation for movement start
tween(warriorBody, {
skewY: -0.05
}, {
duration: 50,
onFinish: function onFinish() {
tween(warriorBody, {
skewY: 0
}, {
duration: 100
});
}
});
};
self.moveRight = function () {
self.velocityX = self.speed;
if (!self.facingRight) {
// Add quick turn animation when changing direction
self.facingRight = true;
tween(warriorBody, {
scaleX: 1.2,
skewX: -0.1
}, {
duration: 100,
onFinish: function onFinish() {
tween(warriorBody, {
scaleX: 1,
skewX: 0
}, {
duration: 100
});
}
});
// No sword position changes needed
} else {
self.facingRight = true;
}
// Add quick leg push animation for movement start
tween(warriorBody, {
skewY: 0.05
}, {
duration: 50,
onFinish: function onFinish() {
tween(warriorBody, {
skewY: 0
}, {
duration: 100
});
}
});
};
self.jump = function () {
console.log("Jump called! onGround:", self.onGround, "velocityY:", self.velocityY);
if (self.onGround || Math.abs(self.velocityY) < 2) {
// First jump with squash animation
self.velocityY = self.jumpPower;
self.onGround = false;
LK.getSound('jump').play();
// Enhanced squash and stretch animation for jump with sword movement
tween(warriorBody, {
scaleY: 0.7,
scaleX: self.facingRight ? 1.3 : -1.3
}, {
duration: 100,
onFinish: function onFinish() {
tween(warriorBody, {
scaleY: 1.2,
scaleX: self.facingRight ? 0.9 : -0.9
}, {
duration: 150,
onFinish: function onFinish() {
tween(warriorBody, {
scaleY: 1,
scaleX: self.facingRight ? 1 : -1
}, {
duration: 200
});
}
});
}
});
// Arms raised during jump for balance
tween(leftArm, {
y: -85,
rotation: -0.4
}, {
duration: 100,
onFinish: function onFinish() {
tween(leftArm, {
y: -80,
rotation: 0
}, {
duration: 300
});
}
});
console.log("Jump executed! New velocityY:", self.velocityY);
} else if (self.canDoubleJump && !self.hasUsedDoubleJump) {
// Double jump with spin animation
self.velocityY = self.jumpPower * 0.8;
self.hasUsedDoubleJump = true;
self.canDoubleJump = false;
LK.getSound('jump').play();
// Enhanced spin animation for double jump with sword trail effect
var startRotation = warriorBody.rotation;
tween(warriorBody, {
rotation: startRotation + (self.facingRight ? Math.PI * 2 : -Math.PI * 2)
}, {
duration: 400,
onFinish: function onFinish() {
warriorBody.rotation = 0;
}
});
// Arms spinning during double jump
tween(leftArm, {
rotation: leftArm.rotation + (self.facingRight ? Math.PI * 2 : -Math.PI * 2)
}, {
duration: 400,
onFinish: function onFinish() {
leftArm.rotation = 0;
}
});
tween(rightArm, {
rotation: rightArm.rotation + (self.facingRight ? Math.PI * 2 : -Math.PI * 2)
}, {
duration: 400,
onFinish: function onFinish() {
rightArm.rotation = 0;
}
});
console.log("Double jump executed!");
} else {
console.log("Cannot jump - not on ground and no double jump available");
}
};
self.attack = function () {
if (self.attackCooldown <= 0) {
self.attackCooldown = 30;
self.isAttacking = true;
LK.getSound('attack').play();
// Hand-to-hand combat - punch animation
var originalWarriorRotation = warriorBody.rotation;
// Wind up phase - pull right arm back for powerful punch
tween(rightArm, {
rotation: -0.8,
x: self.facingRight ? 5 : -5,
y: -75
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
// Powerful punch forward
tween(rightArm, {
rotation: 0.6,
x: self.facingRight ? 25 : -25,
y: -80
}, {
duration: 200,
easing: tween.easeIn,
onFinish: function onFinish() {
// Recovery - return arm to normal position
tween(rightArm, {
rotation: 0,
x: self.facingRight ? 15 : -15,
y: -80
}, {
duration: 250,
easing: tween.easeInOut,
onFinish: function onFinish() {
self.isAttacking = false;
}
});
}
});
// Warrior body movement during punch
tween(warriorBody, {
rotation: originalWarriorRotation + (self.facingRight ? 0.2 : -0.2),
skewY: self.facingRight ? 0.1 : -0.1
}, {
duration: 150,
onFinish: function onFinish() {
tween(warriorBody, {
rotation: originalWarriorRotation - (self.facingRight ? 0.1 : -0.1),
skewY: self.facingRight ? -0.05 : 0.05
}, {
duration: 200,
onFinish: function onFinish() {
tween(warriorBody, {
rotation: originalWarriorRotation,
skewY: 0
}, {
duration: 250
});
}
});
}
});
}
});
// Add warrior body lean and step forward during punch
LK.setTimeout(function () {
// Dynamic body movement during attack
tween(warriorBody, {
scaleX: self.facingRight ? 1.1 : -1.1,
x: self.facingRight ? 8 : -8
}, {
duration: 100,
onFinish: function onFinish() {
tween(warriorBody, {
scaleX: self.facingRight ? 1 : -1,
x: 0
}, {
duration: 150
});
}
});
}, 150);
// Check for enemy hits during forward punch
LK.setTimeout(function () {
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
// Calculate punch position based on warrior's facing direction and arm extension
var punchReach = 80; // Increased reach for better hit detection
var punchX = self.x + (self.facingRight ? punchReach : -punchReach);
var punchY = self.y - 60; // Adjusted height to match enemy center
// Calculate distance from punch position to enemy
var distanceToEnemy = Math.abs(punchX - enemy.x);
var verticalDistance = Math.abs(punchY - enemy.y);
// Improved hit-box - larger rectangular area in front of warrior
var hitBoxWidth = 70; // Increased width of punch hit area
var hitBoxHeight = 80; // Increased height of punch hit area
if (distanceToEnemy < hitBoxWidth && verticalDistance < hitBoxHeight) {
// Additional check: enemy must be in front of warrior
var enemyInFront = self.facingRight ? enemy.x > self.x : enemy.x < self.x;
if (enemyInFront) {
if (enemy.takeDamage(25)) {
// Enemy damaged - check if destroyed
enemies.splice(i, 1);
LK.setScore(LK.getScore() + 100);
storage.coins += 5; // Reward coins for melee kills
scoreText.setText('Score: ' + LK.getScore());
}
// Enhanced knockback effect based on punch direction
var knockbackDirection = self.facingRight ? 1 : -1;
enemy.velocityX += knockbackDirection * 10;
enemy.velocityY = -4; // Slightly stronger upward knockback
}
}
}
}, 120);
}
};
self.shootArrow = function () {
if (self.attackCooldown <= 0 && self.currentAmmo > 0) {
self.attackCooldown = 20; // Shorter cooldown for ranged attacks
self.currentAmmo--; // Consume ammunition
self.timeSinceLastShot = 0; // Reset reload timer
LK.getSound('bow_shoot').play();
// Update ammunition display immediately
if (ammoText) {
ammoText.setText('Arrows: ' + self.currentAmmo + '/' + self.maxAmmo);
ammoText.tint = self.currentAmmo > 0 ? 0xFFFFFF : 0xFF4444;
}
// Create arrow
var arrow = new Arrow();
arrow.x = self.x + (self.facingRight ? 40 : -40);
arrow.y = self.y - 80;
// Set arrow velocity based on facing direction
var arrowSpeed = 12;
arrow.velocityX = self.facingRight ? arrowSpeed : -arrowSpeed;
arrow.velocityY = 0; // Straight horizontal trajectory
// Add arrow to game
arrows.push(arrow);
game.addChild(arrow);
// Bow shooting animation - pull left arm back then forward
var originalLeftArmX = leftArm.x;
var originalLeftArmY = leftArm.y;
var originalLeftArmRotation = leftArm.rotation;
// Pull back animation (drawing the bow)
tween(leftArm, {
rotation: -0.5,
x: self.facingRight ? -20 : 20,
y: -85
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
// Release animation (shooting the arrow)
tween(leftArm, {
rotation: 0.3,
x: self.facingRight ? -10 : 10,
y: -75
}, {
duration: 150,
easing: tween.easeIn,
onFinish: function onFinish() {
// Return to normal position
tween(leftArm, {
rotation: originalLeftArmRotation,
x: originalLeftArmX,
y: originalLeftArmY
}, {
duration: 200,
easing: tween.easeInOut
});
}
});
}
});
// Slight body lean during bow shot
var originalWarriorRotation = warriorBody.rotation;
tween(warriorBody, {
rotation: originalWarriorRotation + (self.facingRight ? -0.1 : 0.1),
x: self.facingRight ? -5 : 5
}, {
duration: 100,
onFinish: function onFinish() {
tween(warriorBody, {
rotation: originalWarriorRotation,
x: 0
}, {
duration: 200
});
}
});
}
};
self.takeDamage = function (damage) {
self.health -= damage;
LK.getSound('hit').play();
// Update health bar if it exists
if (healthText && healthText.healthBarFill) {
var healthPercent = Math.max(0, self.health / self.maxHealth);
healthText.healthBarFill.width = 210 * healthPercent;
healthText.healthBarFill.tint = self.health < 30 ? 0xFF0000 : 0x00FF00;
}
// Enhanced damage flash effect on warrior and sword
var originalSkinTint = skinConfig.tint; // Store the original skin tint
tween(warriorBody, {
tint: 0xFF0066
}, {
duration: 150,
onFinish: function onFinish() {
tween(warriorBody, {
tint: originalSkinTint // Restore original skin tint instead of white
}, {
duration: 150
});
}
});
// Flash arms as well
tween(leftArm, {
tint: 0xFF0066
}, {
duration: 150,
onFinish: function onFinish() {
tween(leftArm, {
tint: 0x8B4513
}, {
duration: 150
});
}
});
tween(rightArm, {
tint: 0xFF0066
}, {
duration: 150,
onFinish: function onFinish() {
tween(rightArm, {
tint: 0x8B4513
}, {
duration: 150
});
}
});
if (self.health <= 0) {
LK.showGameOver();
}
};
return self;
});
var StickmanEnemy = Container.expand(function () {
var self = Container.call(this);
// Apply selected enemy skin with specific assets
var skinColor = storage.selectedEnemySkin || 'default';
var skinAssetMap = {
'default': {
head: 'enemy_head',
body: 'enemy_body',
limb: 'enemy_limb',
sword: 'enemy_sword'
},
'dark': {
head: 'enemy_dark_head',
body: 'enemy_dark_body',
limb: 'enemy_dark_limb',
sword: 'enemy_dark_sword'
},
'green': {
head: 'enemy_green_head',
body: 'enemy_green_body',
limb: 'enemy_green_limb',
sword: 'enemy_green_sword'
},
'purple': {
head: 'enemy_purple_head',
body: 'enemy_purple_body',
limb: 'enemy_purple_limb',
sword: 'enemy_purple_sword'
},
'orange': {
head: 'enemy_orange_head',
body: 'enemy_orange_body',
limb: 'enemy_orange_limb',
sword: 'enemy_orange_sword'
},
'blue': {
head: 'enemy_blue_head',
body: 'enemy_blue_body',
limb: 'enemy_blue_limb',
sword: 'enemy_blue_sword'
}
};
var currentSkinAssets = skinAssetMap[skinColor] || skinAssetMap['default'];
// Create stickman body parts with skin-specific assets
var head = self.attachAsset(currentSkinAssets.head, {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -65
});
var body = self.attachAsset(currentSkinAssets.body, {
anchorX: 0.5,
anchorY: 0,
x: 0,
y: -50
});
var leftArm = self.attachAsset(currentSkinAssets.limb, {
anchorX: 0.5,
anchorY: 0,
x: -10,
y: -40
});
var rightArm = self.attachAsset(currentSkinAssets.limb, {
anchorX: 0.5,
anchorY: 0,
x: 10,
y: -40
});
var leftLeg = self.attachAsset(currentSkinAssets.limb, {
anchorX: 0.5,
anchorY: 0,
x: -5,
y: -20
});
var rightLeg = self.attachAsset(currentSkinAssets.limb, {
anchorX: 0.5,
anchorY: 0,
x: 5,
y: -20
});
var sword = self.attachAsset(currentSkinAssets.sword, {
anchorX: 0.5,
anchorY: 1,
x: 15,
y: -30
});
self.velocityX = 0;
self.velocityY = 0;
self.health = 50;
self.maxHealth = 50;
// Create health bar background
var healthBarBg = self.attachAsset('platform', {
width: 60,
height: 8,
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -90,
tint: 0x000000
});
// Create health bar fill
var healthBarFill = self.attachAsset('platform', {
width: 56,
height: 6,
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -90,
tint: 0x00FF00
});
self.speed = 1.5;
self.direction = 1;
self.onGround = false;
self.attackRange = 80;
self.attackCooldown = 0;
self.animationTick = 0;
self.isAttacking = false;
self.lastPlayerDistance = 999;
self.update = function () {
// Apply gravity
if (!self.onGround) {
self.velocityY += 0.8;
}
// AI behavior - chase player if close enough with enhanced range detection
var distanceToPlayer = Math.abs(self.x - player.x);
var verticalDistance = Math.abs(self.y - player.y);
var attackRange = 300; // Increased detection range
var aggressiveRange = 150; // Close range for aggressive behavior
if (distanceToPlayer < attackRange && verticalDistance < 150) {
// Enhanced chase behavior with speed boost when close
var isInAggressiveRange = distanceToPlayer < aggressiveRange;
var chaseSpeed = isInAggressiveRange ? self.speed * 1.5 : self.speed;
// Chase player
if (player.x > self.x) {
self.direction = 1;
self.velocityX = chaseSpeed;
} else {
self.direction = -1;
self.velocityX = -chaseSpeed;
}
// Aggressive platform jumping when pursuing player
if (self.onGround && (verticalDistance > 60 || Math.abs(player.y - self.y) > 50)) {
// Look for platforms to reach player more aggressively
var nearestPlatform = null;
var nearestDistance = Infinity;
var targetDirection = player.x > self.x ? 1 : -1;
// Check all platforms for strategic positioning
for (var p = 0; p < platforms.length; p++) {
var platform = platforms[p];
var platformDistance = Math.abs(platform.x - self.x);
var platformToPlayerDistance = Math.abs(platform.x - player.x);
// Prefer platforms that are closer to player or provide better positioning
var strategicValue = platformDistance + platformToPlayerDistance * 0.5;
if (platform.y < self.y && platform.y > player.y - 100 && platformDistance < 400) {
if (strategicValue < nearestDistance) {
nearestDistance = strategicValue;
nearestPlatform = platform;
}
}
}
// Jump towards the platform or directly towards player
if (nearestPlatform) {
// Calculate jump direction towards platform
var jumpDirection = nearestPlatform.x > self.x ? 1 : -1;
self.velocityY = -16; // Stronger jump for pursuit
self.velocityX = jumpDirection * (self.speed + 3); // Extra horizontal velocity
self.onGround = false;
LK.getSound('jump').play();
} else if (verticalDistance > 100) {
// Direct jump towards player if no platforms available
self.velocityY = -14;
self.velocityX = targetDirection * (self.speed + 2);
self.onGround = false;
LK.getSound('jump').play();
}
}
// Attack if in range
if (distanceToPlayer < self.attackRange && self.attackCooldown <= 0) {
self.attackPlayer();
}
} else {
// Simple patrol movement
self.velocityX = self.speed * self.direction;
// Random jump towards platforms while patrolling
if (self.onGround && Math.random() < 0.005) {
// 0.5% chance per frame when on ground
// Look for platforms to jump to
var targetPlatform = null;
var patrolDirection = self.direction;
for (var p = 0; p < platforms.length; p++) {
var platform = platforms[p];
var platformDistance = Math.abs(platform.x - self.x);
var platformInDirection = patrolDirection > 0 ? platform.x > self.x : platform.x < self.x;
if (platformInDirection && platform.y < self.y && platformDistance < 200 && platformDistance > 50) {
targetPlatform = platform;
break;
}
}
if (targetPlatform) {
self.velocityY = -12; // Smaller jump for patrol
self.velocityX = patrolDirection * (self.speed + 1);
self.onGround = false;
}
}
}
// Apply velocity
self.x += self.velocityX;
self.y += self.velocityY;
// Reset ground detection
self.onGround = false;
// Reverse direction at edges
if (self.x < 50 || self.x > 1998) {
self.direction *= -1;
}
// Update attack cooldown
if (self.attackCooldown > 0) {
self.attackCooldown--;
}
// Animation
self.animationTick++;
if (!self.isAttacking) {
// Walking animation with more realistic movement
var walkSpeed = Math.abs(self.velocityX) > 0.1 ? 0.25 : 0.1;
var walkCycle = Math.sin(self.animationTick * walkSpeed);
var walkCycleOffset = Math.sin(self.animationTick * walkSpeed + Math.PI);
// Leg animation - alternate walking
leftLeg.rotation = walkCycle * 0.4;
rightLeg.rotation = walkCycleOffset * 0.4;
// Arm animation - opposite to legs (natural walking)
leftArm.rotation = walkCycleOffset * 0.3;
rightArm.rotation = walkCycle * 0.3;
// Body bob animation when walking
if (Math.abs(self.velocityX) > 0.1) {
body.y = -50 + Math.abs(Math.sin(self.animationTick * walkSpeed * 2)) * 2;
head.y = -65 + Math.abs(Math.sin(self.animationTick * walkSpeed * 2)) * 2;
} else {
// Return to normal position when not walking
body.y = -50;
head.y = -65;
}
}
// Face direction
if (self.direction > 0) {
head.scaleX = 1;
body.scaleX = 1;
leftArm.scaleX = 1;
rightArm.scaleX = 1;
leftLeg.scaleX = 1;
rightLeg.scaleX = 1;
sword.scaleX = 1;
sword.x = 15;
} else {
head.scaleX = -1;
body.scaleX = -1;
leftArm.scaleX = -1;
rightArm.scaleX = -1;
leftLeg.scaleX = -1;
rightLeg.scaleX = -1;
sword.scaleX = -1;
sword.x = -15;
}
self.lastPlayerDistance = distanceToPlayer;
};
self.attackPlayer = function () {
if (self.attackCooldown <= 0) {
self.attackCooldown = 120; // 2 seconds at 60fps
self.isAttacking = true;
// Sword attack animation - swing from back to front
tween(sword, {
rotation: -1.8
}, {
duration: 150,
onFinish: function onFinish() {
// Swing forward
tween(sword, {
rotation: 0.8
}, {
duration: 200,
onFinish: function onFinish() {
// Return to normal position
tween(sword, {
rotation: 0
}, {
duration: 250,
onFinish: function onFinish() {
self.isAttacking = false;
}
});
}
});
// Check if player is hit during forward swing (after 150ms delay)
LK.setTimeout(function () {
var distanceToPlayer = Math.abs(self.x - player.x);
if (distanceToPlayer < self.attackRange) {
player.takeDamage(10);
// Knockback effect
var knockbackDirection = player.x > self.x ? 1 : -1;
player.velocityX += knockbackDirection * 8;
}
}, 150);
}
});
}
};
self.takeDamage = function (damage) {
self.health -= damage;
// Update health bar
var healthPercent = Math.max(0, self.health / self.maxHealth);
healthBarFill.width = 56 * healthPercent;
// Change health bar color based on health
if (healthPercent > 0.6) {
healthBarFill.tint = 0x00FF00; // Green
} else if (healthPercent > 0.3) {
healthBarFill.tint = 0xFFFF00; // Yellow
} else {
healthBarFill.tint = 0xFF0000; // Red
}
// Damage flash effect on all body parts
var bodyParts = [head, body, leftArm, rightArm, leftLeg, rightLeg];
for (var i = 0; i < bodyParts.length; i++) {
var part = bodyParts[i];
tween(part, {
tint: 0xFFFFFF
}, {
duration: 100,
onFinish: function onFinish() {
tween(part, {
tint: 0xFF0000
}, {
duration: 100
});
}
});
}
if (self.health <= 0) {
self.destroy();
return true;
}
return false;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x001122,
// Dark digital blue background
width: 2732,
// Optimized for mobile landscape
height: 2048 // Optimized for mobile landscape
});
/****
* Game Code
****/
// Shadow Lord boss attack sound
// Fire Demon boss attack sound
// Purple Giant boss attack sound
// Load current level from storage
// Game state management
// StickmanEnemy skin variations
// FlyingEnemy skin variations
if (storage.currentLevel) {
currentLevel = storage.currentLevel;
}
var gameState = 'menu'; // 'menu', 'mapSelect', 'settings', 'playing', 'shop'
var shopContainer;
var currentShopCategory = 'guardior'; // Global variable for shop category state
var currentLevel = 1;
var enemyBullets = [];
// Input state variables
var leftPressed = false;
var rightPressed = false;
var currentTouchId = null;
// Level progression system - 3 levels + 1 boss, repeating
function getCurrentLevelConfig() {
var levelIndex = (currentLevel - 1) % 4;
var cycleNumber = Math.floor((currentLevel - 1) / 4);
var isBossLevel = levelIndex === 3;
if (isBossLevel) {
return getBossLevel(cycleNumber);
} else {
return getRegularLevel(levelIndex, cycleNumber);
}
}
function getRegularLevel(levelIndex, cycleNumber) {
var baseConfigs = [
// Level 1 theme - Forest Plains with detailed environment
{
name: "Forest Plains",
backgroundColor: 0x1a4d1a,
// Deeper forest green
musicTrack: 'menu_music',
basePlatforms: [{
x: 400,
y: 1800,
type: 'wooden',
// Wooden log platforms
tint: 0x8B4513
}, {
x: 800,
y: 1600,
type: 'stone',
tint: 0x696969
}, {
x: 1200,
y: 1700,
type: 'wooden',
tint: 0x8B4513
}, {
x: 1600,
y: 1500,
type: 'stone',
tint: 0x696969
}, {
x: 1900,
y: 1800,
type: 'wooden',
tint: 0x8B4513
}, {
x: 600,
y: 1450,
type: 'moss_covered',
tint: 0x556B2F
}, {
x: 1000,
y: 1350,
type: 'fallen_log',
tint: 0x654321
}, {
x: 1750,
y: 1400,
type: 'stone_slab',
tint: 0x708090
}],
decorations: [{
type: 'tree',
x: 300,
y: 1900,
tint: 0x228B22
}, {
type: 'tree',
x: 700,
y: 1900,
tint: 0x32CD32
}, {
type: 'tree',
x: 1100,
y: 1900,
tint: 0x228B22
}, {
type: 'tree',
x: 1500,
y: 1900,
tint: 0x32CD32
}, {
type: 'tree',
x: 1800,
y: 1900,
tint: 0x2E8B57
}, {
type: 'tree',
x: 200,
y: 1900,
tint: 0x006400
}, {
type: 'bush',
x: 450,
y: 1880,
tint: 0x006400
}, {
type: 'bush',
x: 850,
y: 1880,
tint: 0x228B22
}, {
type: 'bush',
x: 1250,
y: 1880,
tint: 0x32CD32
}, {
type: 'bush',
x: 1650,
y: 1880,
tint: 0x2E8B57
}, {
type: 'bush',
x: 750,
y: 1850,
tint: 0x3CB371
}, {
type: 'rock',
x: 1050,
y: 1920,
tint: 0x696969
}, {
type: 'rock',
x: 1750,
y: 1920,
tint: 0x808080
}, {
type: 'rock',
x: 350,
y: 1920,
tint: 0x778899
}, {
type: 'rock',
x: 1350,
y: 1920,
tint: 0x2F4F4F
}, {
type: 'flower_patch',
x: 500,
y: 1870,
tint: 0xFF69B4
}, {
type: 'flower_patch',
x: 900,
y: 1870,
tint: 0xFFB6C1
}, {
type: 'flower_patch',
x: 1300,
y: 1870,
tint: 0xFF1493
}, {
type: 'mushroom',
x: 650,
y: 1890,
tint: 0xFF6347
}, {
type: 'mushroom',
x: 1150,
y: 1890,
tint: 0xFF4500
}, {
type: 'mushroom',
x: 1550,
y: 1890,
tint: 0xDC143C
}, {
type: 'fallen_branch',
x: 550,
y: 1910,
tint: 0x8B4513
}, {
type: 'fallen_branch',
x: 950,
y: 1910,
tint: 0xA0522D
}, {
type: 'fallen_branch',
x: 1450,
y: 1910,
tint: 0x654321
}, {
type: 'ivy_patch',
x: 800,
y: 1550,
tint: 0x228B22
}, {
type: 'ivy_patch',
x: 1200,
y: 1650,
tint: 0x32CD32
}, {
type: 'vine_hanging',
x: 1000,
y: 1300,
tint: 0x6B8E23
}, {
type: 'vine_hanging',
x: 1600,
y: 1450,
tint: 0x9ACD32
}, {
type: 'bird_nest',
x: 400,
y: 1750,
tint: 0x8B4513
}, {
type: 'bird_nest',
x: 1700,
y: 1750,
tint: 0xA0522D
}, {
type: 'forest_shrine',
x: 1000,
y: 1850,
tint: 0x708090
}, {
type: 'wooden_sign',
x: 250,
y: 1850,
tint: 0x8B4513
}],
baseEnemies: [{
type: 'stickman',
x: 900,
y: 1550
}, {
type: 'stickman',
x: 1400,
y: 1650
}, {
type: 'flying',
x: 1200,
y: 1400
}]
},
// Level 2 theme - Sky Temple with floating elements
{
name: "Sky Temple",
backgroundColor: 0x1e3a8a,
// Deep sky blue
musicTrack: 'menu_music',
basePlatforms: [{
x: 300,
y: 1700,
type: 'crystal',
tint: 0x87CEEB
}, {
x: 600,
y: 1500,
type: 'marble',
tint: 0xF5F5DC
}, {
x: 900,
y: 1300,
type: 'crystal',
tint: 0x87CEEB
}, {
x: 1300,
y: 1200,
type: 'marble',
tint: 0xF5F5DC
}, {
x: 1700,
y: 1400,
type: 'crystal',
tint: 0x87CEEB
}, {
x: 2000,
y: 1600,
type: 'marble',
tint: 0xF5F5DC
}, {
x: 450,
y: 1350,
type: 'floating_crystal',
tint: 0x00CED1
}, {
x: 750,
y: 1150,
type: 'sky_marble',
tint: 0xE6E6FA
}, {
x: 1050,
y: 1050,
type: 'ethereal_platform',
tint: 0xB0E0E6
}, {
x: 1450,
y: 1350,
type: 'celestial_stone',
tint: 0x87CEFA
}],
decorations: [{
type: 'cloud',
x: 200,
y: 1000,
tint: 0xFFFFFF
}, {
type: 'cloud',
x: 800,
y: 800,
tint: 0xF0F8FF
}, {
type: 'cloud',
x: 1400,
y: 900,
tint: 0xFFFFFF
}, {
type: 'cloud',
x: 1800,
y: 700,
tint: 0xF5F5F5
}, {
type: 'cloud',
x: 500,
y: 600,
tint: 0xFFFAFA
}, {
type: 'cloud',
x: 1100,
y: 500,
tint: 0xF8F8FF
}, {
type: 'pillar',
x: 400,
y: 1750,
tint: 0xDDDDDD
}, {
type: 'pillar',
x: 1200,
y: 1550,
tint: 0xDDDDDD
}, {
type: 'pillar',
x: 1800,
y: 1650,
tint: 0xDDDDDD
}, {
type: 'pillar',
x: 700,
y: 1450,
tint: 0xE0E0E0
}, {
type: 'pillar',
x: 1500,
y: 1150,
tint: 0xD3D3D3
}, {
type: 'crystal',
x: 500,
y: 1450,
tint: 0x00FFFF
}, {
type: 'crystal',
x: 1100,
y: 1250,
tint: 0x00FFFF
}, {
type: 'crystal',
x: 350,
y: 1600,
tint: 0x40E0D0
}, {
type: 'crystal',
x: 1650,
y: 1300,
tint: 0x48D1CC
}, {
type: 'floating_shrine',
x: 900,
y: 1100,
tint: 0xB0C4DE
}, {
type: 'wind_chime',
x: 600,
y: 1300,
tint: 0xFFD700
}, {
type: 'wind_chime',
x: 1300,
y: 1000,
tint: 0xFFA500
}, {
type: 'celestial_orb',
x: 750,
y: 950,
tint: 0xDDA0DD
}, {
type: 'celestial_orb',
x: 1150,
y: 850,
tint: 0xEE82EE
}, {
type: 'celestial_orb',
x: 1550,
y: 1050,
tint: 0xDA70D6
}, {
type: 'sky_rune',
x: 250,
y: 1600,
tint: 0x9370DB
}, {
type: 'sky_rune',
x: 1950,
y: 1500,
tint: 0x8A2BE2
}, {
type: 'ethereal_gateway',
x: 1000,
y: 800,
tint: 0x6495ED
}, {
type: 'starlight_pool',
x: 800,
y: 1400,
tint: 0x87CEEB
}, {
type: 'starlight_pool',
x: 1400,
y: 1100,
tint: 0x87CEFA
}, {
type: 'divine_statue',
x: 600,
y: 1200,
tint: 0xF0F8FF
}, {
type: 'divine_statue',
x: 1600,
y: 1200,
tint: 0xE6E6FA
}, {
type: 'floating_lotus',
x: 450,
y: 1250,
tint: 0xFFB6C1
}, {
type: 'floating_lotus',
x: 1350,
y: 950,
tint: 0xFFC0CB
}],
baseEnemies: [{
type: 'flying',
x: 500,
y: 1400
}, {
type: 'stickman',
x: 1000,
y: 1250
}, {
type: 'flying',
x: 1500,
y: 1300
}, {
type: 'flying',
x: 800,
y: 1100
}]
},
// Level 3 theme - Desert Ruins with ancient structures
{
name: "Desert Ruins",
backgroundColor: 0x8B4513,
// Desert brown
musicTrack: 'menu_music',
basePlatforms: [{
x: 200,
y: 1900,
type: 'sandstone',
tint: 0xF4A460
}, {
x: 500,
y: 1700,
type: 'brick',
tint: 0xCD853F
}, {
x: 800,
y: 1400,
type: 'sandstone',
tint: 0xF4A460
}, {
x: 1200,
y: 1600,
type: 'brick',
tint: 0xCD853F
}, {
x: 1550,
y: 1300,
type: 'sandstone',
tint: 0xF4A460
}, {
x: 1900,
y: 1700,
type: 'brick',
tint: 0xCD853F
}, {
x: 650,
y: 1500,
type: 'ancient_stone',
tint: 0xBDB76B
}, {
x: 1050,
y: 1200,
type: 'weathered_brick',
tint: 0xD2691E
}, {
x: 1750,
y: 1450,
type: 'carved_platform',
tint: 0xBC8F8F
}],
decorations: [{
type: 'pyramid',
x: 150,
y: 1950,
tint: 0xDEB887
}, {
type: 'pyramid',
x: 1950,
y: 1950,
tint: 0xDEB887
}, {
type: 'pyramid',
x: 1000,
y: 1950,
tint: 0xD2B48C
}, {
type: 'column',
x: 400,
y: 1850,
tint: 0xD2B48C
}, {
type: 'column',
x: 900,
y: 1650,
tint: 0xD2B48C
}, {
type: 'column',
x: 1400,
y: 1750,
tint: 0xD2B48C
}, {
type: 'column',
x: 700,
y: 1550,
tint: 0xDDD8C4
}, {
type: 'column',
x: 1700,
y: 1550,
tint: 0xE6E0D4
}, {
type: 'obelisk',
x: 600,
y: 1800,
tint: 0xA0522D
}, {
type: 'obelisk',
x: 1600,
y: 1600,
tint: 0xA0522D
}, {
type: 'obelisk',
x: 300,
y: 1850,
tint: 0x8B4513
}, {
type: 'cactus',
x: 350,
y: 1920,
tint: 0x228B22
}, {
type: 'cactus',
x: 1750,
y: 1920,
tint: 0x228B22
}, {
type: 'cactus',
x: 850,
y: 1920,
tint: 0x2E8B57
}, {
type: 'cactus',
x: 1350,
y: 1920,
tint: 0x6B8E23
}, {
type: 'ancient_tomb',
x: 500,
y: 1850,
tint: 0x8B7355
}, {
type: 'ancient_tomb',
x: 1500,
y: 1750,
tint: 0x8B7D6B
}, {
type: 'hieroglyph_wall',
x: 250,
y: 1800,
tint: 0xDEB887
}, {
type: 'hieroglyph_wall',
x: 1850,
y: 1650,
tint: 0xD2B48C
}, {
type: 'sphinx_statue',
x: 800,
y: 1850,
tint: 0xF5DEB3
}, {
type: 'scarab_carving',
x: 450,
y: 1650,
tint: 0xDAA520
}, {
type: 'scarab_carving',
x: 1250,
y: 1550,
tint: 0xFFD700
}, {
type: 'ancient_vase',
x: 550,
y: 1680,
tint: 0xCD853F
}, {
type: 'ancient_vase',
x: 1150,
y: 1580,
tint: 0xD2691E
}, {
type: 'sand_dune',
x: 200,
y: 1900,
tint: 0xF5DEB3
}, {
type: 'sand_dune',
x: 600,
y: 1900,
tint: 0xF4A460
}, {
type: 'sand_dune',
x: 1000,
y: 1900,
tint: 0xDEB887
}, {
type: 'sand_dune',
x: 1400,
y: 1900,
tint: 0xD2B48C
}, {
type: 'sand_dune',
x: 1800,
y: 1900,
tint: 0xF5DEB3
}, {
type: 'temple_entrance',
x: 1100,
y: 1500,
tint: 0x8B7355
}, {
type: 'ankh_symbol',
x: 750,
y: 1350,
tint: 0xDAA520
}, {
type: 'ankh_symbol',
x: 1450,
y: 1250,
tint: 0xFFD700
}, {
type: 'desert_gem',
x: 650,
y: 1450,
tint: 0x32CD32
}, {
type: 'desert_gem',
x: 1350,
y: 1150,
tint: 0x00CED1
}],
baseEnemies: [{
type: 'stickman',
x: 600,
y: 1650
}, {
type: 'flying',
x: 1000,
y: 1300
}, {
type: 'stickman',
x: 1400,
y: 1250
}, {
type: 'flying',
x: 1750,
y: 1600
}, {
type: 'stickman',
x: 800,
y: 1350
}]
}];
var config = baseConfigs[levelIndex];
var scaledConfig = {
name: config.name + " " + (cycleNumber + 1),
backgroundColor: config.backgroundColor,
musicTrack: config.musicTrack,
platforms: [],
enemies: [],
decorations: []
};
// Scale platforms and add variety with enhanced details
for (var i = 0; i < config.basePlatforms.length; i++) {
var platform = config.basePlatforms[i];
scaledConfig.platforms.push({
x: platform.x + (cycleNumber * 50 - 25),
y: platform.y - cycleNumber * 30,
type: platform.type,
tint: platform.tint,
width: 200 + cycleNumber * 20,
// Larger platforms in higher cycles
height: 40 + cycleNumber * 5
});
}
// Add more detailed platforms for higher cycles
if (cycleNumber > 0) {
scaledConfig.platforms.push({
x: 250 + cycleNumber * 100,
y: 2350 - cycleNumber * 40,
type: 'enhanced',
tint: 0x666666,
width: 250,
height: 50
});
scaledConfig.platforms.push({
x: 1750 - cycleNumber * 100,
y: 2150 - cycleNumber * 20,
type: 'enhanced',
tint: 0x666666,
width: 250,
height: 50
});
}
// Scale and enhance decorations
if (config.decorations) {
for (var i = 0; i < config.decorations.length; i++) {
var decoration = config.decorations[i];
scaledConfig.decorations.push({
type: decoration.type,
x: decoration.x + (cycleNumber * 30 - 15),
y: decoration.y - cycleNumber * 20,
tint: decoration.tint,
scale: 1 + cycleNumber * 0.2 // Bigger decorations in higher cycles
});
}
// Add cycle-specific decorations
for (var i = 0; i < cycleNumber; i++) {
scaledConfig.decorations.push({
type: 'treasure',
x: 400 + i * 600,
y: 1950 - i * 100,
tint: 0xFFD700,
scale: 0.8
});
}
}
// Scale enemies and add more for difficulty
for (var i = 0; i < config.baseEnemies.length; i++) {
var enemy = config.baseEnemies[i];
scaledConfig.enemies.push({
type: enemy.type,
x: enemy.x + (cycleNumber * 30 - 15),
y: enemy.y - cycleNumber * 30
});
}
// Add extra enemies for higher cycles
var extraEnemies = Math.min(cycleNumber, 3);
for (var i = 0; i < extraEnemies; i++) {
var enemyType = Math.random() < 0.6 ? 'stickman' : 'flying';
scaledConfig.enemies.push({
type: enemyType,
x: 300 + i * 400 + Math.random() * 200,
y: 2300 - Math.random() * 200
});
}
return scaledConfig;
}
function getBossLevel(cycleNumber) {
var bossTypes = [
// Boss 1 - Purple Giant's Detailed Lair
{
name: "Purple Giant's Lair",
backgroundColor: 0x4a0e4e,
// Darker, more ominous purple
musicTrack: 'boss_music',
bossType: 'boss',
platforms: [{
x: 600,
y: 1700,
type: 'obsidian',
tint: 0x2F2F2F,
width: 280,
height: 60
}, {
x: 1024,
y: 1800,
type: 'throne',
tint: 0x800080,
width: 350,
height: 80
}, {
x: 1600,
y: 1700,
type: 'obsidian',
tint: 0x2F2F2F,
width: 280,
height: 60
}],
decorations: [{
type: 'statue',
x: 300,
y: 1900,
tint: 0x483D8B,
scale: 2.0
}, {
type: 'statue',
x: 1800,
y: 1900,
tint: 0x483D8B,
scale: 2.0
}, {
type: 'statue',
x: 700,
y: 1900,
tint: 0x4B0082,
scale: 1.8
}, {
type: 'statue',
x: 1400,
y: 1900,
tint: 0x6A5ACD,
scale: 1.8
}, {
type: 'torch',
x: 500,
y: 1600,
tint: 0xFF4500,
scale: 1.5
}, {
type: 'torch',
x: 1500,
y: 1600,
tint: 0xFF4500,
scale: 1.5
}, {
type: 'torch',
x: 800,
y: 1500,
tint: 0xFF6347,
scale: 1.3
}, {
type: 'torch',
x: 1200,
y: 1500,
tint: 0xFF6347,
scale: 1.3
}, {
type: 'torch',
x: 400,
y: 1800,
tint: 0xDC143C,
scale: 1.2
}, {
type: 'torch',
x: 1600,
y: 1800,
tint: 0xDC143C,
scale: 1.2
}, {
type: 'skull',
x: 200,
y: 1950,
tint: 0xF5F5DC,
scale: 1.2
}, {
type: 'skull',
x: 1900,
y: 1950,
tint: 0xF5F5DC,
scale: 1.2
}, {
type: 'skull',
x: 600,
y: 1950,
tint: 0xDDD8C4,
scale: 1.0
}, {
type: 'skull',
x: 1000,
y: 1950,
tint: 0xE6E0D4,
scale: 1.0
}, {
type: 'skull',
x: 1400,
y: 1950,
tint: 0xDDD8C4,
scale: 1.0
}, {
type: 'banner',
x: 1024,
y: 1200,
tint: 0x8B008B,
scale: 3.0
}, {
type: 'banner',
x: 600,
y: 1350,
tint: 0x9932CC,
scale: 2.0
}, {
type: 'banner',
x: 1400,
y: 1350,
tint: 0x9932CC,
scale: 2.0
}, {
type: 'dark_crystal',
x: 450,
y: 1750,
tint: 0x8B008B,
scale: 1.5
}, {
type: 'dark_crystal',
x: 1550,
y: 1750,
tint: 0x8B008B,
scale: 1.5
}, {
type: 'evil_altar',
x: 850,
y: 1800,
tint: 0x2F2F2F,
scale: 1.8
}, {
type: 'evil_altar',
x: 1200,
y: 1800,
tint: 0x2F2F2F,
scale: 1.8
}, {
type: 'bone_pile',
x: 350,
y: 1920,
tint: 0xF5F5DC,
scale: 1.3
}, {
type: 'bone_pile',
x: 750,
y: 1920,
tint: 0xF5F5DC,
scale: 1.3
}, {
type: 'bone_pile',
x: 1150,
y: 1920,
tint: 0xF5F5DC,
scale: 1.3
}, {
type: 'bone_pile',
x: 1650,
y: 1920,
tint: 0xF5F5DC,
scale: 1.3
}, {
type: 'dark_throne',
x: 1024,
y: 1750,
tint: 0x2F2F2F,
scale: 2.5
}, {
type: 'purple_orb',
x: 300,
y: 1700,
tint: 0x9370DB,
scale: 1.2
}, {
type: 'purple_orb',
x: 1700,
y: 1700,
tint: 0x9370DB,
scale: 1.2
}, {
type: 'sacrificial_circle',
x: 1024,
y: 1900,
tint: 0x8B0000,
scale: 3.5
}],
minions: [{
type: 'stickman',
x: 700,
y: 1650
}, {
type: 'stickman',
x: 1500,
y: 1650
}]
},
// Boss 2 - Shadow Lord's Enhanced Domain
{
name: "Shadow Lord's Domain",
backgroundColor: 0x0f0f0f,
// Almost black for shadow realm
musicTrack: 'boss_music',
bossType: 'shadowBoss',
platforms: [{
x: 400,
y: 1600,
type: 'shadow',
tint: 0x1C1C1C,
width: 240,
height: 50
}, {
x: 800,
y: 1400,
type: 'void',
tint: 0x000000,
width: 260,
height: 55
}, {
x: 1200,
y: 1500,
type: 'shadow',
tint: 0x1C1C1C,
width: 240,
height: 50
}, {
x: 1600,
y: 1300,
type: 'void',
tint: 0x000000,
width: 260,
height: 55
}, {
x: 1900,
y: 1700,
type: 'shadow',
tint: 0x1C1C1C,
width: 240,
height: 50
}],
decorations: [{
type: 'portal',
x: 200,
y: 1800,
tint: 0x8A2BE2,
scale: 1.8
}, {
type: 'portal',
x: 1900,
y: 1800,
tint: 0x8A2BE2,
scale: 1.8
}, {
type: 'crystal',
x: 600,
y: 1500,
tint: 0x4B0082,
scale: 1.4
}, {
type: 'crystal',
x: 1400,
y: 1200,
tint: 0x4B0082,
scale: 1.4
}, {
type: 'rune',
x: 300,
y: 1950,
tint: 0x9932CC,
scale: 1.0
}, {
type: 'rune',
x: 700,
y: 1950,
tint: 0x9932CC,
scale: 1.0
}, {
type: 'rune',
x: 1100,
y: 1950,
tint: 0x9932CC,
scale: 1.0
}, {
type: 'rune',
x: 1500,
y: 1950,
tint: 0x9932CC,
scale: 1.0
}, {
type: 'shadowspire',
x: 1024,
y: 1000,
tint: 0x2F2F2F,
scale: 4.0
}],
minions: [{
type: 'flying',
x: 600,
y: 1300
}, {
type: 'flying',
x: 1400,
y: 1200
}, {
type: 'stickman',
x: 1000,
y: 1350
}]
},
// Boss 3 - Fire Demon's Enhanced Inferno
{
name: "Fire Demon's Inferno",
backgroundColor: 0x8B0000,
// Deep fire red
musicTrack: 'boss_music',
bossType: 'fireBoss',
platforms: [{
x: 500,
y: 1800,
type: 'lava',
tint: 0xFF6347,
width: 300,
height: 70
}, {
x: 900,
y: 1600,
type: 'molten',
tint: 0xFF4500,
width: 280,
height: 60
}, {
x: 1300,
y: 1400,
type: 'lava',
tint: 0xFF6347,
width: 300,
height: 70
}, {
x: 1700,
y: 1700,
type: 'molten',
tint: 0xFF4500,
width: 280,
height: 60
}],
decorations: [{
type: 'volcano',
x: 150,
y: 1950,
tint: 0x8B0000,
scale: 2.5
}, {
type: 'volcano',
x: 1950,
y: 1950,
tint: 0x8B0000,
scale: 2.5
}, {
type: 'lavafall',
x: 300,
y: 1000,
tint: 0xFF4500,
scale: 3.0
}, {
type: 'lavafall',
x: 1750,
y: 1000,
tint: 0xFF4500,
scale: 3.0
}, {
type: 'firecrystal',
x: 600,
y: 1700,
tint: 0xFF0000,
scale: 1.6
}, {
type: 'firecrystal',
x: 1200,
y: 1300,
tint: 0xFF0000,
scale: 1.6
}, {
type: 'firecrystal',
x: 1600,
y: 1600,
tint: 0xFF0000,
scale: 1.6
}, {
type: 'brazier',
x: 400,
y: 1850,
tint: 0xFFD700,
scale: 1.3
}, {
type: 'brazier',
x: 1100,
y: 1650,
tint: 0xFFD700,
scale: 1.3
}, {
type: 'brazier',
x: 1800,
y: 1750,
tint: 0xFFD700,
scale: 1.3
}, {
type: 'infernospire',
x: 1024,
y: 800,
tint: 0xFF4500,
scale: 5.0
}],
minions: [{
type: 'flying',
x: 700,
y: 1500
}, {
type: 'stickman',
x: 1100,
y: 1350
}, {
type: 'flying',
x: 1500,
y: 1600
}, {
type: 'stickman',
x: 1900,
y: 1650
}]
}];
var bossIndex = cycleNumber % bossTypes.length;
var bossConfig = bossTypes[bossIndex];
// Enhanced boss level with detailed environment
var enhancedConfig = {
name: bossConfig.name + " " + (cycleNumber + 1),
backgroundColor: bossConfig.backgroundColor,
musicTrack: bossConfig.musicTrack,
platforms: [],
enemies: [{
type: bossConfig.bossType,
x: 1024,
y: 2450
}].concat(bossConfig.minions),
decorations: []
};
// Enhanced platforms with cycle scaling
for (var i = 0; i < bossConfig.platforms.length; i++) {
var platform = bossConfig.platforms[i];
enhancedConfig.platforms.push({
x: platform.x,
y: platform.y - cycleNumber * 15,
// Slightly higher for more challenge
type: platform.type,
tint: platform.tint,
width: platform.width + cycleNumber * 10,
// Larger platforms
height: platform.height + cycleNumber * 5
});
}
// Enhanced decorations with cycle scaling
if (bossConfig.decorations) {
for (var i = 0; i < bossConfig.decorations.length; i++) {
var decoration = bossConfig.decorations[i];
enhancedConfig.decorations.push({
type: decoration.type,
x: decoration.x,
y: decoration.y - cycleNumber * 10,
tint: decoration.tint,
scale: decoration.scale + cycleNumber * 0.1 // Grander decorations
});
}
// Add cycle-specific enhancements
for (var i = 0; i < cycleNumber; i++) {
// Add power crystals that make the boss stronger
enhancedConfig.decorations.push({
type: 'powercrystal',
x: 300 + i * 700,
y: 1200 - i * 50,
tint: 0xFFD700,
scale: 1.5 + i * 0.2
});
}
}
return enhancedConfig;
}
// Game arrays
var platforms = [];
var enemies = [];
var projectiles = [];
var arrows = [];
// UI Elements
var menuContainer, mapSelectContainer, settingsContainer;
// Game objects (will be created when starting game)
var ground, player, staminaBarBackground, staminaBar;
function createMenu() {
menuContainer = new Container();
game.addChild(menuContainer);
// Background decorative elements
// Create background warrior silhouettes
for (var i = 0; i < 8; i++) {
var bgWarrior = LK.getAsset('warrior', {
width: 60,
height: 70,
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.1,
tint: 0x444444
});
bgWarrior.x = 200 + i * 200 + Math.random() * 100;
bgWarrior.y = 800 + Math.random() * 400;
bgWarrior.rotation = Math.random() * Math.PI * 2;
menuContainer.addChild(bgWarrior);
}
// Animated floating swords
for (var i = 0; i < 5; i++) {
var bgSword = LK.getAsset('sword', {
width: 40,
height: 40,
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.15,
tint: 0x666666
});
bgSword.x = 300 + i * 300 + Math.random() * 100;
bgSword.y = 600 + Math.random() * 300;
bgSword.startRotation = Math.random() * Math.PI * 2;
bgSword.rotationSpeed = (Math.random() - 0.5) * 0.02;
menuContainer.addChild(bgSword);
// Animate floating swords
tween(bgSword, {
y: bgSword.y - 50,
alpha: 0.05
}, {
duration: 3000 + Math.random() * 2000,
easing: tween.easeInOut,
repeat: -1,
yoyo: true
});
}
// Decorative border elements
var topBorder = LK.getAsset('platform', {
width: 2048,
height: 8,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFD700
});
topBorder.x = 1024;
topBorder.y = 100;
menuContainer.addChild(topBorder);
var bottomBorder = LK.getAsset('platform', {
width: 2048,
height: 8,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFD700
});
bottomBorder.x = 1024;
bottomBorder.y = 1300;
menuContainer.addChild(bottomBorder);
// Title with enhanced styling
var titleShadow = new Text2('CubikWarrior: Choque de Titanes', {
size: 70,
fill: 0x000000
});
titleShadow.anchor.set(0.5, 0.5);
titleShadow.x = 1028;
titleShadow.y = 404;
menuContainer.addChild(titleShadow);
var title = new Text2('CubikWarrior: Choque de Titanes', {
size: 70,
fill: 0xFFD700
});
title.anchor.set(0.5, 0.5);
title.x = 1024;
title.y = 400;
menuContainer.addChild(title);
// Subtitle
var subtitle = new Text2('EPIC BATTLES AWAIT', {
size: 28,
fill: 0xCCCCCC
});
subtitle.anchor.set(0.5, 0.5);
subtitle.x = 1024;
subtitle.y = 480;
menuContainer.addChild(subtitle);
// Animated title glow effect
var glowCycle = 0;
var titleGlowInterval = LK.setInterval(function () {
glowCycle += 0.05;
var glow = 0.8 + Math.sin(glowCycle) * 0.2;
title.alpha = glow;
}, 50);
// Play button with enhanced styling - larger for Android phones
var playButtonShadow = LK.getAsset('platform', {
width: 408,
height: 128,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x000000
});
playButtonShadow.x = 1028;
playButtonShadow.y = 604;
menuContainer.addChild(playButtonShadow);
var playButton = LK.getAsset('platform', {
width: 400,
height: 120,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x4444FF
});
playButton.x = 1024;
playButton.y = 600;
playButton.interactive = true;
playButton.buttonMode = true;
menuContainer.addChild(playButton);
var playButtonBorder = LK.getAsset('platform', {
width: 408,
height: 128,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFD700,
alpha: 0.3
});
playButtonBorder.x = 1024;
playButtonBorder.y = 600;
menuContainer.addChild(playButtonBorder);
var playText = new Text2('PLAY', {
size: 45,
fill: 0xFFFFFF
});
playText.anchor.set(0.5, 0.5);
playText.x = playButton.x;
playText.y = playButton.y;
menuContainer.addChild(playText);
// Add button glow animation
var playButtonGlow = 0;
var playGlowInterval = LK.setInterval(function () {
playButtonGlow += 0.03;
var glowAlpha = 0.3 + Math.sin(playButtonGlow) * 0.1;
playButtonBorder.alpha = glowAlpha;
}, 50);
playButton.down = function () {
LK.getSound('button_click').play();
// Always start at level 1 for the Play button
currentLevel = 1;
storage.currentLevel = currentLevel;
gameState = 'mapSelect';
menuContainer.visible = false;
createMapSelect();
};
// Settings button with enhanced detailed styling - optimized for mobile
// Multi-layered shadow system for depth
var settingsButtonDeepShadow = LK.getAsset('platform', {
width: 418,
height: 138,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x000000,
alpha: 0.6
});
settingsButtonDeepShadow.x = 1032;
settingsButtonDeepShadow.y = 788;
menuContainer.addChild(settingsButtonDeepShadow);
var settingsButtonShadow = LK.getAsset('platform', {
width: 412,
height: 132,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x222222,
alpha: 0.8
});
settingsButtonShadow.x = 1028;
settingsButtonShadow.y = 784;
menuContainer.addChild(settingsButtonShadow);
// Main settings button with gradient-like effect using multiple layers
var settingsButtonBase = LK.getAsset('platform', {
width: 400,
height: 120,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x2d7a2d
});
settingsButtonBase.x = 1024;
settingsButtonBase.y = 780;
menuContainer.addChild(settingsButtonBase);
var settingsButton = LK.getAsset('platform', {
width: 390,
height: 110,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x44FF44
});
settingsButton.x = 1024;
settingsButton.y = 780;
settingsButton.interactive = true;
settingsButton.buttonMode = true;
menuContainer.addChild(settingsButton);
// Detailed border system with multiple accent layers
var settingsButtonOuterBorder = LK.getAsset('platform', {
width: 416,
height: 136,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x88FF88,
alpha: 0.4
});
settingsButtonOuterBorder.x = 1024;
settingsButtonOuterBorder.y = 780;
menuContainer.addChild(settingsButtonOuterBorder);
var settingsButtonInnerBorder = LK.getAsset('platform', {
width: 408,
height: 128,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xAAFFAA,
alpha: 0.2
});
settingsButtonInnerBorder.x = 1024;
settingsButtonInnerBorder.y = 780;
menuContainer.addChild(settingsButtonInnerBorder);
// Detailed corner accents for enhanced visual appeal
var settingsCornerAccents = [];
for (var i = 0; i < 4; i++) {
var corner = LK.getAsset('platform', {
width: 20,
height: 20,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFD700,
alpha: 0.7
});
var offsetX = i % 2 === 0 ? -180 : 180;
var offsetY = i < 2 ? -40 : 40;
corner.x = 1024 + offsetX;
corner.y = 780 + offsetY;
menuContainer.addChild(corner);
settingsCornerAccents.push(corner);
}
// Enhanced gear icon for settings with detailed design
var settingsGearBase = LK.getAsset('platform', {
width: 40,
height: 40,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFFFFF,
alpha: 0.9
});
settingsGearBase.x = 950;
settingsGearBase.y = 780;
menuContainer.addChild(settingsGearBase);
// Gear teeth details
for (var i = 0; i < 8; i++) {
var tooth = LK.getAsset('platform', {
width: 8,
height: 12,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xCCCCCC,
alpha: 0.8
});
var angle = i / 8 * Math.PI * 2;
tooth.x = 950 + Math.cos(angle) * 18;
tooth.y = 780 + Math.sin(angle) * 18;
tooth.rotation = angle;
menuContainer.addChild(tooth);
}
// Central gear hub
var settingsGearCenter = LK.getAsset('platform', {
width: 16,
height: 16,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x888888,
alpha: 0.9
});
settingsGearCenter.x = 950;
settingsGearCenter.y = 780;
menuContainer.addChild(settingsGearCenter);
// Enhanced settings text with shadow and styling
var settingsTextShadow = new Text2('SETTINGS', {
size: 45,
fill: 0x000000
});
settingsTextShadow.anchor.set(0.5, 0.5);
settingsTextShadow.x = 1026;
settingsTextShadow.y = 782;
menuContainer.addChild(settingsTextShadow);
var settingsText = new Text2('SETTINGS', {
size: 45,
fill: 0xFFFFFF
});
settingsText.anchor.set(0.5, 0.5);
settingsText.x = settingsButton.x;
settingsText.y = settingsButton.y;
menuContainer.addChild(settingsText);
// Detailed icon indicators for settings categories
var volumeIcon = LK.getAsset('platform', {
width: 24,
height: 24,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFD700,
alpha: 0.7
});
volumeIcon.x = 1080;
volumeIcon.y = 765;
menuContainer.addChild(volumeIcon);
var controlsIcon = LK.getAsset('platform', {
width: 20,
height: 20,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFD700,
alpha: 0.7
});
controlsIcon.x = 1080;
controlsIcon.y = 795;
menuContainer.addChild(controlsIcon);
// Enhanced button animation and interaction system
var settingsAnimationInterval;
var settingsButtonElements = [settingsButton, settingsButtonBase, settingsButtonOuterBorder, settingsButtonInnerBorder, settingsGearBase, settingsGearCenter];
// Continuous subtle animation for enhanced appeal
var settingsAnimCycle = 0;
settingsAnimationInterval = LK.setInterval(function () {
settingsAnimCycle += 0.02;
var pulseEffect = 0.95 + Math.sin(settingsAnimCycle) * 0.05;
// Pulse the main button slightly
settingsButton.scaleX = pulseEffect;
settingsButton.scaleY = pulseEffect;
// Rotate the gear elements
settingsGearBase.rotation += 0.01;
settingsGearCenter.rotation -= 0.015;
// Animate corner accents
for (var i = 0; i < settingsCornerAccents.length; i++) {
var corner = settingsCornerAccents[i];
var cornerCycle = settingsAnimCycle + i * Math.PI / 2;
corner.alpha = 0.5 + Math.sin(cornerCycle * 2) * 0.3;
}
// Animate border glow
var glowAlpha = 0.3 + Math.sin(settingsAnimCycle * 1.5) * 0.15;
settingsButtonOuterBorder.alpha = glowAlpha;
settingsButtonInnerBorder.alpha = glowAlpha * 0.7;
}, 50);
// Enhanced button interaction with detailed feedback
settingsButton.down = function () {
LK.getSound('button_click').play();
// Detailed press animation with multiple elements
tween(settingsButton, {
scaleX: 0.95,
scaleY: 0.95,
alpha: 0.9
}, {
duration: 100,
onFinish: function onFinish() {
tween(settingsButton, {
scaleX: 1.05,
scaleY: 1.05,
alpha: 1.0
}, {
duration: 150,
onFinish: function onFinish() {
tween(settingsButton, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100
});
}
});
}
});
// Enhanced text flash effect
tween(settingsText, {
tint: 0x44FF44,
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 100,
onFinish: function onFinish() {
tween(settingsText, {
tint: 0xFFFFFF,
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200
});
}
});
// Enhanced gear spin effect on press
tween(settingsGearBase, {
rotation: settingsGearBase.rotation + Math.PI
}, {
duration: 400,
easing: tween.easeOut
});
// Animate corner accents on press
for (var i = 0; i < settingsCornerAccents.length; i++) {
var corner = settingsCornerAccents[i];
tween(corner, {
scaleX: 1.5,
scaleY: 1.5,
alpha: 1.0
}, {
duration: 200,
onFinish: function onFinish() {
tween(corner, {
scaleX: 1.0,
scaleY: 1.0,
alpha: 0.7
}, {
duration: 300
});
}
});
}
// Navigate to settings
gameState = 'settings';
menuContainer.visible = false;
createSettings();
};
// Shop button with enhanced styling - repositioned for better layout
var shopButtonShadow = LK.getAsset('platform', {
width: 308,
height: 88,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x000000
});
shopButtonShadow.x = 604; // Better positioning
shopButtonShadow.y = 704;
menuContainer.addChild(shopButtonShadow);
var shopButton = LK.getAsset('platform', {
width: 300,
height: 80,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFD700
});
shopButton.x = 600; // Better positioning
shopButton.y = 700;
shopButton.interactive = true;
shopButton.buttonMode = true;
menuContainer.addChild(shopButton);
var shopButtonBorder = LK.getAsset('platform', {
width: 308,
height: 88,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFFF88,
alpha: 0.4
});
shopButtonBorder.x = 600;
shopButtonBorder.y = 700;
menuContainer.addChild(shopButtonBorder);
var shopText = new Text2('SHOP', {
size: 36,
fill: 0x000000
});
shopText.anchor.set(0.5, 0.5);
shopText.x = shopButton.x;
shopText.y = shopButton.y;
menuContainer.addChild(shopText);
// Add map select button for better navigation
var mapButtonShadow = LK.getAsset('platform', {
width: 308,
height: 88,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x000000
});
mapButtonShadow.x = 1444;
mapButtonShadow.y = 704;
menuContainer.addChild(mapButtonShadow);
var mapButton = LK.getAsset('platform', {
width: 300,
height: 80,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFF8844
});
mapButton.x = 1440;
mapButton.y = 700;
mapButton.interactive = true;
mapButton.buttonMode = true;
menuContainer.addChild(mapButton);
var mapButtonBorder = LK.getAsset('platform', {
width: 308,
height: 88,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFAA66,
alpha: 0.4
});
mapButtonBorder.x = 1440;
mapButtonBorder.y = 700;
menuContainer.addChild(mapButtonBorder);
var mapText = new Text2('LEVELS', {
size: 32,
fill: 0xFFFFFF
});
mapText.anchor.set(0.5, 0.5);
mapText.x = mapButton.x;
mapText.y = mapButton.y;
menuContainer.addChild(mapText);
mapButton.down = function () {
LK.getSound('button_click').play();
gameState = 'mapSelect';
menuContainer.visible = false;
createMapSelect();
};
shopButton.down = function () {
LK.getSound('button_click').play();
gameState = 'shop';
menuContainer.visible = false;
createShop();
};
// Statistics panel background
var statsPanel = LK.getAsset('platform', {
width: 600,
height: 280,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x1a1a1a,
alpha: 0.8
});
statsPanel.x = 1024;
statsPanel.y = 1000;
menuContainer.addChild(statsPanel);
// Statistics title
var statsTitle = new Text2('STATISTICS', {
size: 36,
fill: 0xFFD700
});
statsTitle.anchor.set(0.5, 0.5);
statsTitle.x = 1024;
statsTitle.y = 880;
menuContainer.addChild(statsTitle);
// High score display with enhanced styling
var highScoreLabel = new Text2('HIGH SCORE', {
size: 24,
fill: 0xCCCCCC
});
highScoreLabel.anchor.set(0.5, 0.5);
highScoreLabel.x = 1024;
highScoreLabel.y = 920;
menuContainer.addChild(highScoreLabel);
var highScoreText = new Text2(storage.highScore.toString(), {
size: 32,
fill: 0xFFD700
});
highScoreText.anchor.set(0.5, 0.5);
highScoreText.x = 1024;
highScoreText.y = 950;
menuContainer.addChild(highScoreText);
// Levels completed display
var levelsLabel = new Text2('LEVELS UNLOCKED', {
size: 24,
fill: 0xCCCCCC
});
levelsLabel.anchor.set(0.5, 0.5);
levelsLabel.x = 1024;
levelsLabel.y = 990;
menuContainer.addChild(levelsLabel);
var levelsText = new Text2(storage.unlockedLevels.toString(), {
size: 32,
fill: 0x44FF44
});
levelsText.anchor.set(0.5, 0.5);
levelsText.x = 1024;
levelsText.y = 1020;
menuContainer.addChild(levelsText);
// Coins display
var coinsLabel = new Text2('COINS EARNED', {
size: 24,
fill: 0xCCCCCC
});
coinsLabel.anchor.set(0.5, 0.5);
coinsLabel.x = 1024;
coinsLabel.y = 1060;
menuContainer.addChild(coinsLabel);
var coinsText = new Text2(storage.coins.toString(), {
size: 32,
fill: 0xFFD700
});
coinsText.anchor.set(0.5, 0.5);
coinsText.x = 1024;
coinsText.y = 1090;
menuContainer.addChild(coinsText);
// Current skin display
var skinLabel = new Text2('CURRENT SKIN', {
size: 24,
fill: 0xCCCCCC
});
skinLabel.anchor.set(0.5, 0.5);
skinLabel.x = 1024;
skinLabel.y = 1130;
menuContainer.addChild(skinLabel);
var skinName = storage.selectedSkin.charAt(0).toUpperCase() + storage.selectedSkin.slice(1);
var skinText = new Text2(skinName, {
size: 28,
fill: 0x8844FF
});
skinText.anchor.set(0.5, 0.5);
skinText.x = 1024;
skinText.y = 1160;
menuContainer.addChild(skinText);
// Version and credits
var versionText = new Text2('v1.0 - Made with LK Engine', {
size: 20,
fill: 0x666666
});
versionText.anchor.set(0.5, 0.5);
versionText.x = 1024;
versionText.y = 1220;
menuContainer.addChild(versionText);
// Animated background particles
for (var i = 0; i < 15; i++) {
var particle = LK.getAsset('bullet', {
width: 4,
height: 4,
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.3,
tint: 0xFFD700
});
particle.x = Math.random() * 2048;
particle.y = Math.random() * 1400;
particle.velocityX = (Math.random() - 0.5) * 2;
particle.velocityY = (Math.random() - 0.5) * 2;
menuContainer.addChild(particle);
// Animate particles
var _animateParticle = function animateParticle(p) {
tween(p, {
x: p.x + p.velocityX * 100,
y: p.y + p.velocityY * 100,
alpha: 0.1
}, {
duration: 2000 + Math.random() * 3000,
easing: tween.easeInOut,
onFinish: function onFinish() {
p.x = Math.random() * 2048;
p.y = Math.random() * 1400;
p.alpha = 0.3;
_animateParticle(p);
}
});
};
_animateParticle(particle);
}
// Animated menu background warrior showcase
var showcaseWarrior = LK.getAsset('warrior', {
width: 200,
height: 240,
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.4,
tint: 0x4444FF
});
showcaseWarrior.x = 1600;
showcaseWarrior.y = 700;
menuContainer.addChild(showcaseWarrior);
// Animate showcase warrior
var _breatheAnimation = function breatheAnimation() {
tween(showcaseWarrior, {
scaleY: 1.05,
y: showcaseWarrior.y - 10
}, {
duration: 2000,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(showcaseWarrior, {
scaleY: 1.0,
y: showcaseWarrior.y + 10
}, {
duration: 2000,
easing: tween.easeInOut,
onFinish: _breatheAnimation
});
}
});
};
_breatheAnimation();
}
function createMapSelect() {
// Hide all other containers first
if (menuContainer) {
menuContainer.visible = false;
}
if (settingsContainer) {
settingsContainer.visible = false;
}
if (mapSelectContainer) {
mapSelectContainer.destroy();
}
mapSelectContainer = new Container();
game.addChild(mapSelectContainer);
// Enhanced background decorations with animated elements
for (var i = 0; i < 15; i++) {
var bgElement = LK.getAsset('platform', {
width: 8,
height: 8,
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.1,
tint: 0x4444FF
});
bgElement.x = Math.random() * 2048;
bgElement.y = Math.random() * 1200 + 200;
mapSelectContainer.addChild(bgElement);
// Animate background elements
tween(bgElement, {
y: bgElement.y - 50,
alpha: 0.05
}, {
duration: 4000 + Math.random() * 2000,
easing: tween.easeInOut,
repeat: -1,
yoyo: true
});
}
// Decorative border frame with enhanced styling
var topBorder = LK.getAsset('platform', {
width: 1800,
height: 12,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFD700
});
topBorder.x = 1024;
topBorder.y = 150;
mapSelectContainer.addChild(topBorder);
var bottomBorder = LK.getAsset('platform', {
width: 1800,
height: 12,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFD700
});
bottomBorder.x = 1024;
bottomBorder.y = 1100;
mapSelectContainer.addChild(bottomBorder);
// Enhanced title with shadow and glow effects
var titleShadow = new Text2('LEVEL SELECTOR', {
size: 66,
fill: 0x000000
});
titleShadow.anchor.set(0.5, 0.5);
titleShadow.x = 1028;
titleShadow.y = 254;
mapSelectContainer.addChild(titleShadow);
var title = new Text2('LEVEL SELECTOR', {
size: 62,
fill: 0xFFD700
});
title.anchor.set(0.5, 0.5);
title.x = 1024;
title.y = 250;
mapSelectContainer.addChild(title);
// Animated title glow effect
var titleGlowCycle = 0;
var titleGlowInterval = LK.setInterval(function () {
titleGlowCycle += 0.04;
var glow = 0.9 + Math.sin(titleGlowCycle) * 0.1;
title.alpha = glow;
}, 60);
// Enhanced progress panel with detailed statistics
var progressPanelBg = LK.getAsset('platform', {
width: 800,
height: 120,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x1a1a1a,
alpha: 0.8
});
progressPanelBg.x = 1024;
progressPanelBg.y = 360;
mapSelectContainer.addChild(progressPanelBg);
var progressPanelBorder = LK.getAsset('platform', {
width: 808,
height: 128,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x44FF44,
alpha: 0.3
});
progressPanelBorder.x = 1024;
progressPanelBorder.y = 360;
mapSelectContainer.addChild(progressPanelBorder);
// Detailed progress information
var progressTitle = new Text2('CAMPAIGN PROGRESS', {
size: 28,
fill: 0xFFD700
});
progressTitle.anchor.set(0.5, 0.5);
progressTitle.x = 1024;
progressTitle.y = 330;
mapSelectContainer.addChild(progressTitle);
var progressText = new Text2('Levels Unlocked: ' + storage.unlockedLevels + ' | High Score: ' + storage.highScore, {
size: 24,
fill: 0xFFFFFF
});
progressText.anchor.set(0.5, 0.5);
progressText.x = 1024;
progressText.y = 360;
mapSelectContainer.addChild(progressText);
var coinsText = new Text2('Coins Earned: ' + storage.coins + ' | Last Completed: Level ' + storage.lastCompletedLevel, {
size: 24,
fill: 0xCCCCCC
});
coinsText.anchor.set(0.5, 0.5);
coinsText.x = 1024;
coinsText.y = 390;
mapSelectContainer.addChild(coinsText);
// Enhanced current level display with detailed preview card
var levelCardBg = LK.getAsset('platform', {
width: 900,
height: 400,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x2a2a2a,
alpha: 0.9
});
levelCardBg.x = 1024;
levelCardBg.y = 650;
mapSelectContainer.addChild(levelCardBg);
var levelCardBorder = LK.getAsset('platform', {
width: 908,
height: 408,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x4444FF,
alpha: 0.4
});
levelCardBorder.x = 1024;
levelCardBorder.y = 650;
mapSelectContainer.addChild(levelCardBorder);
// Current level header
var levelHeader = new Text2('SELECTED LEVEL: ' + currentLevel, {
size: 36,
fill: 0xFFD700
});
levelHeader.anchor.set(0.5, 0.5);
levelHeader.x = 1024;
levelHeader.y = 490;
mapSelectContainer.addChild(levelHeader);
// Check if current level is unlocked
var isLevelUnlocked = currentLevel <= storage.unlockedLevels;
if (isLevelUnlocked) {
// Enhanced level preview for unlocked levels
var previewConfig = getCurrentLevelConfig();
// Level name with enhanced styling
var levelNameShadow = new Text2(previewConfig.name, {
size: 34,
fill: 0x000000
});
levelNameShadow.anchor.set(0.5, 0.5);
levelNameShadow.x = 1026;
levelNameShadow.y = 542;
mapSelectContainer.addChild(levelNameShadow);
var levelName = new Text2(previewConfig.name, {
size: 32,
fill: 0xFFFFFF
});
levelName.anchor.set(0.5, 0.5);
levelName.x = 1024;
levelName.y = 540;
mapSelectContainer.addChild(levelName);
// Enhanced level type indicator with detailed classification
var isBossLevel = (currentLevel - 1) % 4 === 3;
var cycleNumber = Math.floor((currentLevel - 1) / 4) + 1;
var levelType = isBossLevel ? 'BOSS BATTLE' : 'EXPLORATION LEVEL';
var difficultyText = 'Cycle ' + cycleNumber + (isBossLevel ? ' - Final Challenge' : ' - Stage ' + ((currentLevel - 1) % 4 + 1));
var typeIndicatorBg = LK.getAsset('platform', {
width: 300,
height: 60,
anchorX: 0.5,
anchorY: 0.5,
tint: isBossLevel ? 0x8B0000 : 0x006400
});
typeIndicatorBg.x = 1024;
typeIndicatorBg.y = 590;
mapSelectContainer.addChild(typeIndicatorBg);
var typeText = new Text2(levelType, {
size: 26,
fill: 0xFFFFFF
});
typeText.anchor.set(0.5, 0.5);
typeText.x = 1024;
typeText.y = 590;
mapSelectContainer.addChild(typeText);
var difficultyIndicator = new Text2(difficultyText, {
size: 20,
fill: 0xCCCCCC
});
difficultyIndicator.anchor.set(0.5, 0.5);
difficultyIndicator.x = 1024;
difficultyIndicator.y = 620;
mapSelectContainer.addChild(difficultyIndicator);
// Enhanced level preview with environmental elements
var previewAreaBg = LK.getAsset('platform', {
width: 800,
height: 120,
anchorX: 0.5,
anchorY: 0.5,
tint: previewConfig.backgroundColor || 0x333333,
alpha: 0.3
});
previewAreaBg.x = 1024;
previewAreaBg.y = 690;
mapSelectContainer.addChild(previewAreaBg);
// Level characteristics display
var characteristicsText = new Text2('Environment: ' + previewConfig.name.split(' ')[0] + ' | Enemies: ' + previewConfig.enemies.length + ' | Platforms: ' + previewConfig.platforms.length, {
size: 18,
fill: 0xFFFFFF
});
characteristicsText.anchor.set(0.5, 0.5);
characteristicsText.x = 1024;
characteristicsText.y = 680;
mapSelectContainer.addChild(characteristicsText);
// Special features indicator
var specialFeatures = [];
if (isBossLevel) {
specialFeatures.push('Epic Boss Fight');
}
if (cycleNumber > 1) {
specialFeatures.push('Enhanced Difficulty');
}
if (previewConfig.decorations && previewConfig.decorations.length > 5) {
specialFeatures.push('Rich Environment');
}
if (previewConfig.enemies.length > 3) {
specialFeatures.push('Multiple Enemies');
}
if (specialFeatures.length > 0) {
var featuresText = new Text2('Features: ' + specialFeatures.join(' • '), {
size: 16,
fill: 0xFFD700
});
featuresText.anchor.set(0.5, 0.5);
featuresText.x = 1024;
featuresText.y = 710;
mapSelectContainer.addChild(featuresText);
}
// Enhanced preview miniatures with enemy and platform icons
var miniatureContainer = new Container();
mapSelectContainer.addChild(miniatureContainer);
// Create mini platforms
for (var i = 0; i < Math.min(previewConfig.platforms.length, 5); i++) {
var miniPlatform = LK.getAsset('platform', {
width: 40,
height: 8,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x666666,
alpha: 0.8
});
miniPlatform.x = 700 + i * 50;
miniPlatform.y = 750;
miniatureContainer.addChild(miniPlatform);
}
// Create mini enemies
for (var i = 0; i < Math.min(previewConfig.enemies.length, 4); i++) {
var enemyType = previewConfig.enemies[i].type;
var enemyColor = enemyType === 'boss' ? 0x800080 : enemyType === 'flying' ? 0x8B4513 : 0xFF0000;
var miniEnemy = LK.getAsset('platform', {
width: 12,
height: 16,
anchorX: 0.5,
anchorY: 0.5,
tint: enemyColor
});
miniEnemy.x = 720 + i * 60;
miniEnemy.y = 730;
miniatureContainer.addChild(miniEnemy);
}
// Rewards preview
var rewardsBg = LK.getAsset('platform', {
width: 400,
height: 40,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x1a4d1a,
alpha: 0.6
});
rewardsBg.x = 1024;
rewardsBg.y = 780;
mapSelectContainer.addChild(rewardsBg);
var baseReward = isBossLevel ? 25 : 15;
var bonusCoins = cycleNumber * 5;
var totalReward = baseReward + bonusCoins;
var rewardsText = new Text2('Completion Reward: ' + totalReward + ' coins (' + baseReward + ' base + ' + bonusCoins + ' cycle bonus)', {
size: 18,
fill: 0x44FF44
});
rewardsText.anchor.set(0.5, 0.5);
rewardsText.x = 1024;
rewardsText.y = 780;
mapSelectContainer.addChild(rewardsText);
} else {
// Enhanced locked level display
var lockedCardBg = LK.getAsset('platform', {
width: 600,
height: 200,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x444444,
alpha: 0.7
});
lockedCardBg.x = 1024;
lockedCardBg.y = 650;
mapSelectContainer.addChild(lockedCardBg);
var lockedBorder = LK.getAsset('platform', {
width: 608,
height: 208,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFF4444,
alpha: 0.5
});
lockedBorder.x = 1024;
lockedBorder.y = 650;
mapSelectContainer.addChild(lockedBorder);
// Enhanced lock icon
var lockShadow = LK.getAsset('lock', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0x000000,
scaleX: 2.2,
scaleY: 2.2,
alpha: 0.5
});
lockShadow.x = 1026;
lockShadow.y = 612;
mapSelectContainer.addChild(lockShadow);
var lockGraphic = LK.getAsset('lock', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0x888888,
scaleX: 2,
scaleY: 2
});
lockGraphic.x = 1024;
lockGraphic.y = 610;
mapSelectContainer.addChild(lockGraphic);
// Enhanced locked message
var lockedTitle = new Text2('LEVEL LOCKED', {
size: 36,
fill: 0xFF4444
});
lockedTitle.anchor.set(0.5, 0.5);
lockedTitle.x = 1024;
lockedTitle.y = 550;
mapSelectContainer.addChild(lockedTitle);
// Show unlock requirement with better styling
var requirementBg = LK.getAsset('platform', {
width: 500,
height: 50,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x2a2a2a,
alpha: 0.8
});
requirementBg.x = 1024;
requirementBg.y = 700;
mapSelectContainer.addChild(requirementBg);
var requirementText = new Text2('Complete Level ' + (currentLevel - 1) + ' to unlock this level', {
size: 22,
fill: 0xFFFFFF
});
requirementText.anchor.set(0.5, 0.5);
requirementText.x = 1024;
requirementText.y = 700;
mapSelectContainer.addChild(requirementText);
// Show level preview hint
var hintText = new Text2('Unlock to discover: ' + ((currentLevel - 1) % 4 === 3 ? 'Epic Boss Battle' : 'New Challenges'), {
size: 18,
fill: 0xCCCCCC
});
hintText.anchor.set(0.5, 0.5);
hintText.x = 1024;
hintText.y = 730;
mapSelectContainer.addChild(hintText);
// Animate lock with breathing effect
var lockAnimCycle = 0;
var lockAnimInterval = LK.setInterval(function () {
lockAnimCycle += 0.05;
var breathe = 1 + Math.sin(lockAnimCycle) * 0.1;
lockGraphic.scaleX = 2 * breathe;
lockGraphic.scaleY = 2 * breathe;
}, 50);
}
// Enhanced play button with better styling and animation
var playButtonShadow = LK.getAsset('platform', {
width: 368,
height: 118,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x000000,
alpha: 0.4
});
playButtonShadow.x = 1028;
playButtonShadow.y = 864;
mapSelectContainer.addChild(playButtonShadow);
var playButton = LK.getAsset('platform', {
width: 360,
height: 110,
anchorX: 0.5,
anchorY: 0.5,
tint: isLevelUnlocked ? getCurrentLevelConfig().backgroundColor || 0x4444FF : 0x666666
});
playButton.x = 1024;
playButton.y = 860;
playButton.interactive = isLevelUnlocked;
playButton.buttonMode = isLevelUnlocked;
mapSelectContainer.addChild(playButton);
var playButtonBorder = LK.getAsset('platform', {
width: 368,
height: 118,
anchorX: 0.5,
anchorY: 0.5,
tint: isLevelUnlocked ? 0x88FF88 : 0x888888,
alpha: isLevelUnlocked ? 0.5 : 0.2
});
playButtonBorder.x = 1024;
playButtonBorder.y = 860;
mapSelectContainer.addChild(playButtonBorder);
var playText = new Text2(isLevelUnlocked ? 'ENTER LEVEL ' + currentLevel : 'LOCKED', {
size: 32,
fill: isLevelUnlocked ? 0xFFFFFF : 0x888888
});
playText.anchor.set(0.5, 0.5);
playText.x = playButton.x;
playText.y = playButton.y;
mapSelectContainer.addChild(playText);
// Add animated glow effect for unlocked levels
if (isLevelUnlocked) {
var playGlowCycle = 0;
var playGlowInterval = LK.setInterval(function () {
playGlowCycle += 0.04;
var glow = 0.5 + Math.sin(playGlowCycle) * 0.2;
playButtonBorder.alpha = glow;
}, 60);
playButton.down = function () {
LK.getSound('button_click').play();
// Enhanced button press animation
tween(playButton, {
scaleX: 0.95,
scaleY: 0.95
}, {
duration: 100,
onFinish: function onFinish() {
tween(playButton, {
scaleX: 1.05,
scaleY: 1.05
}, {
duration: 150,
onFinish: function onFinish() {
tween(playButton, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100
});
startGame();
}
});
}
});
};
}
// Enhanced level navigation with detailed styling
var navigationContainer = new Container();
mapSelectContainer.addChild(navigationContainer);
// Navigation background panel
var navPanelBg = LK.getAsset('platform', {
width: 800,
height: 80,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x1a1a1a,
alpha: 0.7
});
navPanelBg.x = 1024;
navPanelBg.y = 950;
navigationContainer.addChild(navPanelBg);
// Previous level button (enhanced)
if (currentLevel > 1) {
var prevButtonShadow = LK.getAsset('platform', {
width: 188,
height: 68,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x000000,
alpha: 0.3
});
prevButtonShadow.x = 704;
prevButtonShadow.y = 954;
navigationContainer.addChild(prevButtonShadow);
var prevButton = LK.getAsset('platform', {
width: 180,
height: 60,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x4444FF
});
prevButton.x = 700;
prevButton.y = 950;
prevButton.interactive = true;
prevButton.buttonMode = true;
navigationContainer.addChild(prevButton);
var prevButtonBorder = LK.getAsset('platform', {
width: 188,
height: 68,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x8888FF,
alpha: 0.4
});
prevButtonBorder.x = 700;
prevButtonBorder.y = 950;
navigationContainer.addChild(prevButtonBorder);
var prevIcon = new Text2('◀', {
size: 24,
fill: 0xFFFFFF
});
prevIcon.anchor.set(0.5, 0.5);
prevIcon.x = 680;
prevIcon.y = 950;
navigationContainer.addChild(prevIcon);
var prevText = new Text2('PREV', {
size: 20,
fill: 0xFFFFFF
});
prevText.anchor.set(0.5, 0.5);
prevText.x = 720;
prevText.y = 950;
navigationContainer.addChild(prevText);
prevButton.down = function () {
LK.getSound('button_click').play();
tween(prevButton, {
alpha: 0.8
}, {
duration: 100,
onFinish: function onFinish() {
tween(prevButton, {
alpha: 1.0
}, {
duration: 100
});
}
});
currentLevel = Math.max(1, currentLevel - 1);
storage.currentLevel = currentLevel;
mapSelectContainer.visible = false;
createMapSelect();
};
}
// Next level button (enhanced, only if unlocked)
if (currentLevel < storage.unlockedLevels) {
var nextButtonShadow = LK.getAsset('platform', {
width: 188,
height: 68,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x000000,
alpha: 0.3
});
nextButtonShadow.x = 1344;
nextButtonShadow.y = 954;
navigationContainer.addChild(nextButtonShadow);
var nextButton = LK.getAsset('platform', {
width: 180,
height: 60,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x4444FF
});
nextButton.x = 1340;
nextButton.y = 950;
nextButton.interactive = true;
nextButton.buttonMode = true;
navigationContainer.addChild(nextButton);
var nextButtonBorder = LK.getAsset('platform', {
width: 188,
height: 68,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x8888FF,
alpha: 0.4
});
nextButtonBorder.x = 1340;
nextButtonBorder.y = 950;
navigationContainer.addChild(nextButtonBorder);
var nextIcon = new Text2('▶', {
size: 24,
fill: 0xFFFFFF
});
nextIcon.anchor.set(0.5, 0.5);
nextIcon.x = 1360;
nextIcon.y = 950;
navigationContainer.addChild(nextIcon);
var nextText = new Text2('NEXT', {
size: 20,
fill: 0xFFFFFF
});
nextText.anchor.set(0.5, 0.5);
nextText.x = 1320;
nextText.y = 950;
navigationContainer.addChild(nextText);
nextButton.down = function () {
LK.getSound('button_click').play();
tween(nextButton, {
alpha: 0.8
}, {
duration: 100,
onFinish: function onFinish() {
tween(nextButton, {
alpha: 1.0
}, {
duration: 100
});
}
});
currentLevel++;
storage.currentLevel = currentLevel;
mapSelectContainer.visible = false;
createMapSelect();
};
}
// Level counter in navigation
var levelCounter = new Text2(currentLevel + ' / ' + storage.unlockedLevels, {
size: 24,
fill: 0xFFD700
});
levelCounter.anchor.set(0.5, 0.5);
levelCounter.x = 1024;
levelCounter.y = 950;
navigationContainer.addChild(levelCounter);
// Quick jump to first/last level buttons
if (storage.unlockedLevels > 3) {
// Jump to first level
var firstLevelButton = LK.getAsset('platform', {
width: 60,
height: 40,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x666666,
alpha: 0.7
});
firstLevelButton.x = 600;
firstLevelButton.y = 950;
firstLevelButton.interactive = currentLevel > 1;
firstLevelButton.buttonMode = currentLevel > 1;
navigationContainer.addChild(firstLevelButton);
var firstLevelText = new Text2('1', {
size: 18,
fill: currentLevel > 1 ? 0xFFFFFF : 0x888888
});
firstLevelText.anchor.set(0.5, 0.5);
firstLevelText.x = 600;
firstLevelText.y = 950;
navigationContainer.addChild(firstLevelText);
if (currentLevel > 1) {
firstLevelButton.down = function () {
LK.getSound('button_click').play();
currentLevel = 1;
storage.currentLevel = currentLevel;
mapSelectContainer.visible = false;
createMapSelect();
};
}
// Jump to latest unlocked level
var lastLevelButton = LK.getAsset('platform', {
width: 80,
height: 40,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x666666,
alpha: 0.7
});
lastLevelButton.x = 1440;
lastLevelButton.y = 950;
lastLevelButton.interactive = currentLevel < storage.unlockedLevels;
lastLevelButton.buttonMode = currentLevel < storage.unlockedLevels;
navigationContainer.addChild(lastLevelButton);
var lastLevelText = new Text2('MAX', {
size: 16,
fill: currentLevel < storage.unlockedLevels ? 0xFFFFFF : 0x888888
});
lastLevelText.anchor.set(0.5, 0.5);
lastLevelText.x = 1440;
lastLevelText.y = 950;
navigationContainer.addChild(lastLevelText);
if (currentLevel < storage.unlockedLevels) {
lastLevelButton.down = function () {
LK.getSound('button_click').play();
currentLevel = storage.unlockedLevels;
storage.currentLevel = currentLevel;
mapSelectContainer.visible = false;
createMapSelect();
};
}
}
// Enhanced bottom navigation panel
var bottomNavBg = LK.getAsset('platform', {
width: 1600,
height: 100,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x1a1a1a,
alpha: 0.8
});
bottomNavBg.x = 1024;
bottomNavBg.y = 1050;
mapSelectContainer.addChild(bottomNavBg);
var bottomNavBorder = LK.getAsset('platform', {
width: 1608,
height: 108,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFD700,
alpha: 0.3
});
bottomNavBorder.x = 1024;
bottomNavBorder.y = 1050;
mapSelectContainer.addChild(bottomNavBorder);
// Enhanced back button with better styling
var backButtonShadow = LK.getAsset('platform', {
width: 248,
height: 78,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x000000,
alpha: 0.4
});
backButtonShadow.x = 1028;
backButtonShadow.y = 1054;
mapSelectContainer.addChild(backButtonShadow);
var backButton = LK.getAsset('platform', {
width: 240,
height: 70,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFF4444
});
backButton.x = 1024;
backButton.y = 1050;
backButton.interactive = true;
backButton.buttonMode = true;
mapSelectContainer.addChild(backButton);
var backButtonBorder = LK.getAsset('platform', {
width: 248,
height: 78,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFF8888,
alpha: 0.4
});
backButtonBorder.x = 1024;
backButtonBorder.y = 1050;
mapSelectContainer.addChild(backButtonBorder);
var backIcon = new Text2('◀', {
size: 24,
fill: 0xFFFFFF
});
backIcon.anchor.set(0.5, 0.5);
backIcon.x = 1000;
backIcon.y = 1050;
mapSelectContainer.addChild(backIcon);
var backText = new Text2('MAIN MENU', {
size: 24,
fill: 0xFFFFFF
});
backText.anchor.set(0.5, 0.5);
backText.x = 1040;
backText.y = 1050;
mapSelectContainer.addChild(backText);
// Add pulsing animation to back button
var backGlowCycle = 0;
var backGlowInterval = LK.setInterval(function () {
backGlowCycle += 0.03;
var glow = 0.4 + Math.sin(backGlowCycle) * 0.1;
backButtonBorder.alpha = glow;
}, 60);
backButton.down = function () {
LK.getSound('button_click').play();
// Enhanced back button animation
tween(backButton, {
scaleX: 0.9,
scaleY: 0.9,
alpha: 0.8
}, {
duration: 100,
onFinish: function onFinish() {
tween(backButton, {
scaleX: 1.1,
scaleY: 1.1,
alpha: 1.0
}, {
duration: 150,
onFinish: function onFinish() {
tween(backButton, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100,
onFinish: function onFinish() {
gameState = 'menu';
if (mapSelectContainer) {
mapSelectContainer.destroy();
}
if (shopContainer) {
shopContainer.visible = false;
}
if (!menuContainer) {
createMenu();
}
menuContainer.visible = true;
}
});
}
});
}
});
};
// Additional quick access buttons
// Shop button
var shopQuickButton = LK.getAsset('platform', {
width: 160,
height: 60,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFD700,
alpha: 0.8
});
shopQuickButton.x = 700;
shopQuickButton.y = 1050;
shopQuickButton.interactive = true;
shopQuickButton.buttonMode = true;
mapSelectContainer.addChild(shopQuickButton);
var shopQuickText = new Text2('SHOP', {
size: 20,
fill: 0x000000
});
shopQuickText.anchor.set(0.5, 0.5);
shopQuickText.x = 700;
shopQuickText.y = 1050;
mapSelectContainer.addChild(shopQuickText);
shopQuickButton.down = function () {
LK.getSound('button_click').play();
gameState = 'shop';
if (mapSelectContainer) {
mapSelectContainer.destroy();
}
if (!shopContainer) {
createShop();
}
};
// Settings button
var settingsQuickButton = LK.getAsset('platform', {
width: 160,
height: 60,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x44FF44,
alpha: 0.8
});
settingsQuickButton.x = 1348;
settingsQuickButton.y = 1050;
settingsQuickButton.interactive = true;
settingsQuickButton.buttonMode = true;
mapSelectContainer.addChild(settingsQuickButton);
var settingsQuickText = new Text2('SETTINGS', {
size: 18,
fill: 0xFFFFFF
});
settingsQuickText.anchor.set(0.5, 0.5);
settingsQuickText.x = 1348;
settingsQuickText.y = 1050;
mapSelectContainer.addChild(settingsQuickText);
settingsQuickButton.down = function () {
LK.getSound('button_click').play();
gameState = 'settings';
if (mapSelectContainer) {
mapSelectContainer.destroy();
}
createSettings();
};
// Level completion status indicator
var completionStatusBg = LK.getAsset('platform', {
width: 300,
height: 30,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x2a2a2a,
alpha: 0.6
});
completionStatusBg.x = 1024;
completionStatusBg.y = 1100;
mapSelectContainer.addChild(completionStatusBg);
var completionPercentage = Math.round(storage.lastCompletedLevel / storage.unlockedLevels * 100);
var completionText = new Text2('Campaign Progress: ' + completionPercentage + '% Complete', {
size: 16,
fill: completionPercentage >= 100 ? 0x44FF44 : completionPercentage >= 50 ? 0xFFD700 : 0xFFFFFF
});
completionText.anchor.set(0.5, 0.5);
completionText.x = 1024;
completionText.y = 1100;
mapSelectContainer.addChild(completionText);
}
function createShop() {
// Hide all other containers first
if (menuContainer) {
menuContainer.visible = false;
}
if (mapSelectContainer) {
mapSelectContainer.visible = false;
}
if (settingsContainer) {
settingsContainer.visible = false;
}
if (shopContainer) {
shopContainer.destroy();
}
shopContainer = new Container();
game.addChild(shopContainer);
// Enhanced background decorations
for (var i = 0; i < 12; i++) {
var bgDecor = LK.getAsset('warrior', {
width: 40,
height: 50,
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.05,
tint: 0x333333
});
bgDecor.x = 100 + i * 150 + Math.random() * 80;
bgDecor.y = 300 + Math.random() * 800;
bgDecor.rotation = Math.random() * Math.PI * 2;
shopContainer.addChild(bgDecor);
}
// Decorative border frame
var topBorder = LK.getAsset('platform', {
width: 1900,
height: 12,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFD700
});
topBorder.x = 1024;
topBorder.y = 120;
shopContainer.addChild(topBorder);
var bottomBorder = LK.getAsset('platform', {
width: 1900,
height: 12,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFD700
});
bottomBorder.x = 1024;
bottomBorder.y = 1150;
shopContainer.addChild(bottomBorder);
// Left and right decorative borders
var leftBorder = LK.getAsset('platform', {
width: 12,
height: 1000,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFD700
});
leftBorder.x = 80;
leftBorder.y = 635;
shopContainer.addChild(leftBorder);
var rightBorder = LK.getAsset('platform', {
width: 12,
height: 1000,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFD700
});
rightBorder.x = 1968;
rightBorder.y = 635;
shopContainer.addChild(rightBorder);
// Title - dynamic based on current category with enhanced styling
var categoryTitles = {
guardior: 'GUARDIOR SHOP',
enemies: 'ENEMY SKINS',
bosses: 'BOSS SKINS',
flying: 'FLYING ENEMY SKINS',
voces: 'VOICE SKINS'
};
// Title shadow for depth
var titleShadow = new Text2(categoryTitles[currentShopCategory] || 'SHOP', {
size: 64,
fill: 0x000000
});
titleShadow.anchor.set(0.5, 0.5);
titleShadow.x = 1028;
titleShadow.y = 204;
shopContainer.addChild(titleShadow);
var title = new Text2(categoryTitles[currentShopCategory] || 'SHOP', {
size: 60,
fill: 0xFFD700
});
title.anchor.set(0.5, 0.5);
title.x = 1024;
title.y = 200;
shopContainer.addChild(title);
// Animated title glow effect
var titleGlowCycle = 0;
var titleGlowInterval = LK.setInterval(function () {
titleGlowCycle += 0.03;
var glow = 0.9 + Math.sin(titleGlowCycle) * 0.1;
title.alpha = glow;
}, 60);
// Enhanced coins display with icon and styling
var coinsBg = LK.getAsset('platform', {
width: 400,
height: 80,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x1a1a1a,
alpha: 0.8
});
coinsBg.x = 1024;
coinsBg.y = 280;
shopContainer.addChild(coinsBg);
var coinsBorder = LK.getAsset('platform', {
width: 408,
height: 88,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFD700,
alpha: 0.3
});
coinsBorder.x = 1024;
coinsBorder.y = 280;
shopContainer.addChild(coinsBorder);
// Coin icon
var coinIcon = LK.getAsset('platform', {
width: 32,
height: 32,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFD700
});
coinIcon.x = 900;
coinIcon.y = 280;
shopContainer.addChild(coinIcon);
var coinsText = new Text2('Coins: ' + storage.coins, {
size: 42,
fill: 0xFFD700
});
coinsText.anchor.set(0.5, 0.5);
coinsText.x = 1024;
coinsText.y = 280;
shopContainer.addChild(coinsText);
// Animated coin counter effect
var coinsGlowCycle = 0;
var coinsGlowInterval = LK.setInterval(function () {
coinsGlowCycle += 0.05;
var glow = 0.8 + Math.sin(coinsGlowCycle) * 0.2;
coinIcon.alpha = glow;
coinsBorder.alpha = 0.3 + Math.sin(coinsGlowCycle * 1.2) * 0.1;
}, 50);
// Shop category tabs with enhanced styling - use global variable to maintain state
if (typeof currentShopCategory === 'undefined') {
var currentShopCategory = 'guardior'; // Initialize if not already set
}
// Tab container background
var tabsBackground = LK.getAsset('platform', {
width: 900,
height: 120,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x1a1a1a,
alpha: 0.7
});
tabsBackground.x = 1024;
tabsBackground.y = 360;
shopContainer.addChild(tabsBackground);
// Enhanced tab styling with shadows and borders
var tabData = [{
key: 'guardior',
text: 'GUARDIOR',
x: 450,
width: 180
}, {
key: 'enemies',
text: 'ENEMIES',
x: 650,
width: 160
}, {
key: 'bosses',
text: 'BOSSES',
x: 830,
width: 140
}, {
key: 'flying',
text: 'FLYING',
x: 990,
width: 120
}, {
key: 'voces',
text: 'VOCES',
x: 1130,
width: 120
}];
var tabButtons = {};
var tabTexts = {};
for (var t = 0; t < tabData.length; t++) {
var tab = tabData[t];
var isActive = currentShopCategory === tab.key;
// Tab shadow
var tabShadow = LK.getAsset('platform', {
width: tab.width + 8,
height: 68,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x000000,
alpha: 0.5
});
tabShadow.x = tab.x + 3;
tabShadow.y = 363;
shopContainer.addChild(tabShadow);
// Tab background
var tabButton = LK.getAsset('platform', {
width: tab.width,
height: 60,
anchorX: 0.5,
anchorY: 0.5,
tint: isActive ? 0x44FF44 : 0x555555
});
tabButton.x = tab.x;
tabButton.y = 360;
tabButton.interactive = true;
tabButton.buttonMode = true;
shopContainer.addChild(tabButton);
// Tab border glow for active tab
if (isActive) {
var tabGlow = LK.getAsset('platform', {
width: tab.width + 8,
height: 68,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x88FF88,
alpha: 0.4
});
tabGlow.x = tab.x;
tabGlow.y = 360;
shopContainer.addChild(tabGlow);
}
// Tab text
var tabText = new Text2(tab.text, {
size: tab.width > 150 ? 24 : 20,
fill: isActive ? 0x000000 : 0xFFFFFF
});
tabText.anchor.set(0.5, 0.5);
tabText.x = tab.x;
tabText.y = 360;
shopContainer.addChild(tabText);
// Store references for event handlers
tabButtons[tab.key] = tabButton;
tabTexts[tab.key] = tabText;
// Add hover effects
(function (button, text, key, originalTint) {
button.down = function () {
LK.getSound('button_click').play();
currentShopCategory = key;
createShop();
};
})(tabButton, tabText, tab.key, isActive ? 0x44FF44 : 0x555555);
}
// Create legacy tab variables for compatibility with existing event handlers
var guardiorTab = tabButtons.guardior;
var enemyTab = tabButtons.enemies;
var bossTab = tabButtons.bosses;
var flyingTab = tabButtons.flying;
var voicesTab = tabButtons.voces;
// Tab event handlers
guardiorTab.down = function () {
LK.getSound('button_click').play();
currentShopCategory = 'guardior';
createShop();
};
enemyTab.down = function () {
LK.getSound('button_click').play();
currentShopCategory = 'enemies';
createShop();
};
bossTab.down = function () {
LK.getSound('button_click').play();
currentShopCategory = 'bosses';
createShop();
};
flyingTab.down = function () {
LK.getSound('button_click').play();
currentShopCategory = 'flying';
createShop();
};
voicesTab.down = function () {
LK.getSound('button_click').play();
currentShopCategory = 'voces';
createShop();
};
// Define available skins first
var skins = [{
id: 'default',
name: 'Classic Guardior',
price: 0,
color: 0xFFFFFF,
description: 'The original warrior'
}, {
id: 'red',
name: 'Fire Warrior',
price: 100,
color: 0xFF4444,
description: 'Blazing red armor'
}, {
id: 'blue',
name: 'Ice Knight',
price: 150,
color: 0x4444FF,
description: 'Frozen blue steel'
}, {
id: 'green',
name: 'Forest Guardian',
price: 200,
color: 0x44FF44,
description: 'Nature\'s protector'
}, {
id: 'purple',
name: 'Shadow Lord',
price: 300,
color: 0x8844FF,
description: 'Master of darkness'
}, {
id: 'gold',
name: 'Golden Hero',
price: 500,
color: 0xFFD700,
description: 'Legendary champion'
}, {
id: 'orange',
name: 'Sunset Warrior',
price: 120,
color: 0xFF8844,
description: 'Strength of dusk'
}, {
id: 'cyan',
name: 'Ocean Guardian',
price: 180,
color: 0x44FFFF,
description: 'Master of tides'
}, {
id: 'magenta',
name: 'Mystic Knight',
price: 250,
color: 0xFF44FF,
description: 'Arcane protector'
}, {
id: 'silver',
name: 'Steel Champion',
price: 350,
color: 0xC0C0C0,
description: 'Unbreakable will'
}, {
id: 'lime',
name: 'Toxic Avenger',
price: 280,
color: 0x88FF44,
description: 'Venomous fighter'
}, {
id: 'bronze',
name: 'Ancient Warrior',
price: 400,
color: 0xCD7F32,
description: 'Timeless legend'
}];
// Define skin categories
var skinCategories = {
guardior: skins,
enemies: [{
id: 'default',
name: 'Red Warrior',
price: 0,
color: 0xFF0000,
description: 'Standard enemy'
}, {
id: 'dark',
name: 'Shadow Fighter',
price: 80,
color: 0x444444,
description: 'Dark assassin'
}, {
id: 'green',
name: 'Forest Bandit',
price: 120,
color: 0x228B22,
description: 'Woodland raider'
}, {
id: 'purple',
name: 'Void Warrior',
price: 150,
color: 0x8B008B,
description: 'Corrupted fighter'
}, {
id: 'orange',
name: 'Fire Soldier',
price: 100,
color: 0xFF6347,
description: 'Burning berserker'
}, {
id: 'blue',
name: 'Ice Guardian',
price: 140,
color: 0x4169E1,
description: 'Frozen sentinel'
}],
bosses: [{
id: 'default',
name: 'Purple Giant',
price: 0,
color: 0x800080,
description: 'Original boss'
}, {
id: 'crimson',
name: 'Crimson Overlord',
price: 200,
color: 0xDC143C,
description: 'Blood tyrant'
}, {
id: 'shadow',
name: 'Dark Emperor',
price: 300,
color: 0x2F2F2F,
description: 'Shadow master'
}, {
id: 'golden',
name: 'Golden Titan',
price: 400,
color: 0xFFD700,
description: 'Legendary ruler'
}, {
id: 'emerald',
name: 'Emerald Colossus',
price: 350,
color: 0x50C878,
description: 'Nature\'s wrath'
}, {
id: 'cyber',
name: 'Cyber Destroyer',
price: 450,
color: 0x00CED1,
description: 'Tech nightmare'
}, {
id: 'inferno',
name: 'Inferno Lord',
price: 500,
color: 0xFF4500,
description: 'Master of flames'
}, {
id: 'frost',
name: 'Frost Monarch',
price: 480,
color: 0x87CEEB,
description: 'Ruler of ice'
}, {
id: 'void',
name: 'Void Emperor',
price: 520,
color: 0x1C1C1C,
description: 'Lord of nothingness'
}],
flying: [{
id: 'default',
name: 'Brown Flyer',
price: 0,
color: 0x8B4513,
description: 'Standard flying enemy'
}, {
id: 'black',
name: 'Night Flyer',
price: 90,
color: 0x2F2F2F,
description: 'Shadow wings'
}, {
id: 'silver',
name: 'Steel Wing',
price: 130,
color: 0xC0C0C0,
description: 'Metal predator'
}, {
id: 'golden',
name: 'Golden Eagle',
price: 180,
color: 0xFFD700,
description: 'Sky sovereign'
}, {
id: 'red',
name: 'Fire Bird',
price: 110,
color: 0xFF4500,
description: 'Burning flyer'
}, {
id: 'blue',
name: 'Storm Wing',
price: 160,
color: 0x1E90FF,
description: 'Lightning fast'
}, {
id: 'toxic',
name: 'Toxic Wasp',
price: 140,
color: 0x9ACD32,
description: 'Poisonous hunter'
}, {
id: 'crystal',
name: 'Crystal Flyer',
price: 200,
color: 0xE6E6FA,
description: 'Crystalline predator'
}, {
id: 'shadow',
name: 'Shadow Bat',
price: 170,
color: 0x404040,
description: 'Darkness incarnate'
}],
voces: [{
id: 'default',
name: 'Classic Voice',
price: 0,
color: 0xFFFFFF,
description: 'Original warrior voice'
}, {
id: 'deep',
name: 'Deep Voice',
price: 80,
color: 0x4169E1,
description: 'Commanding tone'
}, {
id: 'heroic',
name: 'Heroic Voice',
price: 120,
color: 0xFFD700,
description: 'Noble warrior'
}, {
id: 'mysterious',
name: 'Mysterious Voice',
price: 150,
color: 0x8B008B,
description: 'Enigmatic whispers'
}, {
id: 'robotic',
name: 'Robotic Voice',
price: 100,
color: 0x00CED1,
description: 'Cyber warrior'
}, {
id: 'ancient',
name: 'Ancient Voice',
price: 180,
color: 0xCD7F32,
description: 'Wise elder'
}]
};
var currentSkins = skinCategories[currentShopCategory];
var storageKeys = {
guardior: {
selected: 'selectedSkin',
owned: 'ownedSkins'
},
enemies: {
selected: 'selectedEnemySkin',
owned: 'ownedEnemySkins'
},
bosses: {
selected: 'selectedBossSkin',
owned: 'ownedBossSkins'
},
flying: {
selected: 'selectedFlyingSkin',
owned: 'ownedFlyingSkins'
},
voces: {
selected: 'selectedVoiceSkin',
owned: 'ownedVoiceSkins'
}
};
// Create organized skins display container with proper bounds
var skinsDisplayArea = new Container();
shopContainer.addChild(skinsDisplayArea);
// Create background area for skins display
var skinsAreaBg = LK.getAsset('platform', {
width: 1600,
height: 600,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x1a1a1a,
alpha: 0.3
});
skinsAreaBg.x = 1024;
skinsAreaBg.y = 700;
skinsDisplayArea.addChild(skinsAreaBg);
// Create skins grid container with proper organization
var skinsGrid = new Container();
skinsDisplayArea.addChild(skinsGrid);
// Enhanced grid layout with better organization
var itemsPerRow = 4; // Better fit for screen width
var itemWidth = 220; // Slightly smaller for better fit
var itemHeight = 180; // Compact height
var spacingX = 60;
var spacingY = 40;
var startX = 300; // Start position for grid
var startY = 500;
var maxRows = 3; // Limit visible rows
// Calculate grid bounds for container organization
var gridWidth = itemsPerRow * (itemWidth + spacingX) - spacingX;
var gridHeight = maxRows * (itemHeight + spacingY) - spacingY;
// Center the grid within the display area
var gridStartX = 1024 - gridWidth / 2 + itemWidth / 2;
var gridStartY = 550;
for (var i = 0; i < currentSkins.length; i++) {
var skin = currentSkins[i];
var row = Math.floor(i / itemsPerRow);
var col = i % itemsPerRow;
var itemX = gridStartX + col * (itemWidth + spacingX);
var itemY = gridStartY + row * (itemHeight + spacingY);
// Only show skins that fit in visible area
if (row >= maxRows) {
continue; // Skip items that don't fit in visible area
}
var isOwned = storage[storageKeys[currentShopCategory].owned].indexOf(skin.id) !== -1;
var isEquipped = storage[storageKeys[currentShopCategory].selected] === skin.id;
// Create individual skin container for better organization
var skinItemContainer = new Container();
skinsGrid.addChild(skinItemContainer);
// Enhanced skin preview background with shadow and depth
var skinShadow = LK.getAsset('platform', {
width: itemWidth + 8,
height: itemHeight + 8,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x000000,
alpha: 0.4
});
skinShadow.x = itemX + 4;
skinShadow.y = itemY + 4;
skinItemContainer.addChild(skinShadow);
// Main skin background with enhanced colors and better organization
var bgColor = isEquipped ? 0x44FF44 : isOwned ? 0x4444FF : 0x555555;
var skinBg = LK.getAsset('platform', {
width: itemWidth,
height: itemHeight,
anchorX: 0.5,
anchorY: 0.5,
tint: bgColor
});
skinBg.x = itemX;
skinBg.y = itemY;
skinBg.interactive = true;
skinBg.buttonMode = true;
skinItemContainer.addChild(skinBg);
// Enhanced border for special states with better visual hierarchy
if (isEquipped) {
var equippedBorder = LK.getAsset('platform', {
width: itemWidth + 12,
height: itemHeight + 12,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x88FF88,
alpha: 0.8
});
equippedBorder.x = itemX;
equippedBorder.y = itemY;
skinItemContainer.addChild(equippedBorder);
// Add equipped indicator
var equippedIcon = new Text2('★', {
size: 24,
fill: 0x00FF00
});
equippedIcon.anchor.set(0.5, 0.5);
equippedIcon.x = itemX + itemWidth / 2 - 20;
equippedIcon.y = itemY - itemHeight / 2 + 20;
skinItemContainer.addChild(equippedIcon);
} else if (isOwned) {
var ownedBorder = LK.getAsset('platform', {
width: itemWidth + 8,
height: itemHeight + 8,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x8888FF,
alpha: 0.6
});
ownedBorder.x = itemX;
ownedBorder.y = itemY;
skinItemContainer.addChild(ownedBorder);
// Add owned indicator
var ownedIcon = new Text2('✓', {
size: 20,
fill: 0xFFD700
});
ownedIcon.anchor.set(0.5, 0.5);
ownedIcon.x = itemX + itemWidth / 2 - 20;
ownedIcon.y = itemY - itemHeight / 2 + 20;
skinItemContainer.addChild(ownedIcon);
}
// Inner content area with better organization
var contentBg = LK.getAsset('platform', {
width: itemWidth - 20,
height: itemHeight - 20,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x2a2a2a,
alpha: 0.9
});
contentBg.x = itemX;
contentBg.y = itemY;
skinItemContainer.addChild(contentBg);
// Enhanced skin preview with category-appropriate assets
var previewAssets = {
guardior: 'warrior',
enemies: 'enemy_body',
bosses: 'boss',
flying: 'enemy_body',
voces: 'warrior'
};
var previewSize = currentShopCategory === 'bosses' ? {
w: 70,
h: 80
} : {
w: 60,
h: 70
};
var skinPreview = LK.getAsset(previewAssets[currentShopCategory], {
width: previewSize.w,
height: previewSize.h,
anchorX: 0.5,
anchorY: 0.5,
tint: skin.color
});
skinPreview.x = itemX;
skinPreview.y = itemY - 25;
skinItemContainer.addChild(skinPreview);
// Skin name with better sizing and organization
var skinName = new Text2(skin.name, {
size: 18,
fill: 0xFFFFFF
});
skinName.anchor.set(0.5, 0.5);
skinName.x = itemX;
skinName.y = itemY + 20;
skinItemContainer.addChild(skinName);
// Enhanced description text with better fit
var skinDesc = new Text2(skin.description, {
size: 14,
fill: 0xCCCCCC
});
skinDesc.anchor.set(0.5, 0.5);
skinDesc.x = itemX;
skinDesc.y = itemY + 40;
skinItemContainer.addChild(skinDesc);
// Price or status with enhanced styling and better organization
var statusText;
if (isOwned) {
if (isEquipped) {
statusText = new Text2('EQUIPPED', {
size: 16,
fill: 0x00FF00
});
} else {
statusText = new Text2('OWNED', {
size: 16,
fill: 0xFFD700
});
}
} else {
var canAfford = storage.coins >= skin.price;
statusText = new Text2(skin.price + ' COINS', {
size: 16,
fill: canAfford ? 0xFFFFFF : 0xFF4444
});
// Add coin icon for price display with better positioning
if (!isOwned) {
var priceIcon = LK.getAsset('platform', {
width: 16,
height: 16,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFD700
});
priceIcon.x = itemX - 30;
priceIcon.y = itemY + 60;
skinItemContainer.addChild(priceIcon);
}
}
statusText.anchor.set(0.5, 0.5);
statusText.x = itemX;
statusText.y = itemY + 60;
skinItemContainer.addChild(statusText);
// Add rarity indicator for expensive items with better organization
if (skin.price >= 300) {
var rarityBadge = LK.getAsset('platform', {
width: 35,
height: 18,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFD700
});
rarityBadge.x = itemX - itemWidth / 2 + 25;
rarityBadge.y = itemY - itemHeight / 2 + 15;
skinItemContainer.addChild(rarityBadge);
var rarityText = new Text2('RARE', {
size: 10,
fill: 0x000000
});
rarityText.anchor.set(0.5, 0.5);
rarityText.x = rarityBadge.x;
rarityText.y = rarityBadge.y;
skinItemContainer.addChild(rarityText);
}
// Create organized click handler with proper scope
(function (skinData, background, container) {
background.down = function () {
LK.getSound('button_click').play();
var owned = storage[storageKeys[currentShopCategory].owned].indexOf(skinData.id) !== -1;
if (owned) {
// Equip the skin
storage[storageKeys[currentShopCategory].selected] = skinData.id;
// Refresh the shop display
shopContainer.visible = false;
createShop();
} else if (storage.coins >= skinData.price) {
// Purchase the skin
storage.coins -= skinData.price;
storage[storageKeys[currentShopCategory].owned].push(skinData.id);
storage[storageKeys[currentShopCategory].selected] = skinData.id;
// Refresh the shop display
shopContainer.visible = false;
createShop();
} else {
// Not enough coins - flash red with better feedback
tween(background, {
tint: 0xFF0000
}, {
duration: 200,
onFinish: function onFinish() {
tween(background, {
tint: bgColor
}, {
duration: 200
});
}
});
// Shake the container for better feedback
tween(container, {
x: container.x + 10
}, {
duration: 50,
onFinish: function onFinish() {
tween(container, {
x: container.x - 20
}, {
duration: 50,
onFinish: function onFinish() {
tween(container, {
x: container.x + 10
}, {
duration: 50
});
}
});
}
});
}
};
})(skin, skinBg, skinItemContainer);
}
// Add navigation indicators if there are more skins than can be displayed
var totalRows = Math.ceil(currentSkins.length / itemsPerRow);
if (totalRows > maxRows) {
// Add scroll indicator
var scrollIndicator = new Text2('More skins available - ' + (currentSkins.length - maxRows * itemsPerRow) + ' more', {
size: 24,
fill: 0xFFD700
});
scrollIndicator.anchor.set(0.5, 0.5);
scrollIndicator.x = 1024;
scrollIndicator.y = gridStartY + maxRows * (itemHeight + spacingY) + 30;
skinsDisplayArea.addChild(scrollIndicator);
// Add blinking effect to scroll indicator
var scrollBlinkCycle = 0;
var scrollBlinkInterval = LK.setInterval(function () {
scrollBlinkCycle += 0.05;
var alpha = 0.5 + Math.sin(scrollBlinkCycle) * 0.5;
scrollIndicator.alpha = alpha;
}, 50);
}
// Add category-specific organization message
var organizationMessage = new Text2('Organized by: ' + (currentShopCategory === 'guardior' ? 'Hero Skins' : currentShopCategory === 'enemies' ? 'Enemy Variations' : currentShopCategory === 'bosses' ? 'Boss Themes' : currentShopCategory === 'flying' ? 'Flying Units' : 'Voice Packs'), {
size: 20,
fill: 0xCCCCCC
});
organizationMessage.anchor.set(0.5, 0.5);
organizationMessage.x = 1024;
organizationMessage.y = 460;
skinsDisplayArea.addChild(organizationMessage);
// Enhanced back button with styling - positioned for organized layout
var backButtonShadow = LK.getAsset('platform', {
width: 228,
height: 78,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x000000,
alpha: 0.5
});
backButtonShadow.x = 1028;
backButtonShadow.y = 1064; // Positioned below organized skins area
shopContainer.addChild(backButtonShadow);
var backButton = LK.getAsset('platform', {
width: 220,
height: 70,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFF4444
});
backButton.x = 1024;
backButton.y = 1060; // Positioned below organized skins area
backButton.interactive = true;
backButton.buttonMode = true;
shopContainer.addChild(backButton);
var backButtonBorder = LK.getAsset('platform', {
width: 228,
height: 78,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFF8888,
alpha: 0.4
});
backButtonBorder.x = 1024;
backButtonBorder.y = 1200;
shopContainer.addChild(backButtonBorder);
var backText = new Text2('BACK TO MENU', {
size: 28,
fill: 0xFFFFFF
});
backText.anchor.set(0.5, 0.5);
backText.x = backButton.x;
backText.y = backButton.y;
shopContainer.addChild(backText);
// Add button hover effect
var backButtonGlow = 0;
var backGlowInterval = LK.setInterval(function () {
backButtonGlow += 0.04;
var glowAlpha = 0.4 + Math.sin(backButtonGlow) * 0.1;
backButtonBorder.alpha = glowAlpha;
}, 60);
backButton.down = function () {
LK.getSound('button_click').play();
gameState = 'menu';
if (shopContainer) {
shopContainer.destroy();
}
if (!menuContainer) {
createMenu();
}
menuContainer.visible = true;
};
}
function createSettings() {
// Hide all other containers first
if (menuContainer) {
menuContainer.visible = false;
}
if (mapSelectContainer) {
mapSelectContainer.visible = false;
}
if (settingsContainer) {
settingsContainer.destroy();
}
settingsContainer = new Container();
game.addChild(settingsContainer);
// Enhanced background decorations with animated particles
for (var i = 0; i < 20; i++) {
var bgParticle = LK.getAsset('platform', {
width: 6,
height: 6,
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.2,
tint: 0x44FF44
});
bgParticle.x = Math.random() * 2048;
bgParticle.y = Math.random() * 1400 + 200;
settingsContainer.addChild(bgParticle);
// Animate particles with subtle movement
tween(bgParticle, {
y: bgParticle.y - 100,
alpha: 0.05
}, {
duration: 5000 + Math.random() * 3000,
easing: tween.easeInOut,
repeat: -1,
yoyo: true
});
}
// Enhanced decorative frame with better styling
var topBorder = LK.getAsset('platform', {
width: 1800,
height: 15,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x44FF44
});
topBorder.x = 1024;
topBorder.y = 150;
settingsContainer.addChild(topBorder);
var bottomBorder = LK.getAsset('platform', {
width: 1800,
height: 15,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x44FF44
});
bottomBorder.x = 1024;
bottomBorder.y = 1150;
settingsContainer.addChild(bottomBorder);
// Enhanced title with shadow and glow
var titleShadow = new Text2('SETTINGS & OPTIONS', {
size: 66,
fill: 0x000000
});
titleShadow.anchor.set(0.5, 0.5);
titleShadow.x = 1028;
titleShadow.y = 254;
settingsContainer.addChild(titleShadow);
var title = new Text2('SETTINGS & OPTIONS', {
size: 62,
fill: 0x44FF44
});
title.anchor.set(0.5, 0.5);
title.x = 1024;
title.y = 250;
settingsContainer.addChild(title);
// Animated title glow effect
var titleGlowCycle = 0;
var titleGlowInterval = LK.setInterval(function () {
titleGlowCycle += 0.03;
var glow = 0.9 + Math.sin(titleGlowCycle) * 0.1;
title.alpha = glow;
}, 60);
// Initialize storage defaults for new settings
if (storage.graphicsQuality === undefined) {
storage.graphicsQuality = 'high';
}
if (storage.particleEffects === undefined) {
storage.particleEffects = true;
}
if (storage.screenShake === undefined) {
storage.screenShake = true;
}
if (storage.autoSave === undefined) {
storage.autoSave = true;
}
if (storage.showFPS === undefined) {
storage.showFPS = false;
}
if (storage.controlSensitivity === undefined) {
storage.controlSensitivity = 1.0;
}
if (storage.hapticFeedback === undefined) {
storage.hapticFeedback = true;
}
if (storage.colorBlindMode === undefined) {
storage.colorBlindMode = false;
}
// Settings categories container with organized layout
var settingsMainContainer = new Container();
settingsContainer.addChild(settingsMainContainer);
// AUDIO SETTINGS SECTION
var audioSectionBg = LK.getAsset('platform', {
width: 900,
height: 180,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x1a1a1a,
alpha: 0.8
});
audioSectionBg.x = 1024;
audioSectionBg.y = 400;
settingsMainContainer.addChild(audioSectionBg);
var audioSectionBorder = LK.getAsset('platform', {
width: 908,
height: 188,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x44FF44,
alpha: 0.3
});
audioSectionBorder.x = 1024;
audioSectionBorder.y = 400;
settingsMainContainer.addChild(audioSectionBorder);
var audioTitle = new Text2('AUDIO SETTINGS', {
size: 32,
fill: 0x44FF44
});
audioTitle.anchor.set(0.5, 0.5);
audioTitle.x = 1024;
audioTitle.y = 340;
settingsMainContainer.addChild(audioTitle);
// Music volume with enhanced controls
var musicLabel = new Text2('Music Volume: ' + Math.round(storage.musicVolume * 100) + '%', {
size: 28,
fill: 0xFFFFFF
});
musicLabel.anchor.set(0.5, 0.5);
musicLabel.x = 1024;
musicLabel.y = 375;
settingsMainContainer.addChild(musicLabel);
var musicDown = LK.getAsset('platform', {
width: 70,
height: 50,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFF4444
});
musicDown.x = 650;
musicDown.y = 375;
musicDown.interactive = true;
musicDown.buttonMode = true;
settingsMainContainer.addChild(musicDown);
var musicDownText = new Text2('-', {
size: 35,
fill: 0xFFFFFF
});
musicDownText.anchor.set(0.5, 0.5);
musicDownText.x = musicDown.x;
musicDownText.y = musicDown.y;
settingsMainContainer.addChild(musicDownText);
var musicUp = LK.getAsset('platform', {
width: 70,
height: 50,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x44FF44
});
musicUp.x = 1398;
musicUp.y = 375;
musicUp.interactive = true;
musicUp.buttonMode = true;
settingsMainContainer.addChild(musicUp);
var musicUpText = new Text2('+', {
size: 35,
fill: 0xFFFFFF
});
musicUpText.anchor.set(0.5, 0.5);
musicUpText.x = musicUp.x;
musicUpText.y = musicUp.y;
settingsMainContainer.addChild(musicUpText);
// Enhanced music volume bar
var musicVolumeBg = LK.getAsset('platform', {
width: 300,
height: 15,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x333333
});
musicVolumeBg.x = 1024;
musicVolumeBg.y = 405;
settingsMainContainer.addChild(musicVolumeBg);
var musicVolumeFill = LK.getAsset('platform', {
width: 290 * storage.musicVolume,
height: 10,
anchorX: 0,
anchorY: 0.5,
tint: 0x44FF44
});
musicVolumeFill.x = 879; // Start position for left-aligned fill
musicVolumeFill.y = 405;
settingsMainContainer.addChild(musicVolumeFill);
musicDown.down = function () {
storage.musicVolume = Math.max(0, storage.musicVolume - 0.1);
musicLabel.setText('Music Volume: ' + Math.round(storage.musicVolume * 100) + '%');
musicVolumeFill.width = 290 * storage.musicVolume;
LK.getSound('button_click').play();
// Apply volume change immediately
LK.playMusic('menu_music', {
volume: storage.musicVolume
});
};
musicUp.down = function () {
storage.musicVolume = Math.min(1, storage.musicVolume + 0.1);
musicLabel.setText('Music Volume: ' + Math.round(storage.musicVolume * 100) + '%');
musicVolumeFill.width = 290 * storage.musicVolume;
LK.getSound('button_click').play();
// Apply volume change immediately
LK.playMusic('menu_music', {
volume: storage.musicVolume
});
};
// Sound volume with enhanced controls
var soundLabel = new Text2('Sound Volume: ' + Math.round(storage.soundVolume * 100) + '%', {
size: 28,
fill: 0xFFFFFF
});
soundLabel.anchor.set(0.5, 0.5);
soundLabel.x = 1024;
soundLabel.y = 440;
settingsMainContainer.addChild(soundLabel);
var soundDown = LK.getAsset('platform', {
width: 70,
height: 50,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFF4444
});
soundDown.x = 650;
soundDown.y = 440;
soundDown.interactive = true;
soundDown.buttonMode = true;
settingsMainContainer.addChild(soundDown);
var soundDownText = new Text2('-', {
size: 35,
fill: 0xFFFFFF
});
soundDownText.anchor.set(0.5, 0.5);
soundDownText.x = soundDown.x;
soundDownText.y = soundDown.y;
settingsMainContainer.addChild(soundDownText);
var soundUp = LK.getAsset('platform', {
width: 70,
height: 50,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x44FF44
});
soundUp.x = 1398;
soundUp.y = 440;
soundUp.interactive = true;
soundUp.buttonMode = true;
settingsMainContainer.addChild(soundUp);
var soundUpText = new Text2('+', {
size: 35,
fill: 0xFFFFFF
});
soundUpText.anchor.set(0.5, 0.5);
soundUpText.x = soundUp.x;
soundUpText.y = soundUp.y;
settingsMainContainer.addChild(soundUpText);
// Enhanced sound volume bar
var soundVolumeBg = LK.getAsset('platform', {
width: 300,
height: 15,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x333333
});
soundVolumeBg.x = 1024;
soundVolumeBg.y = 470;
settingsMainContainer.addChild(soundVolumeBg);
var soundVolumeFill = LK.getAsset('platform', {
width: 290 * storage.soundVolume,
height: 10,
anchorX: 0,
anchorY: 0.5,
tint: 0xFF8844
});
soundVolumeFill.x = 879;
soundVolumeFill.y = 470;
settingsMainContainer.addChild(soundVolumeFill);
soundDown.down = function () {
storage.soundVolume = Math.max(0, storage.soundVolume - 0.1);
soundLabel.setText('Sound Volume: ' + Math.round(storage.soundVolume * 100) + '%');
soundVolumeFill.width = 290 * storage.soundVolume;
LK.getSound('button_click').play();
};
soundUp.down = function () {
storage.soundVolume = Math.min(1, storage.soundVolume + 0.1);
soundLabel.setText('Sound Volume: ' + Math.round(storage.soundVolume * 100) + '%');
soundVolumeFill.width = 290 * storage.soundVolume;
LK.getSound('button_click').play();
};
// GRAPHICS SETTINGS SECTION
var graphicsSectionBg = LK.getAsset('platform', {
width: 900,
height: 200,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x1a1a1a,
alpha: 0.8
});
graphicsSectionBg.x = 1024;
graphicsSectionBg.y = 580;
settingsMainContainer.addChild(graphicsSectionBg);
var graphicsSectionBorder = LK.getAsset('platform', {
width: 908,
height: 208,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x4444FF,
alpha: 0.3
});
graphicsSectionBorder.x = 1024;
graphicsSectionBorder.y = 580;
settingsMainContainer.addChild(graphicsSectionBorder);
var graphicsTitle = new Text2('GRAPHICS & PERFORMANCE', {
size: 32,
fill: 0x4444FF
});
graphicsTitle.anchor.set(0.5, 0.5);
graphicsTitle.x = 1024;
graphicsTitle.y = 520;
settingsMainContainer.addChild(graphicsTitle);
// Graphics Quality Setting
var qualityLabel = new Text2('Graphics Quality: ' + storage.graphicsQuality.toUpperCase(), {
size: 26,
fill: 0xFFFFFF
});
qualityLabel.anchor.set(0.5, 0.5);
qualityLabel.x = 1024;
qualityLabel.y = 555;
settingsMainContainer.addChild(qualityLabel);
var qualityDown = LK.getAsset('platform', {
width: 80,
height: 45,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFF4444
});
qualityDown.x = 700;
qualityDown.y = 555;
qualityDown.interactive = true;
qualityDown.buttonMode = true;
settingsMainContainer.addChild(qualityDown);
var qualityDownText = new Text2('◀', {
size: 28,
fill: 0xFFFFFF
});
qualityDownText.anchor.set(0.5, 0.5);
qualityDownText.x = qualityDown.x;
qualityDownText.y = qualityDown.y;
settingsMainContainer.addChild(qualityDownText);
var qualityUp = LK.getAsset('platform', {
width: 80,
height: 45,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x44FF44
});
qualityUp.x = 1348;
qualityUp.y = 555;
qualityUp.interactive = true;
qualityUp.buttonMode = true;
settingsMainContainer.addChild(qualityUp);
var qualityUpText = new Text2('▶', {
size: 28,
fill: 0xFFFFFF
});
qualityUpText.anchor.set(0.5, 0.5);
qualityUpText.x = qualityUp.x;
qualityUpText.y = qualityUp.y;
settingsMainContainer.addChild(qualityUpText);
var qualityOptions = ['low', 'medium', 'high', 'ultra'];
var currentQualityIndex = qualityOptions.indexOf(storage.graphicsQuality);
qualityDown.down = function () {
currentQualityIndex = Math.max(0, currentQualityIndex - 1);
storage.graphicsQuality = qualityOptions[currentQualityIndex];
qualityLabel.setText('Graphics Quality: ' + storage.graphicsQuality.toUpperCase());
LK.getSound('button_click').play();
};
qualityUp.down = function () {
currentQualityIndex = Math.min(qualityOptions.length - 1, currentQualityIndex + 1);
storage.graphicsQuality = qualityOptions[currentQualityIndex];
qualityLabel.setText('Graphics Quality: ' + storage.graphicsQuality.toUpperCase());
LK.getSound('button_click').play();
};
// Particle Effects Toggle
var particleLabel = new Text2('Particle Effects: ' + (storage.particleEffects ? 'ON' : 'OFF'), {
size: 24,
fill: 0xFFFFFF
});
particleLabel.anchor.set(0.5, 0.5);
particleLabel.x = 800;
particleLabel.y = 590;
settingsMainContainer.addChild(particleLabel);
var particleToggle = LK.getAsset('platform', {
width: 100,
height: 40,
anchorX: 0.5,
anchorY: 0.5,
tint: storage.particleEffects ? 0x44FF44 : 0x666666
});
particleToggle.x = 1100;
particleToggle.y = 590;
particleToggle.interactive = true;
particleToggle.buttonMode = true;
settingsMainContainer.addChild(particleToggle);
var particleToggleText = new Text2(storage.particleEffects ? 'ON' : 'OFF', {
size: 20,
fill: 0xFFFFFF
});
particleToggleText.anchor.set(0.5, 0.5);
particleToggleText.x = particleToggle.x;
particleToggleText.y = particleToggle.y;
settingsMainContainer.addChild(particleToggleText);
particleToggle.down = function () {
storage.particleEffects = !storage.particleEffects;
particleLabel.setText('Particle Effects: ' + (storage.particleEffects ? 'ON' : 'OFF'));
particleToggleText.setText(storage.particleEffects ? 'ON' : 'OFF');
particleToggle.tint = storage.particleEffects ? 0x44FF44 : 0x666666;
LK.getSound('button_click').play();
};
// Screen Shake Toggle
var shakeLabel = new Text2('Screen Shake: ' + (storage.screenShake ? 'ON' : 'OFF'), {
size: 24,
fill: 0xFFFFFF
});
shakeLabel.anchor.set(0.5, 0.5);
shakeLabel.x = 800;
shakeLabel.y = 625;
settingsMainContainer.addChild(shakeLabel);
var shakeToggle = LK.getAsset('platform', {
width: 100,
height: 40,
anchorX: 0.5,
anchorY: 0.5,
tint: storage.screenShake ? 0x44FF44 : 0x666666
});
shakeToggle.x = 1100;
shakeToggle.y = 625;
shakeToggle.interactive = true;
shakeToggle.buttonMode = true;
settingsMainContainer.addChild(shakeToggle);
var shakeToggleText = new Text2(storage.screenShake ? 'ON' : 'OFF', {
size: 20,
fill: 0xFFFFFF
});
shakeToggleText.anchor.set(0.5, 0.5);
shakeToggleText.x = shakeToggle.x;
shakeToggleText.y = shakeToggle.y;
settingsMainContainer.addChild(shakeToggleText);
shakeToggle.down = function () {
storage.screenShake = !storage.screenShake;
shakeLabel.setText('Screen Shake: ' + (storage.screenShake ? 'ON' : 'OFF'));
shakeToggleText.setText(storage.screenShake ? 'ON' : 'OFF');
shakeToggle.tint = storage.screenShake ? 0x44FF44 : 0x666666;
LK.getSound('button_click').play();
};
// GAMEPLAY SETTINGS SECTION
var gameplaySectionBg = LK.getAsset('platform', {
width: 900,
height: 200,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x1a1a1a,
alpha: 0.8
});
gameplaySectionBg.x = 1024;
gameplaySectionBg.y = 760;
settingsMainContainer.addChild(gameplaySectionBg);
var gameplaySectionBorder = LK.getAsset('platform', {
width: 908,
height: 208,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFD700,
alpha: 0.3
});
gameplaySectionBorder.x = 1024;
gameplaySectionBorder.y = 760;
settingsMainContainer.addChild(gameplaySectionBorder);
var gameplayTitle = new Text2('GAMEPLAY OPTIONS', {
size: 32,
fill: 0xFFD700
});
gameplayTitle.anchor.set(0.5, 0.5);
gameplayTitle.x = 1024;
gameplayTitle.y = 700;
settingsMainContainer.addChild(gameplayTitle);
// Control Sensitivity Setting
var sensitivityLabel = new Text2('Control Sensitivity: ' + Math.round(storage.controlSensitivity * 100) + '%', {
size: 26,
fill: 0xFFFFFF
});
sensitivityLabel.anchor.set(0.5, 0.5);
sensitivityLabel.x = 1024;
sensitivityLabel.y = 735;
settingsMainContainer.addChild(sensitivityLabel);
var sensitivityDown = LK.getAsset('platform', {
width: 70,
height: 50,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFF4444
});
sensitivityDown.x = 650;
sensitivityDown.y = 735;
sensitivityDown.interactive = true;
sensitivityDown.buttonMode = true;
settingsMainContainer.addChild(sensitivityDown);
var sensitivityDownText = new Text2('-', {
size: 35,
fill: 0xFFFFFF
});
sensitivityDownText.anchor.set(0.5, 0.5);
sensitivityDownText.x = sensitivityDown.x;
sensitivityDownText.y = sensitivityDown.y;
settingsMainContainer.addChild(sensitivityDownText);
var sensitivityUp = LK.getAsset('platform', {
width: 70,
height: 50,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x44FF44
});
sensitivityUp.x = 1398;
sensitivityUp.y = 735;
sensitivityUp.interactive = true;
sensitivityUp.buttonMode = true;
settingsMainContainer.addChild(sensitivityUp);
var sensitivityUpText = new Text2('+', {
size: 35,
fill: 0xFFFFFF
});
sensitivityUpText.anchor.set(0.5, 0.5);
sensitivityUpText.x = sensitivityUp.x;
sensitivityUpText.y = sensitivityUp.y;
settingsMainContainer.addChild(sensitivityUpText);
sensitivityDown.down = function () {
storage.controlSensitivity = Math.max(0.5, storage.controlSensitivity - 0.1);
sensitivityLabel.setText('Control Sensitivity: ' + Math.round(storage.controlSensitivity * 100) + '%');
LK.getSound('button_click').play();
};
sensitivityUp.down = function () {
storage.controlSensitivity = Math.min(2.0, storage.controlSensitivity + 0.1);
sensitivityLabel.setText('Control Sensitivity: ' + Math.round(storage.controlSensitivity * 100) + '%');
LK.getSound('button_click').play();
};
// Auto-Save Toggle
var autoSaveLabel = new Text2('Auto-Save: ' + (storage.autoSave ? 'ON' : 'OFF'), {
size: 24,
fill: 0xFFFFFF
});
autoSaveLabel.anchor.set(0.5, 0.5);
autoSaveLabel.x = 800;
autoSaveLabel.y = 770;
settingsMainContainer.addChild(autoSaveLabel);
var autoSaveToggle = LK.getAsset('platform', {
width: 100,
height: 40,
anchorX: 0.5,
anchorY: 0.5,
tint: storage.autoSave ? 0x44FF44 : 0x666666
});
autoSaveToggle.x = 1100;
autoSaveToggle.y = 770;
autoSaveToggle.interactive = true;
autoSaveToggle.buttonMode = true;
settingsMainContainer.addChild(autoSaveToggle);
var autoSaveToggleText = new Text2(storage.autoSave ? 'ON' : 'OFF', {
size: 20,
fill: 0xFFFFFF
});
autoSaveToggleText.anchor.set(0.5, 0.5);
autoSaveToggleText.x = autoSaveToggle.x;
autoSaveToggleText.y = autoSaveToggle.y;
settingsMainContainer.addChild(autoSaveToggleText);
autoSaveToggle.down = function () {
storage.autoSave = !storage.autoSave;
autoSaveLabel.setText('Auto-Save: ' + (storage.autoSave ? 'ON' : 'OFF'));
autoSaveToggleText.setText(storage.autoSave ? 'ON' : 'OFF');
autoSaveToggle.tint = storage.autoSave ? 0x44FF44 : 0x666666;
LK.getSound('button_click').play();
};
// Haptic Feedback Toggle
var hapticLabel = new Text2('Haptic Feedback: ' + (storage.hapticFeedback ? 'ON' : 'OFF'), {
size: 24,
fill: 0xFFFFFF
});
hapticLabel.anchor.set(0.5, 0.5);
hapticLabel.x = 800;
hapticLabel.y = 805;
settingsMainContainer.addChild(hapticLabel);
var hapticToggle = LK.getAsset('platform', {
width: 100,
height: 40,
anchorX: 0.5,
anchorY: 0.5,
tint: storage.hapticFeedback ? 0x44FF44 : 0x666666
});
hapticToggle.x = 1100;
hapticToggle.y = 805;
hapticToggle.interactive = true;
hapticToggle.buttonMode = true;
settingsMainContainer.addChild(hapticToggle);
var hapticToggleText = new Text2(storage.hapticFeedback ? 'ON' : 'OFF', {
size: 20,
fill: 0xFFFFFF
});
hapticToggleText.anchor.set(0.5, 0.5);
hapticToggleText.x = hapticToggle.x;
hapticToggleText.y = hapticToggle.y;
settingsMainContainer.addChild(hapticToggleText);
hapticToggle.down = function () {
storage.hapticFeedback = !storage.hapticFeedback;
hapticLabel.setText('Haptic Feedback: ' + (storage.hapticFeedback ? 'ON' : 'OFF'));
hapticToggleText.setText(storage.hapticFeedback ? 'ON' : 'OFF');
hapticToggle.tint = storage.hapticFeedback ? 0x44FF44 : 0x666666;
LK.getSound('button_click').play();
};
// ACCESSIBILITY SETTINGS SECTION
var accessibilitySectionBg = LK.getAsset('platform', {
width: 900,
height: 140,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x1a1a1a,
alpha: 0.8
});
accessibilitySectionBg.x = 1024;
accessibilitySectionBg.y = 910;
settingsMainContainer.addChild(accessibilitySectionBg);
var accessibilitySectionBorder = LK.getAsset('platform', {
width: 908,
height: 148,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFF44FF,
alpha: 0.3
});
accessibilitySectionBorder.x = 1024;
accessibilitySectionBorder.y = 910;
settingsMainContainer.addChild(accessibilitySectionBorder);
var accessibilityTitle = new Text2('ACCESSIBILITY', {
size: 32,
fill: 0xFF44FF
});
accessibilityTitle.anchor.set(0.5, 0.5);
accessibilityTitle.x = 1024;
accessibilityTitle.y = 860;
settingsMainContainer.addChild(accessibilityTitle);
// Color Blind Mode Toggle
var colorBlindLabel = new Text2('Color Blind Mode: ' + (storage.colorBlindMode ? 'ON' : 'OFF'), {
size: 24,
fill: 0xFFFFFF
});
colorBlindLabel.anchor.set(0.5, 0.5);
colorBlindLabel.x = 800;
colorBlindLabel.y = 895;
settingsMainContainer.addChild(colorBlindLabel);
var colorBlindToggle = LK.getAsset('platform', {
width: 100,
height: 40,
anchorX: 0.5,
anchorY: 0.5,
tint: storage.colorBlindMode ? 0x44FF44 : 0x666666
});
colorBlindToggle.x = 1100;
colorBlindToggle.y = 895;
colorBlindToggle.interactive = true;
colorBlindToggle.buttonMode = true;
settingsMainContainer.addChild(colorBlindToggle);
var colorBlindToggleText = new Text2(storage.colorBlindMode ? 'ON' : 'OFF', {
size: 20,
fill: 0xFFFFFF
});
colorBlindToggleText.anchor.set(0.5, 0.5);
colorBlindToggleText.x = colorBlindToggle.x;
colorBlindToggleText.y = colorBlindToggle.y;
settingsMainContainer.addChild(colorBlindToggleText);
colorBlindToggle.down = function () {
storage.colorBlindMode = !storage.colorBlindMode;
colorBlindLabel.setText('Color Blind Mode: ' + (storage.colorBlindMode ? 'ON' : 'OFF'));
colorBlindToggleText.setText(storage.colorBlindMode ? 'ON' : 'OFF');
colorBlindToggle.tint = storage.colorBlindMode ? 0x44FF44 : 0x666666;
LK.getSound('button_click').play();
};
// Show FPS Toggle
var fpsLabel = new Text2('Show FPS: ' + (storage.showFPS ? 'ON' : 'OFF'), {
size: 24,
fill: 0xFFFFFF
});
fpsLabel.anchor.set(0.5, 0.5);
fpsLabel.x = 800;
fpsLabel.y = 930;
settingsMainContainer.addChild(fpsLabel);
var fpsToggle = LK.getAsset('platform', {
width: 100,
height: 40,
anchorX: 0.5,
anchorY: 0.5,
tint: storage.showFPS ? 0x44FF44 : 0x666666
});
fpsToggle.x = 1100;
fpsToggle.y = 930;
fpsToggle.interactive = true;
fpsToggle.buttonMode = true;
settingsMainContainer.addChild(fpsToggle);
var fpsToggleText = new Text2(storage.showFPS ? 'ON' : 'OFF', {
size: 20,
fill: 0xFFFFFF
});
fpsToggleText.anchor.set(0.5, 0.5);
fpsToggleText.x = fpsToggle.x;
fpsToggleText.y = fpsToggle.y;
settingsMainContainer.addChild(fpsToggleText);
fpsToggle.down = function () {
storage.showFPS = !storage.showFPS;
fpsLabel.setText('Show FPS: ' + (storage.showFPS ? 'ON' : 'OFF'));
fpsToggleText.setText(storage.showFPS ? 'ON' : 'OFF');
fpsToggle.tint = storage.showFPS ? 0x44FF44 : 0x666666;
LK.getSound('button_click').play();
};
// Enhanced bottom navigation panel
var bottomNavBg = LK.getAsset('platform', {
width: 1200,
height: 100,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x1a1a1a,
alpha: 0.8
});
bottomNavBg.x = 1024;
bottomNavBg.y = 1050;
settingsContainer.addChild(bottomNavBg);
var bottomNavBorder = LK.getAsset('platform', {
width: 1208,
height: 108,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x44FF44,
alpha: 0.3
});
bottomNavBorder.x = 1024;
bottomNavBorder.y = 1050;
settingsContainer.addChild(bottomNavBorder);
// Enhanced reset to defaults button
var resetButton = LK.getAsset('platform', {
width: 250,
height: 70,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFF8844
});
resetButton.x = 700;
resetButton.y = 1050;
resetButton.interactive = true;
resetButton.buttonMode = true;
settingsContainer.addChild(resetButton);
var resetText = new Text2('RESET DEFAULTS', {
size: 24,
fill: 0xFFFFFF
});
resetText.anchor.set(0.5, 0.5);
resetText.x = resetButton.x;
resetText.y = resetButton.y;
settingsContainer.addChild(resetText);
resetButton.down = function () {
LK.getSound('button_click').play();
// Reset all settings to defaults
storage.musicVolume = 1.0;
storage.soundVolume = 1.0;
storage.graphicsQuality = 'high';
storage.particleEffects = true;
storage.screenShake = true;
storage.autoSave = true;
storage.showFPS = false;
storage.controlSensitivity = 1.0;
storage.hapticFeedback = true;
storage.colorBlindMode = false;
// Recreate settings menu to reflect changes
settingsContainer.visible = false;
createSettings();
};
// Enhanced back button
var backButton = LK.getAsset('platform', {
width: 250,
height: 70,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFF4444
});
backButton.x = 1348;
backButton.y = 1050;
backButton.interactive = true;
backButton.buttonMode = true;
settingsContainer.addChild(backButton);
var backButtonBorder = LK.getAsset('platform', {
width: 258,
height: 78,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFF8888,
alpha: 0.4
});
backButtonBorder.x = 1348;
backButtonBorder.y = 1050;
settingsContainer.addChild(backButtonBorder);
var backText = new Text2('BACK TO MENU', {
size: 24,
fill: 0xFFFFFF
});
backText.anchor.set(0.5, 0.5);
backText.x = backButton.x;
backText.y = backButton.y;
settingsContainer.addChild(backText);
// Add pulsing animation to back button
var backGlowCycle = 0;
var backGlowInterval = LK.setInterval(function () {
backGlowCycle += 0.03;
var glow = 0.4 + Math.sin(backGlowCycle) * 0.1;
backButtonBorder.alpha = glow;
}, 60);
backButton.down = function () {
LK.getSound('button_click').play();
// Enhanced back button animation
tween(backButton, {
scaleX: 0.9,
scaleY: 0.9,
alpha: 0.8
}, {
duration: 100,
onFinish: function onFinish() {
tween(backButton, {
scaleX: 1.1,
scaleY: 1.1,
alpha: 1.0
}, {
duration: 150,
onFinish: function onFinish() {
tween(backButton, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100,
onFinish: function onFinish() {
gameState = 'menu';
if (settingsContainer) {
settingsContainer.destroy();
}
if (shopContainer) {
shopContainer.visible = false;
}
if (!menuContainer) {
createMenu();
}
menuContainer.visible = true;
}
});
}
});
}
});
};
// Add floating information panel
var infoPanel = LK.getAsset('platform', {
width: 500,
height: 60,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x2a2a2a,
alpha: 0.6
});
infoPanel.x = 1024;
infoPanel.y = 320;
settingsContainer.addChild(infoPanel);
var infoText = new Text2('Settings are automatically saved', {
size: 20,
fill: 0xCCCCCC
});
infoText.anchor.set(0.5, 0.5);
infoText.x = 1024;
infoText.y = 320;
settingsContainer.addChild(infoText);
// Add animated info icon
var infoIcon = LK.getAsset('platform', {
width: 20,
height: 20,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x44FF44
});
infoIcon.x = 750;
infoIcon.y = 320;
settingsContainer.addChild(infoIcon);
// Animate info icon with pulsing effect
var infoGlowCycle = 0;
var infoGlowInterval = LK.setInterval(function () {
infoGlowCycle += 0.05;
var glow = 0.8 + Math.sin(infoGlowCycle) * 0.2;
infoIcon.alpha = glow;
}, 50);
}
function startGame() {
// Check if level is unlocked before starting
if (currentLevel > storage.unlockedLevels) {
// Level is locked, return to map select
LK.getSound('button_click').play();
return;
}
gameState = 'playing';
// Hide all menu containers to prevent text overlap
if (menuContainer) {
menuContainer.visible = false;
}
if (mapSelectContainer) {
mapSelectContainer.visible = false;
}
if (settingsContainer) {
settingsContainer.visible = false;
}
// Get current level configuration
var levelConfig = getCurrentLevelConfig();
// Set background color for current level
game.setBackgroundColor(levelConfig.backgroundColor);
// Create ground
ground = game.addChild(LK.getAsset('ground', {
anchorX: 0.5,
anchorY: 1.0,
x: 1024,
y: 2048
}));
// Create platforms based on current level with enhanced styling
platforms = [];
var platformData = levelConfig.platforms;
for (var i = 0; i < platformData.length; i++) {
var platform = new Platform();
platform.x = platformData[i].x;
platform.y = platformData[i].y;
// Apply enhanced platform styling if available
if (platformData[i].type && platformData[i].tint) {
platform.children[0].tint = platformData[i].tint;
}
if (platformData[i].width) {
platform.children[0].width = platformData[i].width;
}
if (platformData[i].height) {
platform.children[0].height = platformData[i].height;
}
platforms.push(platform);
game.addChild(platform);
}
// Create detailed environmental decorations
if (levelConfig.decorations) {
for (var i = 0; i < levelConfig.decorations.length; i++) {
var decoration = levelConfig.decorations[i];
var decorAsset;
// Create different decoration types with appropriate assets
switch (decoration.type) {
case 'tree':
case 'bush':
case 'rock':
case 'cactus':
case 'flower_patch':
case 'mushroom':
case 'fallen_branch':
case 'ivy_patch':
case 'vine_hanging':
case 'bird_nest':
case 'forest_shrine':
case 'wooden_sign':
decorAsset = LK.getAsset('platform', {
width: decoration.type === 'tree' ? 60 : decoration.type === 'bush' ? 40 : decoration.type === 'flower_patch' ? 35 : decoration.type === 'mushroom' ? 20 : decoration.type === 'fallen_branch' ? 50 : decoration.type === 'ivy_patch' ? 45 : decoration.type === 'vine_hanging' ? 15 : decoration.type === 'bird_nest' ? 25 : decoration.type === 'forest_shrine' ? 80 : decoration.type === 'wooden_sign' ? 40 : 30,
height: decoration.type === 'tree' ? 120 : decoration.type === 'bush' ? 30 : decoration.type === 'flower_patch' ? 15 : decoration.type === 'mushroom' ? 25 : decoration.type === 'fallen_branch' ? 12 : decoration.type === 'ivy_patch' ? 35 : decoration.type === 'vine_hanging' ? 60 : decoration.type === 'bird_nest' ? 15 : decoration.type === 'forest_shrine' ? 100 : decoration.type === 'wooden_sign' ? 60 : 25,
anchorX: 0.5,
anchorY: 1.0,
tint: decoration.tint,
alpha: 0.8
});
break;
case 'cloud':
case 'floating_shrine':
case 'wind_chime':
case 'celestial_orb':
case 'sky_rune':
case 'ethereal_gateway':
case 'starlight_pool':
case 'divine_statue':
case 'floating_lotus':
decorAsset = LK.getAsset('platform', {
width: decoration.type === 'cloud' ? 100 : decoration.type === 'floating_shrine' ? 120 : decoration.type === 'wind_chime' ? 30 : decoration.type === 'celestial_orb' ? 40 : decoration.type === 'sky_rune' ? 50 : decoration.type === 'ethereal_gateway' ? 150 : decoration.type === 'starlight_pool' ? 80 : decoration.type === 'divine_statue' ? 60 : decoration.type === 'floating_lotus' ? 35 : 100,
height: decoration.type === 'cloud' ? 40 : decoration.type === 'floating_shrine' ? 80 : decoration.type === 'wind_chime' ? 50 : decoration.type === 'celestial_orb' ? 40 : decoration.type === 'sky_rune' ? 60 : decoration.type === 'ethereal_gateway' ? 200 : decoration.type === 'starlight_pool' ? 30 : decoration.type === 'divine_statue' ? 120 : decoration.type === 'floating_lotus' ? 25 : 40,
anchorX: 0.5,
anchorY: 0.5,
tint: decoration.tint,
alpha: 0.6
});
break;
case 'pillar':
case 'column':
case 'obelisk':
decorAsset = LK.getAsset('platform', {
width: decoration.type === 'obelisk' ? 25 : 35,
height: decoration.type === 'obelisk' ? 100 : 80,
anchorX: 0.5,
anchorY: 1.0,
tint: decoration.tint,
alpha: 0.9
});
break;
case 'pyramid':
case 'ancient_tomb':
case 'hieroglyph_wall':
case 'sphinx_statue':
case 'scarab_carving':
case 'ancient_vase':
case 'sand_dune':
case 'temple_entrance':
case 'ankh_symbol':
case 'desert_gem':
decorAsset = LK.getAsset('platform', {
width: decoration.type === 'pyramid' ? 80 : decoration.type === 'ancient_tomb' ? 100 : decoration.type === 'hieroglyph_wall' ? 120 : decoration.type === 'sphinx_statue' ? 150 : decoration.type === 'scarab_carving' ? 40 : decoration.type === 'ancient_vase' ? 35 : decoration.type === 'sand_dune' ? 200 : decoration.type === 'temple_entrance' ? 180 : decoration.type === 'ankh_symbol' ? 30 : decoration.type === 'desert_gem' ? 25 : 80,
height: decoration.type === 'pyramid' ? 60 : decoration.type === 'ancient_tomb' ? 80 : decoration.type === 'hieroglyph_wall' ? 100 : decoration.type === 'sphinx_statue' ? 100 : decoration.type === 'scarab_carving' ? 35 : decoration.type === 'ancient_vase' ? 50 : decoration.type === 'sand_dune' ? 40 : decoration.type === 'temple_entrance' ? 150 : decoration.type === 'ankh_symbol' ? 45 : decoration.type === 'desert_gem' ? 30 : 60,
anchorX: 0.5,
anchorY: 1.0,
tint: decoration.tint,
alpha: 0.8
});
break;
case 'crystal':
case 'firecrystal':
decorAsset = LK.getAsset('platform', {
width: 20,
height: 40,
anchorX: 0.5,
anchorY: 1.0,
tint: decoration.tint,
alpha: 0.7
});
break;
case 'statue':
case 'torch':
case 'brazier':
decorAsset = LK.getAsset('platform', {
width: decoration.type === 'statue' ? 40 : 15,
height: decoration.type === 'statue' ? 80 : 50,
anchorX: 0.5,
anchorY: 1.0,
tint: decoration.tint,
alpha: 0.8
});
break;
case 'skull':
case 'rune':
decorAsset = LK.getAsset('platform', {
width: 25,
height: 20,
anchorX: 0.5,
anchorY: 1.0,
tint: decoration.tint,
alpha: 0.7
});
break;
case 'portal':
decorAsset = LK.getAsset('platform', {
width: 60,
height: 100,
anchorX: 0.5,
anchorY: 1.0,
tint: decoration.tint,
alpha: 0.5
});
break;
case 'volcano':
case 'shadowspire':
case 'infernospire':
decorAsset = LK.getAsset('platform', {
width: decoration.type === 'volcano' ? 100 : 40,
height: decoration.type === 'volcano' ? 150 : 200,
anchorX: 0.5,
anchorY: 1.0,
tint: decoration.tint,
alpha: 0.6
});
break;
case 'lavafall':
decorAsset = LK.getAsset('platform', {
width: 30,
height: 400,
anchorX: 0.5,
anchorY: 0.0,
tint: decoration.tint,
alpha: 0.4
});
break;
case 'banner':
case 'dark_crystal':
case 'evil_altar':
case 'bone_pile':
case 'dark_throne':
case 'purple_orb':
case 'sacrificial_circle':
decorAsset = LK.getAsset('platform', {
width: decoration.type === 'banner' ? 80 : decoration.type === 'dark_crystal' ? 50 : decoration.type === 'evil_altar' ? 100 : decoration.type === 'bone_pile' ? 60 : decoration.type === 'dark_throne' ? 120 : decoration.type === 'purple_orb' ? 35 : decoration.type === 'sacrificial_circle' ? 200 : 80,
height: decoration.type === 'banner' ? 120 : decoration.type === 'dark_crystal' ? 80 : decoration.type === 'evil_altar' ? 60 : decoration.type === 'bone_pile' ? 40 : decoration.type === 'dark_throne' ? 150 : decoration.type === 'purple_orb' ? 35 : decoration.type === 'sacrificial_circle' ? 20 : 120,
anchorX: 0.5,
anchorY: decoration.type === 'banner' ? 0.0 : 1.0,
tint: decoration.tint,
alpha: 0.7
});
break;
case 'treasure':
case 'powercrystal':
decorAsset = LK.getAsset('platform', {
width: 30,
height: 25,
anchorX: 0.5,
anchorY: 1.0,
tint: decoration.tint,
alpha: 0.8
});
break;
default:
decorAsset = LK.getAsset('platform', {
width: 30,
height: 30,
anchorX: 0.5,
anchorY: 1.0,
tint: decoration.tint || 0x888888,
alpha: 0.6
});
}
decorAsset.x = decoration.x;
decorAsset.y = decoration.y;
if (decoration.scale) {
decorAsset.scaleX = decoration.scale;
decorAsset.scaleY = decoration.scale;
}
game.addChild(decorAsset);
// Add atmospheric effects for certain decorations
if (decoration.type === 'torch' || decoration.type === 'brazier') {
// Add flickering animation
var originalTint = decorAsset.tint;
var flickerCycle = 0;
var flickerInterval = LK.setInterval(function () {
flickerCycle += 0.1;
var flicker = 0.8 + Math.sin(flickerCycle) * 0.2;
decorAsset.alpha = flicker;
}, 100);
}
if (decoration.type === 'crystal' || decoration.type === 'firecrystal' || decoration.type === 'powercrystal') {
// Add glowing animation
var glowCycle = 0;
var glowInterval = LK.setInterval(function () {
glowCycle += 0.05;
var glow = 0.7 + Math.sin(glowCycle) * 0.3;
decorAsset.alpha = glow;
}, 80);
}
if (decoration.type === 'cloud') {
// Add floating animation
var floatOffset = Math.random() * Math.PI * 2;
var originalY = decorAsset.y;
var floatInterval = LK.setInterval(function () {
floatOffset += 0.02;
decorAsset.y = originalY + Math.sin(floatOffset) * 10;
}, 50);
}
}
}
// Create player
player = new Stickman();
player.x = 200; // Start from left side for horizontal progression
player.y = 1900;
player.canDoubleJump = true;
player.hasUsedDoubleJump = false;
// Apply selected skin
var skinColors = {
'default': 0xFFFFFF,
'red': 0xFF4444,
'blue': 0x4444FF,
'green': 0x44FF44,
'purple': 0x8844FF,
'gold': 0xFFD700
};
if (skinColors[storage.selectedSkin]) {
// Apply tint to all player body parts
player.children.forEach(function (child) {
if (child.tint !== undefined) {
child.tint = skinColors[storage.selectedSkin];
}
});
}
game.addChild(player);
// Create stamina bar
staminaBarBackground = LK.getAsset('platform', {
width: 120,
height: 20,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x000000
});
game.addChild(staminaBarBackground);
staminaBar = LK.getAsset('platform', {
width: 110,
height: 14,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFFFFF
});
game.addChild(staminaBar);
// Clear arrows array
arrows = [];
// Create enemies based on current level
enemies = [];
var enemyData = levelConfig.enemies;
// Create enemies with automatically applied skins from class constructors
for (var i = 0; i < enemyData.length; i++) {
var enemy;
switch (enemyData[i].type) {
case 'stickman':
enemy = new StickmanEnemy();
break;
case 'flying':
enemy = new FlyingEnemy();
break;
case 'boss':
enemy = new Boss();
break;
case 'shadowBoss':
enemy = new ShadowBoss();
break;
case 'fireBoss':
enemy = new FireBoss();
break;
}
enemy.x = enemyData[i].x;
enemy.y = enemyData[i].y;
enemies.push(enemy);
game.addChild(enemy);
}
// Play level-specific music with configurable volume
var currentMusicTrack = levelConfig.musicTrack;
LK.playMusic(currentMusicTrack, {
fade: {
start: 0,
end: storage.musicVolume,
duration: 1000
}
});
// Clear any existing GUI elements first to prevent overlap
if (healthText && healthText.parent) {
healthText.destroy();
}
if (scoreText && scoreText.parent) {
scoreText.destroy();
}
if (ammoText && ammoText.parent) {
ammoText.destroy();
}
if (pauseButton && pauseButton.parent) {
pauseButton.destroy();
}
// Clear existing control buttons to prevent overlap
if (leftButton && leftButton.parent) {
leftButton.destroy();
}
if (rightButton && rightButton.parent) {
rightButton.destroy();
}
if (jumpButton && jumpButton.parent) {
jumpButton.destroy();
}
if (attackButton && attackButton.parent) {
attackButton.destroy();
}
if (bowButton && bowButton.parent) {
bowButton.destroy();
}
// Clear all GUI children to ensure clean state
while (LK.gui.children.length > 0) {
LK.gui.children[0].destroy();
}
// Show game UI
createGameUI();
// Create game controls for mobile interaction
createGameControls();
}
function createGameUI() {
// UI Elements - optimized for Android phone readability
healthText = new Text2('Health: 100', {
size: 50,
fill: 0x00FF00
});
healthText.anchor.set(0, 0);
LK.gui.left.addChild(healthText);
healthText.y = 150; // Position below top-left menu area
// Health bar background
var healthBarBg = LK.getAsset('platform', {
width: 220,
height: 25,
anchorX: 0,
anchorY: 0,
tint: 0x000000
});
healthBarBg.x = 20;
healthBarBg.y = 200;
LK.gui.addChild(healthBarBg);
// Health bar fill
var healthBarFill = LK.getAsset('platform', {
width: 210,
height: 20,
anchorX: 0,
anchorY: 0,
tint: 0x00FF00
});
healthBarFill.x = 25;
healthBarFill.y = 202.5;
LK.gui.addChild(healthBarFill);
// Store references for updating
healthText.healthBarFill = healthBarFill;
scoreText = new Text2('Score: 0', {
size: 50,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
scoreText.y = 50;
// Pause button - positioned in top-right, below the platform menu icon
pauseButton = LK.getAsset('platform', {
width: 120,
height: 80,
anchorX: 1.0,
anchorY: 0.0,
tint: 0x666666
});
pauseButton.x = LK.gui.right.x - 20;
pauseButton.y = 150; // Below the top-left menu area
pauseButton.interactive = true;
pauseButton.buttonMode = true;
LK.gui.addChild(pauseButton);
var pauseText = new Text2('PAUSE', {
size: 28,
fill: 0xFFFFFF
});
pauseText.anchor.set(0.5, 0.5);
pauseText.x = pauseButton.x - pauseButton.width / 2;
pauseText.y = pauseButton.y + pauseButton.height / 2;
LK.gui.addChild(pauseText);
pauseButton.down = function () {
LK.getSound('button_click').play();
showPauseMenu();
};
// Level display - larger text for Android
var levelConfig = getCurrentLevelConfig();
var levelText = new Text2('Level: ' + currentLevel, {
size: 45,
fill: 0xFFD700
});
levelText.anchor.set(1, 0);
levelText.x = LK.gui.right.x - 30;
levelText.y = 230;
LK.gui.addChild(levelText);
// Level name display - larger text for Android
var levelNameText = new Text2(levelConfig.name, {
size: 35,
fill: 0xFFD700
});
levelNameText.anchor.set(1, 0);
levelNameText.x = LK.gui.right.x - 30;
levelNameText.y = 290;
LK.gui.addChild(levelNameText);
// Boss level indicator - larger text for Android
if ((currentLevel - 1) % 4 === 3) {
var bossText = new Text2('BOSS FIGHT!', {
size: 35,
fill: 0xFF4444
});
bossText.anchor.set(1, 0);
bossText.x = LK.gui.right.x - 30;
bossText.y = 340;
LK.gui.addChild(bossText);
}
// Ammunition display - larger text for Android
ammoText = new Text2('Arrows: 5/5', {
size: 50,
fill: 0xFFFFFF
});
ammoText.anchor.set(0, 0);
LK.gui.left.addChild(ammoText);
ammoText.y = 220; // Position below health text
}
// Global UI variables
var healthText, scoreText, ammoText, pauseButton;
var pauseMenuContainer;
var gamePaused = false;
function showPauseMenu() {
if (gamePaused) {
return;
} // Prevent multiple pause menus
gamePaused = true;
// Create pause menu container
pauseMenuContainer = new Container();
game.addChild(pauseMenuContainer);
// Dark overlay
var overlay = LK.getAsset('platform', {
width: 2732,
height: 2048,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x000000,
alpha: 0.7
});
overlay.x = 1366;
overlay.y = 1024;
pauseMenuContainer.addChild(overlay);
// Pause menu background
var menuBg = LK.getAsset('platform', {
width: 600,
height: 800,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x222222
});
menuBg.x = 1366;
menuBg.y = 1024;
pauseMenuContainer.addChild(menuBg);
// Pause title
var pauseTitle = new Text2('GAME PAUSED', {
size: 60,
fill: 0xFFFFFF
});
pauseTitle.anchor.set(0.5, 0.5);
pauseTitle.x = 1366;
pauseTitle.y = 700;
pauseMenuContainer.addChild(pauseTitle);
// Resume button
var resumeButton = LK.getAsset('platform', {
width: 400,
height: 100,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x44FF44
});
resumeButton.x = 1366;
resumeButton.y = 850;
resumeButton.interactive = true;
resumeButton.buttonMode = true;
pauseMenuContainer.addChild(resumeButton);
var resumeText = new Text2('RESUME', {
size: 40,
fill: 0xFFFFFF
});
resumeText.anchor.set(0.5, 0.5);
resumeText.x = resumeButton.x;
resumeText.y = resumeButton.y;
pauseMenuContainer.addChild(resumeText);
resumeButton.down = function () {
LK.getSound('button_click').play();
hidePauseMenu();
};
// Settings button
var pauseSettingsButton = LK.getAsset('platform', {
width: 400,
height: 100,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x4444FF
});
pauseSettingsButton.x = 1366;
pauseSettingsButton.y = 1000;
pauseSettingsButton.interactive = true;
pauseSettingsButton.buttonMode = true;
pauseMenuContainer.addChild(pauseSettingsButton);
var pauseSettingsText = new Text2('SETTINGS', {
size: 40,
fill: 0xFFFFFF
});
pauseSettingsText.anchor.set(0.5, 0.5);
pauseSettingsText.x = pauseSettingsButton.x;
pauseSettingsText.y = pauseSettingsButton.y;
pauseMenuContainer.addChild(pauseSettingsText);
pauseSettingsButton.down = function () {
LK.getSound('button_click').play();
hidePauseMenu();
showPauseSettings();
};
// Main menu button
var mainMenuButton = LK.getAsset('platform', {
width: 400,
height: 100,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFF4444
});
mainMenuButton.x = 1366;
mainMenuButton.y = 1150;
mainMenuButton.interactive = true;
mainMenuButton.buttonMode = true;
pauseMenuContainer.addChild(mainMenuButton);
var mainMenuText = new Text2('MAIN MENU', {
size: 40,
fill: 0xFFFFFF
});
mainMenuText.anchor.set(0.5, 0.5);
mainMenuText.x = mainMenuButton.x;
mainMenuText.y = mainMenuButton.y;
pauseMenuContainer.addChild(mainMenuText);
mainMenuButton.down = function () {
LK.getSound('button_click').play();
returnToMainMenu();
};
}
function hidePauseMenu() {
if (pauseMenuContainer) {
pauseMenuContainer.destroy();
pauseMenuContainer = null;
}
gamePaused = false;
}
function showPauseSettings() {
// Create pause settings container
var pauseSettingsContainer = new Container();
game.addChild(pauseSettingsContainer);
// Dark overlay
var overlay = LK.getAsset('platform', {
width: 2732,
height: 2048,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x000000,
alpha: 0.7
});
overlay.x = 1366;
overlay.y = 1024;
pauseSettingsContainer.addChild(overlay);
// Settings menu background
var settingsBg = LK.getAsset('platform', {
width: 700,
height: 900,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x222222
});
settingsBg.x = 1366;
settingsBg.y = 1024;
pauseSettingsContainer.addChild(settingsBg);
// Settings title
var settingsTitle = new Text2('SETTINGS', {
size: 60,
fill: 0xFFFFFF
});
settingsTitle.anchor.set(0.5, 0.5);
settingsTitle.x = 1366;
settingsTitle.y = 650;
pauseSettingsContainer.addChild(settingsTitle);
// Music volume
var musicLabel = new Text2('Music Volume: ' + Math.round(storage.musicVolume * 100) + '%', {
size: 40,
fill: 0xFFFFFF
});
musicLabel.anchor.set(0.5, 0.5);
musicLabel.x = 1366;
musicLabel.y = 800;
pauseSettingsContainer.addChild(musicLabel);
var musicDown = LK.getAsset('platform', {
width: 80,
height: 80,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFF4444
});
musicDown.x = 1150;
musicDown.y = 850;
musicDown.interactive = true;
musicDown.buttonMode = true;
pauseSettingsContainer.addChild(musicDown);
var musicDownText = new Text2('-', {
size: 50,
fill: 0xFFFFFF
});
musicDownText.anchor.set(0.5, 0.5);
musicDownText.x = musicDown.x;
musicDownText.y = musicDown.y;
pauseSettingsContainer.addChild(musicDownText);
var musicUp = LK.getAsset('platform', {
width: 80,
height: 80,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x44FF44
});
musicUp.x = 1582;
musicUp.y = 850;
musicUp.interactive = true;
musicUp.buttonMode = true;
pauseSettingsContainer.addChild(musicUp);
var musicUpText = new Text2('+', {
size: 50,
fill: 0xFFFFFF
});
musicUpText.anchor.set(0.5, 0.5);
musicUpText.x = musicUp.x;
musicUpText.y = musicUp.y;
pauseSettingsContainer.addChild(musicUpText);
musicDown.down = function () {
storage.musicVolume = Math.max(0, storage.musicVolume - 0.1);
musicLabel.setText('Music Volume: ' + Math.round(storage.musicVolume * 100) + '%');
LK.getSound('button_click').play();
};
musicUp.down = function () {
storage.musicVolume = Math.min(1, storage.musicVolume + 0.1);
musicLabel.setText('Music Volume: ' + Math.round(storage.musicVolume * 100) + '%');
LK.getSound('button_click').play();
};
// Sound volume
var soundLabel = new Text2('Sound Volume: ' + Math.round(storage.soundVolume * 100) + '%', {
size: 40,
fill: 0xFFFFFF
});
soundLabel.anchor.set(0.5, 0.5);
soundLabel.x = 1366;
soundLabel.y = 1000;
pauseSettingsContainer.addChild(soundLabel);
var soundDown = LK.getAsset('platform', {
width: 80,
height: 80,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFF4444
});
soundDown.x = 1150;
soundDown.y = 1050;
soundDown.interactive = true;
soundDown.buttonMode = true;
pauseSettingsContainer.addChild(soundDown);
var soundDownText = new Text2('-', {
size: 50,
fill: 0xFFFFFF
});
soundDownText.anchor.set(0.5, 0.5);
soundDownText.x = soundDown.x;
soundDownText.y = soundDown.y;
pauseSettingsContainer.addChild(soundDownText);
var soundUp = LK.getAsset('platform', {
width: 80,
height: 80,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x44FF44
});
soundUp.x = 1582;
soundUp.y = 1050;
soundUp.interactive = true;
soundUp.buttonMode = true;
pauseSettingsContainer.addChild(soundUp);
var soundUpText = new Text2('+', {
size: 50,
fill: 0xFFFFFF
});
soundUpText.anchor.set(0.5, 0.5);
soundUpText.x = soundUp.x;
soundUpText.y = soundUp.y;
pauseSettingsContainer.addChild(soundUpText);
soundDown.down = function () {
storage.soundVolume = Math.max(0, storage.soundVolume - 0.1);
soundLabel.setText('Sound Volume: ' + Math.round(storage.soundVolume * 100) + '%');
LK.getSound('button_click').play();
};
soundUp.down = function () {
storage.soundVolume = Math.min(1, storage.soundVolume + 0.1);
soundLabel.setText('Sound Volume: ' + Math.round(storage.soundVolume * 100) + '%');
LK.getSound('button_click').play();
};
// Back button
var backButton = LK.getAsset('platform', {
width: 300,
height: 80,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFF4444
});
backButton.x = 1366;
backButton.y = 1250;
backButton.interactive = true;
backButton.buttonMode = true;
pauseSettingsContainer.addChild(backButton);
var backText = new Text2('BACK', {
size: 40,
fill: 0xFFFFFF
});
backText.anchor.set(0.5, 0.5);
backText.x = backButton.x;
backText.y = backButton.y;
pauseSettingsContainer.addChild(backText);
backButton.down = function () {
LK.getSound('button_click').play();
pauseSettingsContainer.destroy();
showPauseMenu();
};
}
function returnToMainMenu() {
// Clean up current game
hidePauseMenu();
// Clear GUI elements first to prevent overlap
if (healthText && healthText.parent) {
healthText.destroy();
}
if (scoreText && scoreText.parent) {
scoreText.destroy();
}
if (ammoText && ammoText.parent) {
ammoText.destroy();
}
if (pauseButton && pauseButton.parent) {
pauseButton.destroy();
}
// Clear control buttons if they exist
if (leftButton && leftButton.parent) {
leftButton.destroy();
}
if (rightButton && rightButton.parent) {
rightButton.destroy();
}
if (jumpButton && jumpButton.parent) {
jumpButton.destroy();
}
if (attackButton && attackButton.parent) {
attackButton.destroy();
}
if (bowButton && bowButton.parent) {
bowButton.destroy();
}
// Clear any GUI children that might be lingering
while (LK.gui.children.length > 0) {
LK.gui.children[0].destroy();
}
// Reset control variables
leftButton = null;
rightButton = null;
jumpButton = null;
attackButton = null;
bowButton = null;
// Clean up game objects
for (var i = game.children.length - 1; i >= 0; i--) {
var child = game.children[i];
if (child !== menuContainer && child !== mapSelectContainer && child !== settingsContainer) {
child.destroy();
}
}
// Clear game arrays
platforms = [];
enemies = [];
arrows = [];
projectiles = [];
enemyBullets = [];
// Reset global UI variables
healthText = null;
scoreText = null;
ammoText = null;
pauseButton = null;
// Reset game state
gameState = 'menu';
gamePaused = false;
// Show menu and play menu music
if (menuContainer) {
menuContainer.visible = true;
} else {
createMenu();
}
// Reset camera position
game.x = 0;
game.y = 0;
// Play menu music
LK.playMusic('menu_music', {
volume: storage.musicVolume || 0.6
});
}
// Unlock cinematic function
function showUnlockCinematic(newLevel, callback) {
// Create cinematic container
var cinematicContainer = new Container();
game.addChild(cinematicContainer);
// Dark overlay
var overlay = LK.getAsset('platform', {
width: 2048,
height: 2732,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x000000,
alpha: 0.8
});
overlay.x = 1024;
overlay.y = 1366;
cinematicContainer.addChild(overlay);
// Level unlock text
var unlockText = new Text2('LEVEL ' + newLevel + ' UNLOCKED!', {
size: 60,
fill: 0xFFD700
});
unlockText.anchor.set(0.5, 0.5);
unlockText.x = 1024;
unlockText.y = 1100;
unlockText.alpha = 0;
cinematicContainer.addChild(unlockText);
// Create pixel-style lock
var lockGraphic = LK.getAsset('lock', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0x666666,
scaleX: 3,
scaleY: 3
});
lockGraphic.x = 1024;
lockGraphic.y = 1366;
cinematicContainer.addChild(lockGraphic);
// Create pixel-style key
var keyGraphic = LK.getAsset('key', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFD700,
scaleX: 2,
scaleY: 2
});
keyGraphic.x = 600; // Start from left side
keyGraphic.y = 1366;
cinematicContainer.addChild(keyGraphic);
// Animation sequence
LK.setTimeout(function () {
// Fade in text
tween(unlockText, {
alpha: 1
}, {
duration: 500
});
}, 200);
// Key moves toward lock
LK.setTimeout(function () {
tween(keyGraphic, {
x: 950,
// Move close to lock
rotation: Math.PI * 2 // Spinning effect
}, {
duration: 1000,
easing: tween.easeInOut
});
}, 500);
// Key enters lock with unlock effect
LK.setTimeout(function () {
// Key enters lock
tween(keyGraphic, {
x: 1024,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 300,
easing: tween.easeIn,
onFinish: function onFinish() {
// Lock opens with flash effect
tween(lockGraphic, {
tint: 0xFFFFFF,
scaleX: 4,
scaleY: 4,
alpha: 0
}, {
duration: 400,
easing: tween.easeOut
});
// Key disappears with glow
tween(keyGraphic, {
tint: 0xFFFFFF,
scaleX: 3,
scaleY: 3,
alpha: 0
}, {
duration: 400,
easing: tween.easeOut
});
// Text grows and glows
tween(unlockText, {
scaleX: 1.5,
scaleY: 1.5,
tint: 0xFFFFFF
}, {
duration: 400,
easing: tween.easeOut
});
}
});
}, 1500);
// Clean up and continue
LK.setTimeout(function () {
tween(cinematicContainer, {
alpha: 0
}, {
duration: 800,
onFinish: function onFinish() {
cinematicContainer.destroy();
if (callback) {
callback();
}
}
});
}, 3000);
}
function createGameControls() {
// Mobile Controls UI - Optimized for Android phones with larger touch targets
// Movement area background - larger for easier touch detection
var movementArea = LK.getAsset('platform', {
width: 350,
height: 320,
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.2,
tint: 0x333333
});
movementArea.x = 180;
movementArea.y = LK.gui.bottom.y - 160;
LK.gui.addChild(movementArea);
// Left movement button - larger for Android phones
leftButton = LK.getAsset('platform', {
width: 150,
height: 150,
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.8,
tint: 0x4444FF
});
leftButton.x = 120;
leftButton.y = LK.gui.bottom.y - 160;
leftButton.interactive = true;
leftButton.buttonMode = true;
LK.gui.addChild(leftButton);
var leftIcon = new Text2('<', {
size: 70,
fill: 0xFFFFFF
});
leftIcon.anchor.set(0.5, 0.5);
leftIcon.x = leftButton.x;
leftIcon.y = leftButton.y;
LK.gui.addChild(leftIcon);
// Right movement button - larger for Android phones
rightButton = LK.getAsset('platform', {
width: 150,
height: 150,
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.8,
tint: 0x4444FF
});
rightButton.x = 240;
rightButton.y = LK.gui.bottom.y - 160;
rightButton.interactive = true;
rightButton.buttonMode = true;
LK.gui.addChild(rightButton);
var rightIcon = new Text2('>', {
size: 70,
fill: 0xFFFFFF
});
rightIcon.anchor.set(0.5, 0.5);
rightIcon.x = rightButton.x;
rightIcon.y = rightButton.y;
LK.gui.addChild(rightIcon);
// Action buttons on the right side - optimized for Android thumb reach
// Jump button - largest and most accessible for Android phones
jumpButton = LK.getAsset('platform', {
width: 180,
height: 180,
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.8,
tint: 0x44FF44
});
jumpButton.x = LK.gui.right.x - 120;
jumpButton.y = LK.gui.bottom.y - 120;
jumpButton.interactive = true;
jumpButton.buttonMode = true;
LK.gui.addChild(jumpButton);
var jumpLabel = new Text2('JUMP', {
size: 32,
fill: 0xFFFFFF
});
jumpLabel.anchor.set(0.5, 0.5);
jumpLabel.x = jumpButton.x;
jumpLabel.y = jumpButton.y;
LK.gui.addChild(jumpLabel);
// Attack button - positioned for comfortable Android thumb reach
attackButton = LK.getAsset('platform', {
width: 160,
height: 160,
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.8,
tint: 0xFF4444
});
attackButton.x = LK.gui.right.x - 300;
attackButton.y = LK.gui.bottom.y - 120;
attackButton.interactive = true;
attackButton.buttonMode = true;
LK.gui.addChild(attackButton);
var attackLabel = new Text2('ATK', {
size: 30,
fill: 0xFFFFFF
});
attackLabel.anchor.set(0.5, 0.5);
attackLabel.x = attackButton.x;
attackLabel.y = attackButton.y;
LK.gui.addChild(attackLabel);
// Bow button - positioned higher for Android ergonomics
bowButton = LK.getAsset('platform', {
width: 140,
height: 140,
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.8,
tint: 0xFF8844
});
bowButton.x = LK.gui.right.x - 210;
bowButton.y = LK.gui.bottom.y - 280;
bowButton.interactive = true;
bowButton.buttonMode = true;
LK.gui.addChild(bowButton);
var bowLabel = new Text2('BOW', {
size: 26,
fill: 0xFFFFFF
});
bowLabel.anchor.set(0.5, 0.5);
bowLabel.x = bowButton.x;
bowLabel.y = bowButton.y;
LK.gui.addChild(bowLabel);
setupControlEvents();
}
// Global control variables
var leftButton, rightButton, jumpButton, attackButton, bowButton;
// Collision detection function
function checkCollisions(obj, platforms) {
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
if (obj.intersects(platform)) {
// Landing on top of platform
if (obj.velocityY > 0 && obj.y - 40 < platform.y) {
obj.y = platform.y - 40;
obj.velocityY = 0;
obj.onGround = true;
// Reset double jump when landing on platforms
if (obj === player) {
obj.canDoubleJump = true;
obj.hasUsedDoubleJump = false;
}
}
}
}
// Ground collision
if (obj.y > 1948) {
obj.y = 1948;
obj.velocityY = 0;
obj.onGround = true;
// Reset double jump when landing on ground
if (obj === player) {
obj.canDoubleJump = true;
obj.hasUsedDoubleJump = false;
}
}
}
function setupControlEvents() {
// Input handling - variables moved to global scope
game.down = function (x, y, obj) {
// Fallback touch handling for areas outside buttons
};
game.up = function (x, y, obj) {
// Fallback touch release handling
};
// Input state variables already declared in global scope
// Control event handlers - enhanced feedback for Android
leftButton.down = function (x, y, obj) {
leftPressed = true;
currentTouchId = 'left';
// Enhanced visual feedback for Android - simulates haptic feedback
tween(leftButton, {
alpha: 1.0,
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 80
});
LK.getSound('button_click').play();
};
leftButton.up = function (x, y, obj) {
leftPressed = false;
if (currentTouchId === 'left') {
currentTouchId = null;
}
tween(leftButton, {
alpha: 0.8,
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 120
});
};
rightButton.down = function (x, y, obj) {
rightPressed = true;
currentTouchId = 'right';
tween(rightButton, {
alpha: 0.9
}, {
duration: 100
});
LK.getSound('button_click').play();
};
rightButton.up = function (x, y, obj) {
rightPressed = false;
if (currentTouchId === 'right') {
currentTouchId = null;
}
tween(rightButton, {
alpha: 0.6
}, {
duration: 100
});
};
jumpButton.down = function (x, y, obj) {
player.jump();
tween(jumpButton, {
alpha: 0.9
}, {
duration: 100
});
};
jumpButton.up = function (x, y, obj) {
tween(jumpButton, {
alpha: 0.6
}, {
duration: 100
});
};
attackButton.down = function (x, y, obj) {
player.attack();
tween(attackButton, {
alpha: 0.9
}, {
duration: 100
});
};
attackButton.up = function (x, y, obj) {
tween(attackButton, {
alpha: 0.6
}, {
duration: 100
});
};
bowButton.down = function (x, y, obj) {
if (player.currentAmmo > 0) {
player.shootArrow();
tween(bowButton, {
alpha: 0.9
}, {
duration: 100
});
} else {
// Visual feedback for no ammo
tween(bowButton, {
tint: 0xFF0000
}, {
duration: 200,
onFinish: function onFinish() {
tween(bowButton, {
tint: 0xFF8844
}, {
duration: 200
});
}
});
}
};
bowButton.up = function (x, y, obj) {
tween(bowButton, {
alpha: 0.6
}, {
duration: 100
});
};
}
// Initialize menu system
LK.playMusic('menu_music', {
volume: storage.musicVolume || 0.6
});
createMenu();
game.update = function () {
if (gameState !== 'playing' || gamePaused) {
return; // Don't update game logic if not playing or paused
}
// Handle input
if (leftPressed) {
player.moveLeft();
}
if (rightPressed) {
player.moveRight();
}
// Check collisions for player
checkCollisions(player, platforms);
// Check collisions for enemies
for (var i = 0; i < enemies.length; i++) {
checkCollisions(enemies[i], platforms);
}
// Update arrows and check enemy hits
for (var i = arrows.length - 1; i >= 0; i--) {
var arrow = arrows[i];
// Check if arrow hits enemies
for (var j = enemies.length - 1; j >= 0; j--) {
var enemy = enemies[j];
if (arrow.intersects(enemy)) {
if (enemy.takeDamage(arrow.damage)) {
// Enemy destroyed
enemies.splice(j, 1);
LK.setScore(LK.getScore() + 150); // More points for ranged kills
storage.coins += 5; // Reward coins for defeating enemies
scoreText.setText('Score: ' + LK.getScore());
}
// Remove arrow
arrow.destroy();
arrows.splice(i, 1);
break;
}
}
// Remove destroyed arrows
if (arrow.parent === null) {
arrows.splice(i, 1);
}
}
// Update projectiles and check enemy hits
for (var i = projectiles.length - 1; i >= 0; i--) {
var projectile = projectiles[i];
// Check if projectile hits enemies
for (var j = enemies.length - 1; j >= 0; j--) {
var enemy = enemies[j];
if (projectile.intersects(enemy)) {
if (enemy.takeDamage(25)) {
// Enemy destroyed
enemies.splice(j, 1);
LK.setScore(LK.getScore() + 100);
storage.coins += 5; // Reward coins for defeating enemies
scoreText.setText('Score: ' + LK.getScore());
}
// Remove projectile
projectile.destroy();
projectiles.splice(i, 1);
break;
}
}
// Remove destroyed projectiles
if (projectile.parent === null) {
projectiles.splice(i, 1);
}
}
// Update enemy bullets and check player hits
for (var i = enemyBullets.length - 1; i >= 0; i--) {
var bullet = enemyBullets[i];
// Check if bullet hits player
if (bullet.intersects(player)) {
player.takeDamage(10);
bullet.destroy();
enemyBullets.splice(i, 1);
continue;
}
// Remove destroyed bullets
if (bullet.parent === null) {
enemyBullets.splice(i, 1);
}
}
// Check player-enemy collisions
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
if (player.intersects(enemy)) {
// Simple knockback and damage
var dx = player.x - enemy.x;
player.velocityX += dx > 0 ? 5 : -5;
player.takeDamage(1);
// Update health display
healthText.setText('Health: ' + Math.max(0, player.health));
healthText.tint = player.health < 30 ? 0xFF0000 : 0x00FF00;
// Update health bar
if (healthText.healthBarFill) {
var healthPercent = Math.max(0, player.health / player.maxHealth);
healthText.healthBarFill.width = 210 * healthPercent;
healthText.healthBarFill.tint = player.health < 30 ? 0xFF0000 : 0x00FF00;
}
}
}
// Win condition - defeat all enemies
if (enemies.length === 0) {
var returnToMainMenu = function returnToMainMenu() {
// Clean up current level more carefully
for (var i = game.children.length - 1; i >= 0; i--) {
var child = game.children[i];
// Don't destroy menu containers
if (child !== menuContainer && child !== mapSelectContainer && child !== settingsContainer) {
child.destroy();
}
}
// Clear arrays
platforms = [];
enemies = [];
arrows = [];
projectiles = [];
enemyBullets = [];
// Reset camera position
game.x = 0;
game.y = 0;
// Change game state to main menu
gameState = 'menu';
gamePaused = false;
// Show main menu and play menu music
if (menuContainer) {
menuContainer.visible = true;
} else {
createMenu();
}
LK.playMusic('menu_music', {
volume: storage.musicVolume || 0.6
});
};
// Update high score
if (LK.getScore() > storage.highScore) {
storage.highScore = LK.getScore();
}
// Award bonus coins for level completion
var levelBonus = 10; // 10 coins for completing any level
storage.coins += levelBonus;
var completedLevel = currentLevel;
var shouldShowUnlock = false;
// Mark this level as completed
storage.lastCompletedLevel = completedLevel;
// Unlock the next level
var nextLevel = currentLevel + 1;
if (nextLevel > storage.unlockedLevels) {
storage.unlockedLevels = nextLevel;
shouldShowUnlock = true;
}
// Reset player health to full when leveling up
player.health = player.maxHealth;
healthText.setText('Health: ' + player.health);
healthText.tint = 0x00FF00;
// Reset current level to 1 for main menu (Play button will advance to next uncompleted level)
currentLevel = 1;
storage.currentLevel = currentLevel;
// Create completion screen overlay
var completionOverlay = LK.getAsset('platform', {
width: 2732,
height: 2048,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x000000,
alpha: 0.8
});
completionOverlay.x = 1366;
completionOverlay.y = 1024;
game.addChild(completionOverlay);
// Create completion message background
var completionBg = LK.getAsset('platform', {
width: 800,
height: 400,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x222222
});
completionBg.x = 1366;
completionBg.y = 1024;
game.addChild(completionBg);
// Show level complete message with enhanced styling
var levelComplete = new Text2('NIVEL ' + completedLevel + ' COMPLETADO', {
size: 60,
fill: 0xFFD700
});
levelComplete.anchor.set(0.5, 0.5);
levelComplete.x = 1366;
levelComplete.y = 950;
levelComplete.alpha = 0;
game.addChild(levelComplete);
// Success message
var successMessage = new Text2('¡Excelente trabajo!', {
size: 40,
fill: 0x00FF00
});
successMessage.anchor.set(0.5, 0.5);
successMessage.x = 1366;
successMessage.y = 1050;
successMessage.alpha = 0;
game.addChild(successMessage);
// Main menu message
var selectorText = new Text2('Regresando al menú principal...', {
size: 35,
fill: 0xFFFFFF
});
selectorText.anchor.set(0.5, 0.5);
selectorText.x = 1366;
selectorText.y = 1150;
selectorText.alpha = 0;
game.addChild(selectorText);
// Animate completion screen entrance
tween(levelComplete, {
alpha: 1,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 600,
easing: tween.easeOut
});
// Animate success message
LK.setTimeout(function () {
tween(successMessage, {
alpha: 1
}, {
duration: 400,
easing: tween.easeOut
});
}, 400);
// Animate selector text
LK.setTimeout(function () {
tween(selectorText, {
alpha: 1
}, {
duration: 400,
easing: tween.easeOut
});
}, 800);
// Return to main menu after 3 seconds
LK.setTimeout(function () {
// Clean up completion screen elements first
if (completionOverlay && completionOverlay.parent) {
completionOverlay.destroy();
}
if (completionBg && completionBg.parent) {
completionBg.destroy();
}
if (levelComplete && levelComplete.parent) {
levelComplete.destroy();
}
if (successMessage && successMessage.parent) {
successMessage.destroy();
}
if (selectorText && selectorText.parent) {
selectorText.destroy();
}
if (shouldShowUnlock) {
// Show unlock cinematic for new level
showUnlockCinematic(nextLevel, function () {
// Return to main menu after cinematic
returnToMainMenu();
});
} else {
// Return to main menu immediately
returnToMainMenu();
}
}, 3000);
}
// Update stamina bar position and appearance - moved higher up
staminaBarBackground.x = player.x;
staminaBarBackground.y = player.y - 130;
staminaBar.x = player.x;
staminaBar.y = player.y - 130;
// Update stamina bar color based on double jump availability
if (player.canDoubleJump && !player.hasUsedDoubleJump) {
staminaBar.tint = 0x00FF00; // Bright green when available
} else {
staminaBar.tint = 0x444444; // Dark gray when used
}
// Update bow button appearance based on ammunition
if (bowButton) {
bowButton.alpha = player.currentAmmo > 0 ? 0.6 : 0.3;
bowButton.tint = player.currentAmmo > 0 ? 0xFF8844 : 0x666666;
}
// Horizontal camera follow player with smooth movement
var targetX = Math.max(-1024, Math.min(0, -(player.x - 1024)));
var targetY = Math.max(-500, Math.min(0, -(player.y - 1024)));
game.x += (targetX - game.x) * 0.08;
game.y += (targetY - game.y) * 0.06;
// Sound volume is now controlled through storage and applied during initialization
};
// Controls will be created when entering levels via startGame()
Crea un personaje estilo pixel art, un guerrero simple y fácil de animar. No debe tener manos ni piernas visibles, solo un cuerpo principal con forma redonda u ovalada. El diseño debe sugerir que es un guerrero usando colores llamativos, ojos brillantes o una armadura pixelada pegada al cuerpo. Puede tener una espada flotando al lado o en la espalda como decoración. Debe verse como un personaje de videojuego, pero sin partes que necesiten animación compleja.. In-Game asset. 2d. High contrast. No shadows
Diseña una espada estilo pixel art, sencilla pero llamativa. Debe ser fácil de animar o colocar junto a un personaje. El mango debe ser corto y simple, y la hoja puede ser recta o con un brillo digital. Usa colores llamativos como azul neón, rojo fuego o plateado con detalles pixelados. El diseño debe parecer futurista o mágico, como si fuera un arma especial de un guerrero digital.. In-Game asset. 2d. High contrast. No shadows