/****
* 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(); ===================================================================
--- original.js
+++ change.js
@@ -613,8 +613,16 @@
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
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