User prompt
Alright, then add 4 buttons: a forward arrow, a backward arrow, a right arrow, and a left arrow.
User prompt
Don't let the tomatoes come from below.
User prompt
build a store on the game screen and have 5 guns
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'to')' in or related to this line: 'tween(m).to({' Line Number: 252
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'to')' in or related to this line: 'tween(m).to({' Line Number: 252
User prompt
Please fix the bug: 'TypeError: tween.to is not a function' in or related to this line: 'tween.to(m, {' Line Number: 252
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'to')' in or related to this line: 'tween(m).to({' Line Number: 252
User prompt
Please fix the bug: 'TypeError: tween.to is not a function' in or related to this line: 'tween.to(m, {' Line Number: 252
User prompt
The money should come directly and the amount of my money should be visible.
User prompt
Kill the tomato and let the money come.
Code edit (1 edits merged)
Please save this source code
User prompt
Ball Blaster: Tomato Attack
Initial prompt
make a ball that shoots bullets, the bullets should kill the tomatoes
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Player Ball
var Ball = Container.expand(function () {
var self = Container.call(this);
var ballGfx = self.attachAsset('ball', {
anchorX: 0.5,
anchorY: 0.5
});
// For possible future use
self.radius = ballGfx.width / 2;
return self;
});
// Bullet
var Bullet = Container.expand(function () {
var self = Container.call(this);
var bulletGfx = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
// Direction (unit vector)
self.dx = 0;
self.dy = -1;
self.speed = 40; // px per frame
self.update = function () {
self.x += self.dx * self.speed;
self.y += self.dy * self.speed;
};
return self;
});
// Tomato Enemy
var Tomato = Container.expand(function () {
var self = Container.call(this);
var tomatoGfx = self.attachAsset('tomato', {
anchorX: 0.5,
anchorY: 0.5
});
// Target to move towards (the player ball)
self.target = null;
self.speed = 7 + Math.random() * 3; // px per frame, randomize a bit
self.update = function () {
if (!self.target) return;
var dx = self.target.x - self.x;
var dy = self.target.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;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x181818
});
/****
* Game Code
****/
// Center player ball
// Game area: 2048x2732
// Ball (player)
// Bullet
// Tomato enemy
// Sound for shooting
var player = new Ball();
player.x = 2048 / 2;
player.y = 2732 - 350;
game.addChild(player);
// Score display
var score = 0;
var scoreTxt = new Text2('0', {
size: 120,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Bullets and tomatoes arrays
var bullets = [];
var tomatoes = [];
// Dragging
var dragNode = null;
// For shooting: track last tap position
var lastTapX = null;
var lastTapY = null;
// Store UI: 5 gun buttons at the bottom of the screen
var gunCount = 5;
var gunButtons = [];
var selectedGun = 0; // default gun
// Gun names (could be used for upgrades later)
var gunNames = ["Basic", "Spread", "Rapid", "Big", "Pierce"];
// Gun colors for button visuals
var gunColors = [0x3a9efd, 0x6cbb3c, 0xf7b32b, 0xd7263d, 0x7c3aed];
// Create gun buttons and add to GUI bottom
for (var i = 0; i < gunCount; i++) {
var btn = new Container();
// Button background
var btnBg = LK.getAsset('bullet', {
width: 180,
height: 180,
color: gunColors[i],
anchorX: 0.5,
anchorY: 0.5
});
btn.addChild(btnBg);
// Button label
var btnLabel = new Text2(gunNames[i], {
size: 48,
fill: "#fff"
});
btnLabel.anchor.set(0.5, 0.5);
btnLabel.y = 50;
btn.addChild(btnLabel);
// Position buttons evenly along the bottom, avoiding bottom corners
btn.x = 2048 / (gunCount + 1) * (i + 1);
btn.y = 2732 - 120;
// Store index for event
btn.gunIndex = i;
// Highlight selected gun
btnBg.alpha = i === selectedGun ? 1 : 0.5;
// Add to GUI
LK.gui.bottom.addChild(btn);
gunButtons.push(btn);
}
// Store gun selection handler
function handleGunButtonDown(x, y, obj) {
// Find which button was pressed
for (var i = 0; i < gunButtons.length; i++) {
var btn = gunButtons[i];
// Convert event to local button space
var local = btn.toLocal({
x: x,
y: y
});
// Button is 180x180 centered
if (local.x > -90 && local.x < 90 && local.y > -90 && local.y < 90) {
selectedGun = btn.gunIndex;
// Update button highlights
for (var j = 0; j < gunButtons.length; j++) {
gunButtons[j].children[0].alpha = j === selectedGun ? 1 : 0.5;
}
break;
}
}
}
// Add event to GUI bottom for gun selection
LK.gui.bottom.down = function (x, y, obj) {
handleGunButtonDown(x, y, obj);
};
// Prevent elements in top left 100x100
// (player and GUI are well away from this area)
// Spawn tomato at random edge
function spawnTomato() {
var t = new Tomato();
// Randomly pick one of four edges
var edge = Math.floor(Math.random() * 4);
var margin = 100;
if (edge === 0) {
// Top
t.x = margin + Math.random() * (2048 - 2 * margin);
t.y = -80;
} else if (edge === 1) {
// Bottom
t.x = margin + Math.random() * (2048 - 2 * margin);
t.y = 2732 + 80;
} else if (edge === 2) {
// Left
t.x = -80;
t.y = margin + Math.random() * (2732 - 2 * margin);
} else {
// Right
t.x = 2048 + 80;
t.y = margin + Math.random() * (2732 - 2 * margin);
}
t.target = player;
tomatoes.push(t);
game.addChild(t);
}
// Initial tomato spawn
for (var i = 0; i < 2; i++) {
spawnTomato();
}
// Tomato spawn timer
var tomatoTimer = LK.setInterval(function () {
spawnTomato();
}, 1200);
// Handle dragging the player ball
function handleMove(x, y, obj) {
if (dragNode) {
// Clamp to game area, avoid top 100px
var r = dragNode.radius;
var nx = Math.max(r, Math.min(2048 - r, x));
var ny = Math.max(100 + r, Math.min(2732 - r, y));
dragNode.x = nx;
dragNode.y = ny;
}
}
game.move = handleMove;
game.down = function (x, y, obj) {
// If touch is on player, start drag
var dx = x - player.x;
var dy = y - player.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < player.radius + 10) {
dragNode = player;
} else {
// Shoot bullet towards tap
shootBullet(x, y);
}
};
game.up = function (x, y, obj) {
dragNode = null;
};
// Shoot bullet from player towards (tx, ty)
function shootBullet(tx, ty) {
// Calculate direction
var dx = tx - player.x;
var dy = ty - player.y;
var dist = Math.sqrt(dx * dx + dy * dy);
var dirX = dist === 0 ? 0 : dx / dist;
var dirY = dist === 0 ? -1 : dy / dist;
// Gun logic
if (selectedGun === 0) {
// Basic: single bullet
var b = new Bullet();
b.x = player.x;
b.y = player.y;
b.dx = dirX;
b.dy = dirY;
bullets.push(b);
game.addChild(b);
} else if (selectedGun === 1) {
// Spread: 3 bullets, spread angle
for (var i = -1; i <= 1; i++) {
var angle = Math.atan2(dirY, dirX) + i * 0.18;
var b = new Bullet();
b.x = player.x;
b.y = player.y;
b.dx = Math.cos(angle);
b.dy = Math.sin(angle);
bullets.push(b);
game.addChild(b);
}
} else if (selectedGun === 2) {
// Rapid: 2 fast bullets
for (var i = 0; i < 2; i++) {
var b = new Bullet();
b.x = player.x;
b.y = player.y;
b.dx = dirX;
b.dy = dirY;
b.speed = 60;
bullets.push(b);
game.addChild(b);
}
} else if (selectedGun === 3) {
// Big: 1 slow, big bullet
var b = new Bullet();
b.x = player.x;
b.y = player.y;
b.dx = dirX;
b.dy = dirY;
b.speed = 25;
// Make bullet bigger
b.children[0].scale.x = 2;
b.children[0].scale.y = 2;
bullets.push(b);
game.addChild(b);
} else if (selectedGun === 4) {
// Pierce: 1 bullet, mark as piercing
var b = new Bullet();
b.x = player.x;
b.y = player.y;
b.dx = dirX;
b.dy = dirY;
b.pierce = true;
bullets.push(b);
game.addChild(b);
}
LK.getSound('shoot').play();
}
// Main game update
game.update = function () {
// Update bullets
for (var i = bullets.length - 1; i >= 0; i--) {
var b = bullets[i];
b.update();
// Remove if off screen
if (b.x < -60 || b.x > 2048 + 60 || b.y < -60 || b.y > 2732 + 60) {
b.destroy();
bullets.splice(i, 1);
continue;
}
}
// Update tomatoes
for (var j = tomatoes.length - 1; j >= 0; j--) {
var t = tomatoes[j];
t.update();
// Check collision with player
if (t.intersects(player)) {
// Flash screen, game over
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
return;
}
// Check collision with bullets
for (var k = bullets.length - 1; k >= 0; k--) {
var b = bullets[k];
if (t.intersects(b)) {
// Destroy tomato
t.destroy();
tomatoes.splice(j, 1);
// If not piercing, destroy bullet
if (!b.pierce) {
b.destroy();
bullets.splice(k, 1);
}
// Score up
score += 1;
LK.setScore(score);
scoreTxt.setText(score);
// Only allow one bullet to hit this tomato
break;
}
}
}
};
// Play music if you want, but not required for MVP
// Clean up on game over (handled by LK automatically) ===================================================================
--- original.js
+++ change.js
@@ -33,24 +33,8 @@
self.y += self.dy * self.speed;
};
return self;
});
-// Money (drops when tomato is killed)
-var Money = Container.expand(function () {
- var self = Container.call(this);
- // Use bullet asset for money for now, but color it gold
- var moneyGfx = self.attachAsset('bullet', {
- anchorX: 0.5,
- anchorY: 0.5
- });
- moneyGfx.tint = 0xffd700; // gold color
- self.value = 1;
- self.dy = 10 + Math.random() * 5; // fall speed
- self.update = function () {
- self.y += self.dy;
- };
- return self;
-});
// Tomato Enemy
var Tomato = Container.expand(function () {
var self = Container.call(this);
var tomatoGfx = self.attachAsset('tomato', {
@@ -82,14 +66,14 @@
/****
* Game Code
****/
-// Sound for shooting
-// Tomato enemy
-// Bullet
-// Ball (player)
-// Game area: 2048x2732
// Center player ball
+// Game area: 2048x2732
+// Ball (player)
+// Bullet
+// Tomato enemy
+// Sound for shooting
var player = new Ball();
player.x = 2048 / 2;
player.y = 2732 - 350;
game.addChild(player);
@@ -100,26 +84,80 @@
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
-// Money display
-var money = 0;
-var moneyTxt = new Text2('0', {
- size: 100,
- fill: 0xffd700
-});
-moneyTxt.anchor.set(0.5, 0);
-moneyTxt.x = 2048 / 2 + 300; // Place to the right of score
-moneyTxt.y = 0;
-LK.gui.top.addChild(moneyTxt);
// Bullets and tomatoes arrays
var bullets = [];
var tomatoes = [];
// Dragging
var dragNode = null;
// For shooting: track last tap position
var lastTapX = null;
var lastTapY = null;
+// Store UI: 5 gun buttons at the bottom of the screen
+var gunCount = 5;
+var gunButtons = [];
+var selectedGun = 0; // default gun
+// Gun names (could be used for upgrades later)
+var gunNames = ["Basic", "Spread", "Rapid", "Big", "Pierce"];
+// Gun colors for button visuals
+var gunColors = [0x3a9efd, 0x6cbb3c, 0xf7b32b, 0xd7263d, 0x7c3aed];
+// Create gun buttons and add to GUI bottom
+for (var i = 0; i < gunCount; i++) {
+ var btn = new Container();
+ // Button background
+ var btnBg = LK.getAsset('bullet', {
+ width: 180,
+ height: 180,
+ color: gunColors[i],
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ btn.addChild(btnBg);
+ // Button label
+ var btnLabel = new Text2(gunNames[i], {
+ size: 48,
+ fill: "#fff"
+ });
+ btnLabel.anchor.set(0.5, 0.5);
+ btnLabel.y = 50;
+ btn.addChild(btnLabel);
+ // Position buttons evenly along the bottom, avoiding bottom corners
+ btn.x = 2048 / (gunCount + 1) * (i + 1);
+ btn.y = 2732 - 120;
+ // Store index for event
+ btn.gunIndex = i;
+ // Highlight selected gun
+ btnBg.alpha = i === selectedGun ? 1 : 0.5;
+ // Add to GUI
+ LK.gui.bottom.addChild(btn);
+ gunButtons.push(btn);
+}
+// Store gun selection handler
+function handleGunButtonDown(x, y, obj) {
+ // Find which button was pressed
+ for (var i = 0; i < gunButtons.length; i++) {
+ var btn = gunButtons[i];
+ // Convert event to local button space
+ var local = btn.toLocal({
+ x: x,
+ y: y
+ });
+ // Button is 180x180 centered
+ if (local.x > -90 && local.x < 90 && local.y > -90 && local.y < 90) {
+ selectedGun = btn.gunIndex;
+ // Update button highlights
+ for (var j = 0; j < gunButtons.length; j++) {
+ gunButtons[j].children[0].alpha = j === selectedGun ? 1 : 0.5;
+ }
+ break;
+ }
+ }
+}
+// Add event to GUI bottom for gun selection
+LK.gui.bottom.down = function (x, y, obj) {
+ handleGunButtonDown(x, y, obj);
+};
// Prevent elements in top left 100x100
// (player and GUI are well away from this area)
// Spawn tomato at random edge
function spawnTomato() {
@@ -184,23 +222,72 @@
dragNode = null;
};
// Shoot bullet from player towards (tx, ty)
function shootBullet(tx, ty) {
- var b = new Bullet();
- b.x = player.x;
- b.y = player.y;
+ // Calculate direction
var dx = tx - player.x;
var dy = ty - player.y;
var dist = Math.sqrt(dx * dx + dy * dy);
- if (dist === 0) {
- b.dx = 0;
- b.dy = -1;
- } else {
- b.dx = dx / dist;
- b.dy = dy / dist;
+ var dirX = dist === 0 ? 0 : dx / dist;
+ var dirY = dist === 0 ? -1 : dy / dist;
+ // Gun logic
+ if (selectedGun === 0) {
+ // Basic: single bullet
+ var b = new Bullet();
+ b.x = player.x;
+ b.y = player.y;
+ b.dx = dirX;
+ b.dy = dirY;
+ bullets.push(b);
+ game.addChild(b);
+ } else if (selectedGun === 1) {
+ // Spread: 3 bullets, spread angle
+ for (var i = -1; i <= 1; i++) {
+ var angle = Math.atan2(dirY, dirX) + i * 0.18;
+ var b = new Bullet();
+ b.x = player.x;
+ b.y = player.y;
+ b.dx = Math.cos(angle);
+ b.dy = Math.sin(angle);
+ bullets.push(b);
+ game.addChild(b);
+ }
+ } else if (selectedGun === 2) {
+ // Rapid: 2 fast bullets
+ for (var i = 0; i < 2; i++) {
+ var b = new Bullet();
+ b.x = player.x;
+ b.y = player.y;
+ b.dx = dirX;
+ b.dy = dirY;
+ b.speed = 60;
+ bullets.push(b);
+ game.addChild(b);
+ }
+ } else if (selectedGun === 3) {
+ // Big: 1 slow, big bullet
+ var b = new Bullet();
+ b.x = player.x;
+ b.y = player.y;
+ b.dx = dirX;
+ b.dy = dirY;
+ b.speed = 25;
+ // Make bullet bigger
+ b.children[0].scale.x = 2;
+ b.children[0].scale.y = 2;
+ bullets.push(b);
+ game.addChild(b);
+ } else if (selectedGun === 4) {
+ // Pierce: 1 bullet, mark as piercing
+ var b = new Bullet();
+ b.x = player.x;
+ b.y = player.y;
+ b.dx = dirX;
+ b.dy = dirY;
+ b.pierce = true;
+ bullets.push(b);
+ game.addChild(b);
}
- bullets.push(b);
- game.addChild(b);
LK.getSound('shoot').play();
}
// Main game update
game.update = function () {
@@ -229,63 +316,24 @@
// Check collision with bullets
for (var k = bullets.length - 1; k >= 0; k--) {
var b = bullets[k];
if (t.intersects(b)) {
- // Destroy both
+ // Destroy tomato
t.destroy();
- b.destroy();
- // Spawn money at tomato position and make it fly to player, then increment money immediately
- var m = new Money();
- m.x = t.x;
- m.y = t.y;
- game.addChild(m);
- // Animate money flying to player
- tween(m).to({
- x: player.x,
- y: player.y
- }, 400).onComplete(function () {
- m.destroy();
- money += m.value;
- moneyTxt.setText(money);
- LK.effects.flashObject(player, 0xffd700, 400);
- }).start();
tomatoes.splice(j, 1);
- bullets.splice(k, 1);
+ // If not piercing, destroy bullet
+ if (!b.pierce) {
+ b.destroy();
+ bullets.splice(k, 1);
+ }
// Score up
score += 1;
LK.setScore(score);
scoreTxt.setText(score);
- // Flash tomato on hit
- // (optional: could tween, but keep minimal)
+ // Only allow one bullet to hit this tomato
break;
}
}
}
- // Update money drops
- if (window.moneyDrops) {
- for (var mIdx = window.moneyDrops.length - 1; mIdx >= 0; mIdx--) {
- var m = window.moneyDrops[mIdx];
- m.update();
- // Remove if off screen
- if (m.lastY <= 2732 + 100 && m.y > 2732 + 100) {
- m.destroy();
- window.moneyDrops.splice(mIdx, 1);
- continue;
- }
- // Collect if player touches
- var dx = m.x - player.x;
- var dy = m.y - player.y;
- var dist = Math.sqrt(dx * dx + dy * dy);
- if (!m.collected && dist < m.collectRadius + player.radius) {
- m.collected = true;
- m.destroy();
- window.moneyDrops.splice(mIdx, 1);
- // (Optional: add to money counter, play sound, etc)
- // For now, just flash a little
- LK.effects.flashObject(player, 0xffd700, 400);
- }
- m.lastY = m.y;
- }
- }
};
// Play music if you want, but not required for MVP
// Clean up on game over (handled by LK automatically)
\ No newline at end of file