/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { highScore: 0, unlockedCombos: 1 }); /**** * Classes ****/ var AnimeSamurai = 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; }); 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() { // Add nature background var natureBackground = LK.getAsset('natureBackground', { anchorX: 0.5, anchorY: 0.5 }); game.addChild(natureBackground); natureBackground.x = 2048 / 2; natureBackground.y = 2732 / 2; // 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();
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScore: 0,
unlockedCombos: 1
});
/****
* Classes
****/
var AnimeSamurai = 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;
});
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() {
// Add nature background
var natureBackground = LK.getAsset('natureBackground', {
anchorX: 0.5,
anchorY: 0.5
});
game.addChild(natureBackground);
natureBackground.x = 2048 / 2;
natureBackground.y = 2732 / 2;
// 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();
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