User prompt
make the background dark green
User prompt
make the enemies bigger
User prompt
the D-Pad doesn't work
User prompt
can you make a D-Pad controller
User prompt
make the enemies bigger
User prompt
it's too hard, make it easier
User prompt
make more enemies
User prompt
make the enemy bigger and the katana swing faster
User prompt
make the enemy have HP bars and make the player have a attack speed bar to show when it atttacks
User prompt
make the enemy flash white when hit
User prompt
make a explosion sprite for when your character does damage to an enemy, and please make it to where when an enemy touches the katana your character does not take damage โช๐ก Consider importing and using the following plugins: @upit/tween.v1
User prompt
make the katana damage enemies and make the ninja blue
Code edit (1 edits merged)
Please save this source code
User prompt
Ninja Survivor
User prompt
can you make it not have any extra stuff other than a katana and a shuriken that throws every 5 seconds, also please make the game like Survivor.io or Vampire survivors?
Initial prompt
make a ARPG about a blue ninja named Harry and he fights monsters through waves.
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphic = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 20;
self.speed = 2;
self.damage = 10;
self.attackCooldown = 0;
self.attackCooldownMax = 30; // Frames between attacks
self.experienceValue = 1;
self.hitByKatana = false;
self.katanaHitTimer = 0;
self.update = function () {
if (player.isDead) return;
// Move toward player
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Normalize and apply speed
if (distance > 0) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
// Attack cooldown
if (self.attackCooldown > 0) {
self.attackCooldown--;
}
// Decrement katana hit timer if active
if (self.katanaHitTimer > 0) {
self.katanaHitTimer--;
if (self.katanaHitTimer === 0) {
self.hitByKatana = false;
}
}
// Attack player if touching and not recently hit by katana
if (self.intersects(player) && self.attackCooldown === 0 && !self.hitByKatana) {
player.takeDamage(self.damage);
self.attackCooldown = self.attackCooldownMax;
}
};
self.takeDamage = function (amount) {
self.health -= amount;
// Flash white when damaged
tween(enemyGraphic, {
tint: 0xFFFFFF
}, {
duration: 50,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(enemyGraphic, {
tint: 0xff2222 // Return to original enemy color
}, {
duration: 50,
easing: tween.easeIn
});
}
});
// Create explosion effect
var explosion = new Explosion();
explosion.x = self.x;
explosion.y = self.y;
game.addChild(explosion);
// Add a small bounce effect using tween
tween(self, {
y: self.y - 10
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
y: self.y + 10
}, {
duration: 100,
easing: tween.easeIn
});
}
});
if (self.health <= 0) {
self.die();
}
};
self.die = function () {
// Spawn experience gem
var expGem = new ExperienceGem();
expGem.value = self.experienceValue;
expGem.x = self.x;
expGem.y = self.y;
game.addChild(expGem);
experienceGems.push(expGem);
// Remove from enemies array and destroy
var index = enemies.indexOf(self);
if (index !== -1) {
enemies.splice(index, 1);
}
self.destroy();
// Increment kill count
killCount++;
killCountText.setText("Kills: " + killCount);
};
return self;
});
var ExperienceGem = Container.expand(function () {
var self = Container.call(this);
var gemGraphic = self.attachAsset('expGem', {
anchorX: 0.5,
anchorY: 0.5
});
self.value = 1;
self.speed = 0;
self.magnetRange = 200;
self.isMovingToPlayer = false;
self.update = function () {
if (player.isDead) return;
// Calculate distance to player
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// If close to player, move toward player (magnetic effect)
if (distance < self.magnetRange || self.isMovingToPlayer) {
self.isMovingToPlayer = true;
self.speed += 0.2;
self.speed = Math.min(self.speed, 15);
if (distance > 0) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
}
// If touching player, give experience
if (self.intersects(player)) {
player.gainExperience(self.value);
// Remove from array and destroy
var index = experienceGems.indexOf(self);
if (index !== -1) {
experienceGems.splice(index, 1);
}
self.destroy();
}
};
return self;
});
var Explosion = Container.expand(function () {
var self = Container.call(this);
var explosionGraphic = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFA500
});
self.lifetime = 0;
self.maxLifetime = 15; // Short lifetime for quick explosion effect
self.update = function () {
self.lifetime++;
// Scale up and fade out
var progress = self.lifetime / self.maxLifetime;
explosionGraphic.scale.x = 1 + progress;
explosionGraphic.scale.y = 1 + progress;
explosionGraphic.alpha = 1 - progress;
// Destroy when animation complete
if (self.lifetime >= self.maxLifetime) {
self.destroy();
}
};
return self;
});
var Katana = Container.expand(function () {
var self = Container.call(this);
var katanaGraphic = self.attachAsset('katana', {
anchorX: 0,
anchorY: 0.5
});
self.damage = 10;
self.rotationSpeed = 0.1;
self.attackCooldown = 0;
self.attackCooldownMax = 20; // Frames between attacks
self.level = 1;
self.update = function () {
if (player.isDead) return;
// Rotate around player
self.rotation += self.rotationSpeed;
// Attack cooldown
if (self.attackCooldown > 0) {
self.attackCooldown--;
}
// Check for enemies in range and attack
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
if (self.intersects(enemy) && self.attackCooldown === 0) {
enemy.takeDamage(self.damage);
self.attackCooldown = self.attackCooldownMax;
LK.getSound('slash').play();
// Mark enemy as being hit by katana - this will be used to prevent damage to player
enemy.hitByKatana = true;
enemy.katanaHitTimer = 30; // Frames of immunity after being hit
// Don't break, allow the katana to hit multiple enemies in a single swing
}
}
};
self.levelUp = function () {
self.level += 1;
self.damage += 5;
self.attackCooldownMax = Math.max(10, self.attackCooldownMax - 2);
};
return self;
});
var LevelUpEffect = Container.expand(function () {
var self = Container.call(this);
var effectGraphic = self.attachAsset('levelUpIndicator', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.7
});
self.lifetime = 0;
self.maxLifetime = 60; // 1 second at 60fps
self.update = function () {
self.lifetime++;
// Scale up and fade out
var progress = self.lifetime / self.maxLifetime;
effectGraphic.scale.x = 1 + progress;
effectGraphic.scale.y = 1 + progress;
effectGraphic.alpha = 0.7 * (1 - progress);
if (self.lifetime >= self.maxLifetime) {
self.destroy();
}
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerBody = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
self.health = 100;
self.maxHealth = 100;
self.level = 1;
self.experience = 0;
self.experienceToNextLevel = 10;
self.isDead = false;
// Health display
self.healthBar = new Container();
self.healthBar.y = -70;
self.healthBarBg = LK.getAsset('player', {
width: 100,
height: 10,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x222222
});
self.healthBarFill = LK.getAsset('player', {
width: 100,
height: 10,
anchorX: 0,
anchorY: 0.5,
tint: 0x00FF00
});
self.healthBarFill.x = -50;
self.healthBar.addChild(self.healthBarBg);
self.healthBar.addChild(self.healthBarFill);
self.addChild(self.healthBar);
self.update = function () {
if (self.isDead) return;
// Update health bar
self.healthBarFill.width = 100 * (self.health / self.maxHealth);
};
self.takeDamage = function (amount) {
if (self.isDead) return;
self.health -= amount;
if (self.health <= 0) {
self.health = 0;
self.die();
} else {
// Flash red when damaged
LK.effects.flashObject(playerBody, 0xFF0000, 200);
}
};
self.gainExperience = function (amount) {
if (self.isDead) return;
self.experience += amount;
if (self.experience >= self.experienceToNextLevel) {
self.levelUp();
}
};
self.levelUp = function () {
self.level += 1;
self.experience = 0;
self.experienceToNextLevel = Math.floor(self.experienceToNextLevel * 1.5);
self.maxHealth += 10;
self.health = self.maxHealth;
// Level up effects
var levelUpEffect = new LevelUpEffect();
levelUpEffect.x = self.x;
levelUpEffect.y = self.y;
game.addChild(levelUpEffect);
LK.getSound('levelup').play();
};
self.die = function () {
if (self.isDead) return;
self.isDead = true;
LK.getSound('death').play();
LK.effects.flashObject(playerBody, 0xFF0000, 1000);
// Game over after a short delay
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
};
return self;
});
var Shuriken = Container.expand(function () {
var self = Container.call(this);
var shurikenGraphic = self.attachAsset('shuriken', {
anchorX: 0.5,
anchorY: 0.5
});
self.damage = 15;
self.speed = 10;
self.direction = {
x: 0,
y: 0
};
self.pierceCount = 1; // How many enemies it can hit before disappearing
self.hitEnemies = []; // Track which enemies we've already hit
self.level = 1;
self.update = function () {
// Move in direction
self.x += self.direction.x * self.speed;
self.y += self.direction.y * self.speed;
// Rotate the shuriken for effect
shurikenGraphic.rotation += 0.2;
// Check if off screen
if (self.x < -100 || self.x > 2148 || self.y < -100 || self.y > 2832) {
self.destroy();
var index = shurikens.indexOf(self);
if (index !== -1) {
shurikens.splice(index, 1);
}
return;
}
// Check for enemy collisions
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
// Skip enemies we've already hit
if (self.hitEnemies.indexOf(enemy) !== -1) {
continue;
}
if (self.intersects(enemy)) {
enemy.takeDamage(self.damage);
LK.getSound('hit').play();
self.hitEnemies.push(enemy);
// If we've hit enough enemies, destroy this shuriken
if (self.hitEnemies.length >= self.pierceCount) {
self.destroy();
var index = shurikens.indexOf(self);
if (index !== -1) {
shurikens.splice(index, 1);
}
return;
}
}
}
};
self.levelUp = function () {
self.level += 1;
self.damage += 5;
self.pierceCount += 1;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Global variables
var player;
var katana;
var shurikens = [];
var enemies = [];
var experienceGems = [];
var dragPosition = null;
var gameTime = 0;
var shurikenTimer = 0;
var enemySpawnTimer = 0;
var waveNumber = 1;
var killCount = 0;
// UI elements
var timeText;
var waveText;
var killCountText;
var levelText;
// Initialize player
player = new Player();
player.x = 2048 / 2;
player.y = 2732 / 2;
game.addChild(player);
// Initialize katana
katana = new Katana();
player.addChild(katana);
// Initialize UI
timeText = new Text2('Time: 0s', {
size: 60,
fill: 0xFFFFFF
});
timeText.anchor.set(1, 0);
LK.gui.topRight.addChild(timeText);
waveText = new Text2('Wave: 1', {
size: 60,
fill: 0xFFFFFF
});
waveText.anchor.set(0.5, 0);
LK.gui.top.addChild(waveText);
killCountText = new Text2('Kills: 0', {
size: 60,
fill: 0xFFFFFF
});
killCountText.anchor.set(0, 0);
LK.gui.topRight.addChild(killCountText);
killCountText.y = 70;
levelText = new Text2('Level: 1', {
size: 60,
fill: 0xFFFFFF
});
levelText.anchor.set(0, 0);
LK.gui.topLeft.addChild(levelText);
levelText.x = 120; // Avoid platform level menu icon area
// Spawn initial enemies
spawnEnemyWave(5);
// Play background music
LK.playMusic('bgmusic');
// Handle player movement
game.down = function (x, y, obj) {
dragPosition = {
x: x,
y: y
};
};
game.move = function (x, y, obj) {
if (dragPosition) {
player.x = x;
player.y = y;
}
};
game.up = function (x, y, obj) {
dragPosition = null;
};
// Main game update loop
game.update = function () {
if (player.isDead) return;
// Update game time (in seconds)
gameTime += 1 / 60;
timeText.setText('Time: ' + Math.floor(gameTime) + 's');
// Update level text
levelText.setText('Level: ' + player.level);
// Shuriken spawning logic
shurikenTimer++;
if (shurikenTimer >= 300) {
// Every 5 seconds (60fps * 5)
spawnShuriken();
shurikenTimer = 0;
}
// Enemy spawning logic
enemySpawnTimer++;
var spawnRate = Math.max(300 - waveNumber * 10, 60); // Faster spawns as waves progress
if (enemySpawnTimer >= spawnRate) {
spawnEnemy();
enemySpawnTimer = 0;
}
// Wave progression
if (Math.floor(gameTime) % 30 === 0 && Math.floor(gameTime) > 0 && Math.floor(gameTime / 30) > waveNumber - 1) {
waveNumber++;
waveText.setText('Wave: ' + waveNumber);
spawnEnemyWave(5 + waveNumber);
}
};
// Helper functions
function spawnShuriken() {
for (var i = 0; i < (player.level > 5 ? 2 : 1); i++) {
var shuriken = new Shuriken();
shuriken.x = player.x;
shuriken.y = player.y;
// Choose a random enemy to target, or random direction if no enemies
if (enemies.length > 0) {
var targetEnemy = enemies[Math.floor(Math.random() * enemies.length)];
var dx = targetEnemy.x - player.x;
var dy = targetEnemy.y - player.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
shuriken.direction = {
x: dx / distance,
y: dy / distance
};
} else {
// Random direction if enemy is directly on top of player
var angle = Math.random() * Math.PI * 2;
shuriken.direction = {
x: Math.cos(angle),
y: Math.sin(angle)
};
}
} else {
// Random direction if no enemies
var angle = Math.random() * Math.PI * 2;
shuriken.direction = {
x: Math.cos(angle),
y: Math.sin(angle)
};
}
game.addChild(shuriken);
shurikens.push(shuriken);
LK.getSound('throw').play();
}
}
function spawnEnemy() {
var enemy = new Enemy();
// Scale enemy stats with wave number
enemy.health = 20 + waveNumber * 5;
enemy.speed = 2 + waveNumber * 0.1;
enemy.damage = 10 + waveNumber * 1;
enemy.experienceValue = 1 + Math.floor(waveNumber / 3);
// Spawn outside the screen
var side = Math.floor(Math.random() * 4);
switch (side) {
case 0:
// Top
enemy.x = Math.random() * 2048;
enemy.y = -100;
break;
case 1:
// Right
enemy.x = 2148;
enemy.y = Math.random() * 2732;
break;
case 2:
// Bottom
enemy.x = Math.random() * 2048;
enemy.y = 2832;
break;
case 3:
// Left
enemy.x = -100;
enemy.y = Math.random() * 2732;
break;
}
game.addChild(enemy);
enemies.push(enemy);
}
function spawnEnemyWave(count) {
for (var i = 0; i < count; i++) {
spawnEnemy();
}
} ===================================================================
--- original.js
+++ change.js
@@ -50,10 +50,23 @@
}
};
self.takeDamage = function (amount) {
self.health -= amount;
- // Flash red when damaged
- LK.effects.flashObject(enemyGraphic, 0xFFFFFF, 100);
+ // Flash white when damaged
+ tween(enemyGraphic, {
+ tint: 0xFFFFFF
+ }, {
+ duration: 50,
+ easing: tween.easeOut,
+ onFinish: function onFinish() {
+ tween(enemyGraphic, {
+ tint: 0xff2222 // Return to original enemy color
+ }, {
+ duration: 50,
+ easing: tween.easeIn
+ });
+ }
+ });
// Create explosion effect
var explosion = new Explosion();
explosion.x = self.x;
explosion.y = self.y;
a ninja star. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
green exp diamond
a katana. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
monster. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
ninja. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
yellow arrow. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat