User prompt
increase the volume of the s shape
User prompt
make the bullets go in S shpae in wave 2
User prompt
the speeds of buullets vary for each wave
User prompt
make the bullets disappear immiedaitly after going outside of the arena
User prompt
add an ouutline to arenaBorderf
Code edit (1 edits merged)
Please save this source code
User prompt
Soul Dodge: Heart of Battle
Initial prompt
make a game like UNDERTALE
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Arena border (visual only) var ArenaBorder = Container.expand(function () { var self = Container.call(this); var border = self.attachAsset('arenaBorder', { anchorX: 0.5, anchorY: 0.5 }); border.alpha = 0.7; return self; }); // Bullet class var Bullet = Container.expand(function () { var self = Container.call(this); var bulletSprite = self.attachAsset('bullet', { anchorX: 0.5, anchorY: 0.5 }); self.vx = 0; self.vy = 0; self.update = function () { self.x += self.vx; self.y += self.vy; }; return self; }); // Soul (player) class var Soul = Container.expand(function () { var self = Container.call(this); var soulSprite = self.attachAsset('soul', { anchorX: 0.5, anchorY: 0.5 }); // For hit flash self.flash = function () { tween(self, { alpha: 0.3 }, { duration: 80, onFinish: function onFinish() { tween(self, { alpha: 1 }, { duration: 120 }); } }); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x181818 }); /**** * Game Code ****/ // Enemy warning (yellow, for telegraphing) // Bullet (white circle) // Arena border (white rectangle, thin) // Heart-shaped soul (red) // Arena dimensions (centered) var ARENA_W = 1200; var ARENA_H = 900; var ARENA_X = 2048 / 2 - ARENA_W / 2; var ARENA_Y = 2732 / 2 - ARENA_H / 2; // Add arena border var arenaBorder = new ArenaBorder(); arenaBorder.x = 2048 / 2; arenaBorder.y = 2732 / 2; game.addChild(arenaBorder); // Add soul (player) var soul = new Soul(); soul.x = 2048 / 2; soul.y = 2732 / 2; game.addChild(soul); // GUI: Timer (shows wave time left) var timerTxt = new Text2('', { size: 80, fill: "#fff" }); timerTxt.anchor.set(0.5, 0); LK.gui.top.addChild(timerTxt); // GUI: Wave counter var waveTxt = new Text2('', { size: 80, fill: "#fff" }); waveTxt.anchor.set(0.5, 0); LK.gui.top.addChild(waveTxt); waveTxt.y = 90; // Game state var bullets = []; var currentWave = 0; var waveTime = 0; var waveTimer = 0; var waveActive = false; var soulAlive = true; var dragSoul = false; var dragOffsetX = 0; var dragOffsetY = 0; // Arena bounds (for clamping soul) function clampSoul(x, y) { var hw = 50, hh = 50; // soul half size var minX = ARENA_X + hw; var maxX = ARENA_X + ARENA_W - hw; var minY = ARENA_Y + hh; var maxY = ARENA_Y + ARENA_H - hh; return { x: Math.max(minX, Math.min(maxX, x)), y: Math.max(minY, Math.min(maxY, y)) }; } // Touch/drag controls function handleSoulMove(x, y, obj) { if (!dragSoul || !soulAlive) return; var pos = clampSoul(x - dragOffsetX, y - dragOffsetY); soul.x = pos.x; soul.y = pos.y; } game.move = function (x, y, obj) { handleSoulMove(x, y, obj); }; game.down = function (x, y, obj) { // Only start drag if inside soul var dx = x - soul.x, dy = y - soul.y; if (dx * dx + dy * dy <= 60 * 60) { dragSoul = true; dragOffsetX = x - soul.x; dragOffsetY = y - soul.y; handleSoulMove(x, y, obj); } }; game.up = function (x, y, obj) { dragSoul = false; }; // Waves definition // Each wave: {duration, spawnFunc(tick, bulletsArr)} var waves = [ // Wave 1: Simple slow bullets from top { duration: 180, // 3s spawnFunc: function spawnFunc(tick, arr) { if (tick % 30 === 0) { for (var i = 0; i < 4; ++i) { var b = new Bullet(); b.x = ARENA_X + 200 + i * 250; b.y = ARENA_Y + 30; b.vx = 0; b.vy = 6; arr.push(b); game.addChild(b); } } } }, // Wave 2: Bullets from left/right { duration: 210, // 3.5s spawnFunc: function spawnFunc(tick, arr) { if (tick % 24 === 0) { var b1 = new Bullet(); b1.x = ARENA_X + 30; b1.y = ARENA_Y + 150 + tick % 2 * 400; b1.vx = 8; b1.vy = 0; arr.push(b1); game.addChild(b1); var b2 = new Bullet(); b2.x = ARENA_X + ARENA_W - 30; b2.y = ARENA_Y + 750 - tick % 2 * 400; b2.vx = -8; b2.vy = 0; arr.push(b2); game.addChild(b2); } } }, // Wave 3: Diagonal bullets from corners { duration: 240, // 4s spawnFunc: function spawnFunc(tick, arr) { if (tick % 36 === 0) { // Top-left var b1 = new Bullet(); b1.x = ARENA_X + 40; b1.y = ARENA_Y + 40; b1.vx = 5.5; b1.vy = 5.5; arr.push(b1); game.addChild(b1); // Top-right var b2 = new Bullet(); b2.x = ARENA_X + ARENA_W - 40; b2.y = ARENA_Y + 40; b2.vx = -5.5; b2.vy = 5.5; arr.push(b2); game.addChild(b2); // Bottom-left var b3 = new Bullet(); b3.x = ARENA_X + 40; b3.y = ARENA_Y + ARENA_H - 40; b3.vx = 5.5; b3.vy = -5.5; arr.push(b3); game.addChild(b3); // Bottom-right var b4 = new Bullet(); b4.x = ARENA_X + ARENA_W - 40; b4.y = ARENA_Y + ARENA_H - 40; b4.vx = -5.5; b4.vy = -5.5; arr.push(b4); game.addChild(b4); } } }, // Wave 4: Random rain { duration: 210, // 3.5s spawnFunc: function spawnFunc(tick, arr) { if (tick % 10 === 0) { var b = new Bullet(); b.x = ARENA_X + 80 + Math.floor(Math.random() * (ARENA_W - 160)); b.y = ARENA_Y + 30; b.vx = 0; b.vy = 10 + Math.random() * 2; arr.push(b); game.addChild(b); } } }, // Wave 5: Spiral (center out) { duration: 270, // 4.5s spawnFunc: function spawnFunc(tick, arr) { if (tick % 12 === 0) { var angle = tick / 12 * 0.5; for (var i = 0; i < 4; ++i) { var a = angle + i * Math.PI / 2; var b = new Bullet(); b.x = 2048 / 2; b.y = 2732 / 2; b.vx = Math.cos(a) * 8; b.vy = Math.sin(a) * 8; arr.push(b); game.addChild(b); } } } }]; // Start first wave function startWave(idx) { currentWave = idx; waveTime = 0; waveActive = true; waveTimer = 0; // Remove all bullets for (var i = bullets.length - 1; i >= 0; --i) { bullets[i].destroy(); bullets.splice(i, 1); } // Update GUI waveTxt.setText("Wave " + (currentWave + 1) + "/" + waves.length); } startWave(0); // Main update loop game.update = function () { if (!soulAlive) return; // Wave logic if (waveActive) { var wave = waves[currentWave]; wave.spawnFunc(waveTime, bullets); waveTime++; // Update timer GUI var tleft = Math.max(0, Math.ceil((wave.duration - waveTime) / 60)); timerTxt.setText("Time: " + tleft + "s"); // End wave? if (waveTime >= wave.duration) { waveActive = false; // Remove all bullets after short delay LK.setTimeout(function () { for (var i = bullets.length - 1; i >= 0; --i) { bullets[i].destroy(); bullets.splice(i, 1); } // Next wave or win if (currentWave + 1 < waves.length) { startWave(currentWave + 1); } else { // Win! LK.showYouWin(); } }, 600); } } // Update bullets for (var i = bullets.length - 1; i >= 0; --i) { var b = bullets[i]; b.update(); // Remove if out of arena if (b.x < ARENA_X - 60 || b.x > ARENA_X + ARENA_W + 60 || b.y < ARENA_Y - 60 || b.y > ARENA_Y + ARENA_H + 60) { b.destroy(); bullets.splice(i, 1); continue; } // Collision with soul var dx = b.x - soul.x, dy = b.y - soul.y; if (dx * dx + dy * dy < 45 * 45) { // Hit! soul.flash(); soulAlive = false; LK.effects.flashScreen(0xff0000, 800); LK.setTimeout(function () { LK.showGameOver(); }, 600); break; } } }; // Initial GUI text timerTxt.setText("Time: "); waveTxt.setText("Wave 1/" + waves.length);
===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,343 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+
+/****
+* Classes
+****/
+// Arena border (visual only)
+var ArenaBorder = Container.expand(function () {
+ var self = Container.call(this);
+ var border = self.attachAsset('arenaBorder', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ border.alpha = 0.7;
+ return self;
+});
+// Bullet class
+var Bullet = Container.expand(function () {
+ var self = Container.call(this);
+ var bulletSprite = self.attachAsset('bullet', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.vx = 0;
+ self.vy = 0;
+ self.update = function () {
+ self.x += self.vx;
+ self.y += self.vy;
+ };
+ return self;
+});
+// Soul (player) class
+var Soul = Container.expand(function () {
+ var self = Container.call(this);
+ var soulSprite = self.attachAsset('soul', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ // For hit flash
+ self.flash = function () {
+ tween(self, {
+ alpha: 0.3
+ }, {
+ duration: 80,
+ onFinish: function onFinish() {
+ tween(self, {
+ alpha: 1
+ }, {
+ duration: 120
+ });
+ }
+ });
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0x181818
+});
+
+/****
+* Game Code
+****/
+// Enemy warning (yellow, for telegraphing)
+// Bullet (white circle)
+// Arena border (white rectangle, thin)
+// Heart-shaped soul (red)
+// Arena dimensions (centered)
+var ARENA_W = 1200;
+var ARENA_H = 900;
+var ARENA_X = 2048 / 2 - ARENA_W / 2;
+var ARENA_Y = 2732 / 2 - ARENA_H / 2;
+// Add arena border
+var arenaBorder = new ArenaBorder();
+arenaBorder.x = 2048 / 2;
+arenaBorder.y = 2732 / 2;
+game.addChild(arenaBorder);
+// Add soul (player)
+var soul = new Soul();
+soul.x = 2048 / 2;
+soul.y = 2732 / 2;
+game.addChild(soul);
+// GUI: Timer (shows wave time left)
+var timerTxt = new Text2('', {
+ size: 80,
+ fill: "#fff"
+});
+timerTxt.anchor.set(0.5, 0);
+LK.gui.top.addChild(timerTxt);
+// GUI: Wave counter
+var waveTxt = new Text2('', {
+ size: 80,
+ fill: "#fff"
+});
+waveTxt.anchor.set(0.5, 0);
+LK.gui.top.addChild(waveTxt);
+waveTxt.y = 90;
+// Game state
+var bullets = [];
+var currentWave = 0;
+var waveTime = 0;
+var waveTimer = 0;
+var waveActive = false;
+var soulAlive = true;
+var dragSoul = false;
+var dragOffsetX = 0;
+var dragOffsetY = 0;
+// Arena bounds (for clamping soul)
+function clampSoul(x, y) {
+ var hw = 50,
+ hh = 50; // soul half size
+ var minX = ARENA_X + hw;
+ var maxX = ARENA_X + ARENA_W - hw;
+ var minY = ARENA_Y + hh;
+ var maxY = ARENA_Y + ARENA_H - hh;
+ return {
+ x: Math.max(minX, Math.min(maxX, x)),
+ y: Math.max(minY, Math.min(maxY, y))
+ };
+}
+// Touch/drag controls
+function handleSoulMove(x, y, obj) {
+ if (!dragSoul || !soulAlive) return;
+ var pos = clampSoul(x - dragOffsetX, y - dragOffsetY);
+ soul.x = pos.x;
+ soul.y = pos.y;
+}
+game.move = function (x, y, obj) {
+ handleSoulMove(x, y, obj);
+};
+game.down = function (x, y, obj) {
+ // Only start drag if inside soul
+ var dx = x - soul.x,
+ dy = y - soul.y;
+ if (dx * dx + dy * dy <= 60 * 60) {
+ dragSoul = true;
+ dragOffsetX = x - soul.x;
+ dragOffsetY = y - soul.y;
+ handleSoulMove(x, y, obj);
+ }
+};
+game.up = function (x, y, obj) {
+ dragSoul = false;
+};
+// Waves definition
+// Each wave: {duration, spawnFunc(tick, bulletsArr)}
+var waves = [
+// Wave 1: Simple slow bullets from top
+{
+ duration: 180,
+ // 3s
+ spawnFunc: function spawnFunc(tick, arr) {
+ if (tick % 30 === 0) {
+ for (var i = 0; i < 4; ++i) {
+ var b = new Bullet();
+ b.x = ARENA_X + 200 + i * 250;
+ b.y = ARENA_Y + 30;
+ b.vx = 0;
+ b.vy = 6;
+ arr.push(b);
+ game.addChild(b);
+ }
+ }
+ }
+},
+// Wave 2: Bullets from left/right
+{
+ duration: 210,
+ // 3.5s
+ spawnFunc: function spawnFunc(tick, arr) {
+ if (tick % 24 === 0) {
+ var b1 = new Bullet();
+ b1.x = ARENA_X + 30;
+ b1.y = ARENA_Y + 150 + tick % 2 * 400;
+ b1.vx = 8;
+ b1.vy = 0;
+ arr.push(b1);
+ game.addChild(b1);
+ var b2 = new Bullet();
+ b2.x = ARENA_X + ARENA_W - 30;
+ b2.y = ARENA_Y + 750 - tick % 2 * 400;
+ b2.vx = -8;
+ b2.vy = 0;
+ arr.push(b2);
+ game.addChild(b2);
+ }
+ }
+},
+// Wave 3: Diagonal bullets from corners
+{
+ duration: 240,
+ // 4s
+ spawnFunc: function spawnFunc(tick, arr) {
+ if (tick % 36 === 0) {
+ // Top-left
+ var b1 = new Bullet();
+ b1.x = ARENA_X + 40;
+ b1.y = ARENA_Y + 40;
+ b1.vx = 5.5;
+ b1.vy = 5.5;
+ arr.push(b1);
+ game.addChild(b1);
+ // Top-right
+ var b2 = new Bullet();
+ b2.x = ARENA_X + ARENA_W - 40;
+ b2.y = ARENA_Y + 40;
+ b2.vx = -5.5;
+ b2.vy = 5.5;
+ arr.push(b2);
+ game.addChild(b2);
+ // Bottom-left
+ var b3 = new Bullet();
+ b3.x = ARENA_X + 40;
+ b3.y = ARENA_Y + ARENA_H - 40;
+ b3.vx = 5.5;
+ b3.vy = -5.5;
+ arr.push(b3);
+ game.addChild(b3);
+ // Bottom-right
+ var b4 = new Bullet();
+ b4.x = ARENA_X + ARENA_W - 40;
+ b4.y = ARENA_Y + ARENA_H - 40;
+ b4.vx = -5.5;
+ b4.vy = -5.5;
+ arr.push(b4);
+ game.addChild(b4);
+ }
+ }
+},
+// Wave 4: Random rain
+{
+ duration: 210,
+ // 3.5s
+ spawnFunc: function spawnFunc(tick, arr) {
+ if (tick % 10 === 0) {
+ var b = new Bullet();
+ b.x = ARENA_X + 80 + Math.floor(Math.random() * (ARENA_W - 160));
+ b.y = ARENA_Y + 30;
+ b.vx = 0;
+ b.vy = 10 + Math.random() * 2;
+ arr.push(b);
+ game.addChild(b);
+ }
+ }
+},
+// Wave 5: Spiral (center out)
+{
+ duration: 270,
+ // 4.5s
+ spawnFunc: function spawnFunc(tick, arr) {
+ if (tick % 12 === 0) {
+ var angle = tick / 12 * 0.5;
+ for (var i = 0; i < 4; ++i) {
+ var a = angle + i * Math.PI / 2;
+ var b = new Bullet();
+ b.x = 2048 / 2;
+ b.y = 2732 / 2;
+ b.vx = Math.cos(a) * 8;
+ b.vy = Math.sin(a) * 8;
+ arr.push(b);
+ game.addChild(b);
+ }
+ }
+ }
+}];
+// Start first wave
+function startWave(idx) {
+ currentWave = idx;
+ waveTime = 0;
+ waveActive = true;
+ waveTimer = 0;
+ // Remove all bullets
+ for (var i = bullets.length - 1; i >= 0; --i) {
+ bullets[i].destroy();
+ bullets.splice(i, 1);
+ }
+ // Update GUI
+ waveTxt.setText("Wave " + (currentWave + 1) + "/" + waves.length);
+}
+startWave(0);
+// Main update loop
+game.update = function () {
+ if (!soulAlive) return;
+ // Wave logic
+ if (waveActive) {
+ var wave = waves[currentWave];
+ wave.spawnFunc(waveTime, bullets);
+ waveTime++;
+ // Update timer GUI
+ var tleft = Math.max(0, Math.ceil((wave.duration - waveTime) / 60));
+ timerTxt.setText("Time: " + tleft + "s");
+ // End wave?
+ if (waveTime >= wave.duration) {
+ waveActive = false;
+ // Remove all bullets after short delay
+ LK.setTimeout(function () {
+ for (var i = bullets.length - 1; i >= 0; --i) {
+ bullets[i].destroy();
+ bullets.splice(i, 1);
+ }
+ // Next wave or win
+ if (currentWave + 1 < waves.length) {
+ startWave(currentWave + 1);
+ } else {
+ // Win!
+ LK.showYouWin();
+ }
+ }, 600);
+ }
+ }
+ // Update bullets
+ for (var i = bullets.length - 1; i >= 0; --i) {
+ var b = bullets[i];
+ b.update();
+ // Remove if out of arena
+ if (b.x < ARENA_X - 60 || b.x > ARENA_X + ARENA_W + 60 || b.y < ARENA_Y - 60 || b.y > ARENA_Y + ARENA_H + 60) {
+ b.destroy();
+ bullets.splice(i, 1);
+ continue;
+ }
+ // Collision with soul
+ var dx = b.x - soul.x,
+ dy = b.y - soul.y;
+ if (dx * dx + dy * dy < 45 * 45) {
+ // Hit!
+ soul.flash();
+ soulAlive = false;
+ LK.effects.flashScreen(0xff0000, 800);
+ LK.setTimeout(function () {
+ LK.showGameOver();
+ }, 600);
+ break;
+ }
+ }
+};
+// Initial GUI text
+timerTxt.setText("Time: ");
+waveTxt.setText("Wave 1/" + waves.length);
\ No newline at end of file