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
****/
// Alien Invader (base)
var Alien = Container.expand(function () {
var self = Container.call(this);
var alien = self.attachAsset('alien', {
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.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;
game.addChild(newAlien);
aliens.push(newAlien);
}
};
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;
self.y += self.speedY;
// Bounce off left/right
if (self.x < self.width / 2) {
self.x = self.width / 2;
self.speedX *= -1;
}
if (self.x > GAME_WIDTH - self.width / 2) {
self.x = GAME_WIDTH - self.width / 2;
self.speedX *= -1;
}
// 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;
};
return self;
});
// Player Cannon
var PlayerCannon = Container.expand(function () {
var self = Container.call(this);
var cannon = self.attachAsset('playerCannon', {
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.update = function () {
self.y += self.speed;
};
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);
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
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
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* 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 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');
// GUI
scoreTxt = new Text2('Score: 0', {
size: 90,
fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
livesTxt = new Text2('Lives: 3', {
size: 70,
fill: "#fff"
});
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;
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
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;
}
};
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();
}
}
// 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();
}
}
// 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;
}
// 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);
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;
}
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();
}
}
// 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();
}
var aliveAliens = 0;
for (var i = 0; i < aliens.length; i++) {
if (aliens[i].alive) aliveAliens++;
}
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
function triggerGameOver() {
if (gameOver) return;
gameOver = true;
LK.effects.flashScreen(0xff0000, 900);
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); ===================================================================
--- original.js
+++ change.js
@@ -5,9 +5,9 @@
/****
* Classes
****/
-// Alien Invader
+// Alien Invader (base)
var Alien = Container.expand(function () {
var self = Container.call(this);
var alien = self.attachAsset('alien', {
anchorX: 0.5,
@@ -16,11 +16,15 @@
self.width = alien.width;
self.height = alien.height;
self.row = 0;
self.col = 0;
- self.type = 0; // for future: different types
+ 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 () {
@@ -36,8 +40,33 @@
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;
+ game.addChild(newAlien);
+ aliens.push(newAlien);
+ }
+ };
+ 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', {
@@ -153,8 +182,34 @@
self.y += self.speed;
};
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);
+ 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
+ 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', {
@@ -180,16 +235,46 @@
/****
* 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;
@@ -280,9 +365,25 @@
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 = new Alien();
+ 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;
@@ -462,13 +563,18 @@
}
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 += ALIEN_MOVE_STEP * alienMoveDir;
+ 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++) {
@@ -539,14 +645,20 @@
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();
}
var aliveAliens = 0;
for (var i = 0; i < aliens.length; i++) {
if (aliens[i].alive) aliveAliens++;