User prompt
When choosing a plugin, creatures should not cause damage, and add more plugins, add plugins that give area damage, etc., and add a background model, I will change it. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
They die without touching me. Add a bullet model and when choosing an add-on, the creatures should not cause damage.
User prompt
There is a level up tab, add it as a model, I will change it and the bullet model should go directly to the man, not as a straight png, but straight
User prompt
add a level screen to show how many levels we have or how much of the other level is left and add an assets screen compatible with the police
User prompt
The issue is that when we get a skill, it should not go to living beings, it should come only to us, and also to living beings with weapons in their hands, and it should slow down the very fast speeds of the living beings a little.
User prompt
Reduce the number of living creatures coming, but increase it by 1 click after 3 minutes, so that it constantly uses weapons, and the gun barrel points to living creatures.
User prompt
Let the gun barrel also look at the creatures, and while you buy the add-ons, the game should pause, and the creatures should be a little smarter, and the creatures should come in stages.
User prompt
Let the gun be visible in our hand and have a bullet model when firing
User prompt
Let the creatures come a little later and give us a weapon model
User prompt
Please fix the bug: 'prepareWave is not defined' in or related to this line: 'prepareWave();' Line Number: 758
User prompt
Knk, look, creatures should behave a little differently from each other because when creatures are gathered somewhere and revolve around them, they cannot do anything. Also, they should come continuously, not in waves, but continuously and without stopping. Also, the game should wait like this while purchasing add-ons.
User prompt
Knk, look, the creatures should behave a little differently from each other because when you gather the creatures somewhere, for example, they cannot do anything when they revolve around you. Also, they should come continuously, not in waves, but continuously and without stopping. Also, the game should wait like this while purchasing add-ons.
User prompt
Let it be a continuous live stream and add something like artificial intelligence to the creatures so that it is not so stupid
User prompt
Don't let the creatures come all at once, let them come continuously and expand the playing area a little.
User prompt
Don't let other creatures come so much, let them increase over time, and make sure that almost no bullets miss. Make a better weapon's mechanic to turn into creatures.
Code edit (1 edits merged)
Please save this source code
Initial prompt
Beast Survivors
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Creature projectile class var CreatureProjectile = Container.expand(function () { var self = Container.call(this); var asset = self.attachAsset('creatureProj', { anchorX: 0.5, anchorY: 0.5 }); self.radius = 32; self.speed = 32; self.angle = 0; self.damage = 1; self.update = function () { // Homing logic: find nearest enemy and adjust angle toward it var nearest = null; var minDist = 999999; for (var i = 0; i < enemies.length; i++) { var e = enemies[i]; var dx = e.x - self.x; var dy = e.y - self.y; var d = Math.sqrt(dx * dx + dy * dy); if (d < minDist) { minDist = d; nearest = e; } } if (nearest && minDist > 1) { var targetAngle = Math.atan2(nearest.y - self.y, nearest.x - self.x); // Smoothly turn toward target var da = targetAngle - self.angle; // Normalize angle to [-PI, PI] while (da > Math.PI) da -= Math.PI * 2; while (da < -Math.PI) da += Math.PI * 2; self.angle += da * 0.25; // turn rate } self.x += Math.cos(self.angle) * self.speed; self.y += Math.sin(self.angle) * self.speed; }; return self; }); // Creature weapon class (auto-attacks for player) var CreatureWeapon = Container.expand(function () { var self = Container.call(this); // Attach asset (box, yellow) var asset = self.attachAsset('creature', { anchorX: 0.5, anchorY: 0.5 }); // Weapon stats self.damage = 1; self.speed = 32; self.cooldown = 60; // frames between shots self.timer = 0; self.projectileCount = 1; self.spread = 0.2; // radians // Update method: fires projectiles if timer is up self.update = function () { if (self.timer > 0) { self.timer--; } else { self.fire(); self.timer = self.cooldown; } }; // Fire projectiles in a spread self.fire = function () { // Projectiles orbit and launch from around the player var now = Date.now(); for (var i = 0; i < self.projectileCount; i++) { // Orbit offset for each projectile var orbitAngle = 2 * Math.PI / self.projectileCount * i + now % 1000 / 1000 * Math.PI * 2; var launchDist = 120 + Math.random() * 30; var px = player.x + Math.cos(orbitAngle) * launchDist; var py = player.y + Math.sin(orbitAngle) * launchDist; // Clamp projectile spawn to play area if (px < 0) px = 0; if (px > GAME_WIDTH) px = GAME_WIDTH; if (py < 0) py = 0; if (py > GAME_HEIGHT) py = GAME_HEIGHT; // Aim at nearest enemy if possible var target = null; var minDist = 999999; for (var j = 0; j < enemies.length; j++) { var e = enemies[j]; var dx = e.x - px; var dy = e.y - py; var d = Math.sqrt(dx * dx + dy * dy); if (d < minDist) { minDist = d; target = e; } } var angle; if (target) { angle = Math.atan2(target.y - py, target.x - px); } else { angle = orbitAngle; } var proj = new CreatureProjectile(); proj.x = px; proj.y = py; proj.angle = angle; proj.speed = self.speed; proj.damage = self.damage; projectiles.push(proj); game.addChild(proj); } }; // Upgrade weapon self.upgrade = function (type) { if (type === 'damage') self.damage++; if (type === 'speed') self.speed += 6; if (type === 'cooldown' && self.cooldown > 20) self.cooldown -= 8; if (type === 'projectile') self.projectileCount++; if (type === 'spread') self.spread += 0.1; }; return self; }); // Enemy class var Enemy = Container.expand(function () { var self = Container.call(this); var asset = self.attachAsset('enemy', { anchorX: 0.5, anchorY: 0.5 }); self.radius = 48; self.speed = 6 + Math.random() * 3; self.hp = 2 + Math.floor(wave * 0.5); self.maxHp = self.hp; // For movement self.update = function () { // Move towards player var dx = player.x - self.x; var dy = player.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 0) { self.x += dx / dist * self.speed; self.y += dy / dist * self.speed; } }; // Take damage self.takeDamage = function (amount) { self.hp -= amount; LK.effects.flashObject(self, 0xffff00, 200); if (self.hp <= 0) { spawnExp(self.x, self.y, 1 + Math.floor(wave * 0.2)); self.destroy(); return true; } return false; }; return self; }); // Experience gem class var ExpGem = Container.expand(function () { var self = Container.call(this); var asset = self.attachAsset('expGem', { anchorX: 0.5, anchorY: 0.5 }); self.radius = 28; self.value = 1; self.update = function () { // If close to player, move towards player var dx = player.x - self.x; var dy = player.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < 300) { self.x += dx / dist * 18; self.y += dy / dist * 18; } }; return self; }); // Player character class var Player = Container.expand(function () { var self = Container.call(this); // Attach player asset (ellipse, green) var playerAsset = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); // Set up player stats self.radius = 60; // for collision self.speed = 18; // movement speed per frame self.level = 1; self.exp = 0; self.expToLevel = 10; self.hp = 3; self.maxHp = 3; // For movement smoothing self.targetX = GAME_WIDTH / 2; self.targetY = GAME_HEIGHT / 2; // For invulnerability after hit self.invulnTicks = 0; // Update method self.update = function () { // Smoothly move towards target var dx = self.targetX - self.x; var dy = self.targetY - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > self.speed) { self.x += dx / dist * self.speed; self.y += dy / dist * self.speed; } else { self.x = self.targetX; self.y = self.targetY; } // Clamp to game area if (self.x < self.radius) self.x = self.radius; if (self.x > GAME_WIDTH - self.radius) self.x = GAME_WIDTH - self.radius; if (self.y < self.radius) self.y = self.radius; if (self.y > GAME_HEIGHT - self.radius) self.y = GAME_HEIGHT - self.radius; // Invulnerability timer if (self.invulnTicks > 0) { self.invulnTicks--; playerAsset.alpha = self.invulnTicks % 10 < 5 ? 0.5 : 1; } else { playerAsset.alpha = 1; } }; // Level up self.gainExp = function (amount) { self.exp += amount; while (self.exp >= self.expToLevel) { self.exp -= self.expToLevel; self.level++; self.expToLevel = Math.floor(self.expToLevel * 1.3 + 5); showLevelUp(); } updateExpBar(); }; // Take damage self.takeDamage = function () { if (self.invulnTicks > 0) return; self.hp--; updateHpBar(); self.invulnTicks = 60; LK.effects.flashObject(self, 0xff0000, 500); if (self.hp <= 0) { LK.effects.flashScreen(0xff0000, 1000); LK.showGameOver(); } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x1a1a1a }); /**** * Game Code ****/ // --- Global variables --- var player; var creatureWeapon; var projectiles = []; var enemies = []; var expGems = []; var wave = 1; var waveTimer = 0; var waveInterval = 600; // frames between waves var dragNode = null; // --- GUI Elements --- var scoreTxt = new Text2('0', { size: 100, fill: "#fff" }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); var expBar = new Text2('', { size: 60, fill: 0xAAFF00 }); expBar.anchor.set(0.5, 0); LK.gui.top.addChild(expBar); var hpBar = new Text2('', { size: 60, fill: 0xFF4444 }); hpBar.anchor.set(0.5, 0); LK.gui.top.addChild(hpBar); function updateExpBar() { expBar.setText('LV ' + player.level + ' EXP: ' + player.exp + '/' + player.expToLevel); } function updateHpBar() { hpBar.setText('HP: ' + player.hp + '/' + player.maxHp); } function updateScore() { scoreTxt.setText('Wave: ' + wave); } // --- Asset initialization (shapes) --- // --- Game setup --- player = new Player(); // Expanded play area var GAME_WIDTH = 3072; var GAME_HEIGHT = 4096; player.x = GAME_WIDTH / 2; player.y = GAME_HEIGHT / 2; game.addChild(player); creatureWeapon = new CreatureWeapon(); game.addChild(creatureWeapon); updateExpBar(); updateHpBar(); updateScore(); // --- Level up popup --- var levelUpPopup = null; function showLevelUp() { if (levelUpPopup) return; // Already showing // Randomly pick 3 upgrades var upgrades = [{ type: 'damage', label: 'Creature Damage +' }, { type: 'speed', label: 'Creature Speed +' }, { type: 'cooldown', label: 'Faster Attacks' }, { type: 'projectile', label: 'More Projectiles' }, { type: 'spread', label: 'Wider Spread' }]; // Shuffle and pick 3 for (var i = upgrades.length - 1; i > 0; i--) { var j = Math.floor(Math.random() * (i + 1)); var t = upgrades[i]; upgrades[i] = upgrades[j]; upgrades[j] = t; } var options = upgrades.slice(0, 3); // Popup container levelUpPopup = new Container(); var bg = LK.getAsset('levelUpBg', { width: 900, height: 700, color: 0x222244, shape: 'box', anchorX: 0.5, anchorY: 0.5 }); levelUpPopup.addChild(bg); bg.x = 0; bg.y = 0; var title = new Text2('LEVEL UP!', { size: 120, fill: "#fff" }); title.anchor.set(0.5, 0); title.x = 0; title.y = -300; levelUpPopup.addChild(title); // Option buttons for (var i = 0; i < 3; i++) { (function (idx) { var opt = options[idx]; var btn = LK.getAsset('levelUpBtn' + idx, { width: 700, height: 140, color: 0x4444aa, shape: 'box', anchorX: 0.5, anchorY: 0.5 }); btn.x = 0; btn.y = -80 + idx * 180; levelUpPopup.addChild(btn); var txt = new Text2(opt.label, { size: 70, fill: "#fff" }); txt.anchor.set(0.5, 0.5); txt.x = 0; txt.y = btn.y; levelUpPopup.addChild(txt); btn.down = function (x, y, obj) { creatureWeapon.upgrade(opt.type); // Remove popup LK.gui.center.removeChild(levelUpPopup); levelUpPopup = null; }; })(i); } levelUpPopup.x = 0; levelUpPopup.y = 0; LK.gui.center.addChild(levelUpPopup); } // --- Spawn experience gem --- function spawnExp(x, y, value) { var gem = new ExpGem(); gem.x = x; gem.y = y; gem.value = value; expGems.push(gem); game.addChild(gem); } // --- Spawn enemies continuously over time --- var enemiesToSpawn = 0; var spawnDelay = 20; // frames between spawns, will decrease with wave var spawnDelayTimer = 0; function prepareWave() { // Calculate how many enemies to spawn this wave enemiesToSpawn = 8 + Math.floor(wave * 2.5) + Math.floor(wave * wave * 0.15); spawnDelay = Math.max(6, 32 - Math.floor(wave * 1.2)); // faster spawns as wave increases spawnDelayTimer = 0; } function spawnEnemy() { var enemy = new Enemy(); // Spawn at random edge var edge = Math.floor(Math.random() * 4); if (edge === 0) { // top enemy.x = Math.random() * GAME_WIDTH; enemy.y = -100; } else if (edge === 1) { // bottom enemy.x = Math.random() * GAME_WIDTH; enemy.y = GAME_HEIGHT + 100; } else if (edge === 2) { // left enemy.x = -100; enemy.y = Math.random() * GAME_HEIGHT; } else { // right enemy.x = GAME_WIDTH + 100; enemy.y = Math.random() * GAME_HEIGHT; } enemies.push(enemy); game.addChild(enemy); } // --- Game move handler (touch/mouse drag to move player) --- function handleMove(x, y, obj) { // Don't allow movement if level up popup is open if (levelUpPopup) return; // Clamp to avoid top left menu if (x < 100) x = 100; if (y < 0) y = 0; player.targetX = x; player.targetY = y; } game.move = handleMove; game.down = function (x, y, obj) { handleMove(x, y, obj); }; game.up = function (x, y, obj) { // No dragNode needed, movement is always allowed }; // --- Main game update loop --- game.update = function () { // Update player player.update(); // Update weapon creatureWeapon.update(); // Update projectiles for (var i = projectiles.length - 1; i >= 0; i--) { var proj = projectiles[i]; proj.update(); // Remove if out of bounds if (proj.x < -100 || proj.x > GAME_WIDTH + 100 || proj.y < -100 || proj.y > GAME_HEIGHT + 100) { proj.destroy(); projectiles.splice(i, 1); continue; } // Check collision with enemies for (var j = enemies.length - 1; j >= 0; j--) { var enemy = enemies[j]; var dx = proj.x - enemy.x; var dy = proj.y - enemy.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < proj.radius + enemy.radius) { var killed = enemy.takeDamage(proj.damage); proj.destroy(); projectiles.splice(i, 1); if (killed) { enemies.splice(j, 1); } break; } } } // Update enemies for (var i = enemies.length - 1; i >= 0; i--) { var enemy = enemies[i]; enemy.update(); // Check collision with player var dx = enemy.x - player.x; var dy = enemy.y - player.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < enemy.radius + player.radius) { player.takeDamage(); // Knockback enemy var angle = Math.atan2(dy, dx); enemy.x += Math.cos(angle) * 120; enemy.y += Math.sin(angle) * 120; } } // Update exp gems for (var i = expGems.length - 1; i >= 0; i--) { var gem = expGems[i]; gem.update(); // Collect if close to player var dx = gem.x - player.x; var dy = gem.y - player.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < gem.radius + player.radius) { player.gainExp(gem.value); gem.destroy(); expGems.splice(i, 1); } } // Wave spawning and continuous enemy spawn if (!levelUpPopup) { // If there are still enemies to spawn, spawn them over time if (enemiesToSpawn > 0) { spawnDelayTimer++; if (spawnDelayTimer >= spawnDelay) { spawnEnemy(); enemiesToSpawn--; spawnDelayTimer = 0; } } // If all enemies for this wave are dead and none left to spawn, start next wave after interval if (enemies.length === 0 && enemiesToSpawn === 0) { waveTimer++; if (waveTimer > waveInterval) { wave++; updateScore(); prepareWave(); waveTimer = 0; } } } }; // --- GUI positioning --- scoreTxt.x = GAME_WIDTH / 2; scoreTxt.y = 20; expBar.x = GAME_WIDTH / 2; expBar.y = 140; hpBar.x = GAME_WIDTH / 2; hpBar.y = 220; // --- Start first wave --- prepareWave();
===================================================================
--- original.js
+++ change.js
@@ -78,8 +78,13 @@
var orbitAngle = 2 * Math.PI / self.projectileCount * i + now % 1000 / 1000 * Math.PI * 2;
var launchDist = 120 + Math.random() * 30;
var px = player.x + Math.cos(orbitAngle) * launchDist;
var py = player.y + Math.sin(orbitAngle) * launchDist;
+ // Clamp projectile spawn to play area
+ if (px < 0) px = 0;
+ if (px > GAME_WIDTH) px = GAME_WIDTH;
+ if (py < 0) py = 0;
+ if (py > GAME_HEIGHT) py = GAME_HEIGHT;
// Aim at nearest enemy if possible
var target = null;
var minDist = 999999;
for (var j = 0; j < enemies.length; j++) {
@@ -190,10 +195,10 @@
self.expToLevel = 10;
self.hp = 3;
self.maxHp = 3;
// For movement smoothing
- self.targetX = 2048 / 2;
- self.targetY = 2732 / 2;
+ self.targetX = GAME_WIDTH / 2;
+ self.targetY = GAME_HEIGHT / 2;
// For invulnerability after hit
self.invulnTicks = 0;
// Update method
self.update = function () {
@@ -209,11 +214,11 @@
self.y = self.targetY;
}
// Clamp to game area
if (self.x < self.radius) self.x = self.radius;
- if (self.x > 2048 - self.radius) self.x = 2048 - self.radius;
+ if (self.x > GAME_WIDTH - self.radius) self.x = GAME_WIDTH - self.radius;
if (self.y < self.radius) self.y = self.radius;
- if (self.y > 2732 - self.radius) self.y = 2732 - self.radius;
+ if (self.y > GAME_HEIGHT - self.radius) self.y = GAME_HEIGHT - self.radius;
// Invulnerability timer
if (self.invulnTicks > 0) {
self.invulnTicks--;
playerAsset.alpha = self.invulnTicks % 10 < 5 ? 0.5 : 1;
@@ -297,10 +302,13 @@
}
// --- Asset initialization (shapes) ---
// --- Game setup ---
player = new Player();
-player.x = 2048 / 2;
-player.y = 2732 / 2;
+// Expanded play area
+var GAME_WIDTH = 3072;
+var GAME_HEIGHT = 4096;
+player.x = GAME_WIDTH / 2;
+player.y = GAME_HEIGHT / 2;
game.addChild(player);
creatureWeapon = new CreatureWeapon();
game.addChild(creatureWeapon);
updateExpBar();
@@ -399,36 +407,41 @@
gem.value = value;
expGems.push(gem);
game.addChild(gem);
}
-// --- Spawn enemies for a wave ---
-function spawnWave() {
- // Increase spawn count and add scaling for more pressure
- var count = 8 + Math.floor(wave * 2.5) + Math.floor(wave * wave * 0.15);
- for (var i = 0; i < count; i++) {
- var enemy = new Enemy();
- // Spawn at random edge
- var edge = Math.floor(Math.random() * 4);
- if (edge === 0) {
- // top
- enemy.x = Math.random() * 2048;
- enemy.y = -100;
- } else if (edge === 1) {
- // bottom
- enemy.x = Math.random() * 2048;
- enemy.y = 2732 + 100;
- } else if (edge === 2) {
- // left
- enemy.x = -100;
- enemy.y = Math.random() * 2732;
- } else {
- // right
- enemy.x = 2048 + 100;
- enemy.y = Math.random() * 2732;
- }
- enemies.push(enemy);
- game.addChild(enemy);
+// --- Spawn enemies continuously over time ---
+var enemiesToSpawn = 0;
+var spawnDelay = 20; // frames between spawns, will decrease with wave
+var spawnDelayTimer = 0;
+function prepareWave() {
+ // Calculate how many enemies to spawn this wave
+ enemiesToSpawn = 8 + Math.floor(wave * 2.5) + Math.floor(wave * wave * 0.15);
+ spawnDelay = Math.max(6, 32 - Math.floor(wave * 1.2)); // faster spawns as wave increases
+ spawnDelayTimer = 0;
+}
+function spawnEnemy() {
+ var enemy = new Enemy();
+ // Spawn at random edge
+ var edge = Math.floor(Math.random() * 4);
+ if (edge === 0) {
+ // top
+ enemy.x = Math.random() * GAME_WIDTH;
+ enemy.y = -100;
+ } else if (edge === 1) {
+ // bottom
+ enemy.x = Math.random() * GAME_WIDTH;
+ enemy.y = GAME_HEIGHT + 100;
+ } else if (edge === 2) {
+ // left
+ enemy.x = -100;
+ enemy.y = Math.random() * GAME_HEIGHT;
+ } else {
+ // right
+ enemy.x = GAME_WIDTH + 100;
+ enemy.y = Math.random() * GAME_HEIGHT;
}
+ enemies.push(enemy);
+ game.addChild(enemy);
}
// --- Game move handler (touch/mouse drag to move player) ---
function handleMove(x, y, obj) {
// Don't allow movement if level up popup is open
@@ -456,9 +469,9 @@
for (var i = projectiles.length - 1; i >= 0; i--) {
var proj = projectiles[i];
proj.update();
// Remove if out of bounds
- if (proj.x < -100 || proj.x > 2048 + 100 || proj.y < -100 || proj.y > 2732 + 100) {
+ if (proj.x < -100 || proj.x > GAME_WIDTH + 100 || proj.y < -100 || proj.y > GAME_HEIGHT + 100) {
proj.destroy();
projectiles.splice(i, 1);
continue;
}
@@ -508,24 +521,36 @@
gem.destroy();
expGems.splice(i, 1);
}
}
- // Wave spawning
- if (enemies.length === 0 && !levelUpPopup) {
- waveTimer++;
- if (waveTimer > waveInterval) {
- wave++;
- updateScore();
- spawnWave();
- waveTimer = 0;
+ // Wave spawning and continuous enemy spawn
+ if (!levelUpPopup) {
+ // If there are still enemies to spawn, spawn them over time
+ if (enemiesToSpawn > 0) {
+ spawnDelayTimer++;
+ if (spawnDelayTimer >= spawnDelay) {
+ spawnEnemy();
+ enemiesToSpawn--;
+ spawnDelayTimer = 0;
+ }
}
+ // If all enemies for this wave are dead and none left to spawn, start next wave after interval
+ if (enemies.length === 0 && enemiesToSpawn === 0) {
+ waveTimer++;
+ if (waveTimer > waveInterval) {
+ wave++;
+ updateScore();
+ prepareWave();
+ waveTimer = 0;
+ }
+ }
}
};
// --- GUI positioning ---
-scoreTxt.x = 2048 / 2;
+scoreTxt.x = GAME_WIDTH / 2;
scoreTxt.y = 20;
-expBar.x = 2048 / 2;
+expBar.x = GAME_WIDTH / 2;
expBar.y = 140;
-hpBar.x = 2048 / 2;
+hpBar.x = GAME_WIDTH / 2;
hpBar.y = 220;
// --- Start first wave ---
-spawnWave();
\ No newline at end of file
+prepareWave();
\ No newline at end of file
police pixel art. In-Game asset. 2d. High contrast. No shadows
black person pixel art. In-Game asset. High contrast. No shadows
glock pixel art. In-Game asset. High contrast. No shadows
pixel art bullet. In-Game asset. High contrast. No shadows
money pixel art. In-Game asset. High contrast. No shadows
a police themed level up screen pixel art. In-Game asset. High contrast. No shadows