/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Obstacle = Container.expand(function () {
var self = Container.call(this);
// Create obstacle graphics
var obstacleGraphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
// Movement properties
self.speed = 5;
self.direction = 1; // 1 for down, -1 for up
self.lastIntersecting = false;
self.update = function () {
// Move obstacle straight down only
self.y += self.speed;
// Remove obstacle if it goes off screen
if (self.y > 2732) {
self.destroy();
}
};
return self;
});
var SoccerBall = Container.expand(function () {
var self = Container.call(this);
// Create ball graphics
var ballBase = self.attachAsset('ball', {
anchorX: 0.5,
anchorY: 0.5
});
// Physics properties
self.velocityY = 0;
self.velocityX = 0;
self.gravity = 0.6;
self.bounceDamping = 0.8;
self.tapForce = -18;
self.maxVelocityY = 25;
self.maxVelocityX = 8;
// Game state
self.isGrounded = false;
self.lastY = 0;
self.update = function () {
// Only update physics if game has started
if (!gameStarted) {
return;
}
// Store last position
self.lastY = self.y;
// Apply gravity
self.velocityY += self.gravity;
// Limit velocities
if (self.velocityY > self.maxVelocityY) {
self.velocityY = self.maxVelocityY;
}
if (self.velocityX > self.maxVelocityX) {
self.velocityX = self.maxVelocityX;
}
if (self.velocityX < -self.maxVelocityX) {
self.velocityX = -self.maxVelocityX;
}
// Update position
self.x += self.velocityX;
self.y += self.velocityY;
// Screen boundaries
var ballRadius = 60;
// Top boundary collision
if (self.y - ballRadius <= 0) {
self.y = ballRadius;
self.velocityY = Math.abs(self.velocityY) * self.bounceDamping;
LK.getSound('bounce').play();
}
// Left/right wall bouncing
if (self.x - ballRadius <= 0) {
self.x = ballRadius;
self.velocityX = Math.abs(self.velocityX) * self.bounceDamping;
LK.getSound('bounce').play();
} else if (self.x + ballRadius >= 2048) {
self.x = 2048 - ballRadius;
self.velocityX = -Math.abs(self.velocityX) * self.bounceDamping;
LK.getSound('bounce').play();
}
// Ground collision detection
if (self.y + ballRadius >= 2732) {
if (!self.isGrounded) {
self.isGrounded = true;
gameOver();
}
}
// Add slight rotation for visual effect
ballBase.rotation += self.velocityX * 0.02;
};
self.applyTapForce = function (tapX) {
if (!self.isGrounded) {
self.velocityY = self.tapForce;
// Apply horizontal force based on tap position
var screenCenter = 1024; // Screen width / 2
var horizontalForce = 6;
if (tapX > screenCenter) {
// Tap on right side - move right
self.velocityX += horizontalForce;
} else {
// Tap on left side - move left
self.velocityX -= horizontalForce;
}
// Visual feedback
tween(self, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 100
});
tween(self, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200
});
LK.getSound('tap').play();
// Increase score
score++;
updateScore();
// Increase difficulty
increaseDifficulty();
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x0a0a1a
});
/****
* Game Code
****/
// Game variables
var ball;
var score = 0;
var baseGravity = 0.6;
var baseTapForce = -18;
var gameStarted = false;
var obstacles = [];
var obstacleSpawnTimer = 0;
var obstacleSpawnInterval = 180; // Spawn every 3 seconds at 60fps
var exitGate;
var exitGateVisible = false;
// Create night sky with stars
var starField = new Container();
game.addChild(starField);
// Create multiple stars of different sizes
for (var i = 0; i < 80; i++) {
var starSize = Math.random() * 3 + 1;
var star = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: starSize / 400,
scaleY: starSize / 400
});
star.x = Math.random() * 2048;
star.y = Math.random() * 2732;
star.alpha = Math.random() * 0.8 + 0.2;
starField.addChild(star);
}
// Add a larger moon
var moon = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.3,
scaleY: 0.3
});
moon.x = 1800;
moon.y = 400;
moon.alpha = 0.9;
moon.tint = 0xffffcc;
starField.addChild(moon);
// Position tracking variables
var positionGrid = {}; // Track time spent in each grid cell
var gridSize = 200; // Size of each grid cell
var positionUpdateTimer = 0;
var positionUpdateInterval = 10; // Update every 10 frames
// UI elements
var scoreTxt = new Text2('0', {
size: 120,
fill: 0xFFD700
});
scoreTxt.anchor.set(0.5, 0);
scoreTxt.y = 50;
LK.gui.top.addChild(scoreTxt);
var scoreLabel = new Text2('SCORE', {
size: 60,
fill: 0xFFFFFF
});
scoreLabel.anchor.set(0.5, 0);
scoreLabel.y = 10;
LK.gui.top.addChild(scoreLabel);
// Welcome screen elements
var welcomeScreen = new Container();
game.addChild(welcomeScreen);
var titleTxt = new Text2('SOCCER BALL KEEPER', {
size: 100,
fill: 0xFFFFFF
});
titleTxt.anchor.set(0.5, 0.5);
titleTxt.x = 1024;
titleTxt.y = 800;
welcomeScreen.addChild(titleTxt);
var subtitleTxt = new Text2('HOĹGELDİNİZ', {
size: 80,
fill: 0xFFD700
});
subtitleTxt.anchor.set(0.5, 0.5);
subtitleTxt.x = 1024;
subtitleTxt.y = 950;
welcomeScreen.addChild(subtitleTxt);
var startButton = LK.getAsset('start', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.0,
scaleY: 1.0,
rotation: 0
});
startButton.x = 1024;
startButton.y = 1200;
startButton.interactive = true;
startButton.buttonMode = true;
startButton.alpha = 0.9;
welcomeScreen.addChild(startButton);
var startButtonText = new Text2('START', {
size: 100,
fill: 0xFFFFFF
});
startButtonText.anchor.set(0.5, 0.5);
startButtonText.x = 1024;
startButtonText.y = 1200;
welcomeScreen.addChild(startButtonText);
var quitButton = new Text2('QUIT', {
size: 120,
fill: 0xFF0000
});
quitButton.anchor.set(0.5, 0.5);
quitButton.x = 1024;
quitButton.y = 1450;
quitButton.interactive = true;
quitButton.buttonMode = true;
quitButton.alpha = 0.9;
welcomeScreen.addChild(quitButton);
// Add button hover effects
startButton.move = function () {
startButton.alpha = 1.0;
tween(startButton, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 150
});
};
quitButton.move = function () {
quitButton.alpha = 1.0;
tween(quitButton, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 150
});
};
var instructionTxt = new Text2('TAP TO KEEP THE BALL UP!', {
size: 80,
fill: 0xFFFFFF
});
instructionTxt.anchor.set(0.5, 0.5);
instructionTxt.x = 1024;
instructionTxt.y = 900;
instructionTxt.visible = false;
game.addChild(instructionTxt);
// Add field elements
var centerLine = LK.getAsset('fieldLine', {
anchorX: 0.5,
anchorY: 0.5
});
centerLine.x = 1024;
centerLine.y = 1366;
game.addChild(centerLine);
var centerCircleOutline = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5
});
centerCircleOutline.x = 1024;
centerCircleOutline.y = 1366;
centerCircleOutline.alpha = 0.3;
game.addChild(centerCircleOutline);
var topGoalArea = LK.getAsset('goalArea', {
anchorX: 0.5,
anchorY: 0.5
});
topGoalArea.x = 1024;
topGoalArea.y = 100;
topGoalArea.alpha = 0.2;
game.addChild(topGoalArea);
var bottomGoalArea = LK.getAsset('goalArea', {
anchorX: 0.5,
anchorY: 0.5
});
bottomGoalArea.x = 1024;
bottomGoalArea.y = 2632;
bottomGoalArea.alpha = 0.2;
game.addChild(bottomGoalArea);
// Initialize ball but hide it initially
ball = game.addChild(new SoccerBall());
ball.x = 1024;
ball.y = 1000;
ball.visible = false;
// Create exit gate
exitGate = LK.getAsset('exitGate', {
anchorX: 0.5,
anchorY: 0.5
});
exitGate.x = 1024;
exitGate.y = 300;
exitGate.visible = false;
game.addChild(exitGate);
// Add exit gate text
var exitGateText = new Text2('EXIT', {
size: 60,
fill: 0x000000
});
exitGateText.anchor.set(0.5, 0.5);
exitGateText.x = 1024;
exitGateText.y = 300;
exitGateText.visible = false;
game.addChild(exitGateText);
// Hide field elements initially
centerLine.visible = false;
centerCircleOutline.visible = false;
topGoalArea.visible = false;
bottomGoalArea.visible = false;
function updateScore() {
scoreTxt.setText(score.toString());
// Check if player reached winning score
if (score >= 100 && !exitGateVisible) {
exitGateVisible = true;
exitGate.visible = true;
exitGateText.visible = true;
// Flash the exit gate to draw attention
tween(exitGate, {
alpha: 0.5
}, {
duration: 500,
repeat: -1,
yoyo: true
});
}
}
function increaseDifficulty() {
// Slightly increase gravity and reduce tap effectiveness as score increases
var difficultyMultiplier = Math.min(1 + score * 0.01, 1.5);
ball.gravity = baseGravity * difficultyMultiplier;
ball.tapForce = baseTapForce * (1 / Math.sqrt(difficultyMultiplier));
}
function gameOver() {
LK.showGameOver();
}
function trackPlayerPosition() {
if (!gameStarted || !ball) return;
// Get grid coordinates
var gridX = Math.floor(ball.x / gridSize);
var gridY = Math.floor(ball.y / gridSize);
var gridKey = gridX + "_" + gridY;
// Increment time spent in this grid cell
if (!positionGrid[gridKey]) {
positionGrid[gridKey] = 0;
}
positionGrid[gridKey]++;
}
function getMostVisitedPosition() {
var maxTime = 0;
var mostVisitedKey = "5_7"; // Default to center area
var mostVisitedX = 1024;
var mostVisitedY = 1400;
// Find grid cell with most time spent
for (var key in positionGrid) {
if (positionGrid[key] > maxTime) {
maxTime = positionGrid[key];
mostVisitedKey = key;
}
}
// Convert grid key back to world coordinates
var parts = mostVisitedKey.split("_");
var gridX = parseInt(parts[0]);
var gridY = parseInt(parts[1]);
mostVisitedX = gridX * gridSize + gridSize / 2;
mostVisitedY = gridY * gridSize + gridSize / 2;
// Add some randomness around the most visited position
var randomOffset = 100;
mostVisitedX += (Math.random() - 0.5) * randomOffset;
mostVisitedY += (Math.random() - 0.5) * randomOffset;
// Keep within screen bounds
mostVisitedX = Math.max(150, Math.min(1898, mostVisitedX));
mostVisitedY = Math.max(100, Math.min(2632, mostVisitedY));
return {
x: mostVisitedX,
y: mostVisitedY
};
}
function startGame() {
if (!gameStarted) {
gameStarted = true;
// Hide welcome screen
welcomeScreen.visible = false;
// Show game elements
ball.visible = true;
centerLine.visible = true;
centerCircleOutline.visible = true;
topGoalArea.visible = true;
bottomGoalArea.visible = true;
instructionTxt.visible = true;
ball.applyTapForce(1024);
// Clear any existing obstacles
for (var i = 0; i < obstacles.length; i++) {
obstacles[i].destroy();
}
obstacles = [];
obstacleSpawnTimer = 0;
// Reset position tracking
positionGrid = {};
positionUpdateTimer = 0;
// Reset exit gate
exitGateVisible = false;
exitGate.visible = false;
exitGateText.visible = false;
}
}
// Event handlers
startButton.down = function (x, y, obj) {
startGame();
};
quitButton.down = function (x, y, obj) {
LK.showGameOver();
};
game.down = function (x, y, obj) {
if (gameStarted) {
ball.applyTapForce(x);
}
};
game.update = function () {
// Game loop handled by ball's update method
if (gameStarted) {
// Track player position
positionUpdateTimer++;
if (positionUpdateTimer >= positionUpdateInterval) {
positionUpdateTimer = 0;
trackPlayerPosition();
}
// Spawn obstacles
obstacleSpawnTimer++;
if (obstacleSpawnTimer >= obstacleSpawnInterval) {
obstacleSpawnTimer = 0;
var obstacle = new Obstacle();
// Spawn obstacle at random X position
obstacle.x = Math.random() * (2048 - 500) + 250; // Random X within screen bounds, accounting for obstacle width
obstacle.y = -50; // Start from top of screen
obstacles.push(obstacle);
game.addChild(obstacle);
}
// Check collision with obstacles
for (var i = obstacles.length - 1; i >= 0; i--) {
var obstacle = obstacles[i];
var currentIntersecting = ball.intersects(obstacle);
if (currentIntersecting) {
// Collision detected - game over immediately
gameOver();
return; // Stop game loop immediately
}
obstacle.lastIntersecting = currentIntersecting;
}
// Check collision with exit gate
if (exitGateVisible && ball.intersects(exitGate)) {
LK.showYouWin();
return;
}
// Remove obstacles that are too old (optional cleanup)
if (obstacles.length > 6) {
var oldObstacle = obstacles.shift();
oldObstacle.destroy();
}
}
};
// Initial score display
updateScore(); /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Obstacle = Container.expand(function () {
var self = Container.call(this);
// Create obstacle graphics
var obstacleGraphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
// Movement properties
self.speed = 5;
self.direction = 1; // 1 for down, -1 for up
self.lastIntersecting = false;
self.update = function () {
// Move obstacle straight down only
self.y += self.speed;
// Remove obstacle if it goes off screen
if (self.y > 2732) {
self.destroy();
}
};
return self;
});
var SoccerBall = Container.expand(function () {
var self = Container.call(this);
// Create ball graphics
var ballBase = self.attachAsset('ball', {
anchorX: 0.5,
anchorY: 0.5
});
// Physics properties
self.velocityY = 0;
self.velocityX = 0;
self.gravity = 0.6;
self.bounceDamping = 0.8;
self.tapForce = -18;
self.maxVelocityY = 25;
self.maxVelocityX = 8;
// Game state
self.isGrounded = false;
self.lastY = 0;
self.update = function () {
// Only update physics if game has started
if (!gameStarted) {
return;
}
// Store last position
self.lastY = self.y;
// Apply gravity
self.velocityY += self.gravity;
// Limit velocities
if (self.velocityY > self.maxVelocityY) {
self.velocityY = self.maxVelocityY;
}
if (self.velocityX > self.maxVelocityX) {
self.velocityX = self.maxVelocityX;
}
if (self.velocityX < -self.maxVelocityX) {
self.velocityX = -self.maxVelocityX;
}
// Update position
self.x += self.velocityX;
self.y += self.velocityY;
// Screen boundaries
var ballRadius = 60;
// Top boundary collision
if (self.y - ballRadius <= 0) {
self.y = ballRadius;
self.velocityY = Math.abs(self.velocityY) * self.bounceDamping;
LK.getSound('bounce').play();
}
// Left/right wall bouncing
if (self.x - ballRadius <= 0) {
self.x = ballRadius;
self.velocityX = Math.abs(self.velocityX) * self.bounceDamping;
LK.getSound('bounce').play();
} else if (self.x + ballRadius >= 2048) {
self.x = 2048 - ballRadius;
self.velocityX = -Math.abs(self.velocityX) * self.bounceDamping;
LK.getSound('bounce').play();
}
// Ground collision detection
if (self.y + ballRadius >= 2732) {
if (!self.isGrounded) {
self.isGrounded = true;
gameOver();
}
}
// Add slight rotation for visual effect
ballBase.rotation += self.velocityX * 0.02;
};
self.applyTapForce = function (tapX) {
if (!self.isGrounded) {
self.velocityY = self.tapForce;
// Apply horizontal force based on tap position
var screenCenter = 1024; // Screen width / 2
var horizontalForce = 6;
if (tapX > screenCenter) {
// Tap on right side - move right
self.velocityX += horizontalForce;
} else {
// Tap on left side - move left
self.velocityX -= horizontalForce;
}
// Visual feedback
tween(self, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 100
});
tween(self, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200
});
LK.getSound('tap').play();
// Increase score
score++;
updateScore();
// Increase difficulty
increaseDifficulty();
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x0a0a1a
});
/****
* Game Code
****/
// Game variables
var ball;
var score = 0;
var baseGravity = 0.6;
var baseTapForce = -18;
var gameStarted = false;
var obstacles = [];
var obstacleSpawnTimer = 0;
var obstacleSpawnInterval = 180; // Spawn every 3 seconds at 60fps
var exitGate;
var exitGateVisible = false;
// Create night sky with stars
var starField = new Container();
game.addChild(starField);
// Create multiple stars of different sizes
for (var i = 0; i < 80; i++) {
var starSize = Math.random() * 3 + 1;
var star = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: starSize / 400,
scaleY: starSize / 400
});
star.x = Math.random() * 2048;
star.y = Math.random() * 2732;
star.alpha = Math.random() * 0.8 + 0.2;
starField.addChild(star);
}
// Add a larger moon
var moon = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.3,
scaleY: 0.3
});
moon.x = 1800;
moon.y = 400;
moon.alpha = 0.9;
moon.tint = 0xffffcc;
starField.addChild(moon);
// Position tracking variables
var positionGrid = {}; // Track time spent in each grid cell
var gridSize = 200; // Size of each grid cell
var positionUpdateTimer = 0;
var positionUpdateInterval = 10; // Update every 10 frames
// UI elements
var scoreTxt = new Text2('0', {
size: 120,
fill: 0xFFD700
});
scoreTxt.anchor.set(0.5, 0);
scoreTxt.y = 50;
LK.gui.top.addChild(scoreTxt);
var scoreLabel = new Text2('SCORE', {
size: 60,
fill: 0xFFFFFF
});
scoreLabel.anchor.set(0.5, 0);
scoreLabel.y = 10;
LK.gui.top.addChild(scoreLabel);
// Welcome screen elements
var welcomeScreen = new Container();
game.addChild(welcomeScreen);
var titleTxt = new Text2('SOCCER BALL KEEPER', {
size: 100,
fill: 0xFFFFFF
});
titleTxt.anchor.set(0.5, 0.5);
titleTxt.x = 1024;
titleTxt.y = 800;
welcomeScreen.addChild(titleTxt);
var subtitleTxt = new Text2('HOĹGELDİNİZ', {
size: 80,
fill: 0xFFD700
});
subtitleTxt.anchor.set(0.5, 0.5);
subtitleTxt.x = 1024;
subtitleTxt.y = 950;
welcomeScreen.addChild(subtitleTxt);
var startButton = LK.getAsset('start', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.0,
scaleY: 1.0,
rotation: 0
});
startButton.x = 1024;
startButton.y = 1200;
startButton.interactive = true;
startButton.buttonMode = true;
startButton.alpha = 0.9;
welcomeScreen.addChild(startButton);
var startButtonText = new Text2('START', {
size: 100,
fill: 0xFFFFFF
});
startButtonText.anchor.set(0.5, 0.5);
startButtonText.x = 1024;
startButtonText.y = 1200;
welcomeScreen.addChild(startButtonText);
var quitButton = new Text2('QUIT', {
size: 120,
fill: 0xFF0000
});
quitButton.anchor.set(0.5, 0.5);
quitButton.x = 1024;
quitButton.y = 1450;
quitButton.interactive = true;
quitButton.buttonMode = true;
quitButton.alpha = 0.9;
welcomeScreen.addChild(quitButton);
// Add button hover effects
startButton.move = function () {
startButton.alpha = 1.0;
tween(startButton, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 150
});
};
quitButton.move = function () {
quitButton.alpha = 1.0;
tween(quitButton, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 150
});
};
var instructionTxt = new Text2('TAP TO KEEP THE BALL UP!', {
size: 80,
fill: 0xFFFFFF
});
instructionTxt.anchor.set(0.5, 0.5);
instructionTxt.x = 1024;
instructionTxt.y = 900;
instructionTxt.visible = false;
game.addChild(instructionTxt);
// Add field elements
var centerLine = LK.getAsset('fieldLine', {
anchorX: 0.5,
anchorY: 0.5
});
centerLine.x = 1024;
centerLine.y = 1366;
game.addChild(centerLine);
var centerCircleOutline = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5
});
centerCircleOutline.x = 1024;
centerCircleOutline.y = 1366;
centerCircleOutline.alpha = 0.3;
game.addChild(centerCircleOutline);
var topGoalArea = LK.getAsset('goalArea', {
anchorX: 0.5,
anchorY: 0.5
});
topGoalArea.x = 1024;
topGoalArea.y = 100;
topGoalArea.alpha = 0.2;
game.addChild(topGoalArea);
var bottomGoalArea = LK.getAsset('goalArea', {
anchorX: 0.5,
anchorY: 0.5
});
bottomGoalArea.x = 1024;
bottomGoalArea.y = 2632;
bottomGoalArea.alpha = 0.2;
game.addChild(bottomGoalArea);
// Initialize ball but hide it initially
ball = game.addChild(new SoccerBall());
ball.x = 1024;
ball.y = 1000;
ball.visible = false;
// Create exit gate
exitGate = LK.getAsset('exitGate', {
anchorX: 0.5,
anchorY: 0.5
});
exitGate.x = 1024;
exitGate.y = 300;
exitGate.visible = false;
game.addChild(exitGate);
// Add exit gate text
var exitGateText = new Text2('EXIT', {
size: 60,
fill: 0x000000
});
exitGateText.anchor.set(0.5, 0.5);
exitGateText.x = 1024;
exitGateText.y = 300;
exitGateText.visible = false;
game.addChild(exitGateText);
// Hide field elements initially
centerLine.visible = false;
centerCircleOutline.visible = false;
topGoalArea.visible = false;
bottomGoalArea.visible = false;
function updateScore() {
scoreTxt.setText(score.toString());
// Check if player reached winning score
if (score >= 100 && !exitGateVisible) {
exitGateVisible = true;
exitGate.visible = true;
exitGateText.visible = true;
// Flash the exit gate to draw attention
tween(exitGate, {
alpha: 0.5
}, {
duration: 500,
repeat: -1,
yoyo: true
});
}
}
function increaseDifficulty() {
// Slightly increase gravity and reduce tap effectiveness as score increases
var difficultyMultiplier = Math.min(1 + score * 0.01, 1.5);
ball.gravity = baseGravity * difficultyMultiplier;
ball.tapForce = baseTapForce * (1 / Math.sqrt(difficultyMultiplier));
}
function gameOver() {
LK.showGameOver();
}
function trackPlayerPosition() {
if (!gameStarted || !ball) return;
// Get grid coordinates
var gridX = Math.floor(ball.x / gridSize);
var gridY = Math.floor(ball.y / gridSize);
var gridKey = gridX + "_" + gridY;
// Increment time spent in this grid cell
if (!positionGrid[gridKey]) {
positionGrid[gridKey] = 0;
}
positionGrid[gridKey]++;
}
function getMostVisitedPosition() {
var maxTime = 0;
var mostVisitedKey = "5_7"; // Default to center area
var mostVisitedX = 1024;
var mostVisitedY = 1400;
// Find grid cell with most time spent
for (var key in positionGrid) {
if (positionGrid[key] > maxTime) {
maxTime = positionGrid[key];
mostVisitedKey = key;
}
}
// Convert grid key back to world coordinates
var parts = mostVisitedKey.split("_");
var gridX = parseInt(parts[0]);
var gridY = parseInt(parts[1]);
mostVisitedX = gridX * gridSize + gridSize / 2;
mostVisitedY = gridY * gridSize + gridSize / 2;
// Add some randomness around the most visited position
var randomOffset = 100;
mostVisitedX += (Math.random() - 0.5) * randomOffset;
mostVisitedY += (Math.random() - 0.5) * randomOffset;
// Keep within screen bounds
mostVisitedX = Math.max(150, Math.min(1898, mostVisitedX));
mostVisitedY = Math.max(100, Math.min(2632, mostVisitedY));
return {
x: mostVisitedX,
y: mostVisitedY
};
}
function startGame() {
if (!gameStarted) {
gameStarted = true;
// Hide welcome screen
welcomeScreen.visible = false;
// Show game elements
ball.visible = true;
centerLine.visible = true;
centerCircleOutline.visible = true;
topGoalArea.visible = true;
bottomGoalArea.visible = true;
instructionTxt.visible = true;
ball.applyTapForce(1024);
// Clear any existing obstacles
for (var i = 0; i < obstacles.length; i++) {
obstacles[i].destroy();
}
obstacles = [];
obstacleSpawnTimer = 0;
// Reset position tracking
positionGrid = {};
positionUpdateTimer = 0;
// Reset exit gate
exitGateVisible = false;
exitGate.visible = false;
exitGateText.visible = false;
}
}
// Event handlers
startButton.down = function (x, y, obj) {
startGame();
};
quitButton.down = function (x, y, obj) {
LK.showGameOver();
};
game.down = function (x, y, obj) {
if (gameStarted) {
ball.applyTapForce(x);
}
};
game.update = function () {
// Game loop handled by ball's update method
if (gameStarted) {
// Track player position
positionUpdateTimer++;
if (positionUpdateTimer >= positionUpdateInterval) {
positionUpdateTimer = 0;
trackPlayerPosition();
}
// Spawn obstacles
obstacleSpawnTimer++;
if (obstacleSpawnTimer >= obstacleSpawnInterval) {
obstacleSpawnTimer = 0;
var obstacle = new Obstacle();
// Spawn obstacle at random X position
obstacle.x = Math.random() * (2048 - 500) + 250; // Random X within screen bounds, accounting for obstacle width
obstacle.y = -50; // Start from top of screen
obstacles.push(obstacle);
game.addChild(obstacle);
}
// Check collision with obstacles
for (var i = obstacles.length - 1; i >= 0; i--) {
var obstacle = obstacles[i];
var currentIntersecting = ball.intersects(obstacle);
if (currentIntersecting) {
// Collision detected - game over immediately
gameOver();
return; // Stop game loop immediately
}
obstacle.lastIntersecting = currentIntersecting;
}
// Check collision with exit gate
if (exitGateVisible && ball.intersects(exitGate)) {
LK.showYouWin();
return;
}
// Remove obstacles that are too old (optional cleanup)
if (obstacles.length > 6) {
var oldObstacle = obstacles.shift();
oldObstacle.destroy();
}
}
};
// Initial score display
updateScore();
Anything . No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
A rocket . No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
Thunder logo. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
A sign . No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
Robotic door metal exit door. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
A stone. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat