/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Ball = Container.expand(function () {
var self = Container.call(this);
var ballGraphics = self.attachAsset('ball', {
anchorX: 0.5,
anchorY: 0.5
});
// Physics properties
self.velocityX = 0;
self.velocityY = 0;
self.gravity = 0.3;
self.bounce = 0.85;
self.speed = 1.0;
self.radius = 175;
// Initialize ball position and velocity
self.x = 1024; // Center X
self.y = 1366; // Center Y
self.velocityX = (Math.random() - 0.5) * 8;
self.velocityY = 0;
// Spinning state
self.isSpinning = false;
self.spinStartTime = 0;
self.update = function () {
// Ball is completely stationary - no movement at all
// Check if we should stop spinning due to inactivity
if (self.isSpinning && Date.now() - self.spinStartTime > 100) {
self.stopSpinning();
}
};
self.onTap = function () {
// Ball doesn't move - no velocity changes
// Update last click time
lastClickTime = Date.now();
// Increase score
LK.setScore(LK.getScore() + 1);
// Play tap sound
LK.getSound('tap').play();
// Stop any existing spin animation
tween.stop(self, {
rotation: true
});
// Start continuous spinning
self.isSpinning = true;
self.spinStartTime = Date.now();
// Scale up and start spinning
tween(self, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 150,
easing: tween.easeOut
});
// Start the spin loop
self.startSpinLoop();
};
self.startSpinLoop = function () {
if (self.isSpinning) {
tween(self, {
rotation: self.rotation + Math.PI * 2
}, {
duration: 150,
easing: tween.linear,
onFinish: function onFinished() {
self.startSpinLoop();
}
});
}
};
self.stopSpinning = function () {
self.isSpinning = false;
tween.stop(self, {
rotation: true
});
// Scale back down immediately
tween(self, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 0,
easing: tween.easeOut
});
};
self.down = function (x, y, obj) {
self.onTap();
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a1a2e
});
/****
* Game Code
****/
// Create score display
var scoreTxt = new Text2('0', {
size: 400,
fill: 0x00FFFF,
font: "Gagalin"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Create max score display
var maxScore = storage.maxScore || 0;
var maxScoreTxt = new Text2('Best: ' + maxScore.toString(), {
size: 150,
fill: 0xFFFF00,
font: "Gagalin"
});
maxScoreTxt.anchor.set(0.5, 0);
maxScoreTxt.y = 450;
LK.gui.top.addChild(maxScoreTxt);
// Create music toggle button
var musicEnabled = true;
var musicButton = new Text2('🎵', {
size: 120,
fill: 0xFFFFFF
});
musicButton.anchor.set(1, 0);
musicButton.x = -20;
musicButton.y = 20;
LK.gui.topRight.addChild(musicButton);
// Music button functionality
musicButton.down = function (x, y, obj) {
if (musicEnabled) {
LK.stopMusic();
musicButton.setText('🔇');
musicEnabled = false;
} else {
LK.playMusic('background');
musicButton.setText('🎵');
musicEnabled = true;
}
};
// Track last milestone reached
var lastMilestone = 0;
// Timer tracking for inactivity
var lastClickTime = Date.now();
var inactivityTimer = 500; // 0.5 seconds - faster losing
// Function to show lose animation
function showLoseAnimation() {
// Play milestone sound when losing
LK.getSound('milestone').play();
// Create lose text
var loseTxt = new Text2('LOSE!', {
size: 300,
fill: 0xFF0000,
font: "Gagalin"
});
loseTxt.anchor.set(0.5, 0.5);
loseTxt.alpha = 0;
LK.gui.center.addChild(loseTxt);
// Animate lose text appearing
tween(loseTxt, {
alpha: 1,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 500,
easing: tween.bounceOut,
onFinish: function onFinish() {
// Wait a moment then fade out
tween(loseTxt, {
alpha: 0,
scaleX: 0.5,
scaleY: 0.5
}, {
duration: 800,
easing: tween.easeIn,
onFinish: function onFinish() {
loseTxt.destroy();
}
});
}
});
}
// Function to celebrate milestone
function celebrateMilestone() {
// Play different milestone sound for 100-point celebration
LK.getSound('milestone_100').play();
// Rainbow color flash effect
LK.effects.flashScreen(0xFF00FF, 500);
// Spectacular score text animation
tween(scoreTxt, {
scaleX: 2.0,
scaleY: 2.0,
rotation: Math.PI * 0.1
}, {
duration: 300,
easing: tween.bounceOut,
onFinish: function onFinished() {
tween(scoreTxt, {
scaleX: 1.0,
scaleY: 1.0,
rotation: 0
}, {
duration: 400,
easing: tween.elasticOut
});
}
});
// Ball celebration animation
tween(ball, {
scaleX: 2.0,
scaleY: 2.0,
rotation: Math.PI * 2
}, {
duration: 600,
easing: tween.bounceInOut,
onFinish: function onFinished() {
tween(ball, {
scaleX: 1.0,
scaleY: 1.0,
rotation: 0
}, {
duration: 300,
easing: tween.easeOut
});
}
});
}
// Create ball
var ball = game.addChild(new Ball());
// Play background music when game starts
LK.playMusic('background');
// Update score display
game.update = function () {
var currentScore = LK.getScore();
scoreTxt.setText(currentScore.toString());
// Update max score if current score is higher
if (currentScore > maxScore) {
maxScore = currentScore;
storage.maxScore = maxScore;
maxScoreTxt.setText('Best: ' + maxScore.toString());
}
// Check for inactivity (no click for 1 second)
var currentTime = Date.now();
if (currentTime - lastClickTime > inactivityTimer && currentScore > 0) {
// Reset score but keep max score
LK.setScore(0);
// Reset last click time to prevent immediate retriggering
lastClickTime = currentTime;
// Reset milestone tracking
lastMilestone = 0;
// Show lose animation
showLoseAnimation();
}
// Check for milestone celebration (every 100 points)
var currentMilestone = Math.floor(currentScore / 100);
if (currentMilestone > lastMilestone && currentScore >= 100) {
celebrateMilestone();
lastMilestone = currentMilestone;
}
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Ball = Container.expand(function () {
var self = Container.call(this);
var ballGraphics = self.attachAsset('ball', {
anchorX: 0.5,
anchorY: 0.5
});
// Physics properties
self.velocityX = 0;
self.velocityY = 0;
self.gravity = 0.3;
self.bounce = 0.85;
self.speed = 1.0;
self.radius = 175;
// Initialize ball position and velocity
self.x = 1024; // Center X
self.y = 1366; // Center Y
self.velocityX = (Math.random() - 0.5) * 8;
self.velocityY = 0;
// Spinning state
self.isSpinning = false;
self.spinStartTime = 0;
self.update = function () {
// Ball is completely stationary - no movement at all
// Check if we should stop spinning due to inactivity
if (self.isSpinning && Date.now() - self.spinStartTime > 100) {
self.stopSpinning();
}
};
self.onTap = function () {
// Ball doesn't move - no velocity changes
// Update last click time
lastClickTime = Date.now();
// Increase score
LK.setScore(LK.getScore() + 1);
// Play tap sound
LK.getSound('tap').play();
// Stop any existing spin animation
tween.stop(self, {
rotation: true
});
// Start continuous spinning
self.isSpinning = true;
self.spinStartTime = Date.now();
// Scale up and start spinning
tween(self, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 150,
easing: tween.easeOut
});
// Start the spin loop
self.startSpinLoop();
};
self.startSpinLoop = function () {
if (self.isSpinning) {
tween(self, {
rotation: self.rotation + Math.PI * 2
}, {
duration: 150,
easing: tween.linear,
onFinish: function onFinished() {
self.startSpinLoop();
}
});
}
};
self.stopSpinning = function () {
self.isSpinning = false;
tween.stop(self, {
rotation: true
});
// Scale back down immediately
tween(self, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 0,
easing: tween.easeOut
});
};
self.down = function (x, y, obj) {
self.onTap();
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a1a2e
});
/****
* Game Code
****/
// Create score display
var scoreTxt = new Text2('0', {
size: 400,
fill: 0x00FFFF,
font: "Gagalin"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Create max score display
var maxScore = storage.maxScore || 0;
var maxScoreTxt = new Text2('Best: ' + maxScore.toString(), {
size: 150,
fill: 0xFFFF00,
font: "Gagalin"
});
maxScoreTxt.anchor.set(0.5, 0);
maxScoreTxt.y = 450;
LK.gui.top.addChild(maxScoreTxt);
// Create music toggle button
var musicEnabled = true;
var musicButton = new Text2('🎵', {
size: 120,
fill: 0xFFFFFF
});
musicButton.anchor.set(1, 0);
musicButton.x = -20;
musicButton.y = 20;
LK.gui.topRight.addChild(musicButton);
// Music button functionality
musicButton.down = function (x, y, obj) {
if (musicEnabled) {
LK.stopMusic();
musicButton.setText('🔇');
musicEnabled = false;
} else {
LK.playMusic('background');
musicButton.setText('🎵');
musicEnabled = true;
}
};
// Track last milestone reached
var lastMilestone = 0;
// Timer tracking for inactivity
var lastClickTime = Date.now();
var inactivityTimer = 500; // 0.5 seconds - faster losing
// Function to show lose animation
function showLoseAnimation() {
// Play milestone sound when losing
LK.getSound('milestone').play();
// Create lose text
var loseTxt = new Text2('LOSE!', {
size: 300,
fill: 0xFF0000,
font: "Gagalin"
});
loseTxt.anchor.set(0.5, 0.5);
loseTxt.alpha = 0;
LK.gui.center.addChild(loseTxt);
// Animate lose text appearing
tween(loseTxt, {
alpha: 1,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 500,
easing: tween.bounceOut,
onFinish: function onFinish() {
// Wait a moment then fade out
tween(loseTxt, {
alpha: 0,
scaleX: 0.5,
scaleY: 0.5
}, {
duration: 800,
easing: tween.easeIn,
onFinish: function onFinish() {
loseTxt.destroy();
}
});
}
});
}
// Function to celebrate milestone
function celebrateMilestone() {
// Play different milestone sound for 100-point celebration
LK.getSound('milestone_100').play();
// Rainbow color flash effect
LK.effects.flashScreen(0xFF00FF, 500);
// Spectacular score text animation
tween(scoreTxt, {
scaleX: 2.0,
scaleY: 2.0,
rotation: Math.PI * 0.1
}, {
duration: 300,
easing: tween.bounceOut,
onFinish: function onFinished() {
tween(scoreTxt, {
scaleX: 1.0,
scaleY: 1.0,
rotation: 0
}, {
duration: 400,
easing: tween.elasticOut
});
}
});
// Ball celebration animation
tween(ball, {
scaleX: 2.0,
scaleY: 2.0,
rotation: Math.PI * 2
}, {
duration: 600,
easing: tween.bounceInOut,
onFinish: function onFinished() {
tween(ball, {
scaleX: 1.0,
scaleY: 1.0,
rotation: 0
}, {
duration: 300,
easing: tween.easeOut
});
}
});
}
// Create ball
var ball = game.addChild(new Ball());
// Play background music when game starts
LK.playMusic('background');
// Update score display
game.update = function () {
var currentScore = LK.getScore();
scoreTxt.setText(currentScore.toString());
// Update max score if current score is higher
if (currentScore > maxScore) {
maxScore = currentScore;
storage.maxScore = maxScore;
maxScoreTxt.setText('Best: ' + maxScore.toString());
}
// Check for inactivity (no click for 1 second)
var currentTime = Date.now();
if (currentTime - lastClickTime > inactivityTimer && currentScore > 0) {
// Reset score but keep max score
LK.setScore(0);
// Reset last click time to prevent immediate retriggering
lastClickTime = currentTime;
// Reset milestone tracking
lastMilestone = 0;
// Show lose animation
showLoseAnimation();
}
// Check for milestone celebration (every 100 points)
var currentMilestone = Math.floor(currentScore / 100);
if (currentMilestone > lastMilestone && currentScore >= 100) {
celebrateMilestone();
lastMilestone = currentMilestone;
}
};