/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
bestScore: 0,
bestReactionTime: 0
});
/****
* Classes
****/
var Target = Container.expand(function () {
var self = Container.call(this);
self.type = 'normal';
self.points = 10;
self.isActive = true;
self.creationTime = Date.now();
var targetGraphic = self.attachAsset('target', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
});
self.resize = function (size) {
targetGraphic.width = size;
targetGraphic.height = size;
};
self.changeColor = function (color) {
targetGraphic.tint = color;
};
self.appear = function (duration) {
tween(targetGraphic, {
alpha: 1,
width: targetGraphic.width * 1.1,
height: targetGraphic.height * 1.1
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(targetGraphic, {
width: targetGraphic.width / 1.1,
height: targetGraphic.height / 1.1
}, {
duration: 200,
easing: tween.easeIn
});
}
});
};
self.disappear = function (callback) {
tween(targetGraphic, {
alpha: 0,
width: targetGraphic.width * 1.5,
height: targetGraphic.height * 1.5
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
if (callback) {
callback();
}
}
});
};
self.hit = function () {
if (!self.isActive) {
return false;
}
self.isActive = false;
var reactionTime = Date.now() - self.creationTime;
tween(targetGraphic, {
alpha: 0,
width: 0,
height: 0
}, {
duration: 200,
easing: tween.easeOut
});
return {
points: self.points,
reactionTime: reactionTime
};
};
self.down = function (x, y, obj) {
if (!self.isActive) {
return;
}
var hitResult = self.hit();
if (hitResult) {
LK.getSound('tap').play();
handleTargetHit(self, hitResult);
}
};
return self;
});
var SpecialTarget = Target.expand(function () {
var self = Target.call(this);
self.type = 'special';
self.points = 25;
var targetGraphic = self.getChildAt(0);
targetGraphic.texture = LK.getAsset('targetSpecial', {
anchorX: 0.5,
anchorY: 0.5
}).texture;
return self;
});
var BombTarget = Target.expand(function () {
var self = Target.call(this);
self.type = 'bomb';
self.points = -30;
var targetGraphic = self.getChildAt(0);
targetGraphic.texture = LK.getAsset('targetBomb', {
anchorX: 0.5,
anchorY: 0.5
}).texture;
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x212121
});
/****
* Game Code
****/
// Game state
var targets = [];
var score = 0;
var level = 1;
var totalTaps = 0;
var successfulTaps = 0;
var totalReactionTime = 0;
var avgReactionTime = 0;
var bestReactionTime = storage.bestReactionTime || 0;
var targetCount = 0;
var isGameActive = false;
var difficulty = {
minTimeout: 1200,
maxTimeout: 2500,
targetDuration: 1500,
targetChance: 0.7,
specialChance: 0.2,
bombChance: 0.1,
maxTargets: 1
};
// UI elements
var instructionText = new Text2('Tap the circles as fast as you can!\nTap anywhere to start', {
size: 60,
fill: 0xFFFFFF,
align: 'center'
});
instructionText.anchor.set(0.5, 0.5);
LK.gui.center.addChild(instructionText);
var scoreText = new Text2('Score: 0', {
size: 50,
fill: 0xFFFFFF
});
scoreText.anchor.set(1, 0);
scoreText.x = -20;
scoreText.y = 20;
LK.gui.topRight.addChild(scoreText);
var levelText = new Text2('Level: 1', {
size: 50,
fill: 0xFFFFFF
});
levelText.anchor.set(0, 0);
levelText.x = 120;
levelText.y = 20;
LK.gui.topRight.addChild(levelText);
var reactionTimeText = new Text2('Avg. Reaction: 0ms', {
size: 40,
fill: 0xFFFFFF
});
reactionTimeText.anchor.set(0.5, 0);
reactionTimeText.y = 20;
LK.gui.top.addChild(reactionTimeText);
var bestText = new Text2('Best Score: ' + storage.bestScore, {
size: 30,
fill: 0xFFD700
});
bestText.anchor.set(0, 1);
bestText.x = 20;
bestText.y = -20;
LK.gui.bottomLeft.addChild(bestText);
// Game functions
function startGame() {
score = 0;
level = 1;
totalTaps = 0;
successfulTaps = 0;
totalReactionTime = 0;
avgReactionTime = 0;
targetCount = 0;
isGameActive = true;
// Reset difficulty for level 1
difficulty = {
minTimeout: 1200,
maxTimeout: 2500,
targetDuration: 1500,
targetChance: 0.7,
specialChance: 0.2,
bombChance: 0.1,
maxTargets: 1
};
updateScoreText();
updateLevelText();
updateReactionTimeText();
instructionText.visible = false;
// Schedule first target
scheduleNextTarget();
// Play background music
LK.playMusic('bgMusic');
}
function scheduleNextTarget() {
if (!isGameActive) {
return;
}
var delay = Math.random() * (difficulty.maxTimeout - difficulty.minTimeout) + difficulty.minTimeout;
LK.setTimeout(function () {
if (!isGameActive) {
return;
}
if (targets.length < difficulty.maxTargets) {
spawnRandomTarget();
}
scheduleNextTarget();
}, delay);
}
function spawnRandomTarget() {
if (!isGameActive) {
return;
}
var rand = Math.random();
var newTarget;
if (rand < difficulty.targetChance) {
newTarget = new Target();
} else if (rand < difficulty.targetChance + difficulty.specialChance) {
newTarget = new SpecialTarget();
} else {
newTarget = new BombTarget();
}
// Position randomly on screen with margins to ensure visibility
newTarget.x = Math.random() * (2048 - 300) + 150;
newTarget.y = Math.random() * (2732 - 400) + 200;
// Ensure not too close to screen edges or other targets
// Top-left corner reserved for menu
if (newTarget.x < 200 && newTarget.y < 200) {
newTarget.x += 200;
newTarget.y += 200;
}
game.addChild(newTarget);
targets.push(newTarget);
targetCount++;
newTarget.appear();
// Schedule target disappearance
LK.setTimeout(function () {
if (newTarget.isActive) {
newTarget.isActive = false;
newTarget.disappear(function () {
// Miss penalty - only for normal and special targets
if (newTarget.type !== 'bomb') {
LK.getSound('fail').play();
score = Math.max(0, score - 5); // Penalty for missing
updateScoreText();
}
removeTarget(newTarget);
});
}
}, difficulty.targetDuration);
}
function handleTargetHit(target, hitResult) {
totalTaps++;
if (target.type === 'bomb') {
LK.getSound('fail').play();
LK.effects.flashScreen(0xFF5722, 300);
} else {
successfulTaps++;
LK.getSound('success').play();
}
score += hitResult.points;
score = Math.max(0, score); // Ensure score doesn't go below 0
totalReactionTime += hitResult.reactionTime;
avgReactionTime = Math.round(totalReactionTime / successfulTaps);
if (successfulTaps > 0 && (bestReactionTime === 0 || avgReactionTime < bestReactionTime)) {
bestReactionTime = avgReactionTime;
storage.bestReactionTime = bestReactionTime;
}
if (score > storage.bestScore) {
storage.bestScore = score;
bestText.setText('Best Score: ' + storage.bestScore);
}
updateScoreText();
updateReactionTimeText();
removeTarget(target);
// Level progression
checkLevelProgression();
}
function removeTarget(target) {
var index = targets.indexOf(target);
if (index !== -1) {
targets.splice(index, 1);
}
LK.setTimeout(function () {
target.destroy();
}, 300);
}
function checkLevelProgression() {
var nextLevel = Math.floor(score / 100) + 1;
if (nextLevel > level) {
level = nextLevel;
increaseDifficulty();
updateLevelText();
LK.getSound('levelUp').play();
LK.effects.flashScreen(0x4CAF50, 500);
var levelUpText = new Text2('LEVEL UP!', {
size: 80,
fill: 0x4CAF50
});
levelUpText.anchor.set(0.5, 0.5);
LK.gui.center.addChild(levelUpText);
// Animate and remove level up text
tween(levelUpText, {
alpha: 0,
y: levelUpText.y - 100
}, {
duration: 1000,
easing: tween.easeOut,
onFinish: function onFinish() {
levelUpText.destroy();
}
});
}
}
function increaseDifficulty() {
// Make game progressively harder with each level
difficulty.minTimeout = Math.max(400, difficulty.minTimeout - 100);
difficulty.maxTimeout = Math.max(1000, difficulty.maxTimeout - 150);
difficulty.targetDuration = Math.max(700, difficulty.targetDuration - 100);
// Adjust spawn chances
if (level % 3 === 0) {
difficulty.maxTargets = Math.min(3, difficulty.maxTargets + 1);
}
if (level > 5) {
difficulty.bombChance = Math.min(0.25, difficulty.bombChance + 0.03);
difficulty.specialChance = Math.min(0.35, difficulty.specialChance + 0.02);
difficulty.targetChance = 1 - difficulty.bombChance - difficulty.specialChance;
}
}
function updateScoreText() {
scoreText.setText('Score: ' + score);
}
function updateLevelText() {
levelText.setText('Level: ' + level);
}
function updateReactionTimeText() {
if (successfulTaps > 0) {
reactionTimeText.setText('Avg. Reaction: ' + avgReactionTime + 'ms');
} else {
reactionTimeText.setText('Avg. Reaction: -');
}
}
function endGame() {
isGameActive = false;
// Clean up any remaining targets
for (var i = targets.length - 1; i >= 0; i--) {
var target = targets[i];
target.isActive = false;
target.disappear(function () {
target.destroy();
});
}
targets = [];
// Show game over
LK.showGameOver();
}
// Global event handlers
game.down = function (x, y, obj) {
if (!isGameActive) {
startGame();
return;
}
// If we clicked on empty space, it counts as a miss
// We need to check if the click was on a target or empty space
var clickedOnTarget = false;
for (var i = 0; i < targets.length; i++) {
if (targets[i].getBounds().contains(x, y)) {
clickedOnTarget = true;
break;
}
}
if (!clickedOnTarget) {
totalTaps++;
score = Math.max(0, score - 2); // Small penalty for tapping blank space
updateScoreText();
}
};
// Game update function
game.update = function () {
// Check for game over condition
if (isGameActive && score < 0) {
endGame();
}
}; ===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,406 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+var storage = LK.import("@upit/storage.v1", {
+ bestScore: 0,
+ bestReactionTime: 0
+});
+
+/****
+* Classes
+****/
+var Target = Container.expand(function () {
+ var self = Container.call(this);
+ self.type = 'normal';
+ self.points = 10;
+ self.isActive = true;
+ self.creationTime = Date.now();
+ var targetGraphic = self.attachAsset('target', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ alpha: 0
+ });
+ self.resize = function (size) {
+ targetGraphic.width = size;
+ targetGraphic.height = size;
+ };
+ self.changeColor = function (color) {
+ targetGraphic.tint = color;
+ };
+ self.appear = function (duration) {
+ tween(targetGraphic, {
+ alpha: 1,
+ width: targetGraphic.width * 1.1,
+ height: targetGraphic.height * 1.1
+ }, {
+ duration: 200,
+ easing: tween.easeOut,
+ onFinish: function onFinish() {
+ tween(targetGraphic, {
+ width: targetGraphic.width / 1.1,
+ height: targetGraphic.height / 1.1
+ }, {
+ duration: 200,
+ easing: tween.easeIn
+ });
+ }
+ });
+ };
+ self.disappear = function (callback) {
+ tween(targetGraphic, {
+ alpha: 0,
+ width: targetGraphic.width * 1.5,
+ height: targetGraphic.height * 1.5
+ }, {
+ duration: 300,
+ easing: tween.easeOut,
+ onFinish: function onFinish() {
+ if (callback) {
+ callback();
+ }
+ }
+ });
+ };
+ self.hit = function () {
+ if (!self.isActive) {
+ return false;
+ }
+ self.isActive = false;
+ var reactionTime = Date.now() - self.creationTime;
+ tween(targetGraphic, {
+ alpha: 0,
+ width: 0,
+ height: 0
+ }, {
+ duration: 200,
+ easing: tween.easeOut
+ });
+ return {
+ points: self.points,
+ reactionTime: reactionTime
+ };
+ };
+ self.down = function (x, y, obj) {
+ if (!self.isActive) {
+ return;
+ }
+ var hitResult = self.hit();
+ if (hitResult) {
+ LK.getSound('tap').play();
+ handleTargetHit(self, hitResult);
+ }
+ };
+ return self;
+});
+var SpecialTarget = Target.expand(function () {
+ var self = Target.call(this);
+ self.type = 'special';
+ self.points = 25;
+ var targetGraphic = self.getChildAt(0);
+ targetGraphic.texture = LK.getAsset('targetSpecial', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ }).texture;
+ return self;
+});
+var BombTarget = Target.expand(function () {
+ var self = Target.call(this);
+ self.type = 'bomb';
+ self.points = -30;
+ var targetGraphic = self.getChildAt(0);
+ targetGraphic.texture = LK.getAsset('targetBomb', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ }).texture;
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0x212121
+});
+
+/****
+* Game Code
+****/
+// Game state
+var targets = [];
+var score = 0;
+var level = 1;
+var totalTaps = 0;
+var successfulTaps = 0;
+var totalReactionTime = 0;
+var avgReactionTime = 0;
+var bestReactionTime = storage.bestReactionTime || 0;
+var targetCount = 0;
+var isGameActive = false;
+var difficulty = {
+ minTimeout: 1200,
+ maxTimeout: 2500,
+ targetDuration: 1500,
+ targetChance: 0.7,
+ specialChance: 0.2,
+ bombChance: 0.1,
+ maxTargets: 1
+};
+// UI elements
+var instructionText = new Text2('Tap the circles as fast as you can!\nTap anywhere to start', {
+ size: 60,
+ fill: 0xFFFFFF,
+ align: 'center'
+});
+instructionText.anchor.set(0.5, 0.5);
+LK.gui.center.addChild(instructionText);
+var scoreText = new Text2('Score: 0', {
+ size: 50,
+ fill: 0xFFFFFF
+});
+scoreText.anchor.set(1, 0);
+scoreText.x = -20;
+scoreText.y = 20;
+LK.gui.topRight.addChild(scoreText);
+var levelText = new Text2('Level: 1', {
+ size: 50,
+ fill: 0xFFFFFF
+});
+levelText.anchor.set(0, 0);
+levelText.x = 120;
+levelText.y = 20;
+LK.gui.topRight.addChild(levelText);
+var reactionTimeText = new Text2('Avg. Reaction: 0ms', {
+ size: 40,
+ fill: 0xFFFFFF
+});
+reactionTimeText.anchor.set(0.5, 0);
+reactionTimeText.y = 20;
+LK.gui.top.addChild(reactionTimeText);
+var bestText = new Text2('Best Score: ' + storage.bestScore, {
+ size: 30,
+ fill: 0xFFD700
+});
+bestText.anchor.set(0, 1);
+bestText.x = 20;
+bestText.y = -20;
+LK.gui.bottomLeft.addChild(bestText);
+// Game functions
+function startGame() {
+ score = 0;
+ level = 1;
+ totalTaps = 0;
+ successfulTaps = 0;
+ totalReactionTime = 0;
+ avgReactionTime = 0;
+ targetCount = 0;
+ isGameActive = true;
+ // Reset difficulty for level 1
+ difficulty = {
+ minTimeout: 1200,
+ maxTimeout: 2500,
+ targetDuration: 1500,
+ targetChance: 0.7,
+ specialChance: 0.2,
+ bombChance: 0.1,
+ maxTargets: 1
+ };
+ updateScoreText();
+ updateLevelText();
+ updateReactionTimeText();
+ instructionText.visible = false;
+ // Schedule first target
+ scheduleNextTarget();
+ // Play background music
+ LK.playMusic('bgMusic');
+}
+function scheduleNextTarget() {
+ if (!isGameActive) {
+ return;
+ }
+ var delay = Math.random() * (difficulty.maxTimeout - difficulty.minTimeout) + difficulty.minTimeout;
+ LK.setTimeout(function () {
+ if (!isGameActive) {
+ return;
+ }
+ if (targets.length < difficulty.maxTargets) {
+ spawnRandomTarget();
+ }
+ scheduleNextTarget();
+ }, delay);
+}
+function spawnRandomTarget() {
+ if (!isGameActive) {
+ return;
+ }
+ var rand = Math.random();
+ var newTarget;
+ if (rand < difficulty.targetChance) {
+ newTarget = new Target();
+ } else if (rand < difficulty.targetChance + difficulty.specialChance) {
+ newTarget = new SpecialTarget();
+ } else {
+ newTarget = new BombTarget();
+ }
+ // Position randomly on screen with margins to ensure visibility
+ newTarget.x = Math.random() * (2048 - 300) + 150;
+ newTarget.y = Math.random() * (2732 - 400) + 200;
+ // Ensure not too close to screen edges or other targets
+ // Top-left corner reserved for menu
+ if (newTarget.x < 200 && newTarget.y < 200) {
+ newTarget.x += 200;
+ newTarget.y += 200;
+ }
+ game.addChild(newTarget);
+ targets.push(newTarget);
+ targetCount++;
+ newTarget.appear();
+ // Schedule target disappearance
+ LK.setTimeout(function () {
+ if (newTarget.isActive) {
+ newTarget.isActive = false;
+ newTarget.disappear(function () {
+ // Miss penalty - only for normal and special targets
+ if (newTarget.type !== 'bomb') {
+ LK.getSound('fail').play();
+ score = Math.max(0, score - 5); // Penalty for missing
+ updateScoreText();
+ }
+ removeTarget(newTarget);
+ });
+ }
+ }, difficulty.targetDuration);
+}
+function handleTargetHit(target, hitResult) {
+ totalTaps++;
+ if (target.type === 'bomb') {
+ LK.getSound('fail').play();
+ LK.effects.flashScreen(0xFF5722, 300);
+ } else {
+ successfulTaps++;
+ LK.getSound('success').play();
+ }
+ score += hitResult.points;
+ score = Math.max(0, score); // Ensure score doesn't go below 0
+ totalReactionTime += hitResult.reactionTime;
+ avgReactionTime = Math.round(totalReactionTime / successfulTaps);
+ if (successfulTaps > 0 && (bestReactionTime === 0 || avgReactionTime < bestReactionTime)) {
+ bestReactionTime = avgReactionTime;
+ storage.bestReactionTime = bestReactionTime;
+ }
+ if (score > storage.bestScore) {
+ storage.bestScore = score;
+ bestText.setText('Best Score: ' + storage.bestScore);
+ }
+ updateScoreText();
+ updateReactionTimeText();
+ removeTarget(target);
+ // Level progression
+ checkLevelProgression();
+}
+function removeTarget(target) {
+ var index = targets.indexOf(target);
+ if (index !== -1) {
+ targets.splice(index, 1);
+ }
+ LK.setTimeout(function () {
+ target.destroy();
+ }, 300);
+}
+function checkLevelProgression() {
+ var nextLevel = Math.floor(score / 100) + 1;
+ if (nextLevel > level) {
+ level = nextLevel;
+ increaseDifficulty();
+ updateLevelText();
+ LK.getSound('levelUp').play();
+ LK.effects.flashScreen(0x4CAF50, 500);
+ var levelUpText = new Text2('LEVEL UP!', {
+ size: 80,
+ fill: 0x4CAF50
+ });
+ levelUpText.anchor.set(0.5, 0.5);
+ LK.gui.center.addChild(levelUpText);
+ // Animate and remove level up text
+ tween(levelUpText, {
+ alpha: 0,
+ y: levelUpText.y - 100
+ }, {
+ duration: 1000,
+ easing: tween.easeOut,
+ onFinish: function onFinish() {
+ levelUpText.destroy();
+ }
+ });
+ }
+}
+function increaseDifficulty() {
+ // Make game progressively harder with each level
+ difficulty.minTimeout = Math.max(400, difficulty.minTimeout - 100);
+ difficulty.maxTimeout = Math.max(1000, difficulty.maxTimeout - 150);
+ difficulty.targetDuration = Math.max(700, difficulty.targetDuration - 100);
+ // Adjust spawn chances
+ if (level % 3 === 0) {
+ difficulty.maxTargets = Math.min(3, difficulty.maxTargets + 1);
+ }
+ if (level > 5) {
+ difficulty.bombChance = Math.min(0.25, difficulty.bombChance + 0.03);
+ difficulty.specialChance = Math.min(0.35, difficulty.specialChance + 0.02);
+ difficulty.targetChance = 1 - difficulty.bombChance - difficulty.specialChance;
+ }
+}
+function updateScoreText() {
+ scoreText.setText('Score: ' + score);
+}
+function updateLevelText() {
+ levelText.setText('Level: ' + level);
+}
+function updateReactionTimeText() {
+ if (successfulTaps > 0) {
+ reactionTimeText.setText('Avg. Reaction: ' + avgReactionTime + 'ms');
+ } else {
+ reactionTimeText.setText('Avg. Reaction: -');
+ }
+}
+function endGame() {
+ isGameActive = false;
+ // Clean up any remaining targets
+ for (var i = targets.length - 1; i >= 0; i--) {
+ var target = targets[i];
+ target.isActive = false;
+ target.disappear(function () {
+ target.destroy();
+ });
+ }
+ targets = [];
+ // Show game over
+ LK.showGameOver();
+}
+// Global event handlers
+game.down = function (x, y, obj) {
+ if (!isGameActive) {
+ startGame();
+ return;
+ }
+ // If we clicked on empty space, it counts as a miss
+ // We need to check if the click was on a target or empty space
+ var clickedOnTarget = false;
+ for (var i = 0; i < targets.length; i++) {
+ if (targets[i].getBounds().contains(x, y)) {
+ clickedOnTarget = true;
+ break;
+ }
+ }
+ if (!clickedOnTarget) {
+ totalTaps++;
+ score = Math.max(0, score - 2); // Small penalty for tapping blank space
+ updateScoreText();
+ }
+};
+// Game update function
+game.update = function () {
+ // Check for game over condition
+ if (isGameActive && score < 0) {
+ endGame();
+ }
+};
\ No newline at end of file