/****
* Classes
****/
// Barrier class: represents a horizontal barrier at the bottom of the screen
var Barrier = Container.expand(function () {
var self = Container.call(this);
// Create a wide, short rectangle as the barrier
var barrierHeight = 120;
var barrierWidth = 2048;
var barrierAsset = self.attachAsset('box', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: barrierWidth / 200,
scaleY: barrierHeight / 200,
tint: 0x222222 // dark gray for visibility
});
self.width = barrierWidth;
self.height = barrierHeight;
return self;
});
// Box class: represents a clickable box that appears randomly on the screen
var Box = Container.expand(function () {
var self = Container.call(this);
// Attach a box asset, centered
var boxAsset = self.attachAsset('box', {
anchorX: 0.5,
anchorY: 0.5
});
// Track lastX, lastY for event transitions
self.lastX = 0;
self.lastY = 0;
self.lastWasDown = false;
// Called when the box is pressed/touched
self.down = function (x, y, obj) {
if (!self.lastWasDown) {
self.lastWasDown = true;
// Notify game that this box was clicked
if (typeof onBoxClicked === "function") {
onBoxClicked(self);
}
}
};
// Called when the box is released
self.up = function (x, y, obj) {
self.lastWasDown = false;
};
// Called every tick
self.update = function () {
// No movement, but could add animations here
};
return self;
});
// DecoyBox class: a misleading box that penalizes the player if tapped
var DecoyBox = Container.expand(function () {
var self = Container.call(this);
// Attach a box asset, but with a different color to distinguish (e.g. red)
var decoyAsset = self.attachAsset('box', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0xD83318 // Red tint for decoy
});
self.lastX = 0;
self.lastY = 0;
self.lastWasDown = false;
// Called when the decoy box is pressed/touched
self.down = function (x, y, obj) {
if (!self.lastWasDown) {
self.lastWasDown = true;
if (typeof onDecoyBoxClicked === "function") {
onDecoyBoxClicked(self);
}
}
};
self.up = function (x, y, obj) {
self.lastWasDown = false;
};
self.update = function () {};
return self;
});
/****
* Initialize Game
****/
// Core game variables
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Core game variables
var barrier = null; // The bottom barrier
var currentBox = null; // The currently visible box
var currentDecoy = null; // The currently visible decoy box
var score = 0; // Player's score
var misses = 0; // Number of missed boxes
var boxLifetime = 1200; // ms, how long a box stays visible (decreases with difficulty)
var minBoxLifetime = 500; // ms, minimum box lifetime
var boxTimer = null; // Timer for box disappearance
var decoyTimer = null; // Timer for decoy disappearance
var scoreTxt = null; // Score display
var missLimit = 3; // Number of misses before game over
// Function to handle box click (defined in Game Code)
var onBoxClicked = null;
var onDecoyBoxClicked = null;
// --- Animated background setup ---
var bgRects = [];
var bgColors = [0x1e3c72, 0x2a5298, 0x38a3a5, 0x57cc99, 0x80ed99, 0xf6f7d4];
var bgRectCount = 6;
var bgRectHeight = Math.ceil(2732 / bgRectCount);
for (var i = 0; i < bgRectCount; i++) {
var rect = LK.getAsset('box', {
anchorX: 0,
anchorY: 0,
scaleX: 2048 / 200,
scaleY: bgRectHeight / 200,
tint: bgColors[i % bgColors.length],
x: 0,
y: i * bgRectHeight
});
rect.originalTint = bgColors[i % bgColors.length];
rect.targetTint = bgColors[(i + 1) % bgColors.length];
rect.tweenTime = 0;
rect.tweenDuration = 180 + Math.floor(Math.random() * 120);
game.addChild(rect);
bgRects.push(rect);
}
// Animate background color transitions
game.update = function (origUpdate) {
return function () {
// Animate background rectangles
for (var i = 0; i < bgRects.length; i++) {
var r = bgRects[i];
r.tweenTime++;
if (r.tweenTime >= r.tweenDuration) {
r.tweenTime = 0;
r.originalTint = r.targetTint;
r.targetTint = bgColors[Math.floor(Math.random() * bgColors.length)];
r.tweenDuration = 180 + Math.floor(Math.random() * 120);
}
// Linear interpolate tint
var t = r.tweenTime / r.tweenDuration;
var ot = r.originalTint,
tt = r.targetTint;
var r1 = ot >> 16 & 0xff,
g1 = ot >> 8 & 0xff,
b1 = ot & 0xff;
var r2 = tt >> 16 & 0xff,
g2 = tt >> 8 & 0xff,
b2 = tt & 0xff;
var rMix = Math.round(r1 + (r2 - r1) * t);
var gMix = Math.round(g1 + (g2 - g1) * t);
var bMix = Math.round(b1 + (b2 - b1) * t);
r.tint = rMix << 16 | gMix << 8 | bMix;
}
if (typeof origUpdate === "function") origUpdate.call(this);
};
}(game.update);
// Utility: get a random position for the box, avoiding the top-left 100x100 area and the barrier at the bottom
function getRandomBoxPosition(boxWidth, boxHeight) {
var margin = 100;
var minX = margin + boxWidth / 2;
var maxX = 2048 - boxWidth / 2;
var minY = margin + boxHeight / 2;
// If barrier exists, keep boxes above it
var barrierHeight = barrier ? barrier.height : 120;
var barrierY = 2732 - barrierHeight / 2;
var maxY = barrierY - boxHeight / 2 - 10; // 10px gap above barrier
var x = minX + Math.random() * (maxX - minX);
var y = minY + Math.random() * (maxY - minY);
return {
x: x,
y: y
};
}
// Show a new box at a random position
function spawnBox() {
// Remove previous box if exists
if (currentBox) {
currentBox.destroy();
currentBox = null;
}
// Remove previous decoy if exists
if (currentDecoy) {
currentDecoy.destroy();
currentDecoy = null;
}
// Create new box
var box = new Box();
var boxW = box.width;
var boxH = box.height;
var pos = getRandomBoxPosition(boxW, boxH);
box.x = pos.x;
box.y = pos.y;
game.addChild(box);
currentBox = box;
// Set up timer for box disappearance
if (boxTimer) {
LK.clearTimeout(boxTimer);
}
boxTimer = LK.setTimeout(function () {
// Missed the box
if (currentBox === box) {
handleBoxMiss();
}
}, boxLifetime);
// Randomly decide to spawn a decoy box (30% chance)
if (Math.random() < 0.3) {
var decoy = new DecoyBox();
var decoyW = decoy.width;
var decoyH = decoy.height;
// Make sure decoy doesn't overlap with the real box
var tries = 0;
var decoyPos;
do {
decoyPos = getRandomBoxPosition(decoyW, decoyH);
tries++;
} while (Math.abs(decoyPos.x - box.x) < (boxW + decoyW) / 1.5 && Math.abs(decoyPos.y - box.y) < (boxH + decoyH) / 1.5 && tries < 10);
decoy.x = decoyPos.x;
decoy.y = decoyPos.y;
game.addChild(decoy);
currentDecoy = decoy;
// Decoy disappears after the same time as the box
if (decoyTimer) {
LK.clearTimeout(decoyTimer);
}
decoyTimer = LK.setTimeout(function () {
if (currentDecoy === decoy) {
currentDecoy.destroy();
currentDecoy = null;
}
}, boxLifetime);
}
}
// Handle when a box is clicked
onBoxClicked = function onBoxClicked(box) {
if (currentBox !== box) return; // Only count if it's the current box
score += 1;
updateScoreText();
// Increase difficulty: decrease box lifetime, but not below minimum
boxLifetime = Math.max(minBoxLifetime, boxLifetime - 30);
// Remove box and spawn a new one
if (boxTimer) {
LK.clearTimeout(boxTimer);
boxTimer = null;
}
if (currentBox) {
currentBox.destroy();
currentBox = null;
}
// Remove decoy if present
if (currentDecoy) {
currentDecoy.destroy();
currentDecoy = null;
}
if (decoyTimer) {
LK.clearTimeout(decoyTimer);
decoyTimer = null;
}
spawnBox();
};
// Handle when a decoy box is clicked
onDecoyBoxClicked = function onDecoyBoxClicked(decoy) {
if (currentDecoy !== decoy) return; // Only count if it's the current decoy
// Penalize: decrease score (min 0), and count as a miss
score = Math.max(0, score - 1);
misses += 1;
updateScoreText();
// Flash screen to indicate penalty
LK.effects.flashScreen(0xff0000, 400);
// Remove decoy and box
if (currentDecoy) {
currentDecoy.destroy();
currentDecoy = null;
}
if (decoyTimer) {
LK.clearTimeout(decoyTimer);
decoyTimer = null;
}
if (currentBox) {
currentBox.destroy();
currentBox = null;
}
if (boxTimer) {
LK.clearTimeout(boxTimer);
boxTimer = null;
}
// Check for game over
if (misses >= missLimit) {
LK.showGameOver();
return;
}
// Spawn next box
spawnBox();
};
// Handle when a box is missed (not clicked in time)
function handleBoxMiss() {
misses += 1;
if (currentBox) {
currentBox.destroy();
currentBox = null;
}
if (boxTimer) {
LK.clearTimeout(boxTimer);
boxTimer = null;
}
if (currentDecoy) {
currentDecoy.destroy();
currentDecoy = null;
}
if (decoyTimer) {
LK.clearTimeout(decoyTimer);
decoyTimer = null;
}
if (misses >= missLimit) {
// Game over
LK.showGameOver();
return;
}
// Show next box
spawnBox();
}
// Update the score display
function updateScoreText() {
if (scoreTxt) {
scoreTxt.setText(score + "");
}
}
// Create and add the barrier at the bottom of the screen
barrier = new Barrier();
barrier.x = 2048 / 2;
barrier.y = 2732 - barrier.height / 2;
game.addChild(barrier);
// Initialize score text UI
scoreTxt = new Text2("0", {
size: 150,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Start the game by spawning the first box
if (currentDecoy) {
currentDecoy.destroy();
currentDecoy = null;
}
if (decoyTimer) {
LK.clearTimeout(decoyTimer);
decoyTimer = null;
}
spawnBox(); ===================================================================
--- original.js
+++ change.js
@@ -103,8 +103,61 @@
var missLimit = 3; // Number of misses before game over
// Function to handle box click (defined in Game Code)
var onBoxClicked = null;
var onDecoyBoxClicked = null;
+// --- Animated background setup ---
+var bgRects = [];
+var bgColors = [0x1e3c72, 0x2a5298, 0x38a3a5, 0x57cc99, 0x80ed99, 0xf6f7d4];
+var bgRectCount = 6;
+var bgRectHeight = Math.ceil(2732 / bgRectCount);
+for (var i = 0; i < bgRectCount; i++) {
+ var rect = LK.getAsset('box', {
+ anchorX: 0,
+ anchorY: 0,
+ scaleX: 2048 / 200,
+ scaleY: bgRectHeight / 200,
+ tint: bgColors[i % bgColors.length],
+ x: 0,
+ y: i * bgRectHeight
+ });
+ rect.originalTint = bgColors[i % bgColors.length];
+ rect.targetTint = bgColors[(i + 1) % bgColors.length];
+ rect.tweenTime = 0;
+ rect.tweenDuration = 180 + Math.floor(Math.random() * 120);
+ game.addChild(rect);
+ bgRects.push(rect);
+}
+// Animate background color transitions
+game.update = function (origUpdate) {
+ return function () {
+ // Animate background rectangles
+ for (var i = 0; i < bgRects.length; i++) {
+ var r = bgRects[i];
+ r.tweenTime++;
+ if (r.tweenTime >= r.tweenDuration) {
+ r.tweenTime = 0;
+ r.originalTint = r.targetTint;
+ r.targetTint = bgColors[Math.floor(Math.random() * bgColors.length)];
+ r.tweenDuration = 180 + Math.floor(Math.random() * 120);
+ }
+ // Linear interpolate tint
+ var t = r.tweenTime / r.tweenDuration;
+ var ot = r.originalTint,
+ tt = r.targetTint;
+ var r1 = ot >> 16 & 0xff,
+ g1 = ot >> 8 & 0xff,
+ b1 = ot & 0xff;
+ var r2 = tt >> 16 & 0xff,
+ g2 = tt >> 8 & 0xff,
+ b2 = tt & 0xff;
+ var rMix = Math.round(r1 + (r2 - r1) * t);
+ var gMix = Math.round(g1 + (g2 - g1) * t);
+ var bMix = Math.round(b1 + (b2 - b1) * t);
+ r.tint = rMix << 16 | gMix << 8 | bMix;
+ }
+ if (typeof origUpdate === "function") origUpdate.call(this);
+ };
+}(game.update);
// Utility: get a random position for the box, avoiding the top-left 100x100 area and the barrier at the bottom
function getRandomBoxPosition(boxWidth, boxHeight) {
var margin = 100;
var minX = margin + boxWidth / 2;