User prompt
If they lose the steak it should still maintain the remaining targets, the game cleanup should only happen if they actually lose
User prompt
If player is on a streak they lose the steak but the game should not end, they just lose the streak. If the player is not on a streak the game ends when they miss.
User prompt
The needle asset is off by 90 degrees
User prompt
The needle is off by 90 degrees
User prompt
The targets are outside the clock now....
User prompt
Either the position of the targets or the needed point might be wrong because I tap exactly on target and it misses
User prompt
The calculation to check if the needle aligns with the targets might be wrong... Fix
Code edit (1 edits merged)
Please save this source code
User prompt
Perfect Tick
Initial prompt
Make the simplest most addictive game you can think of. The concept should be super super simple. ignore most of the previous prompts and just think freely before outputting, it should think step by step, do a bunch of ideation before. Create at list 10 ideas before, and weight in on the mechanics etc do an actual detailed analysis for virality, like single tap or simple control, one mechanic, is best. Come up with something really solid after all the ideas and output that in the requested format.
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { highScore: 0, level: 1 }); /**** * Classes ****/ var ClockNeedle = Container.expand(function () { var self = Container.call(this); var needleGraphics = self.attachAsset('needle', { anchorX: 0.5, anchorY: 1.0, width: 10, height: 500 }); self.angle = 0; self.speed = 1; self.direction = 1; // 1 clockwise, -1 counterclockwise self.randomizeBehavior = false; self.behaviorChangeTimer = 0; self.update = function () { // Rotate the needle self.angle += self.speed * self.direction; // Keep angle between 0-360 if (self.angle >= 360) { self.angle -= 360; } else if (self.angle < 0) { self.angle += 360; } // Update the needle rotation self.rotation = (self.angle + 90) * (Math.PI / 180); // Random behavior changes if enabled if (self.randomizeBehavior && self.behaviorChangeTimer <= 0) { var randomChange = Math.random(); if (randomChange < 0.3) { // Change direction self.direction *= -1; } else if (randomChange < 0.6) { // Change speed (between 0.5 and 2.5) self.speed = 0.5 + Math.random() * 2; } // Set new timer for next behavior change (2-6 seconds) self.behaviorChangeTimer = 120 + Math.floor(Math.random() * 240); } if (self.behaviorChangeTimer > 0) { self.behaviorChangeTimer--; } }; self.setSpeed = function (newSpeed) { self.speed = newSpeed; }; self.enableRandomBehavior = function () { self.randomizeBehavior = true; }; self.disableRandomBehavior = function () { self.randomizeBehavior = false; self.direction = 1; self.speed = 1; }; return self; }); var Target = Container.expand(function (angle, distance) { var self = Container.call(this); var targetGraphics = self.attachAsset('target', { anchorX: 0.5, anchorY: 0.5, width: 60, height: 60 }); self.angle = angle || 0; self.distance = distance || 400; self.active = true; self.hit = false; // Calculate position based on angle and distance self.updatePosition = function () { var radian = self.angle * (Math.PI / 180); self.x = Math.cos(radian) * self.distance; self.y = Math.sin(radian) * self.distance; }; self.markHit = function () { if (!self.active) { return; } self.hit = true; self.active = false; // Replace target with hit effect targetGraphics.destroy(); var hitEffect = self.attachAsset('targetHit', { anchorX: 0.5, anchorY: 0.5, width: 80, height: 80 }); // Animate hit effect tween(hitEffect, { alpha: 0, scaleX: 1.5, scaleY: 1.5 }, { duration: 500, easing: tween.easeOut, onFinish: function onFinish() { // Target stays visible but faded tween(hitEffect, { alpha: 0.3, scaleX: 1, scaleY: 1 }, { duration: 300 }); } }); }; self.markMiss = function () { if (!self.active) { return; } self.active = false; // Replace target with miss effect targetGraphics.destroy(); var missEffect = self.attachAsset('targetMiss', { anchorX: 0.5, anchorY: 0.5, width: 80, height: 80 }); // Animate miss effect tween(missEffect, { alpha: 0 }, { duration: 800, easing: tween.easeOut }); }; self.reset = function () { self.active = true; self.hit = false; if (targetGraphics.parent) { targetGraphics.destroy(); } targetGraphics = self.attachAsset('target', { anchorX: 0.5, anchorY: 0.5, width: 60, height: 60 }); }; // Initialize position self.updatePosition(); return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x121212 }); /**** * Game Code ****/ // Game state variables var score = 0; var currentStreak = 0; var multiplier = 1; var level = storage.level || 1; var highScore = storage.highScore || 0; var targets = []; var needle = null; var clockFace = null; var clockCenter = null; var isGameStarted = false; var targetCount = 0; // UI elements var scoreTxt = new Text2('0', { size: 120, fill: 0xFFFFFF }); var streakTxt = new Text2('Streak: 0', { size: 60, fill: 0xFFFFFF }); var multiplierTxt = new Text2('x1', { size: 80, fill: 0xFFCC00 }); var levelTxt = new Text2('Level 1', { size: 60, fill: 0xFFFFFF }); var highScoreTxt = new Text2('High Score: 0', { size: 40, fill: 0xAAAAAA }); var instructionTxt = new Text2('Tap when the needle hits a target!', { size: 60, fill: 0xFFFFFF }); // Position UI elements scoreTxt.anchor.set(0.5, 0); scoreTxt.y = 100; LK.gui.top.addChild(scoreTxt); streakTxt.anchor.set(0.5, 0); streakTxt.y = 220; LK.gui.top.addChild(streakTxt); multiplierTxt.anchor.set(0.5, 0); multiplierTxt.y = 280; LK.gui.top.addChild(multiplierTxt); levelTxt.anchor.set(0.5, 1); levelTxt.y = -40; LK.gui.bottom.addChild(levelTxt); highScoreTxt.anchor.set(0.5, 1); highScoreTxt.y = -100; LK.gui.bottom.addChild(highScoreTxt); instructionTxt.anchor.set(0.5, 0.5); LK.gui.center.addChild(instructionTxt); // Function to initialize the game function initGame() { // Create clock face clockFace = LK.getAsset('clockFace', { anchorX: 0.5, anchorY: 0.5, width: 1200, height: 1200 }); game.addChild(clockFace); // Position clock face at center of screen clockFace.x = 2048 / 2; clockFace.y = 2732 / 2; // Create clock needle needle = new ClockNeedle(); needle.x = 2048 / 2; needle.y = 2732 / 2; game.addChild(needle); // Create clock center clockCenter = LK.getAsset('clockCenter', { anchorX: 0.5, anchorY: 0.5, width: 50, height: 50 }); clockCenter.x = 2048 / 2; clockCenter.y = 2732 / 2; game.addChild(clockCenter); // Create initial targets createTargetsForLevel(level); // Reset game variables score = 0; currentStreak = 0; multiplier = 1; // Update UI updateUI(); // Play background music LK.playMusic('bgMusic', { fade: { start: 0, end: 0.3, duration: 1000 } }); // Mark game as started isGameStarted = true; // Hide instruction text after 3 seconds LK.setTimeout(function () { tween(instructionTxt, { alpha: 0 }, { duration: 1000, easing: tween.easeOut }); }, 3000); } // Function to create targets based on current level function createTargetsForLevel(level) { // Clear existing targets for (var i = 0; i < targets.length; i++) { if (targets[i].parent) { targets[i].destroy(); } } targets = []; // Calculate number of targets based on level targetCount = Math.min(3 + Math.floor(level / 2), 12); // Create evenly spaced targets var angleStep = 360 / targetCount; var startAngle = Math.random() * 360; // Random starting angle for (var i = 0; i < targetCount; i++) { var angle = (startAngle + i * angleStep) % 360; var target = new Target(angle, 450); // Position relative to center of game target.x += 2048 / 2; target.y += 2732 / 2; targets.push(target); game.addChild(target); } // Set needle behavior based on level if (level >= 3) { needle.setSpeed(1 + level * 0.2); // Increase speed with level } if (level >= 5) { needle.enableRandomBehavior(); } else { needle.disableRandomBehavior(); } } // Function to update UI elements function updateUI() { scoreTxt.setText(score.toString()); streakTxt.setText("Streak: " + currentStreak); multiplierTxt.setText("x" + multiplier); levelTxt.setText("Level " + level); highScoreTxt.setText("High Score: " + highScore); // Update score in LK system LK.setScore(score); } // Function to check if needle is hitting any target function checkNeedleHit() { var needleAngle = needle.angle; var hitTarget = false; var hitAngleTolerance = 10; // Degrees of tolerance for hitting // Check each target for (var i = 0; i < targets.length; i++) { var target = targets[i]; if (!target.active) { continue; } // Calculate angle difference var angleDiff = Math.abs(needleAngle - target.angle); if (angleDiff > 180) { angleDiff = 360 - angleDiff; } // Check if needle is within tolerance range if (angleDiff <= hitAngleTolerance) { hitTarget = true; handleTargetHit(target); break; } } if (!hitTarget) { handleMiss(); } } // Function to handle successful target hit function handleTargetHit(target) { // Mark target as hit target.markHit(); // Play hit sound LK.getSound('hit').play(); // Update streak and multiplier currentStreak++; multiplier = Math.min(5, 1 + Math.floor(currentStreak / 3)); // Add score var pointsGained = 100 * multiplier; score += pointsGained; // Show points animation var pointsText = new Text2("+" + pointsGained, { size: 80, fill: 0x00FF00 }); pointsText.anchor.set(0.5, 0.5); pointsText.x = target.x; pointsText.y = target.y; game.addChild(pointsText); tween(pointsText, { y: pointsText.y - 100, alpha: 0 }, { duration: 800, easing: tween.easeOut, onFinish: function onFinish() { pointsText.destroy(); } }); // Update UI updateUI(); // Check if all targets are hit var allTargetsHit = true; for (var i = 0; i < targets.length; i++) { if (targets[i].active) { allTargetsHit = false; break; } } // If all targets hit, advance to next level if (allTargetsHit) { advanceLevel(); } } // Function to handle missed tap function handleMiss() { // Play miss sound LK.getSound('miss').play(); // Check if the player is on a streak if (currentStreak > 0) { // Reset streak and multiplier currentStreak = 0; multiplier = 1; // Show miss animation LK.effects.flashScreen(0xff0000, 300); // Maintain remaining targets when streak is lost for (var i = 0; i < targets.length; i++) { if (targets[i].active && !targets[i].hit) { targets[i].reset(); } } // Update UI updateUI(); } else { // Show miss animation LK.effects.flashScreen(0xff0000, 300); // Mark all active targets as missed for (var i = 0; i < targets.length; i++) { if (targets[i].active) { targets[i].markMiss(); } } // Update UI updateUI(); // Check if score is higher than high score if (score > highScore) { highScore = score; storage.highScore = highScore; } // Show game over LK.setTimeout(function () { LK.showGameOver(); }, 1000); } } // Function to advance to next level function advanceLevel() { level++; storage.level = level; // Play level up sound LK.getSound('levelUp').play(); // Show level up animation var levelUpText = new Text2("LEVEL UP!", { size: 120, fill: 0xFFCC00 }); levelUpText.anchor.set(0.5, 0.5); levelUpText.x = 2048 / 2; levelUpText.y = 2732 / 2; game.addChild(levelUpText); tween(levelUpText, { scaleX: 1.5, scaleY: 1.5 }, { duration: 1000, easing: tween.easeOut, onFinish: function onFinish() { tween(levelUpText, { alpha: 0 }, { duration: 500, onFinish: function onFinish() { levelUpText.destroy(); // Create new targets for next level createTargetsForLevel(level); } }); } }); // Update UI updateUI(); } // Game tap/click handler game.down = function (x, y, obj) { if (!isGameStarted) { // Start game on first tap initGame(); return; } checkNeedleHit(); }; // Game update function game.update = function () { if (!isGameStarted) { return; } // Nothing needs updating here as the needle has its own update method }; // Initialize the game elements highScore = storage.highScore || 0; level = 1; // Always start at level 1 for a new game highScoreTxt.setText("High Score: " + highScore); // Show start instructions instructionTxt.setText("Tap to start!");
===================================================================
--- original.js
+++ change.js
@@ -402,12 +402,12 @@
currentStreak = 0;
multiplier = 1;
// Show miss animation
LK.effects.flashScreen(0xff0000, 300);
- // Mark all active targets as missed
+ // Maintain remaining targets when streak is lost
for (var i = 0; i < targets.length; i++) {
- if (targets[i].active) {
- targets[i].markMiss();
+ if (targets[i].active && !targets[i].hit) {
+ targets[i].reset();
}
}
// Update UI
updateUI();