/**** * 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(); } // --- LOGIN SCREEN OVERLAY --- var loginOverlay = new Container(); loginOverlay.zIndex = 10000; // ensure on top // Semi-transparent background var overlayBg = LK.getAsset('targetBlue', { anchorX: 0.5, anchorY: 0.5, scaleX: 20, scaleY: 20, x: 2048 / 2, y: 2732 / 2 }); overlayBg.alpha = 0.7; loginOverlay.addChild(overlayBg); // "Login" title var loginTitle = new Text2('Login', { size: 180, fill: 0xFFFFFF }); loginTitle.anchor.set(0.5, 0.5); loginTitle.x = 2048 / 2; loginTitle.y = 700; loginOverlay.addChild(loginTitle); // huzkoz a.ş text var huzkozText = new Text2('made by huzkoz a.ş', { size: 80, fill: 0xFFFFFF }); huzkozText.anchor.set(0.5, 0.5); huzkozText.x = 2048 / 2; huzkozText.y = 900; loginOverlay.addChild(huzkozText); // "Tap to Start" button var tapToStart = new Text2('Tap to Start', { size: 120, fill: 0xFFF700 }); tapToStart.anchor.set(0.5, 0.5); tapToStart.x = 2048 / 2; tapToStart.y = 1200; loginOverlay.addChild(tapToStart); // Add overlay to game game.addChild(loginOverlay); // Block game start until tap var loginActive = true; loginOverlay.down = function (x, y, obj) { if (!loginActive) return; loginActive = false; loginOverlay.destroy(); startGame(); }; // Prevent game from starting automatically // (do not call startGame() here) // 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
/****
* 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();
}
// --- LOGIN SCREEN OVERLAY ---
var loginOverlay = new Container();
loginOverlay.zIndex = 10000; // ensure on top
// Semi-transparent background
var overlayBg = LK.getAsset('targetBlue', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 20,
scaleY: 20,
x: 2048 / 2,
y: 2732 / 2
});
overlayBg.alpha = 0.7;
loginOverlay.addChild(overlayBg);
// "Login" title
var loginTitle = new Text2('Login', {
size: 180,
fill: 0xFFFFFF
});
loginTitle.anchor.set(0.5, 0.5);
loginTitle.x = 2048 / 2;
loginTitle.y = 700;
loginOverlay.addChild(loginTitle);
// huzkoz a.ş text
var huzkozText = new Text2('made by huzkoz a.ş', {
size: 80,
fill: 0xFFFFFF
});
huzkozText.anchor.set(0.5, 0.5);
huzkozText.x = 2048 / 2;
huzkozText.y = 900;
loginOverlay.addChild(huzkozText);
// "Tap to Start" button
var tapToStart = new Text2('Tap to Start', {
size: 120,
fill: 0xFFF700
});
tapToStart.anchor.set(0.5, 0.5);
tapToStart.x = 2048 / 2;
tapToStart.y = 1200;
loginOverlay.addChild(tapToStart);
// Add overlay to game
game.addChild(loginOverlay);
// Block game start until tap
var loginActive = true;
loginOverlay.down = function (x, y, obj) {
if (!loginActive) return;
loginActive = false;
loginOverlay.destroy();
startGame();
};
// Prevent game from starting automatically
// (do not call startGame() here)
// 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