/**** * 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 }); self.angle = 0; self.speed = 0.02; self.ringRadius = 525; // Distance from center to ball center - positioned at center of ring edge thickness self.centerX = 2048 / 2; self.centerY = 2732 / 2; self.update = function () { if (gameStarted) { self.angle += self.speed; if (self.angle > Math.PI * 2) { self.angle -= Math.PI * 2; } } self.x = self.centerX + Math.cos(self.angle) * self.ringRadius; self.y = self.centerY + Math.sin(self.angle) * self.ringRadius; }; return self; }); var HealthPickup = Container.expand(function () { var self = Container.call(this); var healthGraphics = self.attachAsset('healthPickup', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 6; self.centerX = 2048 / 2; self.centerY = 2732 / 2; self.directionX = 0; self.directionY = 0; self.setDirection = function (targetX, targetY) { var dx = targetX - self.x; var dy = targetY - self.y; var distance = Math.sqrt(dx * dx + dy * dy); self.directionX = dx / distance; self.directionY = dy / distance; }; self.update = function () { // Match ball speed magnitude var ballSpeedMagnitude = Math.abs(ball.speed); var adjustedSpeed = ballSpeedMagnitude * 300; // Scale to appropriate movement speed self.x += self.directionX * adjustedSpeed; self.y += self.directionY * adjustedSpeed; }; return self; }); var Trap = Container.expand(function () { var self = Container.call(this); var trapGraphics = self.attachAsset('trap', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 6; self.centerX = 2048 / 2; self.centerY = 2732 / 2; self.directionX = 0; self.directionY = 0; self.setDirection = function (targetX, targetY) { var dx = targetX - self.x; var dy = targetY - self.y; var distance = Math.sqrt(dx * dx + dy * dy); self.directionX = dx / distance; self.directionY = dy / distance; }; self.update = function () { // Match ball speed magnitude var ballSpeedMagnitude = Math.abs(ball.speed); var adjustedSpeed = ballSpeedMagnitude * 300; // Scale to appropriate movement speed self.x += self.directionX * adjustedSpeed; self.y += self.directionY * adjustedSpeed; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x1a1a2e }); /**** * Game Code ****/ // Create central ring var ring = game.addChild(LK.getAsset('ring', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2 })); // Lives system var lives = 1; // Time tracking for score var gameStartTime = 0; var currentTime = 0; var gameRunning = false; var gameStarted = false; // Speed progression variables var initialSpeed = 0.02; var maxSpeed = 0.08; var speedIncreaseInterval = 300; // 5 seconds at 60 FPS var speedIncreaseTimer = 0; // Trap spawning variables var traps = []; var trapSpawnTimer = 0; var trapSpawnInterval = 480; // 8 seconds at 60 FPS var trapSpawnReductionTimer = 0; var trapSpawnReductionInterval = 600; // 10 seconds at 60 FPS // Health pickup spawning variables var healthPickups = []; var healthSpawnTimer = 0; var healthSpawnInterval = 900; // 15 seconds at 60 FPS var healthSpawnIncreaseTimer = 0; var healthSpawnIncreaseInterval = 600; // 10 seconds at 60 FPS var ringHole = game.addChild(LK.getAsset('ringHole', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2 })); // Initialize rotation state ringHole.isRotating = false; // Create ball var ball = game.addChild(new Ball()); // Create lives display with healthPickup icon var livesContainer = new Container(); var livesIcon = livesContainer.addChild(LK.getAsset('healthPickup', { anchorX: 0.5, anchorY: 0.5, x: 0, // Position icon at container origin width: 80, // Match text size height: 80 // Match text size })); var livesText = new Text2(lives, { size: 80, fill: 0xFFFFFF, font: "'GillSans-Bold',Impact,'Arial Black',Tahoma" }); livesText.anchor.set(0, 0.5); // Left-center anchor to align with icon center livesText.x = 50; // Position text to the right of icon with some spacing livesContainer.addChild(livesText); livesContainer.x = 0; livesContainer.y = 0; LK.gui.top.addChild(livesContainer); // Create container for Salt image and time display var topContainer = new Container(); // Create Salt image var saltImage = LK.getAsset('Salt', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.5, scaleY: 1.5 }); saltImage.x = -60; // Position to the left of center saltImage.y = 120; // Align with text baseline topContainer.addChild(saltImage); // Create time display var timeText = new Text2('0', { size: 240, fill: 0xFFFFFF, font: "'GillSans-Bold',Impact,'Arial Black',Tahoma" }); timeText.anchor.set(0, 0.5); // Left-center aligned timeText.x = 60; // Position to the right of center timeText.y = 120; // Align with Salt image center topContainer.addChild(timeText); // Center the container at top topContainer.x = 0; topContainer.y = 0; LK.gui.top.addChild(topContainer); // Create best score display var bestScore = storage.bestScore || 0; var bestScoreText = new Text2(bestScore, { size: 360, fill: 0xFFFFFF, font: "'GillSans-Bold',Impact,'Arial Black',Tahoma" }); bestScoreText.anchor.set(0.5, 0.5); // Center anchor bestScoreText.x = 200; bestScoreText.y = -250; LK.gui.bottom.addChild(bestScoreText); // Create king image at bottom center var kingImage = LK.getAsset('King', { anchorX: 0.5, anchorY: 0.5, scaleX: 3, scaleY: 3 }); kingImage.x = -200; kingImage.y = -250; LK.gui.bottom.addChild(kingImage); // Add tap handler to reverse ball direction game.down = function (x, y, obj) { ball.speed = -ball.speed; // Start game timer on first tap if (!gameRunning) { gameStartTime = Date.now(); gameRunning = true; gameStarted = true; } }; game.update = function () { // Update time display if game is running if (gameRunning) { currentTime = Math.floor((Date.now() - gameStartTime) / 1000); timeText.setText(currentTime); LK.setScore(currentTime); } // Position lives container below top container livesContainer.y = topContainer.y + timeText.height + 40; // Ball will continue moving infinitely around the ring // Start rotation when game starts if (gameStarted && !ringHole.isRotating) { ringHole.isRotating = true; // Create continuous rotation tween tween(ringHole, { rotation: Math.PI * 2 }, { duration: 3000, // 3 seconds for full rotation easing: tween.linear, onFinish: function onFinish() { // Reset rotation to 0 and start again for continuous rotation ringHole.rotation = 0; ringHole.isRotating = false; } }); } // Increase ball speed over time (only after game has started) if (gameStarted) { speedIncreaseTimer++; if (speedIncreaseTimer >= speedIncreaseInterval) { speedIncreaseTimer = 0; // Increase speed by 10% each time, up to maximum var currentSpeedMagnitude = Math.abs(ball.speed); var newSpeed = Math.min(currentSpeedMagnitude * 1.1, maxSpeed); // Maintain direction (positive or negative) ball.speed = ball.speed > 0 ? newSpeed : -newSpeed; } // Reduce trap spawn interval by 10% every 10 seconds trapSpawnReductionTimer++; if (trapSpawnReductionTimer >= trapSpawnReductionInterval) { trapSpawnReductionTimer = 0; // Reduce spawn interval by 10% (minimum 60 frames = 1 second) trapSpawnInterval = Math.max(trapSpawnInterval * 0.90, 60); } // Increase health pickup spawn interval by 5% every 10 seconds healthSpawnIncreaseTimer++; if (healthSpawnIncreaseTimer >= healthSpawnIncreaseInterval) { healthSpawnIncreaseTimer = 0; // Increase spawn interval by 5% (maximum 3600 frames = 60 seconds) healthSpawnInterval = Math.min(healthSpawnInterval * 1.05, 3600); } } // Spawn traps every 8 seconds (only after game has started) if (gameStarted) { trapSpawnTimer++; if (trapSpawnTimer >= trapSpawnInterval) { trapSpawnTimer = 0; // Spawn trap at random position on screen edge var trap = new Trap(); var side = Math.floor(Math.random() * 4); // 0=top, 1=right, 2=bottom, 3=left switch (side) { case 0: // Top edge trap.x = Math.random() * 2048; trap.y = -40; break; case 1: // Right edge trap.x = 2048 + 40; trap.y = Math.random() * 2732; break; case 2: // Bottom edge trap.x = Math.random() * 2048; trap.y = 2732 + 40; break; case 3: // Left edge trap.x = -40; trap.y = Math.random() * 2732; break; } // Set direction toward ring center trap.setDirection(2048 / 2, 2732 / 2); traps.push(trap); game.addChild(trap); } } // Spawn health pickups every 8 seconds (only after game has started) if (gameStarted) { healthSpawnTimer++; if (healthSpawnTimer >= healthSpawnInterval) { healthSpawnTimer = 0; // Spawn health pickup at random position on screen edge var healthPickup = new HealthPickup(); var side = Math.floor(Math.random() * 4); // 0=top, 1=right, 2=bottom, 3=left switch (side) { case 0: // Top edge healthPickup.x = Math.random() * 2048; healthPickup.y = -40; break; case 1: // Right edge healthPickup.x = 2048 + 40; healthPickup.y = Math.random() * 2732; break; case 2: // Bottom edge healthPickup.x = Math.random() * 2048; healthPickup.y = 2732 + 40; break; case 3: // Left edge healthPickup.x = -40; healthPickup.y = Math.random() * 2732; break; } // Set direction toward ring center healthPickup.setDirection(2048 / 2, 2732 / 2); healthPickups.push(healthPickup); game.addChild(healthPickup); } } // Check collision between ball and traps for (var i = traps.length - 1; i >= 0; i--) { var trap = traps[i]; // Check collision with ball if (ball.intersects(trap)) { lives--; livesText.setText(lives); // Remove the trap that hit the ball trap.destroy(); traps.splice(i, 1); // Check game over condition if (lives <= 0) { gameRunning = false; // Update best score if current score is higher if (currentTime > bestScore) { bestScore = currentTime; storage.bestScore = bestScore; bestScoreText.setText(bestScore); } LK.showGameOver(); } ; continue; } // Clean up traps that have moved off screen if (trap.x < -100 || trap.x > 2148 || trap.y < -100 || trap.y > 2832) { trap.destroy(); traps.splice(i, 1); } } // Check collision between ball and health pickups for (var j = healthPickups.length - 1; j >= 0; j--) { var healthPickup = healthPickups[j]; // Check collision with ball if (ball.intersects(healthPickup)) { lives++; livesText.setText(lives); // Remove the health pickup that was collected healthPickup.destroy(); healthPickups.splice(j, 1); continue; } // Clean up health pickups that have moved off screen if (healthPickup.x < -100 || healthPickup.x > 2148 || healthPickup.y < -100 || healthPickup.y > 2832) { healthPickup.destroy(); healthPickups.splice(j, 1); } } };
/****
* 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
});
self.angle = 0;
self.speed = 0.02;
self.ringRadius = 525; // Distance from center to ball center - positioned at center of ring edge thickness
self.centerX = 2048 / 2;
self.centerY = 2732 / 2;
self.update = function () {
if (gameStarted) {
self.angle += self.speed;
if (self.angle > Math.PI * 2) {
self.angle -= Math.PI * 2;
}
}
self.x = self.centerX + Math.cos(self.angle) * self.ringRadius;
self.y = self.centerY + Math.sin(self.angle) * self.ringRadius;
};
return self;
});
var HealthPickup = Container.expand(function () {
var self = Container.call(this);
var healthGraphics = self.attachAsset('healthPickup', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 6;
self.centerX = 2048 / 2;
self.centerY = 2732 / 2;
self.directionX = 0;
self.directionY = 0;
self.setDirection = function (targetX, targetY) {
var dx = targetX - self.x;
var dy = targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
self.directionX = dx / distance;
self.directionY = dy / distance;
};
self.update = function () {
// Match ball speed magnitude
var ballSpeedMagnitude = Math.abs(ball.speed);
var adjustedSpeed = ballSpeedMagnitude * 300; // Scale to appropriate movement speed
self.x += self.directionX * adjustedSpeed;
self.y += self.directionY * adjustedSpeed;
};
return self;
});
var Trap = Container.expand(function () {
var self = Container.call(this);
var trapGraphics = self.attachAsset('trap', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 6;
self.centerX = 2048 / 2;
self.centerY = 2732 / 2;
self.directionX = 0;
self.directionY = 0;
self.setDirection = function (targetX, targetY) {
var dx = targetX - self.x;
var dy = targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
self.directionX = dx / distance;
self.directionY = dy / distance;
};
self.update = function () {
// Match ball speed magnitude
var ballSpeedMagnitude = Math.abs(ball.speed);
var adjustedSpeed = ballSpeedMagnitude * 300; // Scale to appropriate movement speed
self.x += self.directionX * adjustedSpeed;
self.y += self.directionY * adjustedSpeed;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a1a2e
});
/****
* Game Code
****/
// Create central ring
var ring = game.addChild(LK.getAsset('ring', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2
}));
// Lives system
var lives = 1;
// Time tracking for score
var gameStartTime = 0;
var currentTime = 0;
var gameRunning = false;
var gameStarted = false;
// Speed progression variables
var initialSpeed = 0.02;
var maxSpeed = 0.08;
var speedIncreaseInterval = 300; // 5 seconds at 60 FPS
var speedIncreaseTimer = 0;
// Trap spawning variables
var traps = [];
var trapSpawnTimer = 0;
var trapSpawnInterval = 480; // 8 seconds at 60 FPS
var trapSpawnReductionTimer = 0;
var trapSpawnReductionInterval = 600; // 10 seconds at 60 FPS
// Health pickup spawning variables
var healthPickups = [];
var healthSpawnTimer = 0;
var healthSpawnInterval = 900; // 15 seconds at 60 FPS
var healthSpawnIncreaseTimer = 0;
var healthSpawnIncreaseInterval = 600; // 10 seconds at 60 FPS
var ringHole = game.addChild(LK.getAsset('ringHole', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2
}));
// Initialize rotation state
ringHole.isRotating = false;
// Create ball
var ball = game.addChild(new Ball());
// Create lives display with healthPickup icon
var livesContainer = new Container();
var livesIcon = livesContainer.addChild(LK.getAsset('healthPickup', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
// Position icon at container origin
width: 80,
// Match text size
height: 80 // Match text size
}));
var livesText = new Text2(lives, {
size: 80,
fill: 0xFFFFFF,
font: "'GillSans-Bold',Impact,'Arial Black',Tahoma"
});
livesText.anchor.set(0, 0.5); // Left-center anchor to align with icon center
livesText.x = 50; // Position text to the right of icon with some spacing
livesContainer.addChild(livesText);
livesContainer.x = 0;
livesContainer.y = 0;
LK.gui.top.addChild(livesContainer);
// Create container for Salt image and time display
var topContainer = new Container();
// Create Salt image
var saltImage = LK.getAsset('Salt', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
});
saltImage.x = -60; // Position to the left of center
saltImage.y = 120; // Align with text baseline
topContainer.addChild(saltImage);
// Create time display
var timeText = new Text2('0', {
size: 240,
fill: 0xFFFFFF,
font: "'GillSans-Bold',Impact,'Arial Black',Tahoma"
});
timeText.anchor.set(0, 0.5); // Left-center aligned
timeText.x = 60; // Position to the right of center
timeText.y = 120; // Align with Salt image center
topContainer.addChild(timeText);
// Center the container at top
topContainer.x = 0;
topContainer.y = 0;
LK.gui.top.addChild(topContainer);
// Create best score display
var bestScore = storage.bestScore || 0;
var bestScoreText = new Text2(bestScore, {
size: 360,
fill: 0xFFFFFF,
font: "'GillSans-Bold',Impact,'Arial Black',Tahoma"
});
bestScoreText.anchor.set(0.5, 0.5); // Center anchor
bestScoreText.x = 200;
bestScoreText.y = -250;
LK.gui.bottom.addChild(bestScoreText);
// Create king image at bottom center
var kingImage = LK.getAsset('King', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 3,
scaleY: 3
});
kingImage.x = -200;
kingImage.y = -250;
LK.gui.bottom.addChild(kingImage);
// Add tap handler to reverse ball direction
game.down = function (x, y, obj) {
ball.speed = -ball.speed;
// Start game timer on first tap
if (!gameRunning) {
gameStartTime = Date.now();
gameRunning = true;
gameStarted = true;
}
};
game.update = function () {
// Update time display if game is running
if (gameRunning) {
currentTime = Math.floor((Date.now() - gameStartTime) / 1000);
timeText.setText(currentTime);
LK.setScore(currentTime);
}
// Position lives container below top container
livesContainer.y = topContainer.y + timeText.height + 40;
// Ball will continue moving infinitely around the ring
// Start rotation when game starts
if (gameStarted && !ringHole.isRotating) {
ringHole.isRotating = true;
// Create continuous rotation tween
tween(ringHole, {
rotation: Math.PI * 2
}, {
duration: 3000,
// 3 seconds for full rotation
easing: tween.linear,
onFinish: function onFinish() {
// Reset rotation to 0 and start again for continuous rotation
ringHole.rotation = 0;
ringHole.isRotating = false;
}
});
}
// Increase ball speed over time (only after game has started)
if (gameStarted) {
speedIncreaseTimer++;
if (speedIncreaseTimer >= speedIncreaseInterval) {
speedIncreaseTimer = 0;
// Increase speed by 10% each time, up to maximum
var currentSpeedMagnitude = Math.abs(ball.speed);
var newSpeed = Math.min(currentSpeedMagnitude * 1.1, maxSpeed);
// Maintain direction (positive or negative)
ball.speed = ball.speed > 0 ? newSpeed : -newSpeed;
}
// Reduce trap spawn interval by 10% every 10 seconds
trapSpawnReductionTimer++;
if (trapSpawnReductionTimer >= trapSpawnReductionInterval) {
trapSpawnReductionTimer = 0;
// Reduce spawn interval by 10% (minimum 60 frames = 1 second)
trapSpawnInterval = Math.max(trapSpawnInterval * 0.90, 60);
}
// Increase health pickup spawn interval by 5% every 10 seconds
healthSpawnIncreaseTimer++;
if (healthSpawnIncreaseTimer >= healthSpawnIncreaseInterval) {
healthSpawnIncreaseTimer = 0;
// Increase spawn interval by 5% (maximum 3600 frames = 60 seconds)
healthSpawnInterval = Math.min(healthSpawnInterval * 1.05, 3600);
}
}
// Spawn traps every 8 seconds (only after game has started)
if (gameStarted) {
trapSpawnTimer++;
if (trapSpawnTimer >= trapSpawnInterval) {
trapSpawnTimer = 0;
// Spawn trap at random position on screen edge
var trap = new Trap();
var side = Math.floor(Math.random() * 4); // 0=top, 1=right, 2=bottom, 3=left
switch (side) {
case 0:
// Top edge
trap.x = Math.random() * 2048;
trap.y = -40;
break;
case 1:
// Right edge
trap.x = 2048 + 40;
trap.y = Math.random() * 2732;
break;
case 2:
// Bottom edge
trap.x = Math.random() * 2048;
trap.y = 2732 + 40;
break;
case 3:
// Left edge
trap.x = -40;
trap.y = Math.random() * 2732;
break;
}
// Set direction toward ring center
trap.setDirection(2048 / 2, 2732 / 2);
traps.push(trap);
game.addChild(trap);
}
}
// Spawn health pickups every 8 seconds (only after game has started)
if (gameStarted) {
healthSpawnTimer++;
if (healthSpawnTimer >= healthSpawnInterval) {
healthSpawnTimer = 0;
// Spawn health pickup at random position on screen edge
var healthPickup = new HealthPickup();
var side = Math.floor(Math.random() * 4); // 0=top, 1=right, 2=bottom, 3=left
switch (side) {
case 0:
// Top edge
healthPickup.x = Math.random() * 2048;
healthPickup.y = -40;
break;
case 1:
// Right edge
healthPickup.x = 2048 + 40;
healthPickup.y = Math.random() * 2732;
break;
case 2:
// Bottom edge
healthPickup.x = Math.random() * 2048;
healthPickup.y = 2732 + 40;
break;
case 3:
// Left edge
healthPickup.x = -40;
healthPickup.y = Math.random() * 2732;
break;
}
// Set direction toward ring center
healthPickup.setDirection(2048 / 2, 2732 / 2);
healthPickups.push(healthPickup);
game.addChild(healthPickup);
}
}
// Check collision between ball and traps
for (var i = traps.length - 1; i >= 0; i--) {
var trap = traps[i];
// Check collision with ball
if (ball.intersects(trap)) {
lives--;
livesText.setText(lives);
// Remove the trap that hit the ball
trap.destroy();
traps.splice(i, 1);
// Check game over condition
if (lives <= 0) {
gameRunning = false;
// Update best score if current score is higher
if (currentTime > bestScore) {
bestScore = currentTime;
storage.bestScore = bestScore;
bestScoreText.setText(bestScore);
}
LK.showGameOver();
}
;
continue;
}
// Clean up traps that have moved off screen
if (trap.x < -100 || trap.x > 2148 || trap.y < -100 || trap.y > 2832) {
trap.destroy();
traps.splice(i, 1);
}
}
// Check collision between ball and health pickups
for (var j = healthPickups.length - 1; j >= 0; j--) {
var healthPickup = healthPickups[j];
// Check collision with ball
if (ball.intersects(healthPickup)) {
lives++;
livesText.setText(lives);
// Remove the health pickup that was collected
healthPickup.destroy();
healthPickups.splice(j, 1);
continue;
}
// Clean up health pickups that have moved off screen
if (healthPickup.x < -100 || healthPickup.x > 2148 || healthPickup.y < -100 || healthPickup.y > 2832) {
healthPickup.destroy();
healthPickups.splice(j, 1);
}
}
};
Circle smile face record dark color. In-Game asset. 2d. High contrast. No shadows. Cartoon
Circle smile human face. In-Game asset. 2d. High contrast. No shadows. Cartoon
Sand clock smile face. In-Game asset. 2d. High contrast. No shadows. Cartoon. Cartoon
King clock smile face. In-Game asset. 2d. High contrast. No shadows. Cartoon