/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Target class: a tappable, animated target
var Target = Container.expand(function () {
var self = Container.call(this);
// Pick a random color for the target
var colorIds = ['targetRed', 'targetBlue', 'targetGreen', 'targetYellow'];
var colorId = colorIds[Math.floor(Math.random() * colorIds.length)];
// Attach the asset, anchor at center
var targetAsset = self.attachAsset(colorId, {
anchorX: 0.5,
anchorY: 0.5
});
// For animation (pop in)
targetAsset.scaleX = 0.7;
targetAsset.scaleY = 0.7;
tween(targetAsset, {
scaleX: 1,
scaleY: 1
}, {
duration: 120,
easing: tween.easeOut
});
// Mark as not yet tapped
self.tapped = false;
// Called when the target is tapped
self.down = function (x, y, obj) {
if (self.tapped) return;
self.tapped = true;
// Animate: shrink and fade out
tween(targetAsset, {
scaleX: 1.3,
scaleY: 1.3,
alpha: 0
}, {
duration: 120,
easing: tween.easeIn,
onFinish: function onFinish() {
self.destroy();
}
});
// Play pop sound
LK.getSound('pop').play();
// Increase score
LK.setScore(LK.getScore() + 1);
scoreTxt.setText(LK.getScore());
// Spawn next target immediately
spawnNextTarget();
};
// For missed detection
self.missed = false;
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x181818
});
/****
* Game Code
****/
// Targets: Large, colorful circles
// Score display
var scoreTxt = new Text2('0', {
size: 150,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Timer display
var timerTxt = new Text2('30', {
size: 90,
fill: 0xFFF700
});
timerTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(timerTxt);
timerTxt.y = 160;
// Misses display (hearts)
var missesTxt = new Text2('❤❤❤', {
size: 90,
fill: 0xFF3B30
});
missesTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(missesTxt);
missesTxt.y = 260;
// Game state variables
var currentTarget = null;
var misses = 0;
var maxMisses = 3;
var timeLeft = 30.0; // seconds
var targetTimeout = null;
var timerInterval = null;
var targetMinTime = 0.7; // seconds
var targetMaxTime = 1.3; // seconds
var minTargetTime = 0.4; // seconds (minimum as game speeds up)
var speedupEvery = 5; // every 5 points, speed up
var speedupAmount = 0.08; // decrease max/min time by this much
// Helper: spawn a new target at a random position
function spawnNextTarget() {
// If game is over, do not spawn
if (misses >= maxMisses || timeLeft <= 0) return;
// Remove previous target if still present
if (currentTarget && !currentTarget.tapped) {
// Missed!
currentTarget.missed = true;
currentTarget.destroy();
misses += 1;
updateMissesDisplay();
// Flash screen red
LK.effects.flashScreen(0xff3b30, 200);
if (misses >= maxMisses) {
LK.showGameOver();
return;
}
}
// Calculate speedup
var score = LK.getScore();
var speedups = Math.floor(score / speedupEvery);
var minTime = Math.max(targetMinTime - speedups * speedupAmount, minTargetTime);
var maxTime = Math.max(targetMaxTime - speedups * speedupAmount, minTargetTime + 0.2);
// Create new target
var target = new Target();
// Random position, avoid edges (target is 220x220, keep 120px margin)
var margin = 120;
var x = margin + Math.random() * (2048 - 2 * margin);
var y = margin + 200 + Math.random() * (2732 - 2 * margin - 400); // avoid top GUI
target.x = x;
target.y = y;
// Add to game
game.addChild(target);
currentTarget = target;
// Set up timeout for missing the target
if (targetTimeout) LK.clearTimeout(targetTimeout);
var targetTime = minTime + Math.random() * (maxTime - minTime);
targetTimeout = LK.setTimeout(function () {
// If not tapped, count as miss and spawn next
if (!target.tapped && !target.missed) {
target.missed = true;
target.destroy();
misses += 1;
updateMissesDisplay();
LK.effects.flashScreen(0xff3b30, 200);
if (misses >= maxMisses) {
LK.showGameOver();
return;
}
spawnNextTarget();
}
}, targetTime * 1000);
}
// Update misses display (hearts)
function updateMissesDisplay() {
var hearts = '';
for (var i = 0; i < maxMisses - misses; i++) hearts += '❤';
for (var i = 0; i < misses; i++) hearts += '♡';
missesTxt.setText(hearts);
}
// Timer logic
function startTimer() {
if (timerInterval) LK.clearInterval(timerInterval);
timerInterval = LK.setInterval(function () {
timeLeft -= 0.1;
if (timeLeft < 0) timeLeft = 0;
timerTxt.setText(Math.ceil(timeLeft));
if (timeLeft <= 0) {
// End game
if (targetTimeout) LK.clearTimeout(targetTimeout);
LK.showGameOver();
}
}, 100);
}
// Game start/reset logic
function startGame() {
LK.setScore(0);
scoreTxt.setText('0');
misses = 0;
updateMissesDisplay();
timeLeft = 30.0;
timerTxt.setText('30');
if (currentTarget) {
currentTarget.destroy();
currentTarget = null;
}
if (targetTimeout) LK.clearTimeout(targetTimeout);
startTimer();
spawnNextTarget();
}
// Start the game on load
startGame();
// On game over, reset everything (LK will re-init Game, but for safety)
game.on('gameover', function () {
if (targetTimeout) LK.clearTimeout(targetTimeout);
if (timerInterval) LK.clearInterval(timerInterval);
if (currentTarget) currentTarget.destroy();
});
// On you win (not used in this version, but for future)
game.on('youwin', function () {
if (targetTimeout) LK.clearTimeout(targetTimeout);
if (timerInterval) LK.clearInterval(timerInterval);
if (currentTarget) currentTarget.destroy();
});
// Prevent accidental drag (no drag logic needed)
game.move = function (x, y, obj) {};
// Prevent tap-through on GUI
scoreTxt.down = function () {};
timerTxt.down = function () {};
missesTxt.down = function () {};
// No update loop needed, all logic is event/timer based ===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,217 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+
+/****
+* Classes
+****/
+// Target class: a tappable, animated target
+var Target = Container.expand(function () {
+ var self = Container.call(this);
+ // Pick a random color for the target
+ var colorIds = ['targetRed', 'targetBlue', 'targetGreen', 'targetYellow'];
+ var colorId = colorIds[Math.floor(Math.random() * colorIds.length)];
+ // Attach the asset, anchor at center
+ var targetAsset = self.attachAsset(colorId, {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ // For animation (pop in)
+ targetAsset.scaleX = 0.7;
+ targetAsset.scaleY = 0.7;
+ tween(targetAsset, {
+ scaleX: 1,
+ scaleY: 1
+ }, {
+ duration: 120,
+ easing: tween.easeOut
+ });
+ // Mark as not yet tapped
+ self.tapped = false;
+ // Called when the target is tapped
+ self.down = function (x, y, obj) {
+ if (self.tapped) return;
+ self.tapped = true;
+ // Animate: shrink and fade out
+ tween(targetAsset, {
+ scaleX: 1.3,
+ scaleY: 1.3,
+ alpha: 0
+ }, {
+ duration: 120,
+ easing: tween.easeIn,
+ onFinish: function onFinish() {
+ self.destroy();
+ }
+ });
+ // Play pop sound
+ LK.getSound('pop').play();
+ // Increase score
+ LK.setScore(LK.getScore() + 1);
+ scoreTxt.setText(LK.getScore());
+ // Spawn next target immediately
+ spawnNextTarget();
+ };
+ // For missed detection
+ self.missed = false;
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0x181818
+});
+
+/****
+* Game Code
+****/
+// Targets: Large, colorful circles
+// Score display
+var scoreTxt = new Text2('0', {
+ size: 150,
+ fill: 0xFFFFFF
+});
+scoreTxt.anchor.set(0.5, 0);
+LK.gui.top.addChild(scoreTxt);
+// Timer display
+var timerTxt = new Text2('30', {
+ size: 90,
+ fill: 0xFFF700
+});
+timerTxt.anchor.set(0.5, 0);
+LK.gui.top.addChild(timerTxt);
+timerTxt.y = 160;
+// Misses display (hearts)
+var missesTxt = new Text2('❤❤❤', {
+ size: 90,
+ fill: 0xFF3B30
+});
+missesTxt.anchor.set(0.5, 0);
+LK.gui.top.addChild(missesTxt);
+missesTxt.y = 260;
+// Game state variables
+var currentTarget = null;
+var misses = 0;
+var maxMisses = 3;
+var timeLeft = 30.0; // seconds
+var targetTimeout = null;
+var timerInterval = null;
+var targetMinTime = 0.7; // seconds
+var targetMaxTime = 1.3; // seconds
+var minTargetTime = 0.4; // seconds (minimum as game speeds up)
+var speedupEvery = 5; // every 5 points, speed up
+var speedupAmount = 0.08; // decrease max/min time by this much
+// Helper: spawn a new target at a random position
+function spawnNextTarget() {
+ // If game is over, do not spawn
+ if (misses >= maxMisses || timeLeft <= 0) return;
+ // Remove previous target if still present
+ if (currentTarget && !currentTarget.tapped) {
+ // Missed!
+ currentTarget.missed = true;
+ currentTarget.destroy();
+ misses += 1;
+ updateMissesDisplay();
+ // Flash screen red
+ LK.effects.flashScreen(0xff3b30, 200);
+ if (misses >= maxMisses) {
+ LK.showGameOver();
+ return;
+ }
+ }
+ // Calculate speedup
+ var score = LK.getScore();
+ var speedups = Math.floor(score / speedupEvery);
+ var minTime = Math.max(targetMinTime - speedups * speedupAmount, minTargetTime);
+ var maxTime = Math.max(targetMaxTime - speedups * speedupAmount, minTargetTime + 0.2);
+ // Create new target
+ var target = new Target();
+ // Random position, avoid edges (target is 220x220, keep 120px margin)
+ var margin = 120;
+ var x = margin + Math.random() * (2048 - 2 * margin);
+ var y = margin + 200 + Math.random() * (2732 - 2 * margin - 400); // avoid top GUI
+ target.x = x;
+ target.y = y;
+ // Add to game
+ game.addChild(target);
+ currentTarget = target;
+ // Set up timeout for missing the target
+ if (targetTimeout) LK.clearTimeout(targetTimeout);
+ var targetTime = minTime + Math.random() * (maxTime - minTime);
+ targetTimeout = LK.setTimeout(function () {
+ // If not tapped, count as miss and spawn next
+ if (!target.tapped && !target.missed) {
+ target.missed = true;
+ target.destroy();
+ misses += 1;
+ updateMissesDisplay();
+ LK.effects.flashScreen(0xff3b30, 200);
+ if (misses >= maxMisses) {
+ LK.showGameOver();
+ return;
+ }
+ spawnNextTarget();
+ }
+ }, targetTime * 1000);
+}
+// Update misses display (hearts)
+function updateMissesDisplay() {
+ var hearts = '';
+ for (var i = 0; i < maxMisses - misses; i++) hearts += '❤';
+ for (var i = 0; i < misses; i++) hearts += '♡';
+ missesTxt.setText(hearts);
+}
+// Timer logic
+function startTimer() {
+ if (timerInterval) LK.clearInterval(timerInterval);
+ timerInterval = LK.setInterval(function () {
+ timeLeft -= 0.1;
+ if (timeLeft < 0) timeLeft = 0;
+ timerTxt.setText(Math.ceil(timeLeft));
+ if (timeLeft <= 0) {
+ // End game
+ if (targetTimeout) LK.clearTimeout(targetTimeout);
+ LK.showGameOver();
+ }
+ }, 100);
+}
+// Game start/reset logic
+function startGame() {
+ LK.setScore(0);
+ scoreTxt.setText('0');
+ misses = 0;
+ updateMissesDisplay();
+ timeLeft = 30.0;
+ timerTxt.setText('30');
+ if (currentTarget) {
+ currentTarget.destroy();
+ currentTarget = null;
+ }
+ if (targetTimeout) LK.clearTimeout(targetTimeout);
+ startTimer();
+ spawnNextTarget();
+}
+// Start the game on load
+startGame();
+// On game over, reset everything (LK will re-init Game, but for safety)
+game.on('gameover', function () {
+ if (targetTimeout) LK.clearTimeout(targetTimeout);
+ if (timerInterval) LK.clearInterval(timerInterval);
+ if (currentTarget) currentTarget.destroy();
+});
+// On you win (not used in this version, but for future)
+game.on('youwin', function () {
+ if (targetTimeout) LK.clearTimeout(targetTimeout);
+ if (timerInterval) LK.clearInterval(timerInterval);
+ if (currentTarget) currentTarget.destroy();
+});
+// Prevent accidental drag (no drag logic needed)
+game.move = function (x, y, obj) {};
+// Prevent tap-through on GUI
+scoreTxt.down = function () {};
+timerTxt.down = function () {};
+missesTxt.down = function () {};
+// No update loop needed, all logic is event/timer based
\ No newline at end of file