User prompt
Make the zombies and the bullet more slow
Code edit (1 edits merged)
Please save this source code
User prompt
Monster Gold Rush
Initial prompt
Make a game, let there be 3 types of monsters, let them follow me, each of them has different features, ranged, rangeless, attacking from underground, and so on, so that I can kill them and collect gold from them, I can buy something from the store at the top right with the gold that comes out, and the store mechanics are like this, if I buy one of those three items, the other items will go randomly, make the passives of the items yourself, but be unique.
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Burrower monster
var Burrower = Container.expand(function () {
var self = Container.call(this);
var burrowerGfx = self.attachAsset('burrower', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = burrowerGfx.width / 2;
self.speed = 5;
self.hp = 1;
self.type = 'burrower';
self.burrowTimer = 0;
self.burrowInterval = 90 + Math.floor(Math.random() * 60);
self.burrowed = false;
self.update = function () {
if (self.burrowed) {
self.burrowTimer--;
if (self.burrowTimer <= 0) {
// Unburrow
self.burrowed = false;
burrowerGfx.alpha = 1;
self.burrowTimer = self.burrowInterval;
}
// Move fast toward hero
var dx = hero.x - self.x;
var dy = hero.y - self.y;
var d = Math.sqrt(dx * dx + dy * dy);
if (d > 0.1) {
self.x += dx / d * (self.speed * 2.2);
self.y += dy / d * (self.speed * 2.2);
}
} else {
self.burrowTimer--;
if (self.burrowTimer <= 0) {
// Burrow
self.burrowed = true;
burrowerGfx.alpha = 0.3;
self.burrowTimer = 36 + Math.floor(Math.random() * 24);
}
// Move toward hero
var dx = hero.x - self.x;
var dy = hero.y - self.y;
var d = Math.sqrt(dx * dx + dy * dy);
if (d > 0.1) {
self.x += dx / d * self.speed;
self.y += dy / d * self.speed;
}
}
};
self.flash = function () {
tween(burrowerGfx, {
alpha: 0.1
}, {
duration: 40,
onFinish: function onFinish() {
tween(burrowerGfx, {
alpha: self.burrowed ? 0.3 : 1
}, {
duration: 40
});
}
});
};
return self;
});
// Chaser monster
var Chaser = Container.expand(function () {
var self = Container.call(this);
var chaserGfx = self.attachAsset('chaser', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = chaserGfx.width / 2;
self.speed = 3.5;
self.hp = 2;
self.type = 'chaser';
self.update = function () {
// Move toward hero
var dx = hero.x - self.x;
var dy = hero.y - self.y;
var d = Math.sqrt(dx * dx + dy * dy);
if (d > 0.1) {
self.x += dx / d * self.speed;
self.y += dy / d * self.speed;
}
};
self.flash = function () {
tween(chaserGfx, {
alpha: 0.3
}, {
duration: 60,
onFinish: function onFinish() {
tween(chaserGfx, {
alpha: 1
}, {
duration: 60
});
}
});
};
return self;
});
// Gold coin
var Gold = Container.expand(function () {
var self = Container.call(this);
var goldGfx = self.attachAsset('gold', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = goldGfx.width / 2;
self.vx = 0;
self.vy = 0;
self.update = function () {
self.x += self.vx;
self.y += self.vy;
// Slow down
self.vx *= 0.92;
self.vy *= 0.92;
};
return self;
});
// Hero class
var Hero = Container.expand(function () {
var self = Container.call(this);
var heroGfx = self.attachAsset('hero', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = heroGfx.width / 2;
self.speed = 22;
self.shootCooldown = 0;
self.shootInterval = 18; // frames
self.invuln = 0;
self.hp = 3;
self.update = function () {
if (self.shootCooldown > 0) self.shootCooldown--;
if (self.invuln > 0) self.invuln--;
};
// Flash when hit
self.flash = function () {
tween(heroGfx, {
alpha: 0.3
}, {
duration: 80,
onFinish: function onFinish() {
tween(heroGfx, {
alpha: 1
}, {
duration: 80
});
}
});
};
return self;
});
// Hero bullet
var HeroBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGfx = self.attachAsset('herobullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = bulletGfx.width / 2;
self.speed = 18;
self.dirX = 0;
self.dirY = -1;
self.damage = 1;
self.update = function () {
self.x += self.dirX * self.speed;
self.y += self.dirY * self.speed;
};
return self;
});
// Monster bullet (spit)
var MonsterBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGfx = self.attachAsset('herobullet', {
anchorX: 0.5,
anchorY: 0.5
});
bulletGfx.tint = 0x7cfd3a;
self.radius = bulletGfx.width / 2;
self.speed = 16;
self.dirX = 0;
self.dirY = 1;
self.damage = 1;
self.update = function () {
self.x += self.dirX * self.speed;
self.y += self.dirY * self.speed;
};
return self;
});
// Spitter monster
var Spitter = Container.expand(function () {
var self = Container.call(this);
var spitterGfx = self.attachAsset('spitter', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = spitterGfx.width / 2;
self.speed = 2.2;
self.hp = 2;
self.type = 'spitter';
self.shootCooldown = 0;
self.shootInterval = 60 + Math.floor(Math.random() * 30);
self.update = function () {
// Keep distance from hero, shoot
var dx = hero.x - self.x;
var dy = hero.y - self.y;
var d = Math.sqrt(dx * dx + dy * dy);
if (d > 400) {
self.x += dx / d * self.speed;
self.y += dy / d * self.speed;
} else if (d < 320) {
self.x -= dx / d * self.speed;
self.y -= dy / d * self.speed;
}
if (self.shootCooldown > 0) self.shootCooldown--;else {
// Spit at hero
var spit = new MonsterBullet();
spit.x = self.x;
spit.y = self.y;
var tx = hero.x - self.x;
var ty = hero.y - self.y;
var td = Math.sqrt(tx * tx + ty * ty);
spit.dirX = td > 0.1 ? tx / td : 0;
spit.dirY = td > 0.1 ? ty / td : 0;
spit.speed = 16;
spit.radius = 32;
monsterBullets.push(spit);
game.addChild(spit);
self.shootCooldown = self.shootInterval;
}
};
self.flash = function () {
tween(spitterGfx, {
alpha: 0.3
}, {
duration: 60,
onFinish: function onFinish() {
tween(spitterGfx, {
alpha: 1
}, {
duration: 60
});
}
});
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x181818
});
/****
* Game Code
****/
// Global variables
// Hero
// Chaser monster
// Spitter monster
// Burrower monster
// Hero bullet
// Gold coin
// Store button background
// Store button highlight
// Sound effects
var hero = new Hero();
var heroBullets = [];
var monsters = [];
var monsterBullets = [];
var golds = [];
var gold = 0;
var storeBtns = [];
var passives = [];
var availablePassives = [{
id: 'firerate',
name: 'Rapid Fire',
desc: 'Shoot much faster.',
apply: function apply() {
hero.shootInterval = Math.max(6, hero.shootInterval - 8);
}
}, {
id: 'pierce',
name: 'Piercing Shots',
desc: 'Bullets pierce through 1 extra enemy.',
apply: function apply() {
passives.push({
id: 'pierce',
stacks: 1
});
}
}, {
id: 'lifesteal',
name: 'Lifesteal',
desc: 'Gain 1 HP every 8 gold picked up.',
apply: function apply() {
passives.push({
id: 'lifesteal',
stacks: 1,
counter: 0
});
}
}, {
id: 'spread',
name: 'Spread Shot',
desc: 'Shoot 3 bullets in a spread.',
apply: function apply() {
passives.push({
id: 'spread',
stacks: 1
});
}
}, {
id: 'regen',
name: 'Regeneration',
desc: 'Regenerate 1 HP every 12 seconds.',
apply: function apply() {
passives.push({
id: 'regen',
stacks: 1,
timer: 0
});
}
}, {
id: 'speed',
name: 'Speed Boost',
desc: 'Move much faster.',
apply: function apply() {
hero.speed += 7;
}
}, {
id: 'bigshot',
name: 'Big Bullets',
desc: 'Bullets are much larger.',
apply: function apply() {
passives.push({
id: 'bigshot',
stacks: 1
});
}
}, {
id: 'goldboost',
name: 'Gold Magnet',
desc: 'Gold is attracted to you.',
apply: function apply() {
passives.push({
id: 'goldboost',
stacks: 1
});
}
}, {
id: 'maxhp',
name: 'Max HP Up',
desc: 'Increase max HP by 1.',
apply: function apply() {
hero.hp++;
}
}];
// Store state
var storeChoices = [];
function getRandomPassive(excludeIds) {
var pool = [];
for (var i = 0; i < availablePassives.length; ++i) {
var id = availablePassives[i].id;
var already = false;
for (var j = 0; j < excludeIds.length; ++j) {
if (excludeIds[j] === id) {
already = true;
break;
}
}
if (!already) pool.push(availablePassives[i]);
}
if (pool.length === 0) pool = availablePassives;
return pool[Math.floor(Math.random() * pool.length)];
}
function rerollStore() {
storeChoices = [];
var exclude = [];
for (var i = 0; i < 3; ++i) {
var p = getRandomPassive(exclude);
storeChoices.push(p);
exclude.push(p.id);
}
updateStoreBtns();
}
function updateStoreBtns() {
for (var i = 0; i < storeBtns.length; ++i) {
var btn = storeBtns[i];
var p = storeChoices[i];
btn.passive = p;
btn.txt.setText(p.name);
btn.desc.setText(p.desc);
btn.price.setText("5");
}
}
// GUI
var goldTxt = new Text2('0', {
size: 90,
fill: 0xFFE066
});
goldTxt.anchor.set(1, 0);
LK.gui.topRight.addChild(goldTxt);
var hpTxt = new Text2('❤❤❤', {
size: 90,
fill: 0xFF3A3A
});
hpTxt.anchor.set(0, 0);
LK.gui.top.addChild(hpTxt);
// Store buttons (top right, below gold)
for (var i = 0; i < 3; ++i) {
var btn = new Container();
var bg = btn.attachAsset('storebtn', {
anchorX: 1,
anchorY: 0
});
btn.x = 2048 - 40;
btn.y = 160 + i * 140;
btn.txt = new Text2('', {
size: 54,
fill: 0xFFE066
});
btn.txt.anchor.set(1, 0);
btn.txt.x = 380;
btn.txt.y = 12;
btn.addChild(btn.txt);
btn.desc = new Text2('', {
size: 36,
fill: 0xCCCCCC
});
btn.desc.anchor.set(1, 0);
btn.desc.x = 380;
btn.desc.y = 62;
btn.addChild(btn.desc);
btn.price = new Text2('5', {
size: 48,
fill: 0xFFD700
});
btn.price.anchor.set(0, 0);
btn.price.x = 20;
btn.price.y = 30;
btn.addChild(btn.price);
btn.index = i;
storeBtns.push(btn);
game.addChild(btn);
}
// Place hero in center
hero.x = 2048 / 2;
hero.y = 2732 / 2;
game.addChild(hero);
// Initial monsters
function spawnMonster() {
var edge = Math.floor(Math.random() * 4);
var x, y;
if (edge === 0) {
// top
x = 200 + Math.random() * (2048 - 400);
y = -80;
} else if (edge === 1) {
// bottom
x = 200 + Math.random() * (2048 - 400);
y = 2732 + 80;
} else if (edge === 2) {
// left
x = -80;
y = 200 + Math.random() * (2732 - 400);
} else {
// right
x = 2048 + 80;
y = 200 + Math.random() * (2732 - 400);
}
var t = Math.random();
var m;
if (t < 0.4) m = new Chaser();else if (t < 0.7) m = new Spitter();else m = new Burrower();
m.x = x;
m.y = y;
monsters.push(m);
game.addChild(m);
}
for (var i = 0; i < 5; ++i) spawnMonster();
// Store logic
rerollStore();
// Dragging
var dragNode = null;
function handleMove(x, y, obj) {
if (dragNode) {
// Clamp to screen
var r = hero.radius;
dragNode.x = Math.max(r, Math.min(2048 - r, x));
dragNode.y = Math.max(r, Math.min(2732 - r, y));
}
}
game.move = handleMove;
game.down = function (x, y, obj) {
// Check store buttons first
for (var i = 0; i < storeBtns.length; ++i) {
var btn = storeBtns[i];
var bx = btn.x - 420,
by = btn.y,
bw = 420,
bh = 120;
if (x >= bx && x <= bx + bw && y >= by && y <= by + bh) {
// Buy
if (gold >= 5) {
gold -= 5;
goldTxt.setText(gold);
btn.passive.apply();
LK.getSound('buy').play();
rerollStore();
}
return;
}
}
// Drag hero
dragNode = hero;
handleMove(x, y, obj);
};
game.up = function (x, y, obj) {
dragNode = null;
};
// Shoot logic
function shootAt(tx, ty) {
if (hero.shootCooldown > 0) return;
hero.shootCooldown = hero.shootInterval;
var dx = tx - hero.x;
var dy = ty - hero.y;
var d = Math.sqrt(dx * dx + dy * dy);
if (d < 0.1) {
dx = 0;
dy = -1;
d = 1;
}
var spread = 0;
var n = 1;
var big = false;
for (var i = 0; i < passives.length; ++i) {
if (passives[i].id === 'spread') n = 3;
if (passives[i].id === 'bigshot') big = true;
}
for (var i = 0; i < n; ++i) {
var b = new HeroBullet();
b.x = hero.x;
b.y = hero.y;
var angle = Math.atan2(dy, dx);
if (n > 1) angle += (i - 1) * 0.18;
b.dirX = Math.cos(angle);
b.dirY = Math.sin(angle);
if (big) {
b.scaleX = b.scaleY = 1.7;
b.radius *= 1.7;
}
heroBullets.push(b);
game.addChild(b);
}
LK.getSound('shoot').play();
}
// Touch anywhere to shoot
game.on('down', function (x, y, obj) {
// Don't shoot if clicking store
for (var i = 0; i < storeBtns.length; ++i) {
var btn = storeBtns[i];
var bx = btn.x - 420,
by = btn.y,
bw = 420,
bh = 120;
if (x >= bx && x <= bx + bw && y >= by && y <= by + bh) return;
}
shootAt(x, y);
});
// Helper: collision
function circlesIntersect(a, b) {
var dx = a.x - b.x,
dy = a.y - b.y;
var r = (a.radius || 40) + (b.radius || 40);
return dx * dx + dy * dy < r * r;
}
// Update GUI
function updateHP() {
var s = '';
for (var i = 0; i < hero.hp; ++i) s += '❤';
hpTxt.setText(s);
}
// Main update
game.update = function () {
// Hero update
hero.update();
// Regen passive
for (var i = 0; i < passives.length; ++i) {
if (passives[i].id === 'regen') {
passives[i].timer++;
if (passives[i].timer >= 60 * 12) {
hero.hp++;
updateHP();
passives[i].timer = 0;
}
}
}
// Hero bullets
for (var i = heroBullets.length - 1; i >= 0; --i) {
var b = heroBullets[i];
b.update();
// Offscreen
if (b.x < -60 || b.x > 2048 + 60 || b.y < -60 || b.y > 2732 + 60) {
b.destroy();
heroBullets.splice(i, 1);
continue;
}
// Hit monster
var pierced = false;
for (var j = monsters.length - 1; j >= 0; --j) {
var m = monsters[j];
if (m.type === 'burrower' && m.burrowed) continue;
if (circlesIntersect(b, m)) {
m.hp -= b.damage;
m.flash();
LK.getSound('hit').play();
if (m.hp <= 0) {
// Drop gold
var g = new Gold();
g.x = m.x;
g.y = m.y;
g.vx = (Math.random() - 0.5) * 8;
g.vy = (Math.random() - 0.5) * 8;
golds.push(g);
game.addChild(g);
LK.getSound('monsterdie').play();
m.destroy();
monsters.splice(j, 1);
}
// Pierce?
var pierce = 0;
for (var k = 0; k < passives.length; ++k) if (passives[k].id === 'pierce') pierce++;
if (pierce > 0 && !pierced) {
b.damage--;
pierced = true;
if (b.damage <= 0) {
b.destroy();
heroBullets.splice(i, 1);
}
} else {
b.destroy();
heroBullets.splice(i, 1);
}
break;
}
}
}
// Monster bullets
for (var i = monsterBullets.length - 1; i >= 0; --i) {
var b = monsterBullets[i];
b.update();
if (b.x < -60 || b.x > 2048 + 60 || b.y < -60 || b.y > 2732 + 60) {
b.destroy();
monsterBullets.splice(i, 1);
continue;
}
// Hit hero
if (hero.invuln === 0 && circlesIntersect(b, hero)) {
hero.hp--;
updateHP();
hero.invuln = 40;
hero.flash();
b.destroy();
monsterBullets.splice(i, 1);
if (hero.hp <= 0) {
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
return;
}
}
}
// Monsters
for (var i = monsters.length - 1; i >= 0; --i) {
var m = monsters[i];
m.update();
// Hit hero
if (hero.invuln === 0 && circlesIntersect(m, hero)) {
hero.hp--;
updateHP();
hero.invuln = 40;
hero.flash();
if (hero.hp <= 0) {
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
return;
}
}
}
// Gold
for (var i = golds.length - 1; i >= 0; --i) {
var g = golds[i];
g.update();
// Magnet passive
for (var j = 0; j < passives.length; ++j) {
if (passives[j].id === 'goldboost') {
var dx = hero.x - g.x,
dy = hero.y - g.y;
var d = Math.sqrt(dx * dx + dy * dy);
if (d < 600) {
g.vx += dx / d * 2.5;
g.vy += dy / d * 2.5;
}
}
}
// Pick up
if (circlesIntersect(g, hero)) {
gold++;
goldTxt.setText(gold);
LK.getSound('pickup').play();
// Lifesteal
for (var j = 0; j < passives.length; ++j) {
if (passives[j].id === 'lifesteal') {
passives[j].counter++;
if (passives[j].counter >= 8) {
hero.hp++;
updateHP();
passives[j].counter = 0;
}
}
}
g.destroy();
golds.splice(i, 1);
}
}
// Store button highlight
for (var i = 0; i < storeBtns.length; ++i) {
var btn = storeBtns[i];
var bx = btn.x - 420,
by = btn.y,
bw = 420,
bh = 120;
if (game.lastDown && game.lastDown.x >= bx && game.lastDown.x <= bx + bw && game.lastDown.y >= by && game.lastDown.y <= by + bh) {
if (!btn.hl) {
btn.hl = btn.attachAsset('storebtnhl', {
anchorX: 1,
anchorY: 0
});
btn.setChildIndex(btn.hl, 0);
}
} else {
if (btn.hl) {
btn.hl.destroy();
btn.hl = null;
}
}
}
// Spawn monsters
if (LK.ticks % 60 === 0 && monsters.length < 12) {
spawnMonster();
}
};
// Track last down for store highlight
game.lastDown = null;
game.on('down', function (x, y, obj) {
game.lastDown = {
x: x,
y: y
};
});
game.on('up', function (x, y, obj) {
game.lastDown = null;
}); ===================================================================
--- original.js
+++ change.js
@@ -13,9 +13,9 @@
anchorX: 0.5,
anchorY: 0.5
});
self.radius = burrowerGfx.width / 2;
- self.speed = 10;
+ self.speed = 5;
self.hp = 1;
self.type = 'burrower';
self.burrowTimer = 0;
self.burrowInterval = 90 + Math.floor(Math.random() * 60);
@@ -78,9 +78,9 @@
anchorX: 0.5,
anchorY: 0.5
});
self.radius = chaserGfx.width / 2;
- self.speed = 7.5;
+ self.speed = 3.5;
self.hp = 2;
self.type = 'chaser';
self.update = function () {
// Move toward hero
@@ -168,9 +168,9 @@
anchorX: 0.5,
anchorY: 0.5
});
self.radius = bulletGfx.width / 2;
- self.speed = 38;
+ self.speed = 18;
self.dirX = 0;
self.dirY = -1;
self.damage = 1;
self.update = function () {
@@ -205,9 +205,9 @@
anchorX: 0.5,
anchorY: 0.5
});
self.radius = spitterGfx.width / 2;
- self.speed = 4.5;
+ self.speed = 2.2;
self.hp = 2;
self.type = 'spitter';
self.shootCooldown = 0;
self.shootInterval = 60 + Math.floor(Math.random() * 30);
@@ -266,18 +266,18 @@
/****
* Game Code
****/
-// Sound effects
-// Store button highlight
-// Store button background
-// Gold coin
-// Hero bullet
-// Burrower monster
-// Spitter monster
-// Chaser monster
-// Hero
// Global variables
+// Hero
+// Chaser monster
+// Spitter monster
+// Burrower monster
+// Hero bullet
+// Gold coin
+// Store button background
+// Store button highlight
+// Sound effects
var hero = new Hero();
var heroBullets = [];
var monsters = [];
var monsterBullets = [];
a zombie but its half phantom. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
a zombie. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
a gold. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
a spitter zombie. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
a green zombi spitt. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
a man with green tshirt and blue pant. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
a man with green tshirt and blue pant walking up. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
a sword . No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat