Code edit (1 edits merged)
Please save this source code
User prompt
David vs. Giants: Stone Sling Showdown
Initial prompt
I want to make a game exactly like David vs. Goliath by Zango Games. It will be a 2D game. All the weapons, health regeneration, and music will be the same. The character will continuously spin his right arm in a circular motion. First, there will be small giants coming along the path. You will try to defeat these incoming giants by throwing stones at them. However, there will be no blood. When a giant dies, it will immediately disappear. Then, a main giant (boss) will appear on the screen, and you'll have to try to destroy him. There will be different maps and varied environments.
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Boss Giant
var BossGiant = Container.expand(function () {
var self = Container.call(this);
var body = self.attachAsset('bossBody', {
anchorX: 0.5,
anchorY: 1
});
var head = self.attachAsset('bossHead', {
anchorX: 0.5,
anchorY: 1,
y: -body.height
});
self.hp = 15;
self.speed = 2.2;
self.active = true;
self.update = function () {
if (!self.active) return;
self.x -= self.speed;
};
self.takeDamage = function (dmg) {
self.hp -= dmg;
if (self.hp <= 0) {
self.active = false;
LK.getSound('giantVanish').play();
tween(self, {
alpha: 0
}, {
duration: 600,
onFinish: function onFinish() {
self.destroy();
}
});
} else {
LK.getSound('hit').play();
tween(self, {
tint: 0xff7043
}, {
duration: 180,
onFinish: function onFinish() {
tween(self, {
tint: 0xffffff
}, {
duration: 180
});
}
});
}
};
return self;
});
// David (player)
var David = Container.expand(function () {
var self = Container.call(this);
var body = self.attachAsset('davidBody', {
anchorX: 0.5,
anchorY: 1
});
// Arm pivots at shoulder
var arm = self.attachAsset('davidArm', {
anchorX: 0.5,
anchorY: 0.1,
x: body.width / 2 - 10,
y: -body.height + 40
});
self.arm = arm;
self.armAngle = 0;
self.armSpeed = 0.18; // radians per frame
self.armRadius = 70;
self.slingReady = true;
self.stoneCooldown = 0;
self.hp = 5;
self.maxHp = 5;
self.regenTimer = 0;
self.update = function () {
// Spin arm
self.armAngle += self.armSpeed;
if (self.armAngle > Math.PI * 2) self.armAngle -= Math.PI * 2;
// Arm rotates in a circle
self.arm.rotation = self.armAngle;
// Stone cooldown
if (self.stoneCooldown > 0) self.stoneCooldown--;
// Health regen
if (self.hp < self.maxHp) {
self.regenTimer++;
if (self.regenTimer > 180) {
// 3 seconds
self.hp++;
self.regenTimer = 0;
}
} else {
self.regenTimer = 0;
}
};
self.throwStone = function () {
if (!self.slingReady || self.stoneCooldown > 0) return null;
self.slingReady = false;
self.stoneCooldown = 30; // half a second
LK.getSound('throw').play();
// Calculate stone start position (end of arm)
var angle = self.armAngle;
var sx = self.x + Math.cos(angle) * (body.width / 2 + self.arm.height * 0.9);
var sy = self.y - body.height + 40 + Math.sin(angle) * (self.arm.height * 0.9);
var stone = new Stone();
stone.x = sx;
stone.y = sy;
// Velocity: forward and slightly up
stone.vx = Math.cos(angle) * 32 + 10;
stone.vy = Math.sin(angle) * 32 - 10;
return stone;
};
self.takeDamage = function (dmg) {
self.hp -= dmg;
if (self.hp < 0) self.hp = 0;
LK.effects.flashObject(self, 0xff0000, 400);
};
return self;
});
// Giant enemy
var Giant = Container.expand(function () {
var self = Container.call(this);
var body = self.attachAsset('giantBody', {
anchorX: 0.5,
anchorY: 1
});
var head = self.attachAsset('giantHead', {
anchorX: 0.5,
anchorY: 1,
y: -body.height
});
self.hp = 2;
self.speed = 3 + Math.random() * 2;
self.active = true;
self.update = function () {
if (!self.active) return;
self.x -= self.speed;
};
self.takeDamage = function (dmg) {
self.hp -= dmg;
if (self.hp <= 0) {
self.active = false;
LK.getSound('giantVanish').play();
tween(self, {
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
self.destroy();
}
});
} else {
LK.getSound('hit').play();
tween(self, {
tint: 0xffe082
}, {
duration: 120,
onFinish: function onFinish() {
tween(self, {
tint: 0xffffff
}, {
duration: 120
});
}
});
}
};
return self;
});
// Stone projectile
var Stone = Container.expand(function () {
var self = Container.call(this);
var stone = self.attachAsset('slingStone', {
anchorX: 0.5,
anchorY: 0.5
});
self.vx = 0;
self.vy = 0;
self.active = true;
self.damage = 1;
self.update = function () {
if (!self.active) return;
self.x += self.vx;
self.y += self.vy;
// Gravity
self.vy += 0.7;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87ceeb
});
/****
* Game Code
****/
// Character (David)
// --- ENVIRONMENT ---
var sky = LK.getAsset('sky', {
x: 0,
y: 0
});
game.addChild(sky);
var ground = LK.getAsset('ground', {
x: 0,
y: 2532
});
ground.y = 2532; // bottom of screen
game.addChild(ground);
// --- PLAYER ---
var david = new David();
david.x = 320;
david.y = 2532; // standing on ground
game.addChild(david);
// --- UI ---
var score = 0;
var scoreTxt = new Text2('0', {
size: 120,
fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var hpTxt = new Text2('♥♥♥♥♥', {
size: 90,
fill: 0xE53935
});
hpTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(hpTxt);
hpTxt.y = 120;
// --- GAME STATE ---
var stones = [];
var giants = [];
var boss = null;
var wave = 1;
var giantsToSpawn = 5;
var giantsSpawned = 0;
var spawnTimer = 0;
var gameActive = true;
var bossActive = false;
var bossDefeated = false;
// --- MUSIC ---
LK.playMusic('mainTheme');
// --- MAPS/ENVIRONMENTS ---
var environments = [{
sky: 0x87ceeb,
ground: 0x7ec850
},
// blue sky, green grass
{
sky: 0xf7e9a0,
ground: 0xe0c97f
},
// desert
{
sky: 0x9ecae1,
ground: 0x8c8c8c
} // mountain/rocky
];
var currentEnv = 0;
function setEnvironment(idx) {
sky.tint = environments[idx].sky;
ground.tint = environments[idx].ground;
}
setEnvironment(currentEnv);
// --- UI UPDATE ---
function updateScore() {
scoreTxt.setText(score);
}
function updateHp() {
var s = '';
for (var i = 0; i < david.hp; i++) s += '♥';
for (var i = david.hp; i < david.maxHp; i++) s += '♡';
hpTxt.setText(s);
}
updateScore();
updateHp();
// --- INPUT ---
var isTouching = false;
var lastTouchTick = 0;
game.down = function (x, y, obj) {
isTouching = true;
lastTouchTick = LK.ticks;
};
game.up = function (x, y, obj) {
isTouching = false;
// Only allow throw if touch was short (tap)
if (gameActive && !bossDefeated && LK.ticks - lastTouchTick < 30) {
var stone = david.throwStone();
if (stone) {
stones.push(stone);
game.addChild(stone);
// Arm can't throw again until next full rotation
setTimeout(function () {
david.slingReady = true;
}, 400);
}
}
};
game.move = function (x, y, obj) {
// No drag, but could add aiming in future
};
// --- GAME LOOP ---
game.update = function () {
if (!gameActive) return;
// Environment change per wave
if (wave - 1 < environments.length) {
setEnvironment(wave - 1);
}
// David update
david.update();
// Stones update
for (var i = stones.length - 1; i >= 0; i--) {
var s = stones[i];
s.update();
// Remove if off screen
if (s.x > 2048 || s.y > 2732 || s.x < -100 || s.y < -100) {
s.destroy();
stones.splice(i, 1);
continue;
}
}
// Giants update
for (var j = giants.length - 1; j >= 0; j--) {
var g = giants[j];
g.update();
// Remove if off screen
if (g.x < -200) {
g.destroy();
giants.splice(j, 1);
continue;
}
// Collision with David
if (g.active && g.intersects(david)) {
g.active = false;
g.destroy();
giants.splice(j, 1);
david.takeDamage(1);
updateHp();
if (david.hp <= 0) {
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
gameActive = false;
return;
}
continue;
}
// Stones hit giant
for (var k = stones.length - 1; k >= 0; k--) {
var s2 = stones[k];
if (g.active && s2.active && g.intersects(s2)) {
g.takeDamage(s2.damage);
s2.active = false;
s2.destroy();
stones.splice(k, 1);
if (!g.active) {
score += 1;
updateScore();
}
break;
}
}
}
// Boss update
if (bossActive && boss && boss.active) {
boss.update();
// Boss hits David
if (boss.intersects(david)) {
boss.active = false;
boss.destroy();
david.takeDamage(2);
updateHp();
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
gameActive = false;
return;
}
// Stones hit boss
for (var k = stones.length - 1; k >= 0; k--) {
var s2 = stones[k];
if (boss.active && s2.active && boss.intersects(s2)) {
boss.takeDamage(s2.damage);
s2.active = false;
s2.destroy();
stones.splice(k, 1);
if (!boss.active) {
score += 10;
updateScore();
bossDefeated = true;
LK.effects.flashScreen(0x00ff00, 1200);
LK.showYouWin();
gameActive = false;
return;
}
break;
}
}
}
// Spawn logic
if (!bossActive) {
if (giantsSpawned < giantsToSpawn) {
spawnTimer--;
if (spawnTimer <= 0) {
var g = new Giant();
g.x = 2048 + 100;
g.y = 2532;
giants.push(g);
game.addChild(g);
giantsSpawned++;
spawnTimer = 60 + Math.floor(Math.random() * 60);
}
} else if (giants.length === 0) {
// Next wave or boss
if (wave < 3) {
wave++;
giantsToSpawn += 3;
giantsSpawned = 0;
spawnTimer = 60;
} else {
// Boss time
bossActive = true;
boss = new BossGiant();
boss.x = 2048 + 200;
boss.y = 2532;
game.addChild(boss);
}
}
}
}; ===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,438 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+
+/****
+* Classes
+****/
+// Boss Giant
+var BossGiant = Container.expand(function () {
+ var self = Container.call(this);
+ var body = self.attachAsset('bossBody', {
+ anchorX: 0.5,
+ anchorY: 1
+ });
+ var head = self.attachAsset('bossHead', {
+ anchorX: 0.5,
+ anchorY: 1,
+ y: -body.height
+ });
+ self.hp = 15;
+ self.speed = 2.2;
+ self.active = true;
+ self.update = function () {
+ if (!self.active) return;
+ self.x -= self.speed;
+ };
+ self.takeDamage = function (dmg) {
+ self.hp -= dmg;
+ if (self.hp <= 0) {
+ self.active = false;
+ LK.getSound('giantVanish').play();
+ tween(self, {
+ alpha: 0
+ }, {
+ duration: 600,
+ onFinish: function onFinish() {
+ self.destroy();
+ }
+ });
+ } else {
+ LK.getSound('hit').play();
+ tween(self, {
+ tint: 0xff7043
+ }, {
+ duration: 180,
+ onFinish: function onFinish() {
+ tween(self, {
+ tint: 0xffffff
+ }, {
+ duration: 180
+ });
+ }
+ });
+ }
+ };
+ return self;
+});
+// David (player)
+var David = Container.expand(function () {
+ var self = Container.call(this);
+ var body = self.attachAsset('davidBody', {
+ anchorX: 0.5,
+ anchorY: 1
+ });
+ // Arm pivots at shoulder
+ var arm = self.attachAsset('davidArm', {
+ anchorX: 0.5,
+ anchorY: 0.1,
+ x: body.width / 2 - 10,
+ y: -body.height + 40
+ });
+ self.arm = arm;
+ self.armAngle = 0;
+ self.armSpeed = 0.18; // radians per frame
+ self.armRadius = 70;
+ self.slingReady = true;
+ self.stoneCooldown = 0;
+ self.hp = 5;
+ self.maxHp = 5;
+ self.regenTimer = 0;
+ self.update = function () {
+ // Spin arm
+ self.armAngle += self.armSpeed;
+ if (self.armAngle > Math.PI * 2) self.armAngle -= Math.PI * 2;
+ // Arm rotates in a circle
+ self.arm.rotation = self.armAngle;
+ // Stone cooldown
+ if (self.stoneCooldown > 0) self.stoneCooldown--;
+ // Health regen
+ if (self.hp < self.maxHp) {
+ self.regenTimer++;
+ if (self.regenTimer > 180) {
+ // 3 seconds
+ self.hp++;
+ self.regenTimer = 0;
+ }
+ } else {
+ self.regenTimer = 0;
+ }
+ };
+ self.throwStone = function () {
+ if (!self.slingReady || self.stoneCooldown > 0) return null;
+ self.slingReady = false;
+ self.stoneCooldown = 30; // half a second
+ LK.getSound('throw').play();
+ // Calculate stone start position (end of arm)
+ var angle = self.armAngle;
+ var sx = self.x + Math.cos(angle) * (body.width / 2 + self.arm.height * 0.9);
+ var sy = self.y - body.height + 40 + Math.sin(angle) * (self.arm.height * 0.9);
+ var stone = new Stone();
+ stone.x = sx;
+ stone.y = sy;
+ // Velocity: forward and slightly up
+ stone.vx = Math.cos(angle) * 32 + 10;
+ stone.vy = Math.sin(angle) * 32 - 10;
+ return stone;
+ };
+ self.takeDamage = function (dmg) {
+ self.hp -= dmg;
+ if (self.hp < 0) self.hp = 0;
+ LK.effects.flashObject(self, 0xff0000, 400);
+ };
+ return self;
+});
+// Giant enemy
+var Giant = Container.expand(function () {
+ var self = Container.call(this);
+ var body = self.attachAsset('giantBody', {
+ anchorX: 0.5,
+ anchorY: 1
+ });
+ var head = self.attachAsset('giantHead', {
+ anchorX: 0.5,
+ anchorY: 1,
+ y: -body.height
+ });
+ self.hp = 2;
+ self.speed = 3 + Math.random() * 2;
+ self.active = true;
+ self.update = function () {
+ if (!self.active) return;
+ self.x -= self.speed;
+ };
+ self.takeDamage = function (dmg) {
+ self.hp -= dmg;
+ if (self.hp <= 0) {
+ self.active = false;
+ LK.getSound('giantVanish').play();
+ tween(self, {
+ alpha: 0
+ }, {
+ duration: 300,
+ onFinish: function onFinish() {
+ self.destroy();
+ }
+ });
+ } else {
+ LK.getSound('hit').play();
+ tween(self, {
+ tint: 0xffe082
+ }, {
+ duration: 120,
+ onFinish: function onFinish() {
+ tween(self, {
+ tint: 0xffffff
+ }, {
+ duration: 120
+ });
+ }
+ });
+ }
+ };
+ return self;
+});
+// Stone projectile
+var Stone = Container.expand(function () {
+ var self = Container.call(this);
+ var stone = self.attachAsset('slingStone', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.vx = 0;
+ self.vy = 0;
+ self.active = true;
+ self.damage = 1;
+ self.update = function () {
+ if (!self.active) return;
+ self.x += self.vx;
+ self.y += self.vy;
+ // Gravity
+ self.vy += 0.7;
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0x87ceeb
+});
+
+/****
+* Game Code
+****/
+// Character (David)
+// --- ENVIRONMENT ---
+var sky = LK.getAsset('sky', {
+ x: 0,
+ y: 0
+});
+game.addChild(sky);
+var ground = LK.getAsset('ground', {
+ x: 0,
+ y: 2532
+});
+ground.y = 2532; // bottom of screen
+game.addChild(ground);
+// --- PLAYER ---
+var david = new David();
+david.x = 320;
+david.y = 2532; // standing on ground
+game.addChild(david);
+// --- UI ---
+var score = 0;
+var scoreTxt = new Text2('0', {
+ size: 120,
+ fill: "#fff"
+});
+scoreTxt.anchor.set(0.5, 0);
+LK.gui.top.addChild(scoreTxt);
+var hpTxt = new Text2('♥♥♥♥♥', {
+ size: 90,
+ fill: 0xE53935
+});
+hpTxt.anchor.set(0.5, 0);
+LK.gui.top.addChild(hpTxt);
+hpTxt.y = 120;
+// --- GAME STATE ---
+var stones = [];
+var giants = [];
+var boss = null;
+var wave = 1;
+var giantsToSpawn = 5;
+var giantsSpawned = 0;
+var spawnTimer = 0;
+var gameActive = true;
+var bossActive = false;
+var bossDefeated = false;
+// --- MUSIC ---
+LK.playMusic('mainTheme');
+// --- MAPS/ENVIRONMENTS ---
+var environments = [{
+ sky: 0x87ceeb,
+ ground: 0x7ec850
+},
+// blue sky, green grass
+{
+ sky: 0xf7e9a0,
+ ground: 0xe0c97f
+},
+// desert
+{
+ sky: 0x9ecae1,
+ ground: 0x8c8c8c
+} // mountain/rocky
+];
+var currentEnv = 0;
+function setEnvironment(idx) {
+ sky.tint = environments[idx].sky;
+ ground.tint = environments[idx].ground;
+}
+setEnvironment(currentEnv);
+// --- UI UPDATE ---
+function updateScore() {
+ scoreTxt.setText(score);
+}
+function updateHp() {
+ var s = '';
+ for (var i = 0; i < david.hp; i++) s += '♥';
+ for (var i = david.hp; i < david.maxHp; i++) s += '♡';
+ hpTxt.setText(s);
+}
+updateScore();
+updateHp();
+// --- INPUT ---
+var isTouching = false;
+var lastTouchTick = 0;
+game.down = function (x, y, obj) {
+ isTouching = true;
+ lastTouchTick = LK.ticks;
+};
+game.up = function (x, y, obj) {
+ isTouching = false;
+ // Only allow throw if touch was short (tap)
+ if (gameActive && !bossDefeated && LK.ticks - lastTouchTick < 30) {
+ var stone = david.throwStone();
+ if (stone) {
+ stones.push(stone);
+ game.addChild(stone);
+ // Arm can't throw again until next full rotation
+ setTimeout(function () {
+ david.slingReady = true;
+ }, 400);
+ }
+ }
+};
+game.move = function (x, y, obj) {
+ // No drag, but could add aiming in future
+};
+// --- GAME LOOP ---
+game.update = function () {
+ if (!gameActive) return;
+ // Environment change per wave
+ if (wave - 1 < environments.length) {
+ setEnvironment(wave - 1);
+ }
+ // David update
+ david.update();
+ // Stones update
+ for (var i = stones.length - 1; i >= 0; i--) {
+ var s = stones[i];
+ s.update();
+ // Remove if off screen
+ if (s.x > 2048 || s.y > 2732 || s.x < -100 || s.y < -100) {
+ s.destroy();
+ stones.splice(i, 1);
+ continue;
+ }
+ }
+ // Giants update
+ for (var j = giants.length - 1; j >= 0; j--) {
+ var g = giants[j];
+ g.update();
+ // Remove if off screen
+ if (g.x < -200) {
+ g.destroy();
+ giants.splice(j, 1);
+ continue;
+ }
+ // Collision with David
+ if (g.active && g.intersects(david)) {
+ g.active = false;
+ g.destroy();
+ giants.splice(j, 1);
+ david.takeDamage(1);
+ updateHp();
+ if (david.hp <= 0) {
+ LK.effects.flashScreen(0xff0000, 1000);
+ LK.showGameOver();
+ gameActive = false;
+ return;
+ }
+ continue;
+ }
+ // Stones hit giant
+ for (var k = stones.length - 1; k >= 0; k--) {
+ var s2 = stones[k];
+ if (g.active && s2.active && g.intersects(s2)) {
+ g.takeDamage(s2.damage);
+ s2.active = false;
+ s2.destroy();
+ stones.splice(k, 1);
+ if (!g.active) {
+ score += 1;
+ updateScore();
+ }
+ break;
+ }
+ }
+ }
+ // Boss update
+ if (bossActive && boss && boss.active) {
+ boss.update();
+ // Boss hits David
+ if (boss.intersects(david)) {
+ boss.active = false;
+ boss.destroy();
+ david.takeDamage(2);
+ updateHp();
+ LK.effects.flashScreen(0xff0000, 1000);
+ LK.showGameOver();
+ gameActive = false;
+ return;
+ }
+ // Stones hit boss
+ for (var k = stones.length - 1; k >= 0; k--) {
+ var s2 = stones[k];
+ if (boss.active && s2.active && boss.intersects(s2)) {
+ boss.takeDamage(s2.damage);
+ s2.active = false;
+ s2.destroy();
+ stones.splice(k, 1);
+ if (!boss.active) {
+ score += 10;
+ updateScore();
+ bossDefeated = true;
+ LK.effects.flashScreen(0x00ff00, 1200);
+ LK.showYouWin();
+ gameActive = false;
+ return;
+ }
+ break;
+ }
+ }
+ }
+ // Spawn logic
+ if (!bossActive) {
+ if (giantsSpawned < giantsToSpawn) {
+ spawnTimer--;
+ if (spawnTimer <= 0) {
+ var g = new Giant();
+ g.x = 2048 + 100;
+ g.y = 2532;
+ giants.push(g);
+ game.addChild(g);
+ giantsSpawned++;
+ spawnTimer = 60 + Math.floor(Math.random() * 60);
+ }
+ } else if (giants.length === 0) {
+ // Next wave or boss
+ if (wave < 3) {
+ wave++;
+ giantsToSpawn += 3;
+ giantsSpawned = 0;
+ spawnTimer = 60;
+ } else {
+ // Boss time
+ bossActive = true;
+ boss = new BossGiant();
+ boss.x = 2048 + 200;
+ boss.y = 2532;
+ game.addChild(boss);
+ }
+ }
+ }
+};
\ No newline at end of file
Create a spaceship as the main hero. It will be in the center, with the front tip pointing upwards. There will be a firing mechanism on both sides.
Imagine a multi-legged space machine, its legs sprawling at varied, dynamic angles, giving it an organic yet mechanical feel. Encased within a transparent tube, a one-eyed green alien watches intently. Beneath the ship, vivid rocket flames burst forth, illuminating the dark void of space with fiery intensity.
The background will be a dynamic space scene, featuring only blue and dark navy colors. top to bottom, creating a lively and immersive environment."