/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScore: 0,
unlockedCombos: 1
});
/****
* Classes
****/
var AttackEffect = Container.expand(function () {
var self = Container.call(this);
var effect = self.attachAsset('attackEffect', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.7
});
self.lifespan = 12; // frames the effect will last
self.direction = 1; // 1 for right, -1 for left
self.update = function () {
self.lifespan--;
self.alpha -= 0.08;
if (self.lifespan <= 0) {
self.destroy();
}
};
return self;
});
var ComboIndicator = Container.expand(function () {
var self = Container.call(this);
var circle = self.attachAsset('comboIndicator', {
anchorX: 0.5,
anchorY: 0.5
});
self.comboText = new Text2('1x', {
size: 30,
fill: 0x000000
});
self.comboText.anchor.set(0.5, 0.5);
self.addChild(self.comboText);
self.update = function () {
if (player.combo > 1) {
self.visible = true;
self.comboText.setText(player.combo + 'x');
self.x = player.x;
self.y = player.y - 100;
// Pulse effect based on combo timer
var scale = 1 + 0.2 * (player.comboTimer / 60);
self.scale.set(scale);
} else {
self.visible = false;
}
};
return self;
});
var Enemy = Container.expand(function () {
var self = Container.call(this);
var sprite = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 50;
self.maxHealth = 50;
self.speed = 3 + Math.random() * 2;
self.jumpVelocity = 0;
self.gravity = 1;
self.isGrounded = false;
self.attackCooldown = 0;
self.direction = -1; // Initially facing left toward player
self.attackRange = 150;
self.type = Math.floor(Math.random() * 3); // 0 = normal, 1 = fast, 2 = tank
self.scoreValue = 10 * (self.type + 1);
// Adjust stats based on type
if (self.type === 1) {
// Fast enemy
self.speed += 3;
self.health = 30;
self.maxHealth = 30;
sprite.tint = 0x00AEEF; // Blue tint
} else if (self.type === 2) {
// Tank enemy
self.speed -= 1;
self.health = 100;
self.maxHealth = 100;
sprite.tint = 0x8B4513; // Brown tint
}
self.takeDamage = function (amount) {
self.health -= amount;
// Flash enemy when hit
LK.effects.flashObject(self, 0xFFFFFF, 200);
// Play hit sound
LK.getSound('hit').play();
if (self.health <= 0) {
// Play defeat sound
LK.getSound('enemyDefeat').play();
// Add score
LK.setScore(LK.getScore() + self.scoreValue);
// Remove from enemies array
var index = enemies.indexOf(self);
if (index !== -1) {
enemies.splice(index, 1);
}
// Destroy the enemy
self.destroy();
}
};
self.attack = function () {
if (self.attackCooldown <= 0) {
// Damage player if in range
var distance = Math.abs(player.x - self.x);
if (distance < self.attackRange) {
player.takeDamage(5 + self.type * 3);
}
self.attackCooldown = 60; // 1 second cooldown
}
};
self.update = function () {
// Update cooldowns
if (self.attackCooldown > 0) {
self.attackCooldown--;
}
// Apply gravity
if (!self.isGrounded) {
self.jumpVelocity += self.gravity;
self.y += self.jumpVelocity;
}
// Check ground collision
if (self.y >= groundY - sprite.height / 2) {
self.y = groundY - sprite.height / 2;
self.isGrounded = true;
self.jumpVelocity = 0;
}
// Move toward player
var distanceToPlayer = player.x - self.x;
self.direction = distanceToPlayer > 0 ? 1 : -1;
// Flip sprite based on direction
sprite.scale.x = self.direction;
// Move if not attacking and not too close
if (Math.abs(distanceToPlayer) > self.attackRange / 2) {
self.x += self.direction * self.speed;
} else if (self.attackCooldown <= 0) {
self.attack();
}
};
return self;
});
var Samurai = Container.expand(function () {
var self = Container.call(this);
var sprite = self.attachAsset('samurai', {
anchorX: 0.5,
anchorY: 0.5
});
// Player stats
self.health = 100;
self.maxHealth = 100;
self.speed = 10;
self.jumpVelocity = 0;
self.gravity = 1;
self.isGrounded = false;
self.isAttacking = false;
self.attackCooldown = 0;
self.direction = 1; // 1 for right, -1 for left
self.combo = 0;
self.comboTimer = 0;
self.isDashing = false;
self.dashCooldown = 0;
self.invulnerable = 0;
self.jump = function () {
if (self.isGrounded) {
self.jumpVelocity = -25;
self.isGrounded = false;
}
};
self.attack = function () {
if (self.attackCooldown <= 0 && !self.isDashing) {
self.isAttacking = true;
self.attackCooldown = 15;
// Create attack effect
var attackEffect = new AttackEffect();
attackEffect.x = self.x + 100 * self.direction;
attackEffect.y = self.y;
attackEffect.direction = self.direction;
if (self.direction === -1) {
attackEffect.scale.x = -1;
}
game.addChild(attackEffect);
// Play slash sound
LK.getSound('slash').play();
// Increment combo if within time window
if (self.comboTimer > 0) {
self.combo++;
if (self.combo > storage.unlockedCombos) {
storage.unlockedCombos = self.combo;
}
} else {
self.combo = 1;
}
self.comboTimer = 60; // 1 second combo window
// Check for enemy hits
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
var distance = Math.abs(enemy.x - self.x);
// Only hit enemies in front of the player and within attack range
if (self.direction === 1 && enemy.x > self.x && distance < 200 || self.direction === -1 && enemy.x < self.x && distance < 200) {
// Calculate damage based on combo
var damage = 10 + self.combo * 5;
enemy.takeDamage(damage);
// Apply knockback to enemy
enemy.x += self.direction * 30;
}
}
}
};
self.dash = function () {
if (!self.isDashing && self.dashCooldown <= 0) {
self.isDashing = true;
self.invulnerable = 20; // Invulnerable during dash
// Apply dash movement
tween(self, {
x: self.x + self.direction * 300
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
self.isDashing = false;
self.dashCooldown = 60; // 1 second cooldown
}
});
}
};
self.takeDamage = function (amount) {
if (self.invulnerable <= 0) {
self.health -= amount;
self.invulnerable = 30; // Half-second invulnerability
// Flash player red when hit
LK.effects.flashObject(self, 0xFF0000, 500);
// Play hit sound
LK.getSound('playerHit').play();
// Check for game over
if (self.health <= 0) {
LK.showGameOver();
}
}
};
self.update = function () {
// Update cooldowns
if (self.attackCooldown > 0) {
self.attackCooldown--;
}
if (self.comboTimer > 0) {
self.comboTimer--;
}
if (self.dashCooldown > 0) {
self.dashCooldown--;
}
if (self.invulnerable > 0) {
self.invulnerable--;
}
// Apply gravity
if (!self.isGrounded) {
self.jumpVelocity += self.gravity;
self.y += self.jumpVelocity;
}
// Check ground collision
if (self.y >= groundY - sprite.height / 2) {
self.y = groundY - sprite.height / 2;
self.isGrounded = true;
self.jumpVelocity = 0;
}
// Reset attack state
if (self.attackCooldown <= 0) {
self.isAttacking = false;
}
// Blink when invulnerable
if (self.invulnerable > 0) {
self.alpha = self.invulnerable % 4 < 2 ? 0.5 : 1;
} else {
self.alpha = 1;
}
// Keep player within bounds
if (self.x < sprite.width / 2) {
self.x = sprite.width / 2;
} else if (self.x > 2048 - sprite.width / 2) {
self.x = 2048 - sprite.width / 2;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB // Sky blue background
});
/****
* Game Code
****/
// Game constants
var groundY = 2400;
var spawnTimer = 0;
var gameStarted = false;
var waveNumber = 1;
var enemiesPerWave = 5;
var remainingEnemies = enemiesPerWave;
var waveDelay = 180; // 3 seconds between waves
var waveCountdown = 0;
// Game objects
var ground, player, healthBar, healthBarBg, comboIndicator;
var enemies = [];
var controlButtons = {};
// Initialize UI
function initUI() {
// Health bar background
healthBarBg = LK.getAsset('healthBarBackground', {
anchorX: 0,
anchorY: 0
});
LK.gui.top.addChild(healthBarBg);
healthBarBg.x = 50;
healthBarBg.y = 50;
// Health bar
healthBar = LK.getAsset('healthBar', {
anchorX: 0,
anchorY: 0
});
LK.gui.top.addChild(healthBar);
healthBar.x = 55;
healthBar.y = 55;
// Score text
var scoreTxt = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(1, 0);
LK.gui.topRight.addChild(scoreTxt);
scoreTxt.x = -50;
scoreTxt.y = 50;
// Wave indicator
var waveTxt = new Text2('Wave: 1', {
size: 60,
fill: 0xFFFFFF
});
waveTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(waveTxt);
waveTxt.y = 50;
// High Score
var highScoreTxt = new Text2('Best: ' + storage.highScore, {
size: 40,
fill: 0xFFFFFF
});
highScoreTxt.anchor.set(1, 0);
LK.gui.topRight.addChild(highScoreTxt);
highScoreTxt.x = -50;
highScoreTxt.y = 120;
// Update score display
LK.setInterval(function () {
scoreTxt.setText('Score: ' + LK.getScore());
waveTxt.setText('Wave: ' + waveNumber);
// Update high score if beaten
if (LK.getScore() > storage.highScore) {
storage.highScore = LK.getScore();
highScoreTxt.setText('Best: ' + storage.highScore);
}
}, 100);
// Create control buttons
createControlButtons();
}
function createControlButtons() {
// Left button
var leftBtn = new Container();
var leftCircle = LK.getAsset('comboIndicator', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 4,
scaleY: 4,
alpha: 0.5
});
leftBtn.addChild(leftCircle);
var leftTxt = new Text2('←', {
size: 80,
fill: 0x000000
});
leftTxt.anchor.set(0.5, 0.5);
leftBtn.addChild(leftTxt);
leftBtn.x = 200;
leftBtn.y = 2600;
game.addChild(leftBtn);
controlButtons.left = leftBtn;
// Right button
var rightBtn = new Container();
var rightCircle = LK.getAsset('comboIndicator', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 4,
scaleY: 4,
alpha: 0.5
});
rightBtn.addChild(rightCircle);
var rightTxt = new Text2('→', {
size: 80,
fill: 0x000000
});
rightTxt.anchor.set(0.5, 0.5);
rightBtn.addChild(rightTxt);
rightBtn.x = 400;
rightBtn.y = 2600;
game.addChild(rightBtn);
controlButtons.right = rightBtn;
// Jump button
var jumpBtn = new Container();
var jumpCircle = LK.getAsset('comboIndicator', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 4,
scaleY: 4,
alpha: 0.5
});
jumpBtn.addChild(jumpCircle);
var jumpTxt = new Text2('Jump', {
size: 60,
fill: 0x000000
});
jumpTxt.anchor.set(0.5, 0.5);
jumpBtn.addChild(jumpTxt);
jumpBtn.x = 1648;
jumpBtn.y = 2600;
game.addChild(jumpBtn);
controlButtons.jump = jumpBtn;
// Attack button
var attackBtn = new Container();
var attackCircle = LK.getAsset('comboIndicator', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 4,
scaleY: 4,
alpha: 0.5
});
attackBtn.addChild(attackCircle);
var attackTxt = new Text2('Attack', {
size: 60,
fill: 0x000000
});
attackTxt.anchor.set(0.5, 0.5);
attackBtn.addChild(attackTxt);
attackBtn.x = 1848;
attackBtn.y = 2600;
game.addChild(attackBtn);
controlButtons.attack = attackBtn;
// Dash button
var dashBtn = new Container();
var dashCircle = LK.getAsset('comboIndicator', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 4,
scaleY: 4,
alpha: 0.5
});
dashBtn.addChild(dashCircle);
var dashTxt = new Text2('Dash', {
size: 60,
fill: 0x000000
});
dashTxt.anchor.set(0.5, 0.5);
dashBtn.addChild(dashTxt);
dashBtn.x = 1648;
dashBtn.y = 2400;
game.addChild(dashBtn);
controlButtons.dash = dashBtn;
}
function initGame() {
// Create ground
ground = LK.getAsset('ground', {
anchorX: 0.5,
anchorY: 0
});
game.addChild(ground);
ground.x = 2048 / 2;
ground.y = groundY;
// Create player
player = new Samurai();
game.addChild(player);
player.x = 200;
player.y = groundY - 120;
// Create combo indicator
comboIndicator = new ComboIndicator();
game.addChild(comboIndicator);
comboIndicator.visible = false;
// Initialize user interface
initUI();
// Start the background music
LK.playMusic('battleMusic');
// Initialize game state
gameStarted = true;
LK.setScore(0);
waveNumber = 1;
spawnWave();
}
function spawnWave() {
remainingEnemies = enemiesPerWave + Math.floor(waveNumber / 2);
// Show wave text
var waveBanner = new Text2('WAVE ' + waveNumber, {
size: 150,
fill: 0xFFFFFF
});
waveBanner.anchor.set(0.5, 0.5);
waveBanner.x = 2048 / 2;
waveBanner.y = 2732 / 2;
game.addChild(waveBanner);
// Animate and remove the banner
tween(waveBanner, {
alpha: 0
}, {
duration: 2000,
easing: tween.easeOut,
onFinish: function onFinish() {
waveBanner.destroy();
}
});
// Spawn initial enemies
for (var i = 0; i < Math.min(3, remainingEnemies); i++) {
spawnEnemy();
}
}
function spawnEnemy() {
if (remainingEnemies <= 0) {
return;
}
var enemy = new Enemy();
game.addChild(enemy);
// Spawn on right side of screen
enemy.x = 2048 + Math.random() * 500;
enemy.y = groundY - enemy.height / 2;
enemies.push(enemy);
remainingEnemies--;
}
function handleInput() {
// Check for button presses
if (pressedButton) {
if (pressedButton === controlButtons.left) {
player.x -= player.speed;
player.direction = -1;
player.scale.x = -1;
} else if (pressedButton === controlButtons.right) {
player.x += player.speed;
player.direction = 1;
player.scale.x = 1;
} else if (pressedButton === controlButtons.jump) {
player.jump();
} else if (pressedButton === controlButtons.attack) {
player.attack();
} else if (pressedButton === controlButtons.dash) {
player.dash();
}
}
}
function updateHealth() {
// Update health bar width based on player health percentage
var healthPercent = player.health / player.maxHealth;
healthBar.scale.x = healthPercent;
}
// Initialize button press tracking
var pressedButton = null;
// Handle input events
game.down = function (x, y, obj) {
// Check which button was pressed
for (var key in controlButtons) {
var button = controlButtons[key];
if (button && x >= button.x - 100 && x <= button.x + 100 && y >= button.y - 100 && y <= button.y + 100) {
pressedButton = button;
break;
}
}
};
game.move = function (x, y, obj) {
// Check if still pressing a button
var stillPressing = false;
for (var key in controlButtons) {
var button = controlButtons[key];
if (button && x >= button.x - 100 && x <= button.x + 100 && y >= button.y - 100 && y <= button.y + 100) {
pressedButton = button;
stillPressing = true;
break;
}
}
if (!stillPressing) {
pressedButton = null;
}
};
game.up = function (x, y, obj) {
pressedButton = null;
};
// Main game update loop
game.update = function () {
if (!gameStarted) {
initGame();
return;
}
// Handle player input
handleInput();
// Update game objects
updateHealth();
// Spawn enemies
spawnTimer++;
if (spawnTimer >= 120 && remainingEnemies > 0) {
// Spawn every 2 seconds
spawnEnemy();
spawnTimer = 0;
}
// Check if wave is complete
if (enemies.length === 0 && remainingEnemies === 0) {
if (waveCountdown <= 0) {
waveCountdown = waveDelay;
} else {
waveCountdown--;
if (waveCountdown === 0) {
waveNumber++;
enemiesPerWave = 5 + Math.floor(waveNumber / 2);
spawnWave();
}
}
}
};
// Start the game
initGame(); ===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,628 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+var storage = LK.import("@upit/storage.v1", {
+ highScore: 0,
+ unlockedCombos: 1
+});
+
+/****
+* Classes
+****/
+var AttackEffect = Container.expand(function () {
+ var self = Container.call(this);
+ var effect = self.attachAsset('attackEffect', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ alpha: 0.7
+ });
+ self.lifespan = 12; // frames the effect will last
+ self.direction = 1; // 1 for right, -1 for left
+ self.update = function () {
+ self.lifespan--;
+ self.alpha -= 0.08;
+ if (self.lifespan <= 0) {
+ self.destroy();
+ }
+ };
+ return self;
+});
+var ComboIndicator = Container.expand(function () {
+ var self = Container.call(this);
+ var circle = self.attachAsset('comboIndicator', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.comboText = new Text2('1x', {
+ size: 30,
+ fill: 0x000000
+ });
+ self.comboText.anchor.set(0.5, 0.5);
+ self.addChild(self.comboText);
+ self.update = function () {
+ if (player.combo > 1) {
+ self.visible = true;
+ self.comboText.setText(player.combo + 'x');
+ self.x = player.x;
+ self.y = player.y - 100;
+ // Pulse effect based on combo timer
+ var scale = 1 + 0.2 * (player.comboTimer / 60);
+ self.scale.set(scale);
+ } else {
+ self.visible = false;
+ }
+ };
+ return self;
+});
+var Enemy = Container.expand(function () {
+ var self = Container.call(this);
+ var sprite = self.attachAsset('enemy', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.health = 50;
+ self.maxHealth = 50;
+ self.speed = 3 + Math.random() * 2;
+ self.jumpVelocity = 0;
+ self.gravity = 1;
+ self.isGrounded = false;
+ self.attackCooldown = 0;
+ self.direction = -1; // Initially facing left toward player
+ self.attackRange = 150;
+ self.type = Math.floor(Math.random() * 3); // 0 = normal, 1 = fast, 2 = tank
+ self.scoreValue = 10 * (self.type + 1);
+ // Adjust stats based on type
+ if (self.type === 1) {
+ // Fast enemy
+ self.speed += 3;
+ self.health = 30;
+ self.maxHealth = 30;
+ sprite.tint = 0x00AEEF; // Blue tint
+ } else if (self.type === 2) {
+ // Tank enemy
+ self.speed -= 1;
+ self.health = 100;
+ self.maxHealth = 100;
+ sprite.tint = 0x8B4513; // Brown tint
+ }
+ self.takeDamage = function (amount) {
+ self.health -= amount;
+ // Flash enemy when hit
+ LK.effects.flashObject(self, 0xFFFFFF, 200);
+ // Play hit sound
+ LK.getSound('hit').play();
+ if (self.health <= 0) {
+ // Play defeat sound
+ LK.getSound('enemyDefeat').play();
+ // Add score
+ LK.setScore(LK.getScore() + self.scoreValue);
+ // Remove from enemies array
+ var index = enemies.indexOf(self);
+ if (index !== -1) {
+ enemies.splice(index, 1);
+ }
+ // Destroy the enemy
+ self.destroy();
+ }
+ };
+ self.attack = function () {
+ if (self.attackCooldown <= 0) {
+ // Damage player if in range
+ var distance = Math.abs(player.x - self.x);
+ if (distance < self.attackRange) {
+ player.takeDamage(5 + self.type * 3);
+ }
+ self.attackCooldown = 60; // 1 second cooldown
+ }
+ };
+ self.update = function () {
+ // Update cooldowns
+ if (self.attackCooldown > 0) {
+ self.attackCooldown--;
+ }
+ // Apply gravity
+ if (!self.isGrounded) {
+ self.jumpVelocity += self.gravity;
+ self.y += self.jumpVelocity;
+ }
+ // Check ground collision
+ if (self.y >= groundY - sprite.height / 2) {
+ self.y = groundY - sprite.height / 2;
+ self.isGrounded = true;
+ self.jumpVelocity = 0;
+ }
+ // Move toward player
+ var distanceToPlayer = player.x - self.x;
+ self.direction = distanceToPlayer > 0 ? 1 : -1;
+ // Flip sprite based on direction
+ sprite.scale.x = self.direction;
+ // Move if not attacking and not too close
+ if (Math.abs(distanceToPlayer) > self.attackRange / 2) {
+ self.x += self.direction * self.speed;
+ } else if (self.attackCooldown <= 0) {
+ self.attack();
+ }
+ };
+ return self;
+});
+var Samurai = Container.expand(function () {
+ var self = Container.call(this);
+ var sprite = self.attachAsset('samurai', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ // Player stats
+ self.health = 100;
+ self.maxHealth = 100;
+ self.speed = 10;
+ self.jumpVelocity = 0;
+ self.gravity = 1;
+ self.isGrounded = false;
+ self.isAttacking = false;
+ self.attackCooldown = 0;
+ self.direction = 1; // 1 for right, -1 for left
+ self.combo = 0;
+ self.comboTimer = 0;
+ self.isDashing = false;
+ self.dashCooldown = 0;
+ self.invulnerable = 0;
+ self.jump = function () {
+ if (self.isGrounded) {
+ self.jumpVelocity = -25;
+ self.isGrounded = false;
+ }
+ };
+ self.attack = function () {
+ if (self.attackCooldown <= 0 && !self.isDashing) {
+ self.isAttacking = true;
+ self.attackCooldown = 15;
+ // Create attack effect
+ var attackEffect = new AttackEffect();
+ attackEffect.x = self.x + 100 * self.direction;
+ attackEffect.y = self.y;
+ attackEffect.direction = self.direction;
+ if (self.direction === -1) {
+ attackEffect.scale.x = -1;
+ }
+ game.addChild(attackEffect);
+ // Play slash sound
+ LK.getSound('slash').play();
+ // Increment combo if within time window
+ if (self.comboTimer > 0) {
+ self.combo++;
+ if (self.combo > storage.unlockedCombos) {
+ storage.unlockedCombos = self.combo;
+ }
+ } else {
+ self.combo = 1;
+ }
+ self.comboTimer = 60; // 1 second combo window
+ // Check for enemy hits
+ for (var i = 0; i < enemies.length; i++) {
+ var enemy = enemies[i];
+ var distance = Math.abs(enemy.x - self.x);
+ // Only hit enemies in front of the player and within attack range
+ if (self.direction === 1 && enemy.x > self.x && distance < 200 || self.direction === -1 && enemy.x < self.x && distance < 200) {
+ // Calculate damage based on combo
+ var damage = 10 + self.combo * 5;
+ enemy.takeDamage(damage);
+ // Apply knockback to enemy
+ enemy.x += self.direction * 30;
+ }
+ }
+ }
+ };
+ self.dash = function () {
+ if (!self.isDashing && self.dashCooldown <= 0) {
+ self.isDashing = true;
+ self.invulnerable = 20; // Invulnerable during dash
+ // Apply dash movement
+ tween(self, {
+ x: self.x + self.direction * 300
+ }, {
+ duration: 300,
+ easing: tween.easeOut,
+ onFinish: function onFinish() {
+ self.isDashing = false;
+ self.dashCooldown = 60; // 1 second cooldown
+ }
+ });
+ }
+ };
+ self.takeDamage = function (amount) {
+ if (self.invulnerable <= 0) {
+ self.health -= amount;
+ self.invulnerable = 30; // Half-second invulnerability
+ // Flash player red when hit
+ LK.effects.flashObject(self, 0xFF0000, 500);
+ // Play hit sound
+ LK.getSound('playerHit').play();
+ // Check for game over
+ if (self.health <= 0) {
+ LK.showGameOver();
+ }
+ }
+ };
+ self.update = function () {
+ // Update cooldowns
+ if (self.attackCooldown > 0) {
+ self.attackCooldown--;
+ }
+ if (self.comboTimer > 0) {
+ self.comboTimer--;
+ }
+ if (self.dashCooldown > 0) {
+ self.dashCooldown--;
+ }
+ if (self.invulnerable > 0) {
+ self.invulnerable--;
+ }
+ // Apply gravity
+ if (!self.isGrounded) {
+ self.jumpVelocity += self.gravity;
+ self.y += self.jumpVelocity;
+ }
+ // Check ground collision
+ if (self.y >= groundY - sprite.height / 2) {
+ self.y = groundY - sprite.height / 2;
+ self.isGrounded = true;
+ self.jumpVelocity = 0;
+ }
+ // Reset attack state
+ if (self.attackCooldown <= 0) {
+ self.isAttacking = false;
+ }
+ // Blink when invulnerable
+ if (self.invulnerable > 0) {
+ self.alpha = self.invulnerable % 4 < 2 ? 0.5 : 1;
+ } else {
+ self.alpha = 1;
+ }
+ // Keep player within bounds
+ if (self.x < sprite.width / 2) {
+ self.x = sprite.width / 2;
+ } else if (self.x > 2048 - sprite.width / 2) {
+ self.x = 2048 - sprite.width / 2;
+ }
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0x87CEEB // Sky blue background
+});
+
+/****
+* Game Code
+****/
+// Game constants
+var groundY = 2400;
+var spawnTimer = 0;
+var gameStarted = false;
+var waveNumber = 1;
+var enemiesPerWave = 5;
+var remainingEnemies = enemiesPerWave;
+var waveDelay = 180; // 3 seconds between waves
+var waveCountdown = 0;
+// Game objects
+var ground, player, healthBar, healthBarBg, comboIndicator;
+var enemies = [];
+var controlButtons = {};
+// Initialize UI
+function initUI() {
+ // Health bar background
+ healthBarBg = LK.getAsset('healthBarBackground', {
+ anchorX: 0,
+ anchorY: 0
+ });
+ LK.gui.top.addChild(healthBarBg);
+ healthBarBg.x = 50;
+ healthBarBg.y = 50;
+ // Health bar
+ healthBar = LK.getAsset('healthBar', {
+ anchorX: 0,
+ anchorY: 0
+ });
+ LK.gui.top.addChild(healthBar);
+ healthBar.x = 55;
+ healthBar.y = 55;
+ // Score text
+ var scoreTxt = new Text2('Score: 0', {
+ size: 60,
+ fill: 0xFFFFFF
+ });
+ scoreTxt.anchor.set(1, 0);
+ LK.gui.topRight.addChild(scoreTxt);
+ scoreTxt.x = -50;
+ scoreTxt.y = 50;
+ // Wave indicator
+ var waveTxt = new Text2('Wave: 1', {
+ size: 60,
+ fill: 0xFFFFFF
+ });
+ waveTxt.anchor.set(0.5, 0);
+ LK.gui.top.addChild(waveTxt);
+ waveTxt.y = 50;
+ // High Score
+ var highScoreTxt = new Text2('Best: ' + storage.highScore, {
+ size: 40,
+ fill: 0xFFFFFF
+ });
+ highScoreTxt.anchor.set(1, 0);
+ LK.gui.topRight.addChild(highScoreTxt);
+ highScoreTxt.x = -50;
+ highScoreTxt.y = 120;
+ // Update score display
+ LK.setInterval(function () {
+ scoreTxt.setText('Score: ' + LK.getScore());
+ waveTxt.setText('Wave: ' + waveNumber);
+ // Update high score if beaten
+ if (LK.getScore() > storage.highScore) {
+ storage.highScore = LK.getScore();
+ highScoreTxt.setText('Best: ' + storage.highScore);
+ }
+ }, 100);
+ // Create control buttons
+ createControlButtons();
+}
+function createControlButtons() {
+ // Left button
+ var leftBtn = new Container();
+ var leftCircle = LK.getAsset('comboIndicator', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ scaleX: 4,
+ scaleY: 4,
+ alpha: 0.5
+ });
+ leftBtn.addChild(leftCircle);
+ var leftTxt = new Text2('←', {
+ size: 80,
+ fill: 0x000000
+ });
+ leftTxt.anchor.set(0.5, 0.5);
+ leftBtn.addChild(leftTxt);
+ leftBtn.x = 200;
+ leftBtn.y = 2600;
+ game.addChild(leftBtn);
+ controlButtons.left = leftBtn;
+ // Right button
+ var rightBtn = new Container();
+ var rightCircle = LK.getAsset('comboIndicator', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ scaleX: 4,
+ scaleY: 4,
+ alpha: 0.5
+ });
+ rightBtn.addChild(rightCircle);
+ var rightTxt = new Text2('→', {
+ size: 80,
+ fill: 0x000000
+ });
+ rightTxt.anchor.set(0.5, 0.5);
+ rightBtn.addChild(rightTxt);
+ rightBtn.x = 400;
+ rightBtn.y = 2600;
+ game.addChild(rightBtn);
+ controlButtons.right = rightBtn;
+ // Jump button
+ var jumpBtn = new Container();
+ var jumpCircle = LK.getAsset('comboIndicator', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ scaleX: 4,
+ scaleY: 4,
+ alpha: 0.5
+ });
+ jumpBtn.addChild(jumpCircle);
+ var jumpTxt = new Text2('Jump', {
+ size: 60,
+ fill: 0x000000
+ });
+ jumpTxt.anchor.set(0.5, 0.5);
+ jumpBtn.addChild(jumpTxt);
+ jumpBtn.x = 1648;
+ jumpBtn.y = 2600;
+ game.addChild(jumpBtn);
+ controlButtons.jump = jumpBtn;
+ // Attack button
+ var attackBtn = new Container();
+ var attackCircle = LK.getAsset('comboIndicator', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ scaleX: 4,
+ scaleY: 4,
+ alpha: 0.5
+ });
+ attackBtn.addChild(attackCircle);
+ var attackTxt = new Text2('Attack', {
+ size: 60,
+ fill: 0x000000
+ });
+ attackTxt.anchor.set(0.5, 0.5);
+ attackBtn.addChild(attackTxt);
+ attackBtn.x = 1848;
+ attackBtn.y = 2600;
+ game.addChild(attackBtn);
+ controlButtons.attack = attackBtn;
+ // Dash button
+ var dashBtn = new Container();
+ var dashCircle = LK.getAsset('comboIndicator', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ scaleX: 4,
+ scaleY: 4,
+ alpha: 0.5
+ });
+ dashBtn.addChild(dashCircle);
+ var dashTxt = new Text2('Dash', {
+ size: 60,
+ fill: 0x000000
+ });
+ dashTxt.anchor.set(0.5, 0.5);
+ dashBtn.addChild(dashTxt);
+ dashBtn.x = 1648;
+ dashBtn.y = 2400;
+ game.addChild(dashBtn);
+ controlButtons.dash = dashBtn;
+}
+function initGame() {
+ // Create ground
+ ground = LK.getAsset('ground', {
+ anchorX: 0.5,
+ anchorY: 0
+ });
+ game.addChild(ground);
+ ground.x = 2048 / 2;
+ ground.y = groundY;
+ // Create player
+ player = new Samurai();
+ game.addChild(player);
+ player.x = 200;
+ player.y = groundY - 120;
+ // Create combo indicator
+ comboIndicator = new ComboIndicator();
+ game.addChild(comboIndicator);
+ comboIndicator.visible = false;
+ // Initialize user interface
+ initUI();
+ // Start the background music
+ LK.playMusic('battleMusic');
+ // Initialize game state
+ gameStarted = true;
+ LK.setScore(0);
+ waveNumber = 1;
+ spawnWave();
+}
+function spawnWave() {
+ remainingEnemies = enemiesPerWave + Math.floor(waveNumber / 2);
+ // Show wave text
+ var waveBanner = new Text2('WAVE ' + waveNumber, {
+ size: 150,
+ fill: 0xFFFFFF
+ });
+ waveBanner.anchor.set(0.5, 0.5);
+ waveBanner.x = 2048 / 2;
+ waveBanner.y = 2732 / 2;
+ game.addChild(waveBanner);
+ // Animate and remove the banner
+ tween(waveBanner, {
+ alpha: 0
+ }, {
+ duration: 2000,
+ easing: tween.easeOut,
+ onFinish: function onFinish() {
+ waveBanner.destroy();
+ }
+ });
+ // Spawn initial enemies
+ for (var i = 0; i < Math.min(3, remainingEnemies); i++) {
+ spawnEnemy();
+ }
+}
+function spawnEnemy() {
+ if (remainingEnemies <= 0) {
+ return;
+ }
+ var enemy = new Enemy();
+ game.addChild(enemy);
+ // Spawn on right side of screen
+ enemy.x = 2048 + Math.random() * 500;
+ enemy.y = groundY - enemy.height / 2;
+ enemies.push(enemy);
+ remainingEnemies--;
+}
+function handleInput() {
+ // Check for button presses
+ if (pressedButton) {
+ if (pressedButton === controlButtons.left) {
+ player.x -= player.speed;
+ player.direction = -1;
+ player.scale.x = -1;
+ } else if (pressedButton === controlButtons.right) {
+ player.x += player.speed;
+ player.direction = 1;
+ player.scale.x = 1;
+ } else if (pressedButton === controlButtons.jump) {
+ player.jump();
+ } else if (pressedButton === controlButtons.attack) {
+ player.attack();
+ } else if (pressedButton === controlButtons.dash) {
+ player.dash();
+ }
+ }
+}
+function updateHealth() {
+ // Update health bar width based on player health percentage
+ var healthPercent = player.health / player.maxHealth;
+ healthBar.scale.x = healthPercent;
+}
+// Initialize button press tracking
+var pressedButton = null;
+// Handle input events
+game.down = function (x, y, obj) {
+ // Check which button was pressed
+ for (var key in controlButtons) {
+ var button = controlButtons[key];
+ if (button && x >= button.x - 100 && x <= button.x + 100 && y >= button.y - 100 && y <= button.y + 100) {
+ pressedButton = button;
+ break;
+ }
+ }
+};
+game.move = function (x, y, obj) {
+ // Check if still pressing a button
+ var stillPressing = false;
+ for (var key in controlButtons) {
+ var button = controlButtons[key];
+ if (button && x >= button.x - 100 && x <= button.x + 100 && y >= button.y - 100 && y <= button.y + 100) {
+ pressedButton = button;
+ stillPressing = true;
+ break;
+ }
+ }
+ if (!stillPressing) {
+ pressedButton = null;
+ }
+};
+game.up = function (x, y, obj) {
+ pressedButton = null;
+};
+// Main game update loop
+game.update = function () {
+ if (!gameStarted) {
+ initGame();
+ return;
+ }
+ // Handle player input
+ handleInput();
+ // Update game objects
+ updateHealth();
+ // Spawn enemies
+ spawnTimer++;
+ if (spawnTimer >= 120 && remainingEnemies > 0) {
+ // Spawn every 2 seconds
+ spawnEnemy();
+ spawnTimer = 0;
+ }
+ // Check if wave is complete
+ if (enemies.length === 0 && remainingEnemies === 0) {
+ if (waveCountdown <= 0) {
+ waveCountdown = waveDelay;
+ } else {
+ waveCountdown--;
+ if (waveCountdown === 0) {
+ waveNumber++;
+ enemiesPerWave = 5 + Math.floor(waveNumber / 2);
+ spawnWave();
+ }
+ }
+ }
+};
+// Start the game
+initGame();
\ No newline at end of file
blue armored samurai with long katana. Single Game Texture. In-Game asset. Blank background. High contrast. No shadows
black ninja with katana Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
green meadow surface. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
blue sky and with cloud. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
anime style green dark forest. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
silver star. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
blue lighting dragon head. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows