/**** * 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); // Ball graphics var ballGraphics = self.attachAsset('ball', { anchorX: 0.5, anchorY: 0.5 }); // Physics properties self.vx = 0; self.vy = 0; self.gravity = 0.3; self.friction = 0.99; self.bounceForce = 10; self.maxSpeed = 25; self.lastTouched = 0; // Bounce the ball when touched self.bounce = function (touchX, touchY) { // Calculate direction vector from touch point to ball center var dx = self.x - touchX; var dy = self.y - touchY; // Normalize the direction vector var length = Math.sqrt(dx * dx + dy * dy); if (length > 0) { dx /= length; dy /= length; } // Apply bounce force in the direction away from touch self.vx += dx * self.bounceForce; self.vy += dy * self.bounceForce; // Cap the speed var speed = Math.sqrt(self.vx * self.vx + self.vy * self.vy); if (speed > self.maxSpeed) { self.vx = self.vx / speed * self.maxSpeed; self.vy = self.vy / speed * self.maxSpeed; } // Scale the ball quickly tween(ballGraphics, { scaleX: 1.3, scaleY: 1.3 }, { duration: 100, onFinish: function onFinish() { tween(ballGraphics, { scaleX: 1, scaleY: 1 }, { duration: 200, easing: tween.elasticOut }); } }); // Record the time of last touch self.lastTouched = Date.now(); // Play bounce sound LK.getSound('bounce').play(); return true; }; // Change the color of the ball self.changeColor = function () { var colors = [0xFFCC00, 0xFF6666, 0x66FF66, 0x6666FF, 0xFF66FF, 0x66FFFF, 0xFFFF66]; var randomColor = colors[Math.floor(Math.random() * colors.length)]; tween(ballGraphics, { tint: randomColor }, { duration: 300 }); }; // Check if ball was touched recently (within the last second) self.recentlyTouched = function () { return Date.now() - self.lastTouched < 1000; }; // Update ball physics self.update = function () { // Apply gravity self.vy += self.gravity; // Apply friction self.vx *= self.friction; self.vy *= self.friction; // Update position self.x += self.vx; self.y += self.vy; // Check boundaries - game width is 2048, height is 2732 var radius = ballGraphics.width / 2; var bounced = false; if (self.x < radius) { self.x = radius; self.vx = Math.abs(self.vx) * 0.8; bounced = true; } else if (self.x > 2048 - radius) { self.x = 2048 - radius; self.vx = -Math.abs(self.vx) * 0.8; bounced = true; } if (self.y < radius) { self.y = radius; self.vy = Math.abs(self.vy) * 0.8; bounced = true; } else if (self.y > 2732 - radius) { self.y = 2732 - radius; self.vy = -Math.abs(self.vy) * 0.8; bounced = true; } // Play edge bounce sound if we hit an edge if (bounced) { LK.getSound('edge').play(); } // Rotate based on horizontal speed ballGraphics.rotation += self.vx * 0.01; }; // Handle touch/click on ball self.down = function (x, y, obj) { self.bounce(x, y); }; return self; }); var TouchEffect = Container.expand(function () { var self = Container.call(this); var effectGraphics = self.attachAsset('touchEffect', { anchorX: 0.5, anchorY: 0.5, alpha: 0.7 }); self.init = function (x, y, color) { self.x = x; self.y = y; effectGraphics.tint = color || 0xFFFFFF; effectGraphics.scaleX = 0.1; effectGraphics.scaleY = 0.1; effectGraphics.alpha = 0.7; // Animate the effect tween(effectGraphics, { scaleX: 2, scaleY: 2, alpha: 0 }, { duration: 500, onFinish: function onFinish() { self.destroy(); } }); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x222222 }); /**** * Game Code ****/ // Game variables var ball; var score = 0; var scoreText; var timeText; var startTime; var gameActive = false; var touchEffects = []; var difficulty = 1; // Create and position score text scoreText = new Text2('0', { size: 120, fill: 0xFFFFFF }); scoreText.anchor.set(0.5, 0); LK.gui.top.addChild(scoreText); // Create and position time text timeText = new Text2('Time: 0', { size: 60, fill: 0xCCCCCC }); timeText.anchor.set(0.5, 0); timeText.y = 130; LK.gui.top.addChild(timeText); // Create instructions text at the start var instructionsText = new Text2('Tap the ball to keep it bouncing!', { size: 80, fill: 0xFFFFFF }); instructionsText.anchor.set(0.5, 0.5); LK.gui.center.addChild(instructionsText); // Initialize the game function initGame() { // Create the ball ball = new Ball(); ball.x = 2048 / 2; ball.y = 2732 / 3; game.addChild(ball); // Apply initial gentle force ball.vx = Math.random() * 4 - 2; ball.vy = -5; // Reset game variables score = 0; difficulty = 1; scoreText.setText('0'); startTime = Date.now(); gameActive = true; // Remove instructions if (instructionsText.parent) { instructionsText.parent.removeChild(instructionsText); } // Play background music LK.playMusic('gameplay'); } // Create touch effect function createTouchEffect(x, y) { var colors = [0xFFCC00, 0xFF6666, 0x66FF66, 0x6666FF, 0xFF66FF, 0x66FFFF, 0xFFFF66]; var randomColor = colors[Math.floor(Math.random() * colors.length)]; var effect = new TouchEffect(); effect.init(x, y, randomColor); game.addChild(effect); touchEffects.push(effect); } // Handle touch/click on the game game.down = function (x, y, obj) { // Start the game if not active if (!gameActive) { initGame(); return; } // Check if we directly touched the ball var touchedBall = false; // Calculate distance to ball var dx = x - ball.x; var dy = y - ball.y; var distance = Math.sqrt(dx * dx + dy * dy); // If we're within the ball radius, the bounce was handled by ball.down // If we're close to the ball, count it as a touch if (distance < ball.children[0].width) { touchedBall = true; } else if (distance < ball.children[0].width * 2) { // Close enough to count as a touch, but need to call bounce manually touchedBall = ball.bounce(x, y); } // Create touch effect and update score if we touched the ball if (touchedBall) { createTouchEffect(x, y); score += Math.floor(10 * difficulty); scoreText.setText(score.toString()); ball.changeColor(); } else { // We missed the ball LK.getSound('miss').play(); } }; // Update game state game.update = function () { if (!gameActive) { return; } // Update game timer var elapsedSeconds = Math.floor((Date.now() - startTime) / 1000); timeText.setText('Time: ' + elapsedSeconds); // Increase difficulty over time difficulty = 1 + elapsedSeconds / 30; // If difficulty increases, increase ball speed ball.maxSpeed = 25 + difficulty * 3; ball.gravity = 0.3 + difficulty * 0.05; // Check if the ball is moving too slowly var speed = Math.sqrt(ball.vx * ball.vx + ball.vy * ball.vy); if (speed < 1 && !ball.recentlyTouched()) { // Ball stopped moving for too long, game over LK.effects.flashScreen(0xFF0000, 500); LK.stopMusic(); LK.showGameOver(); gameActive = false; } // Handle cleanup of touch effects for (var i = touchEffects.length - 1; i >= 0; i--) { if (!touchEffects[i].parent) { touchEffects.splice(i, 1); } } }; // Start with a welcome screen - game will start on first touch gameActive = false;
/****
* 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);
// Ball graphics
var ballGraphics = self.attachAsset('ball', {
anchorX: 0.5,
anchorY: 0.5
});
// Physics properties
self.vx = 0;
self.vy = 0;
self.gravity = 0.3;
self.friction = 0.99;
self.bounceForce = 10;
self.maxSpeed = 25;
self.lastTouched = 0;
// Bounce the ball when touched
self.bounce = function (touchX, touchY) {
// Calculate direction vector from touch point to ball center
var dx = self.x - touchX;
var dy = self.y - touchY;
// Normalize the direction vector
var length = Math.sqrt(dx * dx + dy * dy);
if (length > 0) {
dx /= length;
dy /= length;
}
// Apply bounce force in the direction away from touch
self.vx += dx * self.bounceForce;
self.vy += dy * self.bounceForce;
// Cap the speed
var speed = Math.sqrt(self.vx * self.vx + self.vy * self.vy);
if (speed > self.maxSpeed) {
self.vx = self.vx / speed * self.maxSpeed;
self.vy = self.vy / speed * self.maxSpeed;
}
// Scale the ball quickly
tween(ballGraphics, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 100,
onFinish: function onFinish() {
tween(ballGraphics, {
scaleX: 1,
scaleY: 1
}, {
duration: 200,
easing: tween.elasticOut
});
}
});
// Record the time of last touch
self.lastTouched = Date.now();
// Play bounce sound
LK.getSound('bounce').play();
return true;
};
// Change the color of the ball
self.changeColor = function () {
var colors = [0xFFCC00, 0xFF6666, 0x66FF66, 0x6666FF, 0xFF66FF, 0x66FFFF, 0xFFFF66];
var randomColor = colors[Math.floor(Math.random() * colors.length)];
tween(ballGraphics, {
tint: randomColor
}, {
duration: 300
});
};
// Check if ball was touched recently (within the last second)
self.recentlyTouched = function () {
return Date.now() - self.lastTouched < 1000;
};
// Update ball physics
self.update = function () {
// Apply gravity
self.vy += self.gravity;
// Apply friction
self.vx *= self.friction;
self.vy *= self.friction;
// Update position
self.x += self.vx;
self.y += self.vy;
// Check boundaries - game width is 2048, height is 2732
var radius = ballGraphics.width / 2;
var bounced = false;
if (self.x < radius) {
self.x = radius;
self.vx = Math.abs(self.vx) * 0.8;
bounced = true;
} else if (self.x > 2048 - radius) {
self.x = 2048 - radius;
self.vx = -Math.abs(self.vx) * 0.8;
bounced = true;
}
if (self.y < radius) {
self.y = radius;
self.vy = Math.abs(self.vy) * 0.8;
bounced = true;
} else if (self.y > 2732 - radius) {
self.y = 2732 - radius;
self.vy = -Math.abs(self.vy) * 0.8;
bounced = true;
}
// Play edge bounce sound if we hit an edge
if (bounced) {
LK.getSound('edge').play();
}
// Rotate based on horizontal speed
ballGraphics.rotation += self.vx * 0.01;
};
// Handle touch/click on ball
self.down = function (x, y, obj) {
self.bounce(x, y);
};
return self;
});
var TouchEffect = Container.expand(function () {
var self = Container.call(this);
var effectGraphics = self.attachAsset('touchEffect', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.7
});
self.init = function (x, y, color) {
self.x = x;
self.y = y;
effectGraphics.tint = color || 0xFFFFFF;
effectGraphics.scaleX = 0.1;
effectGraphics.scaleY = 0.1;
effectGraphics.alpha = 0.7;
// Animate the effect
tween(effectGraphics, {
scaleX: 2,
scaleY: 2,
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
self.destroy();
}
});
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x222222
});
/****
* Game Code
****/
// Game variables
var ball;
var score = 0;
var scoreText;
var timeText;
var startTime;
var gameActive = false;
var touchEffects = [];
var difficulty = 1;
// Create and position score text
scoreText = new Text2('0', {
size: 120,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
// Create and position time text
timeText = new Text2('Time: 0', {
size: 60,
fill: 0xCCCCCC
});
timeText.anchor.set(0.5, 0);
timeText.y = 130;
LK.gui.top.addChild(timeText);
// Create instructions text at the start
var instructionsText = new Text2('Tap the ball to keep it bouncing!', {
size: 80,
fill: 0xFFFFFF
});
instructionsText.anchor.set(0.5, 0.5);
LK.gui.center.addChild(instructionsText);
// Initialize the game
function initGame() {
// Create the ball
ball = new Ball();
ball.x = 2048 / 2;
ball.y = 2732 / 3;
game.addChild(ball);
// Apply initial gentle force
ball.vx = Math.random() * 4 - 2;
ball.vy = -5;
// Reset game variables
score = 0;
difficulty = 1;
scoreText.setText('0');
startTime = Date.now();
gameActive = true;
// Remove instructions
if (instructionsText.parent) {
instructionsText.parent.removeChild(instructionsText);
}
// Play background music
LK.playMusic('gameplay');
}
// Create touch effect
function createTouchEffect(x, y) {
var colors = [0xFFCC00, 0xFF6666, 0x66FF66, 0x6666FF, 0xFF66FF, 0x66FFFF, 0xFFFF66];
var randomColor = colors[Math.floor(Math.random() * colors.length)];
var effect = new TouchEffect();
effect.init(x, y, randomColor);
game.addChild(effect);
touchEffects.push(effect);
}
// Handle touch/click on the game
game.down = function (x, y, obj) {
// Start the game if not active
if (!gameActive) {
initGame();
return;
}
// Check if we directly touched the ball
var touchedBall = false;
// Calculate distance to ball
var dx = x - ball.x;
var dy = y - ball.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// If we're within the ball radius, the bounce was handled by ball.down
// If we're close to the ball, count it as a touch
if (distance < ball.children[0].width) {
touchedBall = true;
} else if (distance < ball.children[0].width * 2) {
// Close enough to count as a touch, but need to call bounce manually
touchedBall = ball.bounce(x, y);
}
// Create touch effect and update score if we touched the ball
if (touchedBall) {
createTouchEffect(x, y);
score += Math.floor(10 * difficulty);
scoreText.setText(score.toString());
ball.changeColor();
} else {
// We missed the ball
LK.getSound('miss').play();
}
};
// Update game state
game.update = function () {
if (!gameActive) {
return;
}
// Update game timer
var elapsedSeconds = Math.floor((Date.now() - startTime) / 1000);
timeText.setText('Time: ' + elapsedSeconds);
// Increase difficulty over time
difficulty = 1 + elapsedSeconds / 30;
// If difficulty increases, increase ball speed
ball.maxSpeed = 25 + difficulty * 3;
ball.gravity = 0.3 + difficulty * 0.05;
// Check if the ball is moving too slowly
var speed = Math.sqrt(ball.vx * ball.vx + ball.vy * ball.vy);
if (speed < 1 && !ball.recentlyTouched()) {
// Ball stopped moving for too long, game over
LK.effects.flashScreen(0xFF0000, 500);
LK.stopMusic();
LK.showGameOver();
gameActive = false;
}
// Handle cleanup of touch effects
for (var i = touchEffects.length - 1; i >= 0; i--) {
if (!touchEffects[i].parent) {
touchEffects.splice(i, 1);
}
}
};
// Start with a welcome screen - game will start on first touch
gameActive = false;