/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { highScore: 0, difficulty: 1, gameMode: "single" }); /**** * Classes ****/ var Ball = Container.expand(function () { var self = Container.call(this); self.graphics = self.attachAsset('ball', { anchorX: 0.5, anchorY: 0.5 }); self.radius = 15; // Half of the ball width/height self.speedX = 0; self.speedY = 0; self.baseSpeed = 12; self.reset = function () { self.x = 2048 / 2; self.y = 2732 / 2; // Randomize initial direction var angle = Math.random() * Math.PI / 4 + Math.PI / 4; // 45-90 degrees if (Math.random() < 0.5) { angle = Math.PI - angle; } // Left or right self.speedX = Math.cos(angle) * self.baseSpeed; self.speedY = (Math.random() < 0.5 ? -1 : 1) * Math.sin(angle) * self.baseSpeed; }; self.increaseSpeed = function () { var currentSpeed = Math.sqrt(self.speedX * self.speedX + self.speedY * self.speedY); var multiplier = 1.2; self.speedX = self.speedX / currentSpeed * (currentSpeed * multiplier); self.speedY = self.speedY / currentSpeed * (currentSpeed * multiplier); }; self.update = function () { // Update position self.x += self.speedX; self.y += self.speedY; // Handle collisions with side walls if (self.x - self.radius < 0) { self.x = self.radius; self.speedX = -self.speedX; LK.getSound('hit').play(); } else if (self.x + self.radius > 2048) { self.x = 2048 - self.radius; self.speedX = -self.speedX; LK.getSound('hit').play(); } // Check for collisions with paddles self.checkPaddleCollisions(); // Check for score (ball off screen) if (self.y - self.radius < 0) { // Opponent scores increaseScore(false); self.reset(); } else if (self.y + self.radius > 2732) { // Player scores increaseScore(true); self.reset(); } }; self.checkPaddleCollisions = function () { // Check collision with player paddle if (self.speedY > 0 && self.y + self.radius >= playerPaddle.y - playerPaddle.height / 2 && self.y - self.radius <= playerPaddle.y + playerPaddle.height / 2 && self.x >= playerPaddle.x - playerPaddle.graphics.width / 2 && self.x <= playerPaddle.x + playerPaddle.graphics.width / 2) { // Bounce with angle based on hit position self.speedY = -self.speedY; var hitPos = (self.x - playerPaddle.x) / (playerPaddle.graphics.width / 2); self.speedX = hitPos * (self.baseSpeed * 0.8); // Ensure minimum vertical speed var currentSpeed = Math.sqrt(self.speedX * self.speedX + self.speedY * self.speedY); if (currentSpeed < self.baseSpeed) { var factor = self.baseSpeed / currentSpeed; self.speedX *= factor; self.speedY *= factor; } self.y = playerPaddle.y - playerPaddle.height / 2 - self.radius - 1; // Move out of collision LK.getSound('hit').play(); } // Check collision with opponent paddle if (self.speedY < 0 && self.y - self.radius <= opponentPaddle.y + opponentPaddle.height / 2 && self.y + self.radius >= opponentPaddle.y - opponentPaddle.height / 2 && self.x >= opponentPaddle.x - opponentPaddle.graphics.width / 2 && self.x <= opponentPaddle.x + opponentPaddle.graphics.width / 2) { // Bounce with angle based on hit position self.speedY = -self.speedY; var hitPos = (self.x - opponentPaddle.x) / (opponentPaddle.graphics.width / 2); self.speedX = hitPos * (self.baseSpeed * 0.8); // Ensure minimum vertical speed var currentSpeed = Math.sqrt(self.speedX * self.speedX + self.speedY * self.speedY); if (currentSpeed < self.baseSpeed) { var factor = self.baseSpeed / currentSpeed; self.speedX *= factor; self.speedY *= factor; } self.y = opponentPaddle.y + opponentPaddle.height / 2 + self.radius + 1; // Move out of collision LK.getSound('hit').play(); } }; return self; }); var Paddle = Container.expand(function () { var self = Container.call(this); self.width = 300; self.height = 50; self.speed = 15; self.originalWidth = 300; self.init = function (isPlayer) { self.isPlayer = isPlayer; var assetId = isPlayer ? 'paddlePlayer' : 'paddleOpponent'; self.graphics = self.attachAsset(assetId, { anchorX: 0.5, anchorY: 0.5 }); }; self.resetSize = function () { tween(self.graphics, { width: self.originalWidth }, { duration: 300, easing: tween.easeOut }); }; self.enlarge = function () { tween(self.graphics, { width: self.originalWidth * 1.5 }, { duration: 300, easing: tween.easeOut }); }; self.shrink = function () { tween(self.graphics, { width: self.originalWidth * 0.7 }, { duration: 300, easing: tween.easeOut }); }; self.update = function () { // AI movement for opponent in single player mode if (!self.isPlayer && gameMode === 'single' && ball) { var targetX = ball.x; var difficulty = storage.difficulty || 1; // 1-3 (easy to hard) var maxSpeed = self.speed * (0.5 + difficulty * 0.25); // Add some delay and imperfection for easier difficulties if (difficulty < 3) { var reactionDelay = (3 - difficulty) * 10; if (LK.ticks % reactionDelay === 0) { // Only update target position occasionally based on difficulty var error = (3 - difficulty) * 100; targetX += Math.random() * error * 2 - error; } } // Move paddle towards the ball with speed based on difficulty var moveDirection = targetX > self.x ? 1 : -1; var distance = Math.abs(targetX - self.x); if (distance > 10) { var moveAmount = Math.min(distance, maxSpeed); self.x += moveDirection * moveAmount; } } // Keep paddles within game boundaries if (self.x < self.graphics.width / 2) { self.x = self.graphics.width / 2; } else if (self.x > 2048 - self.graphics.width / 2) { self.x = 2048 - self.graphics.width / 2; } }; return self; }); var PowerUp = Container.expand(function () { var self = Container.call(this); self.graphics = self.attachAsset('powerUp', { anchorX: 0.5, anchorY: 0.5 }); self.type = 'none'; self.active = false; self.radius = 25; // Half of the powerup width/height self.spawn = function () { // Choose random type var types = ['speed', 'enlarge', 'shrink']; self.type = types[Math.floor(Math.random() * types.length)]; // Set position randomly on field self.x = Math.random() * (2048 - 200) + 100; self.y = Math.random() * (2732 - 500) + 250; // Set color based on type switch (self.type) { case 'speed': self.graphics.tint = 0xff5500; // Orange break; case 'enlarge': self.graphics.tint = 0x00ff00; // Green break; case 'shrink': self.graphics.tint = 0xff0000; // Red break; } self.active = true; game.addChild(self); // Auto-despawn after 7 seconds LK.setTimeout(function () { if (self.active) { self.despawn(); } }, 7000); }; self.despawn = function () { self.active = false; game.removeChild(self); }; self.update = function () { if (!self.active || !ball) { return; } // Check collision with ball var dx = ball.x - self.x; var dy = ball.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < ball.radius + self.radius) { self.applyEffect(); self.despawn(); LK.getSound('powerup').play(); } }; self.applyEffect = function () { switch (self.type) { case 'speed': ball.increaseSpeed(); LK.effects.flashObject(ball, 0xff5500, 1000); // Flash orange break; case 'enlarge': // Enlarge the paddle that's about to receive the ball if (ball.speedY > 0) { playerPaddle.enlarge(); LK.effects.flashObject(playerPaddle, 0x00ff00, 1000); // Flash green // Reset size after 10 seconds LK.setTimeout(function () { playerPaddle.resetSize(); }, 10000); } else { opponentPaddle.enlarge(); LK.effects.flashObject(opponentPaddle, 0x00ff00, 1000); // Flash green // Reset size after 10 seconds LK.setTimeout(function () { opponentPaddle.resetSize(); }, 10000); } break; case 'shrink': // Shrink the paddle that's about to receive the ball if (ball.speedY > 0) { opponentPaddle.shrink(); LK.effects.flashObject(opponentPaddle, 0xff0000, 1000); // Flash red // Reset size after 10 seconds LK.setTimeout(function () { opponentPaddle.resetSize(); }, 10000); } else { playerPaddle.shrink(); LK.effects.flashObject(playerPaddle, 0xff0000, 1000); // Flash red // Reset size after 10 seconds LK.setTimeout(function () { playerPaddle.resetSize(); }, 10000); } break; } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x222222 }); /**** * Game Code ****/ // Game variables var gameMode = storage.gameMode || 'single'; var playerScore = 0; var opponentScore = 0; var highScore = storage.highScore || 0; var maxScore = 5; var isPaused = false; var activePowerUp = null; var draggingPlayerPaddle = false; var draggingOpponentPaddle = false; // Game elements var playerPaddle; var opponentPaddle; var ball; var centerLine; // UI elements var playerScoreText; var opponentScoreText; var gameModeText; var gameModeToggle; function setupGameElements() { // Create center line centerLine = LK.getAsset('centerLine', { anchorX: 0.5, anchorY: 0.5, alpha: 0.3 }); centerLine.x = 2048 / 2; centerLine.y = 2732 / 2; game.addChild(centerLine); // Create paddles playerPaddle = new Paddle(); playerPaddle.init(true); playerPaddle.x = 2048 / 2; playerPaddle.y = 2732 - 200; game.addChild(playerPaddle); opponentPaddle = new Paddle(); opponentPaddle.init(false); opponentPaddle.x = 2048 / 2; opponentPaddle.y = 200; game.addChild(opponentPaddle); // Create ball ball = new Ball(); ball.reset(); game.addChild(ball); // Create power-up activePowerUp = new PowerUp(); // Schedule regular power-up spawns LK.setInterval(function () { if (!activePowerUp.active) { activePowerUp.spawn(); } }, 15000); // Every 15 seconds // Set up UI setupUI(); } function setupUI() { // Player score text playerScoreText = new Text2('0', { size: 120, fill: 0x3498DB }); playerScoreText.anchor.set(0.5, 0.5); playerScoreText.x = 2048 / 2; playerScoreText.y = 2732 / 2 + 150; game.addChild(playerScoreText); // Opponent score text opponentScoreText = new Text2('0', { size: 120, fill: 0xE74C3C }); opponentScoreText.anchor.set(0.5, 0.5); opponentScoreText.x = 2048 / 2; opponentScoreText.y = 2732 / 2 - 150; game.addChild(opponentScoreText); // High score text var highScoreText = new Text2('High Score: ' + highScore, { size: 40, fill: 0xFFFFFF }); highScoreText.anchor.set(0.5, 0.5); highScoreText.x = 2048 / 2; highScoreText.y = 2732 / 2; game.addChild(highScoreText); // Game mode text gameModeText = new Text2(gameMode === 'single' ? 'SINGLE PLAYER' : 'MULTIPLAYER', { size: 40, fill: 0xFFFFFF }); gameModeText.anchor.set(0.5, 0.5); LK.gui.topRight.addChild(gameModeText); gameModeText.x = -200; gameModeText.y = 100; // Game mode toggle button gameModeToggle = LK.getAsset('centerLine', { width: 300, height: 60, color: 0x555555, anchorX: 0.5, anchorY: 0.5 }); gameModeToggle.x = -200; gameModeToggle.y = 180; var toggleText = new Text2('CHANGE MODE', { size: 30, fill: 0xFFFFFF }); toggleText.anchor.set(0.5, 0.5); gameModeToggle.addChild(toggleText); LK.gui.topRight.addChild(gameModeToggle); // Add event listener for mode toggle gameModeToggle.interactive = true; gameModeToggle.down = function () { toggleGameMode(); }; } function toggleGameMode() { gameMode = gameMode === 'single' ? 'multi' : 'single'; storage.gameMode = gameMode; gameModeText.setText(gameMode === 'single' ? 'SINGLE PLAYER' : 'MULTIPLAYER'); // Reset game when mode changes resetGame(); } function resetGame() { playerScore = 0; opponentScore = 0; updateScoreDisplay(); if (ball) { ball.reset(); } if (playerPaddle) { playerPaddle.x = 2048 / 2; playerPaddle.resetSize(); } if (opponentPaddle) { opponentPaddle.x = 2048 / 2; opponentPaddle.resetSize(); } if (activePowerUp && activePowerUp.active) { activePowerUp.despawn(); } } function increaseScore(isPlayer) { if (isPlayer) { playerScore++; } else { opponentScore++; } updateScoreDisplay(); LK.getSound('score').play(); // Check for game over if (playerScore >= maxScore || opponentScore >= maxScore) { LK.setTimeout(function () { if (playerScore >= maxScore) { if (playerScore > highScore) { highScore = playerScore; storage.highScore = highScore; } LK.showYouWin(); } else { LK.showGameOver(); } }, 500); } } function updateScoreDisplay() { playerScoreText.setText(playerScore.toString()); opponentScoreText.setText(opponentScore.toString()); } function handlePaddleMovement(x, y) { if (draggingPlayerPaddle) { playerPaddle.x = x; } if (gameMode === 'multi' && draggingOpponentPaddle) { opponentPaddle.x = x; } } // Input handlers game.down = function (x, y, obj) { // Check if clicking on player paddle if (y > 2732 / 2) { draggingPlayerPaddle = true; handlePaddleMovement(x, y); } // Check if clicking on opponent paddle (only in multiplayer) else if (gameMode === 'multi' && y < 2732 / 2) { draggingOpponentPaddle = true; handlePaddleMovement(x, y); } }; game.up = function (x, y, obj) { draggingPlayerPaddle = false; draggingOpponentPaddle = false; }; game.move = function (x, y, obj) { handlePaddleMovement(x, y); }; // Game loop game.update = function () { if (isPaused) { return; } // Update game elements if (playerPaddle) { playerPaddle.update(); } if (opponentPaddle) { opponentPaddle.update(); } if (ball) { ball.update(); } if (activePowerUp && activePowerUp.active) { activePowerUp.update(); } }; // Initialize game setupGameElements(); resetGame(); // Play background music LK.playMusic('gameMusic', { fade: { start: 0, end: 0.3, duration: 1000 } });
===================================================================
--- original.js
+++ change.js
@@ -286,8 +286,9 @@
// Game variables
var gameMode = storage.gameMode || 'single';
var playerScore = 0;
var opponentScore = 0;
+var highScore = storage.highScore || 0;
var maxScore = 5;
var isPaused = false;
var activePowerUp = null;
var draggingPlayerPaddle = false;
@@ -356,8 +357,17 @@
opponentScoreText.anchor.set(0.5, 0.5);
opponentScoreText.x = 2048 / 2;
opponentScoreText.y = 2732 / 2 - 150;
game.addChild(opponentScoreText);
+ // High score text
+ var highScoreText = new Text2('High Score: ' + highScore, {
+ size: 40,
+ fill: 0xFFFFFF
+ });
+ highScoreText.anchor.set(0.5, 0.5);
+ highScoreText.x = 2048 / 2;
+ highScoreText.y = 2732 / 2;
+ game.addChild(highScoreText);
// Game mode text
gameModeText = new Text2(gameMode === 'single' ? 'SINGLE PLAYER' : 'MULTIPLAYER', {
size: 40,
fill: 0xFFFFFF
@@ -426,8 +436,12 @@
// Check for game over
if (playerScore >= maxScore || opponentScore >= maxScore) {
LK.setTimeout(function () {
if (playerScore >= maxScore) {
+ if (playerScore > highScore) {
+ highScore = playerScore;
+ storage.highScore = highScore;
+ }
LK.showYouWin();
} else {
LK.showGameOver();
}