User prompt
add easy medium and hard ai choises on the home screen
User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'reset')' in or related to this line: 'ball.reset();' Line Number: 398
User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'x')' in or related to this line: 'playerScoreText.x = table.x - 200;' Line Number: 301
User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'width')' in or related to this line: 'var originalPaddleWidth = playerPaddle.width;' Line Number: 288
User prompt
add homescreen
User prompt
add powerupps
User prompt
add win and lose when ten points is reached
User prompt
ad a ping pong table
User prompt
Classic Ping Pong
Initial prompt
standard table tennis
/**** * Classes ****/ var Ball = Container.expand(function () { var self = Container.call(this); var ballGraphics = self.attachAsset('ball', { anchorX: 0.5, anchorY: 0.5 }); self.width = ballGraphics.width; self.height = ballGraphics.height; self.velocityX = 0; self.velocityY = 0; self.speed = 10; self.maxSpeed = 20; self.active = false; self.lastX = 0; self.lastY = 0; self.isClone = false; self.reset = function () { self.x = table.x; self.y = table.y; self.velocityY = self.speed; self.velocityX = Math.random() * 6 - 3; self.active = true; self.lastX = self.x; self.lastY = self.y; }; self.update = function () { if (!self.active) { return; } self.lastX = self.x; self.lastY = self.y; self.x += self.velocityX; self.y += self.velocityY; // Side wall collision if (self.x < table.x - table.width / 2 + self.width / 2 || self.x > table.x + table.width / 2 - self.width / 2) { self.velocityX = -self.velocityX; LK.getSound('hit').play(); } }; self.checkPaddleCollision = function (paddle) { if (self.intersects(paddle) && (self.velocityY > 0 && self.y < paddle.y || self.velocityY < 0 && self.y > paddle.y)) { // Calculate bounce angle based on where ball hit paddle var hitPos = (self.x - paddle.x) / (paddle.width / 2); self.velocityX = hitPos * 10; // Reverse Y velocity self.velocityY = -self.velocityY; // Increase speed slightly if (Math.abs(self.velocityY) < self.maxSpeed) { self.velocityY *= 1.05; } LK.getSound('hit').play(); return true; } return false; }; return self; }); // Game dimensions are 2048x2732 var Paddle = Container.expand(function () { var self = Container.call(this); var paddleGraphics = self.attachAsset('paddle', { anchorX: 0.5, anchorY: 0.5 }); self.width = paddleGraphics.width; self.height = paddleGraphics.height; self.speed = 10; self.isAI = false; self.targetX = 0; self.update = function () { if (self.isAI) { // AI movement logic if (Math.abs(self.x - self.targetX) > self.speed) { if (self.x < self.targetX) { self.x += self.speed; } else { self.x -= self.speed; } } } // Keep paddle within table bounds if (self.x < table.x - table.width / 2 + self.width / 2 + 20) { self.x = table.x - table.width / 2 + self.width / 2 + 20; } else if (self.x > table.x + table.width / 2 - self.width / 2 - 20) { self.x = table.x + table.width / 2 - self.width / 2 - 20; } }; return self; }); var PowerUp = Container.expand(function () { var self = Container.call(this); var powerUpGraphics = self.attachAsset('powerup', { anchorX: 0.5, anchorY: 0.5 }); self.width = powerUpGraphics.width; self.height = powerUpGraphics.height; self.type = 'none'; self.active = false; self.speed = 3; self.activate = function (type) { self.type = type; self.active = true; // Set appearance based on power-up type switch (type) { case 'wide': powerUpGraphics.tint = 0x00ff00; // Green for paddle widening break; case 'slow': powerUpGraphics.tint = 0x0000ff; // Blue for ball slowing break; case 'multi': powerUpGraphics.tint = 0xff00ff; // Purple for multi-ball break; } // Position randomly on table self.x = table.x + (Math.random() * table.width - table.width / 2) * 0.8; self.y = table.y + (Math.random() * table.height - table.height / 2) * 0.6; }; self.update = function () { if (!self.active) { return; } // Slowly move downward self.y += self.speed; // Remove if off table if (self.y > table.y + table.height / 2) { self.active = false; self.visible = false; } }; self.collect = function () { self.active = false; self.visible = false; return self.type; }; self.reset = function () { self.active = false; self.visible = false; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ // Game dimensions are 2048x2732 game.setBackgroundColor(0x1a1a1a); // Create table var table = game.addChild(LK.getAsset('table', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2 })); // Create net var net = game.addChild(LK.getAsset('net', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2 })); // Create player paddle var playerPaddle = new Paddle(); playerPaddle.x = 2048 / 2; playerPaddle.y = table.y + table.height / 2 - playerPaddle.height - 50; game.addChild(playerPaddle); // Create AI paddle var aiPaddle = new Paddle(); aiPaddle.x = 2048 / 2; aiPaddle.y = table.y - table.height / 2 + aiPaddle.height + 50; aiPaddle.isAI = true; game.addChild(aiPaddle); // Create ball var ball = new Ball(); game.addChild(ball); // Create additional balls for multi-ball power-up var balls = [ball]; var maxBalls = 3; for (var i = 1; i < maxBalls; i++) { var extraBall = new Ball(); extraBall.isClone = true; extraBall.visible = false; extraBall.active = false; game.addChild(extraBall); balls.push(extraBall); } // Create power-ups var powerUps = []; var maxPowerUps = 3; for (var i = 0; i < maxPowerUps; i++) { var powerUp = new PowerUp(); powerUp.visible = false; game.addChild(powerUp); powerUps.push(powerUp); } // Power-up state variables var powerUpTimer = null; var powerUpActive = false; var powerUpType = 'none'; var originalPaddleWidth = playerPaddle.width; var originalBallSpeed = ball.speed; // Create score text var playerScore = 0; var aiScore = 0; var playerScoreText = new Text2(playerScore.toString(), { size: 80, fill: 0xFFFFFF }); playerScoreText.anchor.set(0.5, 0.5); playerScoreText.x = table.x - 200; playerScoreText.y = table.y; game.addChild(playerScoreText); var aiScoreText = new Text2(aiScore.toString(), { size: 80, fill: 0xFFFFFF }); aiScoreText.anchor.set(0.5, 0.5); aiScoreText.x = table.x + 200; aiScoreText.y = table.y; game.addChild(aiScoreText); // Handle paddle dragging var isDragging = false; game.down = function (x, y, obj) { isDragging = true; playerPaddle.x = x; }; game.up = function (x, y, obj) { isDragging = false; }; game.move = function (x, y, obj) { if (isDragging) { playerPaddle.x = x; } }; // Power-up activation function function activatePowerUp(type) { // Clear any existing power-up effect if (powerUpTimer) { LK.clearTimeout(powerUpTimer); } // Reset previous power-up effects if (powerUpActive) { deactivatePowerUp(); } powerUpActive = true; powerUpType = type; switch (type) { case 'wide': // Widen paddle playerPaddle.width = originalPaddleWidth * 1.5; paddleGraphics = playerPaddle.children[0]; paddleGraphics.scale.x = 1.5; break; case 'slow': // Slow down ball for (var i = 0; i < balls.length; i++) { if (balls[i].active) { balls[i].velocityX *= 0.6; balls[i].velocityY *= 0.6; } } break; case 'multi': // Activate multi-ball for (var i = 1; i < balls.length; i++) { if (!balls[i].active) { balls[i].x = balls[0].x; balls[i].y = balls[0].y; balls[i].velocityX = balls[0].velocityX * (Math.random() > 0.5 ? 1 : -1); balls[i].velocityY = balls[0].velocityY; balls[i].active = true; balls[i].visible = true; break; } } break; } // Power-up lasts for 10 seconds powerUpTimer = LK.setTimeout(function () { deactivatePowerUp(); }, 10000); } // Function to deactivate power-ups function deactivatePowerUp() { powerUpActive = false; switch (powerUpType) { case 'wide': playerPaddle.width = originalPaddleWidth; paddleGraphics = playerPaddle.children[0]; paddleGraphics.scale.x = 1; break; case 'slow': // Ball speed will naturally increase over time break; case 'multi': // Multi-balls will remain until they go off screen break; } powerUpType = 'none'; } // Start the game with the ball ball.reset(); // Main game loop game.update = function () { // Update game objects playerPaddle.update(); aiPaddle.update(); // Update all balls for (var i = 0; i < balls.length; i++) { if (balls[i].active) { balls[i].update(); } } // Update power-ups for (var i = 0; i < powerUps.length; i++) { if (powerUps[i].active) { powerUps[i].update(); // Check if player paddle collects power-up if (powerUps[i].active && powerUps[i].intersects(playerPaddle)) { // Apply power-up effect var powerType = powerUps[i].collect(); activatePowerUp(powerType); LK.getSound('powerup').play(); } } } // Randomly spawn power-ups (about every 10 seconds on average) if (Math.random() < 0.002 && !powerUpActive) { // Find inactive power-up for (var i = 0; i < powerUps.length; i++) { if (!powerUps[i].active) { var types = ['wide', 'slow', 'multi']; var randomType = types[Math.floor(Math.random() * types.length)]; powerUps[i].activate(randomType); powerUps[i].visible = true; break; } } } // AI behavior - track the ball (closest one moving toward AI) var closestBall = null; var closestDistance = Infinity; // Find closest ball that's moving toward AI for (var i = 0; i < balls.length; i++) { if (balls[i].active && balls[i].velocityY < 0) { var distance = Math.abs(balls[i].y - aiPaddle.y); if (distance < closestDistance) { closestDistance = distance; closestBall = balls[i]; } } } // If no balls moving toward AI, track main ball if active if (!closestBall && balls[0].active) { closestBall = balls[0]; } // Track the chosen ball if (closestBall) { aiPaddle.targetX = closestBall.x; // Add some difficulty - AI gets less accurate at higher speeds var difficultyFactor = Math.min(Math.abs(closestBall.velocityY) / 15, 1); var randomOffset = (Math.random() * 300 - 150) * difficultyFactor; aiPaddle.targetX += randomOffset; } // Check for collisions with all active balls for (var i = 0; i < balls.length; i++) { var currentBall = balls[i]; if (currentBall.active) { currentBall.checkPaddleCollision(playerPaddle); currentBall.checkPaddleCollision(aiPaddle); // Check if ball goes off table (scoring) // Player scores if (currentBall.y < table.y - table.height / 2) { // Only count score for non-clone balls or if it's the last active ball if (!currentBall.isClone || countActiveBalls() == 1) { playerScore++; playerScoreText.setText(playerScore.toString()); LK.getSound('score').play(); // If this is the main ball, reset after short delay if (!currentBall.isClone) { // Deactivate all balls for (var j = 0; j < balls.length; j++) { balls[j].active = false; if (j > 0) { balls[j].visible = false; } } LK.setTimeout(function () { balls[0].reset(); }, 1000); // Check win condition if (playerScore === 10) { LK.showYouWin(); } } else { currentBall.active = false; currentBall.visible = false; } } else { currentBall.active = false; currentBall.visible = false; } } // AI scores if (currentBall.y > table.y + table.height / 2) { // Only count score for non-clone balls or if it's the last active ball if (!currentBall.isClone || countActiveBalls() == 1) { aiScore++; aiScoreText.setText(aiScore.toString()); LK.getSound('score').play(); // If this is the main ball, reset after short delay if (!currentBall.isClone) { // Deactivate all balls for (var j = 0; j < balls.length; j++) { balls[j].active = false; if (j > 0) { balls[j].visible = false; } } LK.setTimeout(function () { balls[0].reset(); }, 1000); // Check loss condition if (aiScore === 10) { LK.showGameOver(); } } else { currentBall.active = false; currentBall.visible = false; } } else { currentBall.active = false; currentBall.visible = false; } } } } // Helper function to count active balls function countActiveBalls() { var count = 0; for (var i = 0; i < balls.length; i++) { if (balls[i].active) { count++; } } return count; } // Update score in LK system LK.setScore(playerScore); };
===================================================================
--- original.js
+++ change.js
@@ -15,8 +15,9 @@
self.maxSpeed = 20;
self.active = false;
self.lastX = 0;
self.lastY = 0;
+ self.isClone = false;
self.reset = function () {
self.x = table.x;
self.y = table.y;
self.velocityY = self.speed;
@@ -88,8 +89,61 @@
}
};
return self;
});
+var PowerUp = Container.expand(function () {
+ var self = Container.call(this);
+ var powerUpGraphics = self.attachAsset('powerup', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.width = powerUpGraphics.width;
+ self.height = powerUpGraphics.height;
+ self.type = 'none';
+ self.active = false;
+ self.speed = 3;
+ self.activate = function (type) {
+ self.type = type;
+ self.active = true;
+ // Set appearance based on power-up type
+ switch (type) {
+ case 'wide':
+ powerUpGraphics.tint = 0x00ff00; // Green for paddle widening
+ break;
+ case 'slow':
+ powerUpGraphics.tint = 0x0000ff; // Blue for ball slowing
+ break;
+ case 'multi':
+ powerUpGraphics.tint = 0xff00ff; // Purple for multi-ball
+ break;
+ }
+ // Position randomly on table
+ self.x = table.x + (Math.random() * table.width - table.width / 2) * 0.8;
+ self.y = table.y + (Math.random() * table.height - table.height / 2) * 0.6;
+ };
+ self.update = function () {
+ if (!self.active) {
+ return;
+ }
+ // Slowly move downward
+ self.y += self.speed;
+ // Remove if off table
+ if (self.y > table.y + table.height / 2) {
+ self.active = false;
+ self.visible = false;
+ }
+ };
+ self.collect = function () {
+ self.active = false;
+ self.visible = false;
+ return self.type;
+ };
+ self.reset = function () {
+ self.active = false;
+ self.visible = false;
+ };
+ return self;
+});
/****
* Initialize Game
****/
@@ -129,8 +183,34 @@
game.addChild(aiPaddle);
// Create ball
var ball = new Ball();
game.addChild(ball);
+// Create additional balls for multi-ball power-up
+var balls = [ball];
+var maxBalls = 3;
+for (var i = 1; i < maxBalls; i++) {
+ var extraBall = new Ball();
+ extraBall.isClone = true;
+ extraBall.visible = false;
+ extraBall.active = false;
+ game.addChild(extraBall);
+ balls.push(extraBall);
+}
+// Create power-ups
+var powerUps = [];
+var maxPowerUps = 3;
+for (var i = 0; i < maxPowerUps; i++) {
+ var powerUp = new PowerUp();
+ powerUp.visible = false;
+ game.addChild(powerUp);
+ powerUps.push(powerUp);
+}
+// Power-up state variables
+var powerUpTimer = null;
+var powerUpActive = false;
+var powerUpType = 'none';
+var originalPaddleWidth = playerPaddle.width;
+var originalBallSpeed = ball.speed;
// Create score text
var playerScore = 0;
var aiScore = 0;
var playerScoreText = new Text2(playerScore.toString(), {
@@ -162,59 +242,220 @@
if (isDragging) {
playerPaddle.x = x;
}
};
+// Power-up activation function
+function activatePowerUp(type) {
+ // Clear any existing power-up effect
+ if (powerUpTimer) {
+ LK.clearTimeout(powerUpTimer);
+ }
+ // Reset previous power-up effects
+ if (powerUpActive) {
+ deactivatePowerUp();
+ }
+ powerUpActive = true;
+ powerUpType = type;
+ switch (type) {
+ case 'wide':
+ // Widen paddle
+ playerPaddle.width = originalPaddleWidth * 1.5;
+ paddleGraphics = playerPaddle.children[0];
+ paddleGraphics.scale.x = 1.5;
+ break;
+ case 'slow':
+ // Slow down ball
+ for (var i = 0; i < balls.length; i++) {
+ if (balls[i].active) {
+ balls[i].velocityX *= 0.6;
+ balls[i].velocityY *= 0.6;
+ }
+ }
+ break;
+ case 'multi':
+ // Activate multi-ball
+ for (var i = 1; i < balls.length; i++) {
+ if (!balls[i].active) {
+ balls[i].x = balls[0].x;
+ balls[i].y = balls[0].y;
+ balls[i].velocityX = balls[0].velocityX * (Math.random() > 0.5 ? 1 : -1);
+ balls[i].velocityY = balls[0].velocityY;
+ balls[i].active = true;
+ balls[i].visible = true;
+ break;
+ }
+ }
+ break;
+ }
+ // Power-up lasts for 10 seconds
+ powerUpTimer = LK.setTimeout(function () {
+ deactivatePowerUp();
+ }, 10000);
+}
+// Function to deactivate power-ups
+function deactivatePowerUp() {
+ powerUpActive = false;
+ switch (powerUpType) {
+ case 'wide':
+ playerPaddle.width = originalPaddleWidth;
+ paddleGraphics = playerPaddle.children[0];
+ paddleGraphics.scale.x = 1;
+ break;
+ case 'slow':
+ // Ball speed will naturally increase over time
+ break;
+ case 'multi':
+ // Multi-balls will remain until they go off screen
+ break;
+ }
+ powerUpType = 'none';
+}
// Start the game with the ball
ball.reset();
// Main game loop
game.update = function () {
// Update game objects
playerPaddle.update();
aiPaddle.update();
- ball.update();
- // AI behavior - track the ball
- if (ball.active) {
- aiPaddle.targetX = ball.x;
+ // Update all balls
+ for (var i = 0; i < balls.length; i++) {
+ if (balls[i].active) {
+ balls[i].update();
+ }
+ }
+ // Update power-ups
+ for (var i = 0; i < powerUps.length; i++) {
+ if (powerUps[i].active) {
+ powerUps[i].update();
+ // Check if player paddle collects power-up
+ if (powerUps[i].active && powerUps[i].intersects(playerPaddle)) {
+ // Apply power-up effect
+ var powerType = powerUps[i].collect();
+ activatePowerUp(powerType);
+ LK.getSound('powerup').play();
+ }
+ }
+ }
+ // Randomly spawn power-ups (about every 10 seconds on average)
+ if (Math.random() < 0.002 && !powerUpActive) {
+ // Find inactive power-up
+ for (var i = 0; i < powerUps.length; i++) {
+ if (!powerUps[i].active) {
+ var types = ['wide', 'slow', 'multi'];
+ var randomType = types[Math.floor(Math.random() * types.length)];
+ powerUps[i].activate(randomType);
+ powerUps[i].visible = true;
+ break;
+ }
+ }
+ }
+ // AI behavior - track the ball (closest one moving toward AI)
+ var closestBall = null;
+ var closestDistance = Infinity;
+ // Find closest ball that's moving toward AI
+ for (var i = 0; i < balls.length; i++) {
+ if (balls[i].active && balls[i].velocityY < 0) {
+ var distance = Math.abs(balls[i].y - aiPaddle.y);
+ if (distance < closestDistance) {
+ closestDistance = distance;
+ closestBall = balls[i];
+ }
+ }
+ }
+ // If no balls moving toward AI, track main ball if active
+ if (!closestBall && balls[0].active) {
+ closestBall = balls[0];
+ }
+ // Track the chosen ball
+ if (closestBall) {
+ aiPaddle.targetX = closestBall.x;
// Add some difficulty - AI gets less accurate at higher speeds
- var difficultyFactor = Math.min(Math.abs(ball.velocityY) / 15, 1);
+ var difficultyFactor = Math.min(Math.abs(closestBall.velocityY) / 15, 1);
var randomOffset = (Math.random() * 300 - 150) * difficultyFactor;
aiPaddle.targetX += randomOffset;
}
- // Check for collisions
- ball.checkPaddleCollision(playerPaddle);
- ball.checkPaddleCollision(aiPaddle);
- // Check if ball goes off table (scoring)
- if (ball.active) {
- // Player scores
- if (ball.y < table.y - table.height / 2) {
- playerScore++;
- playerScoreText.setText(playerScore.toString());
- LK.getSound('score').play();
- // Reset ball after short delay
- ball.active = false;
- LK.setTimeout(function () {
- ball.reset();
- }, 1000);
- // Check win condition
- if (playerScore === 10) {
- LK.showYouWin();
+ // Check for collisions with all active balls
+ for (var i = 0; i < balls.length; i++) {
+ var currentBall = balls[i];
+ if (currentBall.active) {
+ currentBall.checkPaddleCollision(playerPaddle);
+ currentBall.checkPaddleCollision(aiPaddle);
+ // Check if ball goes off table (scoring)
+ // Player scores
+ if (currentBall.y < table.y - table.height / 2) {
+ // Only count score for non-clone balls or if it's the last active ball
+ if (!currentBall.isClone || countActiveBalls() == 1) {
+ playerScore++;
+ playerScoreText.setText(playerScore.toString());
+ LK.getSound('score').play();
+ // If this is the main ball, reset after short delay
+ if (!currentBall.isClone) {
+ // Deactivate all balls
+ for (var j = 0; j < balls.length; j++) {
+ balls[j].active = false;
+ if (j > 0) {
+ balls[j].visible = false;
+ }
+ }
+ LK.setTimeout(function () {
+ balls[0].reset();
+ }, 1000);
+ // Check win condition
+ if (playerScore === 10) {
+ LK.showYouWin();
+ }
+ } else {
+ currentBall.active = false;
+ currentBall.visible = false;
+ }
+ } else {
+ currentBall.active = false;
+ currentBall.visible = false;
+ }
}
+ // AI scores
+ if (currentBall.y > table.y + table.height / 2) {
+ // Only count score for non-clone balls or if it's the last active ball
+ if (!currentBall.isClone || countActiveBalls() == 1) {
+ aiScore++;
+ aiScoreText.setText(aiScore.toString());
+ LK.getSound('score').play();
+ // If this is the main ball, reset after short delay
+ if (!currentBall.isClone) {
+ // Deactivate all balls
+ for (var j = 0; j < balls.length; j++) {
+ balls[j].active = false;
+ if (j > 0) {
+ balls[j].visible = false;
+ }
+ }
+ LK.setTimeout(function () {
+ balls[0].reset();
+ }, 1000);
+ // Check loss condition
+ if (aiScore === 10) {
+ LK.showGameOver();
+ }
+ } else {
+ currentBall.active = false;
+ currentBall.visible = false;
+ }
+ } else {
+ currentBall.active = false;
+ currentBall.visible = false;
+ }
+ }
}
- // AI scores
- if (ball.y > table.y + table.height / 2) {
- aiScore++;
- aiScoreText.setText(aiScore.toString());
- LK.getSound('score').play();
- // Reset ball after short delay
- ball.active = false;
- LK.setTimeout(function () {
- ball.reset();
- }, 1000);
- // Check loss condition
- if (aiScore === 10) {
- LK.showGameOver();
+ }
+ // Helper function to count active balls
+ function countActiveBalls() {
+ var count = 0;
+ for (var i = 0; i < balls.length; i++) {
+ if (balls[i].active) {
+ count++;
}
}
+ return count;
}
// Update score in LK system
LK.setScore(playerScore);
};
\ No newline at end of file