User prompt
let’s create a title screen. the title can be Invader Blits 2 But with a delay. the delay can be 3 seconds. so it will be Invader Blits (wait 3 seconds) 2 ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
not like start fresh to a ball game. I’m talking about just a black screen with all codes and all sprites removed.
User prompt
let’s start fresh.
User prompt
please fix it :)
User prompt
Please fix the bug: 'TypeError: undefined is not an object (evaluating 'self.children[0].tint = c[0] << 16 | c[1] << 8 | c[2]')' in or related to this line: 'self.children[0].tint = c[0] << 16 | c[1] << 8 | c[2];' Line Number: 214
User prompt
Please fix the bug: 'undefined is not an object (evaluating 'self.children[0].tint = 0xff2222')' in or related to this line: 'self.children[0].tint = 0xff2222;' Line Number: 225
User prompt
make big invaders. they split when ever hit. and make red invaders. red invaders are 2x faster than the green invaders. make some of the invaders rainbow too.
User prompt
when I’m not by the screen edge. even when it’s not by the screen edge. it still acts like it. FIX THIS!!
User prompt
make the bomb appear every 10 seconds and moves by itself and bounces off the screen.
User prompt
make the lines blink when shooting every 0.7 seconds.
User prompt
make the lines blink every 0.3 seconds when shooting
User prompt
make the lines blink every 0.1 second when shooting.
User prompt
you made the stuff correct. it’s just the invaders isn’t dieing when target is on them and shooting.
User prompt
Please fix the bug: 'ReferenceError: Can't find variable: player' in or related to this line: 'if (!player.invincible && b.intersects(player)) {' Line Number: 446
User prompt
that third one is still in the middle. REMOVE THAT THIRD ONE. and the target isn’t shooting anything. you also forgot the blue lines.
User prompt
Please fix the bug: 'undefined is not an object (evaluating 'player.x = GAME_WIDTH / 2')' in or related to this line: 'player.x = GAME_WIDTH / 2;' Line Number: 330
User prompt
there’s 3 cannons. remove that third cannon. and the target only moves when moving hand.
User prompt
can you make the target? the target always moves but the blue block (the cannon) is always in the corner. make another one and that other one goes in a different corner (it only has to be on the bottom.) and when shooting. Blue lines go to the target and blink when ever shooting.
User prompt
I can’t shoot. how do I fix this?
Code edit (1 edits merged)
Please save this source code
User prompt
Invader Blitz
Initial prompt
we are making a game similar to space invaders frenzy.
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Ball - the main player object that bounces
var Ball = Container.expand(function () {
var self = Container.call(this);
var ballGraphic = self.attachAsset('ball', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = ballGraphic.width;
self.height = ballGraphic.height;
self.speedY = 0;
self.gravity = 1.2;
self.bounceStrength = -25;
self.maxSpeed = 20;
self.update = function () {
// Apply gravity
self.speedY += self.gravity;
// Limit max fall speed
if (self.speedY > self.maxSpeed) {
self.speedY = self.maxSpeed;
}
// Move ball
self.y += self.speedY;
// Bounce off bottom
if (self.y + self.height / 2 > GAME_HEIGHT - 100) {
self.y = GAME_HEIGHT - 100 - self.height / 2;
self.speedY = self.bounceStrength;
LK.getSound('bounce').play();
}
// Bounce off top
if (self.y - self.height / 2 < 100) {
self.y = 100 + self.height / 2;
self.speedY = Math.abs(self.speedY) * 0.5;
}
};
self.jump = function () {
self.speedY = self.bounceStrength * 1.2;
LK.getSound('bounce').play();
};
return self;
});
// Star - collectible that falls from the sky
var Star = Container.expand(function () {
var self = Container.call(this);
var starGraphic = self.attachAsset('star', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = starGraphic.width;
self.height = starGraphic.height;
self.speed = 8 + Math.random() * 4;
self.rotationSpeed = 0.1 + Math.random() * 0.1;
self.update = function () {
self.y += self.speed;
self.rotation += self.rotationSpeed;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Game constants
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2732;
// Game state
var ball;
var stars = [];
var score = 0;
var gameOver = false;
var starSpawnTimer = 0;
var starSpawnInterval = 120; // spawn star every 2 seconds at 60fps
// GUI
var scoreTxt = new Text2('Score: 0', {
size: 120,
fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var instructionTxt = new Text2('Tap to make the ball jump!', {
size: 80,
fill: 0xFFFF88
});
instructionTxt.anchor.set(0.5, 0.5);
instructionTxt.x = GAME_WIDTH / 2;
instructionTxt.y = GAME_HEIGHT / 2 - 200;
game.addChild(instructionTxt);
// Play music
LK.playMusic('happyTune');
// Create the ball
ball = new Ball();
ball.x = GAME_WIDTH / 2;
ball.y = GAME_HEIGHT / 2;
game.addChild(ball);
// Input handling - tap anywhere to make ball jump
game.down = function (x, y, obj) {
if (!gameOver) {
ball.jump();
}
};
// Spawn a new star
function spawnStar() {
var star = new Star();
star.x = Math.random() * (GAME_WIDTH - 200) + 100;
star.y = -star.height;
stars.push(star);
game.addChild(star);
}
// Check collision between two objects
function checkCollision(obj1, obj2) {
return obj1.x + obj1.width / 2 > obj2.x - obj2.width / 2 && obj1.x - obj1.width / 2 < obj2.x + obj2.width / 2 && obj1.y + obj1.height / 2 > obj2.y - obj2.height / 2 && obj1.y - obj1.height / 2 < obj2.y + obj2.height / 2;
}
// Main game update loop
game.update = function () {
if (gameOver) return;
// Update ball
ball.update();
// Spawn stars
starSpawnTimer++;
if (starSpawnTimer >= starSpawnInterval) {
starSpawnTimer = 0;
spawnStar();
// Make stars spawn faster as score increases
if (starSpawnInterval > 40) {
starSpawnInterval -= 2;
}
}
// Update stars and check collisions
for (var i = stars.length - 1; i >= 0; i--) {
var star = stars[i];
star.update();
// Check collision with ball
if (checkCollision(ball, star)) {
// Collect star
score += 10;
LK.setScore(score);
scoreTxt.setText('Score: ' + score);
LK.getSound('collect').play();
// Flash star before removing
tween(star, {
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 200,
onFinish: function onFinish() {
star.destroy();
}
});
stars.splice(i, 1);
continue;
}
// Remove stars that fall off screen
if (star.y > GAME_HEIGHT + star.height) {
star.destroy();
stars.splice(i, 1);
}
}
// Keep ball in screen bounds (left/right)
if (ball.x - ball.width / 2 < 0) {
ball.x = ball.width / 2;
}
if (ball.x + ball.width / 2 > GAME_WIDTH) {
ball.x = GAME_WIDTH - ball.width / 2;
}
// Check for game over (ball falls off bottom for too long)
if (ball.y > GAME_HEIGHT + 200) {
triggerGameOver();
}
};
// Game over function
function triggerGameOver() {
if (gameOver) return;
gameOver = true;
LK.effects.flashScreen(0xff3333, 1000);
LK.showGameOver();
}
// Set initial score
LK.setScore(score);
scoreTxt.setText('Score: ' + score); ===================================================================
--- original.js
+++ change.js
@@ -5,237 +5,65 @@
/****
* Classes
****/
-// Alien Invader (base)
-var Alien = Container.expand(function () {
+// Ball - the main player object that bounces
+var Ball = Container.expand(function () {
var self = Container.call(this);
- var alien = self.attachAsset('alien', {
+ var ballGraphic = self.attachAsset('ball', {
anchorX: 0.5,
anchorY: 0.5
});
- self.width = alien.width;
- self.height = alien.height;
- self.row = 0;
- self.col = 0;
- self.type = 0; // 0: green, 1: red, 2: rainbow, 3: big
- self.alive = true;
- self.shootCooldown = 0;
- self.speedMultiplier = 1;
- self.isBig = false;
- self.isRainbow = false;
- self.split = function () {};
- return self;
-});
-// Alien Bullet
-var AlienBullet = Container.expand(function () {
- var self = Container.call(this);
- var bullet = self.attachAsset('alienBullet', {
- anchorX: 0.5,
- anchorY: 0.5
- });
- self.width = bullet.width;
- self.height = bullet.height;
- self.speed = 22; // Downwards
+ self.width = ballGraphic.width;
+ self.height = ballGraphic.height;
+ self.speedY = 0;
+ self.gravity = 1.2;
+ self.bounceStrength = -25;
+ self.maxSpeed = 20;
self.update = function () {
- self.y += self.speed;
- };
- return self;
-});
-// Big Alien (splits into two smaller aliens when hit)
-var BigAlien = Container.expand(function () {
- var self = Container.call(this);
- self.isBig = true;
- self.type = 3;
- // Make it visually bigger
- self.scale.set(1.7, 1.7);
- self.width = self.width * 1.7;
- self.height = self.height * 1.7;
- // Split logic: spawn two normal aliens at this position
- self.split = function () {
- for (var i = 0; i < 2; i++) {
- var newAlien = new Alien();
- newAlien.x = self.x + (i === 0 ? -self.width / 4 : self.width / 4);
- newAlien.y = self.y;
- newAlien.row = self.row;
- newAlien.col = self.col;
- newAlien.type = 0;
- newAlien.alive = true;
- // Ensure new aliens are not immediately destroyed by blue line
- // Place them slightly offset vertically if needed
- if (typeof target !== "undefined" && blueLineAlpha > 0 && target.x + target.width / 2 > newAlien.x - newAlien.width / 2 && target.x - target.width / 2 < newAlien.x + newAlien.width / 2 && target.y + target.height / 2 > newAlien.y - newAlien.height / 2 && target.y - target.height / 2 < newAlien.y + newAlien.height / 2) {
- // Move new alien just below the target to avoid instant kill
- newAlien.y += newAlien.height;
- }
- game.addChild(newAlien);
- aliens.push(newAlien);
+ // Apply gravity
+ self.speedY += self.gravity;
+ // Limit max fall speed
+ if (self.speedY > self.maxSpeed) {
+ self.speedY = self.maxSpeed;
}
- };
- return self;
-});
-// Bomb (appears every 10s, moves and bounces off screen)
-var Bomb = Container.expand(function () {
- var self = Container.call(this);
- var bombAsset = self.attachAsset('powerup', {
- anchorX: 0.5,
- anchorY: 0.5
- });
- self.width = bombAsset.width;
- self.height = bombAsset.height;
- // Random initial direction
- var angle = Math.random() * Math.PI * 2;
- self.speed = 28 + Math.random() * 10;
- self.speedX = Math.cos(angle) * self.speed;
- self.speedY = Math.sin(angle) * self.speed;
- self.update = function () {
- // Save lastX/lastY for good practice (if needed for future triggers)
- if (typeof self.lastX === "undefined") self.lastX = self.x;
- if (typeof self.lastY === "undefined") self.lastY = self.y;
- self.x += self.speedX;
+ // Move ball
self.y += self.speedY;
- // Bounce off left/right
- if (self.x < self.width / 2) {
- self.x = self.width / 2;
- self.speedX *= -1;
+ // Bounce off bottom
+ if (self.y + self.height / 2 > GAME_HEIGHT - 100) {
+ self.y = GAME_HEIGHT - 100 - self.height / 2;
+ self.speedY = self.bounceStrength;
+ LK.getSound('bounce').play();
}
- if (self.x > GAME_WIDTH - self.width / 2) {
- self.x = GAME_WIDTH - self.width / 2;
- self.speedX *= -1;
+ // Bounce off top
+ if (self.y - self.height / 2 < 100) {
+ self.y = 100 + self.height / 2;
+ self.speedY = Math.abs(self.speedY) * 0.5;
}
- // Bounce off top/bottom
- if (self.y < self.height / 2 + 100) {
- self.y = self.height / 2 + 100;
- self.speedY *= -1;
- }
- if (self.y > GAME_HEIGHT - self.height / 2 - 200) {
- self.y = GAME_HEIGHT - self.height / 2 - 200;
- self.speedY *= -1;
- }
- self.lastX = self.x;
- self.lastY = self.y;
};
- return self;
-});
-// Cannon in a fixed corner (bottom left or right)
-var CannonInCorner = Container.expand(function () {
- var self = Container.call(this);
- var cannonAsset = self.attachAsset('playerCannon', {
- anchorX: 0.5,
- anchorY: 0.5
- });
- self.width = cannonAsset.width;
- self.height = cannonAsset.height;
- self.shootCooldown = 0;
- self.corner = "left"; // "left" or "right"
- return self;
-});
-// Player Bullet
-var PlayerBullet = Container.expand(function () {
- var self = Container.call(this);
- var bullet = self.attachAsset('playerBullet', {
- anchorX: 0.5,
- anchorY: 0.5
- });
- self.width = bullet.width;
- self.height = bullet.height;
- self.speed = -32; // Upwards
- self.update = function () {
- self.y += self.speed;
+ self.jump = function () {
+ self.speedY = self.bounceStrength * 1.2;
+ LK.getSound('bounce').play();
};
return self;
});
-// Player Cannon
-var PlayerCannon = Container.expand(function () {
+// Star - collectible that falls from the sky
+var Star = Container.expand(function () {
var self = Container.call(this);
- var cannon = self.attachAsset('playerCannon', {
+ var starGraphic = self.attachAsset('star', {
anchorX: 0.5,
anchorY: 0.5
});
- self.width = cannon.width;
- self.height = cannon.height;
- self.shootCooldown = 0; // frames until next shot allowed
- self.lives = 3;
- self.invincible = false;
- self.invincibleTimer = 0;
- // Flash when hit
- self.flash = function () {
- tween(self, {
- alpha: 0.3
- }, {
- duration: 80,
- onFinish: function onFinish() {
- tween(self, {
- alpha: 1
- }, {
- duration: 80
- });
- }
- });
- };
- return self;
-});
-// Powerup
-var Powerup = Container.expand(function () {
- var self = Container.call(this);
- var p = self.attachAsset('powerup', {
- anchorX: 0.5,
- anchorY: 0.5
- });
- self.width = p.width;
- self.height = p.height;
- self.type = 'life'; // only one type for MVP
- self.speed = 12;
+ self.width = starGraphic.width;
+ self.height = starGraphic.height;
+ self.speed = 8 + Math.random() * 4;
+ self.rotationSpeed = 0.1 + Math.random() * 0.1;
self.update = function () {
self.y += self.speed;
+ self.rotation += self.rotationSpeed;
};
return self;
});
-// Rainbow Alien (cycles color)
-var RainbowAlien = Container.expand(function () {
- var self = Container.call(this);
- self.type = 2;
- self.isRainbow = true;
- self._rainbowTick = 0;
- self.update = function () {
- self._rainbowTick++;
- // Cycle through hues
- var hue = self._rainbowTick * 4 % 360;
- // Convert hue to rgb
- var c = hsvToRgb(hue / 360, 1, 1);
- if (self.children && self.children.length > 0 && self.children[0]) {
- self.children[0].tint = c[0] << 16 | c[1] << 8 | c[2];
- }
- };
- return self;
-});
-// Helper: HSV to RGB
-// Red Alien (2x speed)
-var RedAlien = Container.expand(function () {
- var self = Container.call(this);
- self.type = 1;
- self.speedMultiplier = 2;
- // Tint red, but only if child exists
- if (self.children && self.children.length > 0 && self.children[0]) {
- self.children[0].tint = 0xff2222;
- }
- return self;
-});
-// Target (moves around the screen)
-var Target = Container.expand(function () {
- var self = Container.call(this);
- var targetAsset = self.attachAsset('alien', {
- anchorX: 0.5,
- anchorY: 0.5
- });
- self.width = targetAsset.width;
- self.height = targetAsset.height;
- self.speedX = 18 + Math.random() * 10;
- self.speedY = 14 + Math.random() * 8;
- self.update = function () {
- // Target no longer moves or bounces by itself. All movement is handled by drag in game.move.
- };
- return self;
-});
/****
* Initialize Game
****/
@@ -245,516 +73,122 @@
/****
* Game Code
****/
-// Helper: HSV to RGB
// Game constants
-// Player cannon
-// Player bullet
-// Alien invader
-// Alien bullet
-// Power-up
-// Sound effects
-// Music
-function hsvToRgb(h, s, v) {
- var r, g, b, i, f, p, q, t;
- i = Math.floor(h * 6);
- f = h * 6 - i;
- p = v * (1 - s);
- q = v * (1 - f * s);
- t = v * (1 - (1 - f) * s);
- switch (i % 6) {
- case 0:
- r = v, g = t, b = p;
- break;
- case 1:
- r = q, g = v, b = p;
- break;
- case 2:
- r = p, g = v, b = t;
- break;
- case 3:
- r = p, g = q, b = v;
- break;
- case 4:
- r = t, g = p, b = v;
- break;
- case 5:
- r = v, g = p, b = q;
- break;
- }
- return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
-}
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2732;
-var PLAYER_Y = GAME_HEIGHT - 180;
-var PLAYER_SPEED = 36;
-var PLAYER_SHOOT_COOLDOWN = 18; // frames
-var ALIEN_ROWS = 4;
-var ALIEN_COLS = 8;
-var ALIEN_X_MARGIN = 120;
-var ALIEN_Y_MARGIN = 120;
-var ALIEN_X_SPACING = 180;
-var ALIEN_Y_SPACING = 140;
-var ALIEN_MOVE_INTERVAL = 32; // frames between moves
-var ALIEN_MOVE_STEP = 48;
-var ALIEN_DESCEND_STEP = 80;
-var ALIEN_SHOOT_CHANCE = 0.012; // per alien per move
-var ALIEN_SPEEDUP_EVERY = 6; // speed up every N moves
-var ALIEN_MIN_MOVE_INTERVAL = 10;
-var POWERUP_CHANCE = 0.08; // chance per alien death
-var POWERUP_DURATION = 600; // frames to stay on screen
-// Bomb spawn
-var bomb = null;
-var bombTimer = 0; // frames until next bomb spawn
-var BOMB_SPAWN_INTERVAL = 600; // 10 seconds at 60fps
// Game state
-// Removed the middle player cannon (player) as requested
-var playerBullets = [];
-var alienBullets = [];
-var aliens = [];
-var powerups = [];
+var ball;
+var stars = [];
var score = 0;
-// No lives for the middle cannon
-var level = 1;
-var alienMoveDir = 1; // 1: right, -1: left
-var alienMoveTimer = 0;
-var alienMoveCount = 0;
-var alienMoveInterval = ALIEN_MOVE_INTERVAL;
-var alienLeftBound = 0;
-var alienRightBound = 0;
var gameOver = false;
-var youWin = false;
-var dragNode = null;
-var lastTouchX = 0;
-var scoreTxt, livesTxt, levelTxt;
-// Music
-LK.playMusic('arcadeLoop');
+var starSpawnTimer = 0;
+var starSpawnInterval = 120; // spawn star every 2 seconds at 60fps
// GUI
-scoreTxt = new Text2('Score: 0', {
- size: 90,
+var scoreTxt = new Text2('Score: 0', {
+ size: 120,
fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
-livesTxt = new Text2('Lives: 3', {
- size: 70,
- fill: "#fff"
+var instructionTxt = new Text2('Tap to make the ball jump!', {
+ size: 80,
+ fill: 0xFFFF88
});
-livesTxt.anchor.set(0, 0);
-LK.gui.top.addChild(livesTxt);
-livesTxt.x = 120; // avoid top left menu
-levelTxt = new Text2('Level: 1', {
- size: 70,
- fill: "#fff"
-});
-levelTxt.anchor.set(1, 0);
-LK.gui.top.addChild(levelTxt);
-levelTxt.x = LK.gui.top.width - 120;
-// Add two cannons in corners
-var cannonLeft = new CannonInCorner();
-cannonLeft.corner = "left";
-cannonLeft.x = cannonLeft.width / 2 + 40;
-cannonLeft.y = GAME_HEIGHT - cannonLeft.height / 2 - 40;
-game.addChild(cannonLeft);
-var cannonRight = new CannonInCorner();
-cannonRight.corner = "right";
-cannonRight.x = GAME_WIDTH - cannonRight.width / 2 - 40;
-cannonRight.y = GAME_HEIGHT - cannonRight.height / 2 - 40;
-game.addChild(cannonRight);
-// Add moving target
-var target = new Target();
-target.x = GAME_WIDTH / 2;
-target.y = GAME_HEIGHT / 3;
-game.addChild(target);
-// For blue line blink effect
-var blueLineAlpha = 0;
-var blueLineBlinkTimer = 0;
-// Initialize aliens
-function spawnAliens() {
- aliens = [];
- var startX = (GAME_WIDTH - (ALIEN_COLS - 1) * ALIEN_X_SPACING) / 2;
- var startY = 260;
- for (var row = 0; row < ALIEN_ROWS; row++) {
- for (var col = 0; col < ALIEN_COLS; col++) {
- var alien;
- // Big aliens: first row
- if (row === 0 && col % 2 === 0) {
- alien = new BigAlien();
- }
- // Red aliens: second row
- else if (row === 1 && col % 2 === 1) {
- alien = new RedAlien();
- }
- // Rainbow aliens: third row
- else if (row === 2 && col % 3 === 0) {
- alien = new RainbowAlien();
- }
- // Default green
- else {
- alien = new Alien();
- }
- alien.x = startX + col * ALIEN_X_SPACING;
- alien.y = startY + row * ALIEN_Y_SPACING;
- alien.row = row;
- alien.col = col;
- // Ensure special aliens are not spawned under the target if blue line is active
- if (typeof target !== "undefined" && blueLineAlpha > 0 && target.x + target.width / 2 > alien.x - alien.width / 2 && target.x - target.width / 2 < alien.x + alien.width / 2 && target.y + target.height / 2 > alien.y - alien.height / 2 && target.y - target.height / 2 < alien.y + alien.height / 2) {
- alien.y += alien.height;
- }
- game.addChild(alien);
- aliens.push(alien);
- }
- }
- updateAlienBounds();
- alienMoveDir = 1;
- alienMoveTimer = 0;
- alienMoveCount = 0;
- alienMoveInterval = Math.max(ALIEN_MOVE_INTERVAL - (level - 1) * 2, ALIEN_MIN_MOVE_INTERVAL);
-}
-function updateAlienBounds() {
- if (aliens.length === 0) {
- alienLeftBound = 0;
- alienRightBound = 0;
- return;
- }
- var minX = GAME_WIDTH,
- maxX = 0;
- for (var i = 0; i < aliens.length; i++) {
- if (!aliens[i].alive) continue;
- if (aliens[i].x < minX) minX = aliens[i].x;
- if (aliens[i].x > maxX) maxX = aliens[i].x;
- }
- alienLeftBound = minX;
- alienRightBound = maxX;
-}
-// Reset game state for new game or level
-function resetGameState() {
- // Remove all bullets, aliens, powerups
- for (var i = 0; i < playerBullets.length; i++) playerBullets[i].destroy();
- for (var i = 0; i < alienBullets.length; i++) alienBullets[i].destroy();
- for (var i = 0; i < powerups.length; i++) powerups[i].destroy();
- for (var i = 0; i < aliens.length; i++) aliens[i].destroy();
- playerBullets = [];
- alienBullets = [];
- powerups = [];
- aliens = [];
- // Remove bomb if present
- if (typeof bomb !== "undefined" && bomb && bomb.destroy) {
- bomb.destroy();
- }
- bomb = null;
- bombTimer = BOMB_SPAWN_INTERVAL;
- // No middle player cannon to reset
- // Spawn aliens
- spawnAliens();
-}
-// Start first level
-resetGameState();
-// Handle player movement and shooting
+instructionTxt.anchor.set(0.5, 0.5);
+instructionTxt.x = GAME_WIDTH / 2;
+instructionTxt.y = GAME_HEIGHT / 2 - 200;
+game.addChild(instructionTxt);
+// Play music
+LK.playMusic('happyTune');
+// Create the ball
+ball = new Ball();
+ball.x = GAME_WIDTH / 2;
+ball.y = GAME_HEIGHT / 2;
+game.addChild(ball);
+// Input handling - tap anywhere to make ball jump
game.down = function (x, y, obj) {
- // Allow drag on target if touch is on target
- if (typeof target !== "undefined" && x >= target.x - target.width / 2 && x <= target.x + target.width / 2 && y >= target.y - target.height / 2 && y <= target.y + target.height / 2) {
- dragNode = target;
- lastTouchX = x;
- lastTouchY = y;
+ if (!gameOver) {
+ ball.jump();
}
};
-game.move = function (x, y, obj) {
- if (dragNode === target) {
- // Move target to finger position, clamp to screen
- target.x = x;
- target.y = y;
- if (target.x < target.width / 2) target.x = target.width / 2;
- if (target.x > GAME_WIDTH - target.width / 2) target.x = GAME_WIDTH - target.width / 2;
- if (target.y < target.height / 2 + 100) target.y = target.height / 2 + 100;
- if (target.y > GAME_HEIGHT - target.height / 2 - 200) target.y = GAME_HEIGHT - target.height / 2 - 200;
- lastTouchX = x;
- lastTouchY = y;
- // When target is moved, shoot blue lines from both cannons
- shootFromCannon(cannonLeft);
- shootFromCannon(cannonRight);
- // Blink blue line for 0.7s (42 frames at 60fps)
- blueLineAlpha = 1;
- blueLineBlinkTimer = 42;
- }
-};
-game.up = function (x, y, obj) {
- dragNode = null;
-};
-// Tap anywhere in lower half to shoot
-game.downAnywhere = function (x, y, obj) {
- if (y > GAME_HEIGHT / 2) {
- // Only shoot if not currently dragging the player (to avoid double fire)
- if (dragNode !== player) {
- // Shoot from both cannons
- shootFromCannon(cannonLeft);
- shootFromCannon(cannonRight);
- // Blink blue line for 0.7s (42 frames at 60fps)
- blueLineAlpha = 1;
- blueLineBlinkTimer = 42;
- }
- }
-};
-// Register downAnywhere
-LK.on('down', function (obj) {
- if (obj && obj.x !== undefined && obj.y !== undefined) {
- game.downAnywhere(obj.x, obj.y, obj);
- }
-});
-// Player shooting
-function tryShoot() {
- if (player.shootCooldown <= 0 && !gameOver && !youWin) {
- var bullet = new PlayerBullet();
- bullet.x = player.x;
- bullet.y = player.y - player.height / 2 - bullet.height / 2;
- playerBullets.push(bullet);
- game.addChild(bullet);
- player.shootCooldown = PLAYER_SHOOT_COOLDOWN;
- LK.getSound('shoot').play();
- }
+// Spawn a new star
+function spawnStar() {
+ var star = new Star();
+ star.x = Math.random() * (GAME_WIDTH - 200) + 100;
+ star.y = -star.height;
+ stars.push(star);
+ game.addChild(star);
}
-// Shoot from a corner cannon and blink blue line
-function shootFromCannon(cannon) {
- if (cannon.shootCooldown <= 0 && !gameOver && !youWin) {
- // No bullet, just blink blue line
- cannon.shootCooldown = PLAYER_SHOOT_COOLDOWN;
- LK.getSound('shoot').play();
- }
+// Check collision between two objects
+function checkCollision(obj1, obj2) {
+ return obj1.x + obj1.width / 2 > obj2.x - obj2.width / 2 && obj1.x - obj1.width / 2 < obj2.x + obj2.width / 2 && obj1.y + obj1.height / 2 > obj2.y - obj2.height / 2 && obj1.y - obj1.height / 2 < obj2.y + obj2.height / 2;
}
// Main game update loop
game.update = function () {
- if (gameOver || youWin) return;
- // Corner cannons shoot cooldown
- if (typeof cannonLeft !== "undefined" && cannonLeft.shootCooldown > 0) cannonLeft.shootCooldown--;
- if (typeof cannonRight !== "undefined" && cannonRight.shootCooldown > 0) cannonRight.shootCooldown--;
- // Update target
- if (typeof target !== "undefined" && target.update) target.update();
- // Blue line blink timer
- if (blueLineBlinkTimer > 0) {
- blueLineBlinkTimer--;
- blueLineAlpha = blueLineBlinkTimer % 2 === 0 ? 1 : 0.2;
- } else {
- blueLineAlpha = 0;
- }
- // No player invincibility for the middle cannon
- // No player bullets for the middle cannon
- // Move alien bullets
- for (var i = alienBullets.length - 1; i >= 0; i--) {
- var b = alienBullets[i];
- b.update();
- if (b.y > GAME_HEIGHT + b.height) {
- b.destroy();
- alienBullets.splice(i, 1);
- continue;
+ if (gameOver) return;
+ // Update ball
+ ball.update();
+ // Spawn stars
+ starSpawnTimer++;
+ if (starSpawnTimer >= starSpawnInterval) {
+ starSpawnTimer = 0;
+ spawnStar();
+ // Make stars spawn faster as score increases
+ if (starSpawnInterval > 40) {
+ starSpawnInterval -= 2;
}
- // No player collision for the middle cannon (player removed)
}
- // Move powerups
- for (var i = powerups.length - 1; i >= 0; i--) {
- var p = powerups[i];
- p.update();
- p.timer--;
- if (p.y > GAME_HEIGHT + p.height || p.timer <= 0) {
- p.destroy();
- powerups.splice(i, 1);
+ // Update stars and check collisions
+ for (var i = stars.length - 1; i >= 0; i--) {
+ var star = stars[i];
+ star.update();
+ // Check collision with ball
+ if (checkCollision(ball, star)) {
+ // Collect star
+ score += 10;
+ LK.setScore(score);
+ scoreTxt.setText('Score: ' + score);
+ LK.getSound('collect').play();
+ // Flash star before removing
+ tween(star, {
+ alpha: 0,
+ scaleX: 2,
+ scaleY: 2
+ }, {
+ duration: 200,
+ onFinish: function onFinish() {
+ star.destroy();
+ }
+ });
+ stars.splice(i, 1);
continue;
}
- // No player to collect powerup (player removed)
- }
- // Move aliens
- alienMoveTimer++;
- if (alienMoveTimer >= alienMoveInterval) {
- alienMoveTimer = 0;
- var shouldDescend = false;
- // Check if any alien at edge
- updateAlienBounds();
- if (alienMoveDir === 1 && alienRightBound + ALIEN_MOVE_STEP > GAME_WIDTH - ALIEN_X_MARGIN) {
- shouldDescend = true;
- alienMoveDir = -1;
- } else if (alienMoveDir === -1 && alienLeftBound - ALIEN_MOVE_STEP < ALIEN_X_MARGIN) {
- shouldDescend = true;
- alienMoveDir = 1;
+ // Remove stars that fall off screen
+ if (star.y > GAME_HEIGHT + star.height) {
+ star.destroy();
+ stars.splice(i, 1);
}
- for (var i = 0; i < aliens.length; i++) {
- var a = aliens[i];
- if (!a.alive) continue;
- var moveStep = ALIEN_MOVE_STEP;
- // Red aliens move 2x faster
- if (a.speedMultiplier) moveStep *= a.speedMultiplier;
- if (shouldDescend) {
- a.y += ALIEN_DESCEND_STEP;
- } else {
- a.x += moveStep * alienMoveDir;
- }
- // Rainbow aliens animate
- if (a.isRainbow && typeof a.update === "function") a.update();
- }
- if (shouldDescend) {
- // Check for game over (aliens reach player line)
- for (var i = 0; i < aliens.length; i++) {
- var a = aliens[i];
- if (!a.alive) continue;
- if (a.y + a.height / 2 >= PLAYER_Y - 40) {
- // Use a fixed margin instead of player.height/2
- triggerGameOver();
- return;
- }
- }
- }
- // Aliens shoot
- for (var i = 0; i < aliens.length; i++) {
- var a = aliens[i];
- if (!a.alive) continue;
- if (Math.random() < ALIEN_SHOOT_CHANCE) {
- var b = new AlienBullet();
- b.x = a.x;
- b.y = a.y + a.height / 2 + b.height / 2;
- alienBullets.push(b);
- game.addChild(b);
- LK.getSound('alienShoot').play();
- }
- }
- alienMoveCount++;
- // Speed up
- if (alienMoveCount % ALIEN_SPEEDUP_EVERY === 0 && alienMoveInterval > ALIEN_MIN_MOVE_INTERVAL) {
- alienMoveInterval--;
- }
}
- // --- Bomb spawn and update ---
- if (!gameOver && !youWin) {
- // Spawn bomb every 10 seconds if not present
- if (bomb == null) {
- bombTimer--;
- if (bombTimer <= 0) {
- bomb = new Bomb();
- // Spawn at random edge
- var edge = Math.floor(Math.random() * 4);
- if (edge === 0) {
- // left
- bomb.x = bomb.width / 2;
- bomb.y = 200 + Math.random() * (GAME_HEIGHT - 400);
- } else if (edge === 1) {
- // right
- bomb.x = GAME_WIDTH - bomb.width / 2;
- bomb.y = 200 + Math.random() * (GAME_HEIGHT - 400);
- } else if (edge === 2) {
- // top
- bomb.x = 200 + Math.random() * (GAME_WIDTH - 400);
- bomb.y = bomb.height / 2 + 100;
- } else {
- // bottom
- bomb.x = 200 + Math.random() * (GAME_WIDTH - 400);
- bomb.y = GAME_HEIGHT - bomb.height / 2 - 200;
- }
- game.addChild(bomb);
- bombTimer = BOMB_SPAWN_INTERVAL;
- }
- } else {
- // Update bomb
- if (bomb.update) bomb.update();
- }
+ // Keep ball in screen bounds (left/right)
+ if (ball.x - ball.width / 2 < 0) {
+ ball.x = ball.width / 2;
}
- // Kill aliens if target is on them and blue line is blinking (shooting)
- for (var i = 0; i < aliens.length; i++) {
- var a = aliens[i];
- if (!a.alive) continue;
- // Only kill if blue line is blinking (shooting) and target overlaps alien
- if (blueLineAlpha > 0 && target.x + target.width / 2 > a.x - a.width / 2 && target.x - target.width / 2 < a.x + a.width / 2 && target.y + target.height / 2 > a.y - a.height / 2 && target.y - target.height / 2 < a.y + a.height / 2) {
- // If big alien, split
- if (a.isBig && typeof a.split === "function") {
- a.split();
- }
- a.alive = false;
- a.destroy();
- score += 100;
- LK.setScore(score);
- scoreTxt.setText('Score: ' + score);
- }
- // Rainbow aliens animate even if not moving
- if (a.isRainbow && typeof a.update === "function") a.update();
+ if (ball.x + ball.width / 2 > GAME_WIDTH) {
+ ball.x = GAME_WIDTH - ball.width / 2;
}
- var aliveAliens = 0;
- for (var i = 0; i < aliens.length; i++) {
- if (aliens[i].alive) aliveAliens++;
+ // Check for game over (ball falls off bottom for too long)
+ if (ball.y > GAME_HEIGHT + 200) {
+ triggerGameOver();
}
- if (aliveAliens === 0) {
- // Next level
- level++;
- levelTxt.setText('Level: ' + level);
- resetGameState();
- }
- // Draw blue lines from both cannons to target and blink when shooting
- if (typeof target !== "undefined" && blueLineAlpha > 0) {
- // Remove previous lines if any
- if (game._blueLineLeft) {
- game._blueLineLeft.destroy();
- game._blueLineLeft = null;
- }
- if (game._blueLineRight) {
- game._blueLineRight.destroy();
- game._blueLineRight = null;
- }
- // Draw left line
- var leftLine = LK.getAsset('playerBullet', {
- anchorX: 0,
- anchorY: 0.5
- });
- var dxL = target.x - cannonLeft.x;
- var dyL = target.y - cannonLeft.y;
- var distL = Math.sqrt(dxL * dxL + dyL * dyL);
- leftLine.width = distL;
- leftLine.height = 18;
- leftLine.x = cannonLeft.x;
- leftLine.y = cannonLeft.y;
- leftLine.rotation = Math.atan2(dyL, dxL);
- leftLine.alpha = blueLineAlpha;
- leftLine.tint = 0x33aaff;
- game.addChild(leftLine);
- game._blueLineLeft = leftLine;
- // Draw right line
- var dxR = target.x - cannonRight.x;
- var dyR = target.y - cannonRight.y;
- var distR = Math.sqrt(dxR * dxR + dyR * dyR);
- var rightLine = LK.getAsset('playerBullet', {
- anchorX: 0,
- anchorY: 0.5
- });
- rightLine.width = distR;
- rightLine.height = 18;
- rightLine.x = cannonRight.x;
- rightLine.y = cannonRight.y;
- rightLine.rotation = Math.atan2(dyR, dxR);
- rightLine.alpha = blueLineAlpha;
- rightLine.tint = 0x33aaff;
- game.addChild(rightLine);
- game._blueLineRight = rightLine;
- } else {
- // Remove lines if not blinking
- if (game._blueLineLeft) {
- game._blueLineLeft.destroy();
- game._blueLineLeft = null;
- }
- if (game._blueLineRight) {
- game._blueLineRight.destroy();
- game._blueLineRight = null;
- }
- }
};
-// No loseLife or gainLife for the middle cannon
-// Game over
+// Game over function
function triggerGameOver() {
if (gameOver) return;
gameOver = true;
- LK.effects.flashScreen(0xff0000, 900);
+ LK.effects.flashScreen(0xff3333, 1000);
LK.showGameOver();
}
-// Win (not used in MVP, but for future)
-function triggerYouWin() {
- if (youWin) return;
- youWin = true;
- LK.effects.flashScreen(0x00ff00, 900);
- LK.showYouWin();
-}
// Set initial score
LK.setScore(score);
scoreTxt.setText('Score: ' + score);
\ No newline at end of file