User prompt
when the attract mode timer is up. hide the timer and prevent the timer from resetting gameplay
User prompt
when the timer restarts. remove the current timer for the attract mode. and the warning sign can now appear in the last 10 seconds. in gameplay.
User prompt
remove the timer when tapped and restart the timer when it’s time for gameplay. add the timer back too. and when tapped on the title screen without the warning sign. prevent that sign from spawning overtime and restart the timing for appear
User prompt
Please fix the bug: 'Timeout.tick error: The supplied DisplayObject must be a child of the caller' in or related to this line: 'titleText.parent.setChildIndex(warningGroup, Math.max(0, titleText.parent.getChildIndex(titleText)));' Line Number: 526
User prompt
make the warning sign go in the middle and layer it under the title and the “FRENZY” and make the warning sign BIG so it can fit in screen.
User prompt
on the final 10 second countdown. a red text says “WARNING!” and add red lines under and over the warning. and on the red lines. it also says “WARNING!” And make the text scroll on the red lines and in the middle of the red lines.
User prompt
put the timer under “FREE PLAY”
User prompt
the 60 second timer doesn’t show the developer notice. it just restarts it. and make it visible to see.
User prompt
add the timer for attract mode and gameplay.
User prompt
add a 60 second timer for the notice to pop up when timer is over
User prompt
when you complete a level. A notice popping up shows this “this is still in development! So it’s a beta. please do not get mad. I made this 40 minutes before bedtime. not my fault!” also make the text small to fit in.
User prompt
put the notice on the bottom middle.
User prompt
make the text small to fit in.
User prompt
move that spot to the middle.
User prompt
remove the development notice and add another one. using the same words.
User prompt
make the text visible.
User prompt
put on the bottom left “still in development. I will update some fridays”
User prompt
every 60 seconds. the next level starts. which mean reset the gameplay.
User prompt
after the how to play screen. reset the attract mode. but change the attract mode to gameplay. so the player can actually play instead of the AI
User prompt
after the 5 second countdown. make the attract mode (AI-CANNON that shoots invaders.) disappear.
User prompt
do the same thing with attract mode (AI-CANNON that shoots invaders.
User prompt
when a person taps before the “FRENZY” or the “Press Start! FREE PLAY” prevent those words from appearing before the text is there. And if the text is there. and the person taps after a word while another word isn’t there. that word that didn’t appear dissapears before it appears.
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// --- Bullet Setup ---
var Bullet = Container.expand(function () {
var self = Container.call(this);
var bulletSprite = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speedY = -18;
self.update = function () {
self.y += self.speedY;
// Remove if off screen
if (self.y < -100) {
self.destroy();
if (bullets.indexOf(self) !== -1) bullets.splice(bullets.indexOf(self), 1);
}
};
return self;
});
// --- Arrays to track objects ---
// --- Invader Setup ---
// Create a simple invader class
var Invader = Container.expand(function () {
var self = Container.call(this);
var invaderSprite = self.attachAsset('invader', {
anchorX: 0.5,
anchorY: 0.5
});
// Start at random X, near top
self.x = 200 + Math.random() * (2048 - 400);
self.y = 300 + Math.random() * 200;
// Move down slowly
self.speedY = 2 + Math.random() * 2;
self.update = function () {
self.y += self.speedY;
// Remove if off screen
if (self.y > 2732 + 100) {
self.destroy();
if (invaders.indexOf(self) !== -1) invaders.splice(invaders.indexOf(self), 1);
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// --- Arrays to track objects ---
var bullets = [];
var invaders = [];
// --- Development Notice (bottom middle) ---
var devNoticeText = new Text2('still in development. I will update some fridays', {
size: 38,
fill: 0xFFFF00,
align: 'center',
stroke: 0x000000,
strokeThickness: 6
});
devNoticeText.anchor.set(0.5, 1); // center bottom
// Add to bottom center of the GUI
LK.gui.bottom.addChild(devNoticeText);
var titleText = new Text2('Pixelossed Rush', {
size: 180,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 2048 / 2;
titleText.y = 2732 / 2;
game.addChild(titleText);
;
// --- Tap to Start: 5s Countdown then How to Play screen ---
var countdownActive = false;
var countdownValue = 5;
var countdownText = null;
var howToPlayText = null;
var countdownTimer = null;
var attractModeStarted = false;
// Helper to clear countdown UI
function clearCountdownUI() {
if (countdownText && countdownText.parent) countdownText.parent.removeChild(countdownText);
countdownText = null;
}
// Helper to clear How to Play UI
function clearHowToPlayUI() {
if (howToPlayText && howToPlayText.parent) howToPlayText.parent.removeChild(howToPlayText);
howToPlayText = null;
}
// Tap handler for game
game.down = function (x, y, obj) {
if (countdownActive || attractModeStarted) return;
countdownActive = true;
countdownValue = 5;
// Remove attract mode UI if present
clearHowToPlayUI();
clearCountdownUI();
// Remove title, attract, Press Start, and FREE PLAY messages if present
if (titleText && titleText.parent) titleText.parent.removeChild(titleText);
titleText = null;
if (typeof frenzyText !== "undefined" && frenzyText && frenzyText.parent) frenzyText.parent.removeChild(frenzyText);
if (typeof pressStartText !== "undefined" && pressStartText && pressStartText.parent) pressStartText.parent.removeChild(pressStartText);
if (typeof freePlayText !== "undefined" && freePlayText && freePlayText.parent) freePlayText.parent.removeChild(freePlayText);
// Prevent any of these texts from being created after tap if they weren't already present
if (typeof frenzyText === "undefined" || !frenzyText) window.frenzyTextBlocked = true;
if (typeof pressStartText === "undefined" || !pressStartText) window.pressStartTextBlocked = true;
if (typeof freePlayText === "undefined" || !freePlayText) window.freePlayTextBlocked = true;
// REMOVE ATTRACT MODE (AI) ON TAP
// Block attract mode from being created if tap occurred before attract mode creation
window.attractModeBlocked = true;
if (typeof attractMode !== "undefined") {
attractMode = false;
// Remove AI cannon if present
if (typeof cannon !== "undefined" && cannon && cannon.parent) {
cannon.parent.removeChild(cannon);
}
// Optionally clear invaders and bullets for a clean start
for (var i = invaders.length - 1; i >= 0; i--) {
if (invaders[i] && invaders[i].parent) invaders[i].parent.removeChild(invaders[i]);
invaders[i].destroy && invaders[i].destroy();
invaders.splice(i, 1);
}
for (var i = bullets.length - 1; i >= 0; i--) {
if (bullets[i] && bullets[i].parent) bullets[i].parent.removeChild(bullets[i]);
bullets[i].destroy && bullets[i].destroy();
bullets.splice(i, 1);
}
}
// Show countdown text in center
countdownText = new Text2(countdownValue + '', {
size: 220,
fill: 0xFFFF00
});
countdownText.anchor.set(0.5, 0.5);
countdownText.x = 2048 / 2;
countdownText.y = 2732 / 2;
game.addChild(countdownText);
// Start countdown timer
countdownTimer = LK.setInterval(function () {
countdownValue--;
if (countdownText) countdownText.setText(countdownValue + '');
if (countdownValue <= 0) {
LK.clearInterval(countdownTimer);
clearCountdownUI();
// Show How to Play screen
howToPlayText = new Text2('How to Play\n\nMove the cannon to shoot invaders!\nDon\'t let any escape!', {
size: 120,
fill: 0xFFFFFF,
align: 'center'
});
howToPlayText.anchor.set(0.5, 0.5);
howToPlayText.x = 2048 / 2;
howToPlayText.y = 2732 / 2;
game.addChild(howToPlayText);
// After 2s, remove How to Play and start attract mode
LK.setTimeout(function () {
clearHowToPlayUI();
attractModeStarted = true;
// Remove attract mode (AI cannon and invaders) after 5s countdown, then start real gameplay
LK.setTimeout(function () {
// Remove AI cannon if present
if (typeof cannon !== "undefined" && cannon && cannon.parent) {
cannon.parent.removeChild(cannon);
}
// Remove all invaders
for (var i = invaders.length - 1; i >= 0; i--) {
if (invaders[i] && invaders[i].parent) invaders[i].parent.removeChild(invaders[i]);
invaders[i].destroy && invaders[i].destroy();
invaders.splice(i, 1);
}
// Remove all bullets
for (var i = bullets.length - 1; i >= 0; i--) {
if (bullets[i] && bullets[i].parent) bullets[i].parent.removeChild(bullets[i]);
bullets[i].destroy && bullets[i].destroy();
bullets.splice(i, 1);
}
// End attract mode
if (typeof attractMode !== "undefined") {
attractMode = false;
}
// --- Start Real Gameplay ---
// Start/reset level timer for 60s level cycles
startLevelTimer();
// Create player cannon
var playerCannon = LK.getAsset('cannon', {
anchorX: 0.5,
anchorY: 0.5
});
playerCannon.x = 2048 / 2;
playerCannon.y = 2732 - 200;
game.addChild(playerCannon);
// Player state
var playerShootCooldown = 0;
var playerLeftBound = 120;
var playerRightBound = 2048 - 120;
// Touch drag for cannon
var dragging = false;
game.down = function (x, y, obj) {
// Only allow drag if tap is near cannon
if (Math.abs(x - playerCannon.x) < 200 && Math.abs(y - playerCannon.y) < 200) {
dragging = true;
}
};
game.move = function (x, y, obj) {
if (dragging) {
playerCannon.x = Math.max(playerLeftBound, Math.min(playerRightBound, x));
}
};
game.up = function (x, y, obj) {
dragging = false;
};
// Spawn invaders at interval
var gameplayInvaderTimer = LK.setInterval(function () {
var inv = new Invader();
invaders.push(inv);
game.addChild(inv);
}, 700);
// --- Level Timer: Reset gameplay every 60 seconds ---
var levelTimer = null;
var levelNoticeText = null;
var levelNoticeTimeout = null;
function showLevelNotice() {
// Remove previous if present
if (levelNoticeText && levelNoticeText.parent) levelNoticeText.parent.removeChild(levelNoticeText);
levelNoticeText = new Text2("this is still in development! So it’s a beta. please do not get mad. I made this 40 minutes before bedtime. not my fault!", {
size: 38,
fill: 0xFFFF00,
align: 'center',
stroke: 0x000000,
strokeThickness: 6
});
levelNoticeText.anchor.set(0.5, 0.5);
// Center of screen
levelNoticeText.x = 2048 / 2;
levelNoticeText.y = 2732 / 2;
LK.gui.center.addChild(levelNoticeText);
// Remove after 2.5 seconds
if (levelNoticeTimeout) LK.clearTimeout(levelNoticeTimeout);
levelNoticeTimeout = LK.setTimeout(function () {
if (levelNoticeText && levelNoticeText.parent) levelNoticeText.parent.removeChild(levelNoticeText);
levelNoticeText = null;
}, 2500);
}
function startLevelTimer() {
if (levelTimer) LK.clearInterval(levelTimer);
// Show the notice after 60 seconds
levelTimer = LK.setInterval(function () {
showLevelNotice();
// Reset gameplay: clear all invaders and bullets, reset player cannon position, reset score if needed, etc.
// Remove all invaders
for (var i = invaders.length - 1; i >= 0; i--) {
if (invaders[i] && invaders[i].parent) invaders[i].parent.removeChild(invaders[i]);
invaders[i].destroy && invaders[i].destroy();
invaders.splice(i, 1);
}
// Remove all bullets
for (var i = bullets.length - 1; i >= 0; i--) {
if (bullets[i] && bullets[i].parent) bullets[i].parent.removeChild(bullets[i]);
bullets[i].destroy && bullets[i].destroy();
bullets.splice(i, 1);
}
// Reset player cannon position if it exists
if (typeof playerCannon !== "undefined" && playerCannon) {
playerCannon.x = 2048 / 2;
playerCannon.y = 2732 - 200;
}
// Optionally: reset playerShootCooldown
if (typeof playerShootCooldown !== "undefined") playerShootCooldown = 0;
// Optionally: you can increase difficulty here (e.g. decrease invader spawn interval, increase speed, etc.)
}, 60000); // 60 seconds
}
// Main update loop for gameplay
game.update = function () {
// Player shooting (auto-fire)
playerShootCooldown--;
if (playerShootCooldown <= 0) {
// Shoot bullet
var bullet = new Bullet();
bullet.x = playerCannon.x;
bullet.y = playerCannon.y - 60;
bullets.push(bullet);
game.addChild(bullet);
playerShootCooldown = 18;
}
// Update bullets
for (var b = bullets.length - 1; b >= 0; b--) {
var bullet = bullets[b];
if (bullet.update) bullet.update();
// Check collision with invaders
for (var j = invaders.length - 1; j >= 0; j--) {
var inv = invaders[j];
if (bullet.intersects(inv)) {
bullet.destroy();
inv.destroy();
bullets.splice(b, 1);
invaders.splice(j, 1);
break;
}
}
}
// Update invaders
for (var i = invaders.length - 1; i >= 0; i--) {
if (invaders[i].update) invaders[i].update();
// If any invader escapes, end game and show game over
if (invaders[i].y > 2732 + 100) {
LK.showGameOver();
break;
}
}
};
}, 5000);
}, 2000);
}
}, 1000);
};
// Add FRENZY title after 2 seconds with upward tween animation, positioned under the main title
// Expose to global scope for removal
var frenzyText = null;
var pressStartText = null;
var freePlayText = null;
LK.setTimeout(function () {
// Block FRENZY, Press Start, and FREE PLAY if tap occurred before their creation
if (window.frenzyTextBlocked) {
frenzyText = null;
} else {
frenzyText = new Text2('FRENZY', {
size: 200,
fill: 0xFFFFFF
});
frenzyText.anchor.set(0.5, 0.5);
frenzyText.x = 2048 / 2;
// Start below the main title, animate up to just under the main title
var spacing = 120;
var targetY;
if (titleText) {
targetY = titleText.y + titleText.height / 2 + frenzyText.height / 2 + spacing;
} else {
// Fallback: center of screen + some offset if titleText is gone
targetY = 2732 / 2 + 200 + frenzyText.height / 2 + spacing;
}
frenzyText.y = targetY + 200;
game.addChild(frenzyText);
// Animate the title going up to its target position
tween(frenzyText, {
y: targetY
}, {
duration: 900,
easing: tween.easeOut
});
}
if (window.pressStartTextBlocked) {
pressStartText = null;
} else {
// Add "Press Start!" message at the top of the screen
pressStartText = new Text2('Press Start!', {
size: 120,
fill: 0xFFFF00
});
pressStartText.anchor.set(0.5, 0);
// Centered horizontally, top of screen (leave 40px margin for safety)
pressStartText.x = 2048 / 2;
pressStartText.y = 40;
game.addChild(pressStartText);
}
if (window.freePlayTextBlocked) {
freePlayText = null;
} else {
// Add "FREE PLAY" message below "Press Start!" at the top
freePlayText = new Text2('FREE PLAY', {
size: 90,
fill: 0x00FF00
});
freePlayText.anchor.set(0.5, 0);
// Centered horizontally, just below "Press Start!"
freePlayText.x = 2048 / 2;
freePlayText.y = pressStartText && pressStartText.y ? pressStartText.y + pressStartText.height + 20 : 40 + 120 + 20;
game.addChild(freePlayText);
}
}, 2000);
;
// Attract mode: start after FRENZY appears (2s + animation ~1s)
LK.setTimeout(function () {
// Block attract mode if tap occurred before attract mode creation
if (window.attractModeBlocked) return;
// --- Attract Mode State ---
var attractMode = true;
// --- Cannon Setup ---
// Create a cannon asset (box shape, centered at bottom)
var cannon = LK.getAsset('cannon', {
anchorX: 0.5,
anchorY: 0.5
});
// Place cannon at bottom center
cannon.x = 2048 / 2;
cannon.y = 2732 - 200;
game.addChild(cannon);
// --- Arrays to track objects ---
// --- Spawn Invaders ---
var invaderTimer = LK.setInterval(function () {
if (!attractMode) return;
var inv = new Invader();
invaders.push(inv);
game.addChild(inv);
}, 700);
// --- Cannon AI movement ---
var cannonDir = 1; // 1 = right, -1 = left
var cannonSpeed = 16;
var leftBound = 120;
var rightBound = 2048 - 120;
// For shooting
var shootCooldown = 0;
// --- Attract Mode Timer: Only reset attract mode every 60s (no developer notice) ---
// Add a visible countdown timer under the FREE PLAY text
var attractCountdownValue = 60;
var attractCountdownText = new Text2(attractCountdownValue + "s", {
size: 80,
fill: 0xFFFF00,
align: 'center',
stroke: 0x000000,
strokeThickness: 6
});
attractCountdownText.anchor.set(0.5, 0);
// Place under FREE PLAY if it exists, else fallback to top center
if (typeof freePlayText !== "undefined" && freePlayText && freePlayText.parent) {
attractCountdownText.x = freePlayText.x;
attractCountdownText.y = freePlayText.y + freePlayText.height + 10;
game.addChild(attractCountdownText);
} else {
// fallback: top center
attractCountdownText.x = 2048 / 2;
attractCountdownText.y = 40 + 120 + 20 + 90 + 10; // same as FREE PLAY default + 10px
game.addChild(attractCountdownText);
}
function resetAttractCountdown() {
attractCountdownValue = 60;
if (attractCountdownText) attractCountdownText.setText(attractCountdownValue + "s");
}
var attractCountdownInterval = LK.setInterval(function () {
attractCountdownValue--;
if (attractCountdownText) attractCountdownText.setText(attractCountdownValue + "s");
if (attractCountdownValue <= 0) {
resetAttractCountdown();
// Reset attract mode: clear all invaders and bullets, reset cannon position
for (var i = invaders.length - 1; i >= 0; i--) {
if (invaders[i] && invaders[i].parent) invaders[i].parent.removeChild(invaders[i]);
invaders[i].destroy && invaders[i].destroy();
invaders.splice(i, 1);
}
for (var i = bullets.length - 1; i >= 0; i--) {
if (bullets[i] && bullets[i].parent) bullets[i].parent.removeChild(bullets[i]);
bullets[i].destroy && bullets[i].destroy();
bullets.splice(i, 1);
}
if (typeof cannon !== "undefined" && cannon) {
cannon.x = 2048 / 2;
cannon.y = 2732 - 200;
}
// Optionally: reset shootCooldown
shootCooldown = 0;
}
}, 1000); // every second
// When attract mode ends, remove the countdown text and interval
function clearAttractCountdown() {
if (attractCountdownInterval) LK.clearInterval(attractCountdownInterval);
if (attractCountdownText && attractCountdownText.parent) attractCountdownText.parent.removeChild(attractCountdownText);
attractCountdownText = null;
}
// --- Main update loop for attract mode ---
game.update = function () {
if (!attractMode) return;
// --- AI Cannon Movement: Prioritize intercepting invaders about to escape ---
// Find invader closest to bottom (about to escape)
var escapeInvader = null;
var maxY = -99999;
for (var i = 0; i < invaders.length; i++) {
if (invaders[i].y > maxY) {
maxY = invaders[i].y;
escapeInvader = invaders[i];
}
}
// If any invader is close to escaping (e.g. y > 2732-350), target it
var targetInvader = null;
if (escapeInvader && escapeInvader.y > 2732 - 350) {
targetInvader = escapeInvader;
} else {
// Otherwise, target nearest in X as before
var nearest = null;
var minDist = 99999;
for (var i = 0; i < invaders.length; i++) {
var dx = Math.abs(invaders[i].x - cannon.x);
if (dx < minDist) {
minDist = dx;
nearest = invaders[i];
}
}
targetInvader = nearest;
}
// Move cannon toward target invader, but not instantly
if (targetInvader) {
var dx = targetInvader.x - cannon.x;
// Move at most cannonSpeed per frame, but slow down as it gets close
if (Math.abs(dx) > 10) {
cannon.x += Math.sign(dx) * Math.min(cannonSpeed, Math.abs(dx));
}
}
// Clamp cannon within bounds
if (cannon.x > rightBound) cannon.x = rightBound;
if (cannon.x < leftBound) cannon.x = leftBound;
// --- AI Cannon Shooting: Shoot at escaping invaders with higher priority ---
shootCooldown--;
var shouldShoot = false;
if (shootCooldown <= 0 && invaders.length > 0 && targetInvader) {
// If targeting an escaping invader, shoot if aligned in X
if (escapeInvader && escapeInvader === targetInvader && Math.abs(cannon.x - targetInvader.x) < 120) {
// 98% chance to shoot at escaping invader
if (Math.random() < 0.98) shouldShoot = true;
} else if (Math.abs(cannon.x - targetInvader.x) < 120) {
// 80% chance to shoot at other invaders
if (Math.random() < 0.8) shouldShoot = true;
}
if (shouldShoot) {
var bullet = new Bullet();
bullet.x = cannon.x;
bullet.y = cannon.y - 60;
bullets.push(bullet);
game.addChild(bullet);
}
// Randomize next cooldown (faster or slower)
shootCooldown = 18 + Math.floor(Math.random() * 18);
}
// Update bullets
for (var b = bullets.length - 1; b >= 0; b--) {
var bullet = bullets[b];
if (bullet.update) bullet.update();
// Check collision with invaders
for (var j = invaders.length - 1; j >= 0; j--) {
var inv = invaders[j];
if (bullet.intersects(inv)) {
// Destroy both
bullet.destroy();
inv.destroy();
bullets.splice(b, 1);
invaders.splice(j, 1);
break;
}
}
}
// Update invaders
for (var i = invaders.length - 1; i >= 0; i--) {
if (invaders[i].update) invaders[i].update();
// If any invader escapes, end attract mode and show game over
if (invaders[i].y > 2732 + 100) {
attractMode = false;
LK.showGameOver();
break;
}
}
};
}, 3000); // 2s for FRENZY + 1s for animation
; ===================================================================
--- original.js
+++ change.js
@@ -421,9 +421,9 @@
var rightBound = 2048 - 120;
// For shooting
var shootCooldown = 0;
// --- Attract Mode Timer: Only reset attract mode every 60s (no developer notice) ---
- // Add a visible countdown timer at the top center
+ // Add a visible countdown timer under the FREE PLAY text
var attractCountdownValue = 60;
var attractCountdownText = new Text2(attractCountdownValue + "s", {
size: 80,
fill: 0xFFFF00,
@@ -431,9 +431,19 @@
stroke: 0x000000,
strokeThickness: 6
});
attractCountdownText.anchor.set(0.5, 0);
- LK.gui.top.addChild(attractCountdownText);
+ // Place under FREE PLAY if it exists, else fallback to top center
+ if (typeof freePlayText !== "undefined" && freePlayText && freePlayText.parent) {
+ attractCountdownText.x = freePlayText.x;
+ attractCountdownText.y = freePlayText.y + freePlayText.height + 10;
+ game.addChild(attractCountdownText);
+ } else {
+ // fallback: top center
+ attractCountdownText.x = 2048 / 2;
+ attractCountdownText.y = 40 + 120 + 20 + 90 + 10; // same as FREE PLAY default + 10px
+ game.addChild(attractCountdownText);
+ }
function resetAttractCountdown() {
attractCountdownValue = 60;
if (attractCountdownText) attractCountdownText.setText(attractCountdownValue + "s");
}