User prompt
When the ball collides with the racket near its sides then make the ball curve and go more to the side
User prompt
Remove curveball
User prompt
Remove bounce effects
User prompt
Add bounce effects to the ball ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Please fix the bug: 'Script error.' in or related to this line: 'ball.y = servedBy === 'player' ? PLAYER_Y - 80 : AI_Y + 80;' Line Number: 628
User prompt
Revert the gameplay back to the original
User prompt
Please fix the bug: 'Script error.' in or related to this line: 'tween(ball, {' Line Number: 632 ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Please fix the bug: 'Script error.' in or related to this line: 'tween.to(ball, {' Line Number: 632 ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Make the gameplay look more polished
User prompt
Make the menu screen look polished
User prompt
Change the insane difficulty name to impossible
User prompt
Add one more difficulty named insane
User prompt
Make the ai’s racket a random one from the list of rackets
User prompt
Put the difficulty selection lower down on the screen
User prompt
When you pick a racket at the bottom of the screen but a description of its attributes
User prompt
Make all rackets visible on screen by putting them in rows
User prompt
Give each racket certain attributes
User prompt
Add more racket designs
User prompt
Make the energy bar blue
User prompt
Get extra energy when your opponent scores
User prompt
Add a energy bar to each player and when it is full do a power shot
User prompt
Remove powerups
User prompt
Add power ups which can go to you or your opponent which can do power shots or increase ball size or decrease it or slow down the ball.
User prompt
Revert sprites back to how they were
User prompt
Make all sprites look realistic
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Ball class var Ball = Container.expand(function () { var self = Container.call(this); self.asset = self.attachAsset('ball', { anchorX: 0.5, anchorY: 0.5 }); // Ball velocity self.vx = 0; self.vy = 0; // For collision, get bounds self.getBounds = function () { return { x: self.x - self.asset.width / 2, y: self.y - self.asset.height / 2, width: self.asset.width, height: self.asset.height }; }; // Ball update self.update = function () { self.x += self.vx; self.y += self.vy; }; return self; }); // Racket class (player or AI) var Racket = Container.expand(function () { var self = Container.call(this); // Default: rectangle self.racketType = 'racket_rect'; self.asset = null; // Set racket type and color self.setType = function (type) { if (self.asset) { self.removeChild(self.asset); } self.racketType = type; self.asset = self.attachAsset(type, { anchorX: 0.5, anchorY: 0.5 }); // For 'rounded' design, tint the box to look different if (type === 'racket_rounded') { self.asset.tint = 0x27ae60; } }; // Set initial type self.setType('racket_rect'); // For collision, get bounds self.getBounds = function () { return { x: self.x - self.asset.width / 2, y: self.y - self.asset.height / 2, width: self.asset.width, height: self.asset.height }; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x145a32 // Table green }); /**** * Game Code ****/ // --- Game constants --- // Racket shapes (3 designs) // Will tint for rounded look // Ball // Table (background, not interactive) // Net // Sounds (optional, not used in MVP as per instructions) // LK.init.sound('hit', {volume:0.5}); // LK.init.sound('score', {volume:0.5}); var TABLE_WIDTH = 2048; var TABLE_HEIGHT = 2732; var NET_Y = TABLE_HEIGHT / 2; var PLAYER_Y = TABLE_HEIGHT - 200; var AI_Y = 200; var RACKET_TYPES = ['racket_rect', 'racket_ellipse', 'racket_rounded']; var DIFFICULTIES = [{ name: 'Easy', aiSpeed: 16, aiError: 120, aiReact: 0.5 }, { name: 'Medium', aiSpeed: 24, aiError: 60, aiReact: 0.7 }, { name: 'Hard', aiSpeed: 36, aiError: 20, aiReact: 0.9 }]; // --- Game state --- var playerScore = 0; var aiScore = 0; var maxScore = 7; // First to 7 wins var selectedRacketType = RACKET_TYPES[0]; var selectedDifficulty = DIFFICULTIES[1]; // Default: Medium // --- Energy bar state --- var playerEnergy = 0; var aiEnergy = 0; var maxEnergy = 100; var playerPowerShotReady = false; var aiPowerShotReady = false; var playerPowerShotActive = false; var aiPowerShotActive = false; // --- UI elements --- var scoreText = null; var aiScoreText = null; var playerScoreText = null; var infoText = null; var menuContainer = null; // --- Game objects --- var playerRacket = null; var aiRacket = null; var ball = null; var net = null; var table = null; // --- Drag state --- var dragging = false; // --- AI state --- var aiTargetX = 0; var aiReactTimer = 0; // --- Utility: collision detection (AABB) --- function rectsIntersect(a, b) { return !(a.x + a.width < b.x || a.x > b.x + b.width || a.y + a.height < b.y || a.y > b.y + b.height); } // --- Utility: clamp --- function clamp(val, min, max) { return Math.max(min, Math.min(max, val)); } // --- Show menu for racket and difficulty selection --- function showMenu() { menuContainer = new Container(); // Title var title = new Text2('Ping Pong AI', { size: 120, fill: 0xFFFFFF }); title.anchor.set(0.5, 0); title.x = TABLE_WIDTH / 2; title.y = 200; menuContainer.addChild(title); // Racket selection var racketLabel = new Text2('Choose your racket:', { size: 70, fill: 0xFFFFFF }); racketLabel.anchor.set(0.5, 0); racketLabel.x = TABLE_WIDTH / 2; racketLabel.y = 400; menuContainer.addChild(racketLabel); var racketButtons = []; for (var i = 0; i < RACKET_TYPES.length; i++) { var type = RACKET_TYPES[i]; var btn = LK.getAsset(type, { anchorX: 0.5, anchorY: 0.5, x: TABLE_WIDTH / 2 + (i - 1) * 400, y: 600 }); // Tint for rounded if (type === 'racket_rounded') btn.tint = 0x27ae60; btn.interactive = true; btn.buttonMode = true; (function (idx, btnObj) { btnObj.down = function (x, y, obj) { selectedRacketType = RACKET_TYPES[idx]; // Highlight selection for (var j = 0; j < racketButtons.length; j++) { racketButtons[j].alpha = j === idx ? 1 : 0.5; } }; })(i, btn); if (i === 0) btn.alpha = 1;else btn.alpha = 0.5; racketButtons.push(btn); menuContainer.addChild(btn); } // Difficulty selection var diffLabel = new Text2('Select difficulty:', { size: 70, fill: 0xFFFFFF }); diffLabel.anchor.set(0.5, 0); diffLabel.x = TABLE_WIDTH / 2; diffLabel.y = 800; menuContainer.addChild(diffLabel); var diffButtons = []; for (var d = 0; d < DIFFICULTIES.length; d++) { var diff = DIFFICULTIES[d]; var diffBtn = new Text2(diff.name, { size: 70, fill: 0xFFFFFF }); diffBtn.anchor.set(0.5, 0.5); diffBtn.x = TABLE_WIDTH / 2 + (d - 1) * 350; diffBtn.y = 950; diffBtn.interactive = true; diffBtn.buttonMode = true; (function (idx, btnObj) { btnObj.down = function (x, y, obj) { selectedDifficulty = DIFFICULTIES[idx]; for (var j = 0; j < diffButtons.length; j++) { diffButtons[j].alpha = j === idx ? 1 : 0.5; } }; })(d, diffBtn); if (d === 1) diffBtn.alpha = 1;else diffBtn.alpha = 0.5; diffButtons.push(diffBtn); menuContainer.addChild(diffBtn); } // Start button var startBtn = new Text2('START', { size: 100, fill: 0xF1C40F }); startBtn.anchor.set(0.5, 0.5); startBtn.x = TABLE_WIDTH / 2; startBtn.y = 1200; startBtn.interactive = true; startBtn.buttonMode = true; startBtn.down = function (x, y, obj) { // Remove menu and start game game.removeChild(menuContainer); menuContainer = null; startGame(); }; menuContainer.addChild(startBtn); game.addChild(menuContainer); } // --- Start or restart the game --- function startGame() { // Reset scores playerScore = 0; aiScore = 0; // Remove previous objects if any if (table) game.removeChild(table); if (net) game.removeChild(net); if (playerRacket) game.removeChild(playerRacket); if (aiRacket) game.removeChild(aiRacket); if (ball) game.removeChild(ball); if (scoreText) LK.gui.top.removeChild(scoreText); if (aiScoreText) LK.gui.top.removeChild(aiScoreText); if (playerScoreText) LK.gui.top.removeChild(playerScoreText); if (infoText) LK.gui.top.removeChild(infoText); if (typeof playerEnergyBar !== "undefined" && playerEnergyBar) LK.gui.top.removeChild(playerEnergyBar); if (typeof aiEnergyBar !== "undefined" && aiEnergyBar) LK.gui.top.removeChild(aiEnergyBar); // Table table = LK.getAsset('table', { anchorX: 0, anchorY: 0, x: 0, y: 0 }); game.addChild(table); // Net net = LK.getAsset('net', { anchorX: 0.5, anchorY: 0.5, x: TABLE_WIDTH / 2, y: NET_Y }); game.addChild(net); // Player racket playerRacket = new Racket(); playerRacket.setType(selectedRacketType); playerRacket.x = TABLE_WIDTH / 2; playerRacket.y = PLAYER_Y; game.addChild(playerRacket); // AI racket aiRacket = new Racket(); aiRacket.setType(selectedRacketType); aiRacket.x = TABLE_WIDTH / 2; aiRacket.y = AI_Y; game.addChild(aiRacket); // Ball ball = new Ball(); resetBall('player'); game.addChild(ball); // Score display scoreText = new Text2(playerScore + " : " + aiScore, { size: 120, fill: 0xFFFFFF }); scoreText.anchor.set(0.5, 0); LK.gui.top.addChild(scoreText); // Player and AI score (smaller, left/right) playerScoreText = new Text2("You", { size: 60, fill: 0xFFFFFF }); playerScoreText.anchor.set(0, 0); LK.gui.top.addChild(playerScoreText); aiScoreText = new Text2("AI", { size: 60, fill: 0xFFFFFF }); aiScoreText.anchor.set(1, 0); LK.gui.top.addChild(aiScoreText); // Info text (centered, for serve etc) infoText = new Text2("", { size: 80, fill: 0xF1C40F }); infoText.anchor.set(0.5, 0); LK.gui.top.addChild(infoText); // Energy bar UI playerEnergy = 0; aiEnergy = 0; playerPowerShotReady = false; aiPowerShotReady = false; playerPowerShotActive = false; aiPowerShotActive = false; // Player energy bar (bottom left, above player label) playerEnergyBar = LK.getAsset('table', { anchorX: 0, anchorY: 0, x: 120, y: 110, width: 400, height: 30, color: 0x333333 }); playerEnergyBarBar = LK.getAsset('table', { anchorX: 0, anchorY: 0, x: 120, y: 110, width: 0, height: 30, color: 0xF1C40F }); LK.gui.top.addChild(playerEnergyBar); LK.gui.top.addChild(playerEnergyBarBar); // AI energy bar (top right, above AI label) aiEnergyBar = LK.getAsset('table', { anchorX: 1, anchorY: 0, x: LK.gui.top.width - 120, y: 110, width: 400, height: 30, color: 0x333333 }); aiEnergyBarBar = LK.getAsset('table', { anchorX: 1, anchorY: 0, x: LK.gui.top.width - 120, y: 110, width: 0, height: 30, color: 0xF1C40F }); LK.gui.top.addChild(aiEnergyBar); LK.gui.top.addChild(aiEnergyBarBar); // Position GUI scoreText.x = LK.gui.top.width / 2; scoreText.y = 20; playerScoreText.x = 120; playerScoreText.y = 40; aiScoreText.x = LK.gui.top.width - 120; aiScoreText.y = 40; infoText.x = LK.gui.top.width / 2; infoText.y = 170; // Reset drag dragging = false; // AI state aiTargetX = aiRacket.x; aiReactTimer = 0; // Show serve info infoText.setText("Tap and drag to move your racket!"); // Start update loop game.update = gameUpdate; game.move = gameMove; game.down = gameDown; game.up = gameUp; } // --- Reset ball to serve (by: 'player' or 'ai') --- function resetBall(servedBy) { ball.x = TABLE_WIDTH / 2; ball.y = servedBy === 'player' ? PLAYER_Y - 80 : AI_Y + 80; // Ball speed var angle = servedBy === 'player' ? -Math.PI / 2 + (Math.random() - 0.5) * 0.3 : Math.PI / 2 + (Math.random() - 0.5) * 0.3; var speed = 20; ball.vx = Math.cos(angle) * speed; ball.vy = Math.sin(angle) * speed; } // --- Update score display --- function updateScoreDisplay() { scoreText.setText(playerScore + " : " + aiScore); } // --- Show info text for a short time --- function showInfo(msg, duration) { infoText.setText(msg); if (duration) { LK.setTimeout(function () { infoText.setText(""); }, duration); } } // --- Game update loop --- function gameUpdate() { // Ball movement ball.update(); // Ball wall bounce (left/right) if (ball.x < ball.asset.width / 2) { ball.x = ball.asset.width / 2; ball.vx *= -1; } if (ball.x > TABLE_WIDTH - ball.asset.width / 2) { ball.x = TABLE_WIDTH - ball.asset.width / 2; ball.vx *= -1; } // Ball out of bounds (top/bottom) if (ball.y < 0) { // Player scores playerScore++; updateScoreDisplay(); // Reset energy and power shot state playerEnergy = 0; aiEnergy = 0; playerPowerShotReady = false; aiPowerShotReady = false; playerPowerShotActive = false; aiPowerShotActive = false; if (playerEnergyBarBar) playerEnergyBarBar.width = 0; if (aiEnergyBarBar) aiEnergyBarBar.width = 0; if (playerScore >= maxScore) { LK.showYouWin(); return; } showInfo("You scored!", 1000); resetBall('ai'); return; } if (ball.y > TABLE_HEIGHT) { // AI scores aiScore++; updateScoreDisplay(); // Reset energy and power shot state playerEnergy = 0; aiEnergy = 0; playerPowerShotReady = false; aiPowerShotReady = false; playerPowerShotActive = false; aiPowerShotActive = false; if (playerEnergyBarBar) playerEnergyBarBar.width = 0; if (aiEnergyBarBar) aiEnergyBarBar.width = 0; if (aiScore >= maxScore) { LK.showGameOver(); return; } showInfo("AI scored!", 1000); resetBall('player'); return; } // Ball collision with player racket if (ball.vy > 0) { var b = ball.getBounds(); var r = playerRacket.getBounds(); if (rectsIntersect(b, r) && ball.y < playerRacket.y) { // Bounce ball.y = r.y - ball.asset.height / 2; ball.vy *= -1; // Add spin based on where hit var dx = (ball.x - playerRacket.x) / (playerRacket.asset.width / 2); ball.vx += dx * 10; // Energy gain if (!playerPowerShotReady) { playerEnergy += 20; if (playerEnergy >= maxEnergy) { playerEnergy = maxEnergy; playerPowerShotReady = true; showInfo("Power Shot Ready!", 1000); } } // Power shot activation if (playerPowerShotReady && dragging) { playerPowerShotActive = true; playerPowerShotReady = false; playerEnergy = 0; // Power shot: boost ball speed and color var powerShotSpeed = 40; var angle = Math.atan2(ball.vy, ball.vx); ball.vx = Math.cos(angle) * powerShotSpeed; ball.vy = -Math.abs(Math.sin(angle) * powerShotSpeed); ball.asset.tint = 0xF1C40F; showInfo("Power Shot!", 800); } else { playerPowerShotActive = false; ball.asset.tint = 0xffffff; } // Clamp speed var speed = Math.sqrt(ball.vx * ball.vx + ball.vy * ball.vy); var maxSpeed = playerPowerShotActive ? 40 : 25; if (speed > maxSpeed) { ball.vx *= maxSpeed / speed; ball.vy *= maxSpeed / speed; } } } // Ball collision with AI racket if (ball.vy < 0) { var b = ball.getBounds(); var r = aiRacket.getBounds(); if (rectsIntersect(b, r) && ball.y > aiRacket.y) { // Bounce ball.y = r.y + r.height + ball.asset.height / 2; ball.vy *= -1; // Add spin based on where hit var dx = (ball.x - aiRacket.x) / (aiRacket.asset.width / 2); ball.vx += dx * 10; // Energy gain if (!aiPowerShotReady) { aiEnergy += 20; if (aiEnergy >= maxEnergy) { aiEnergy = maxEnergy; aiPowerShotReady = true; } } // Power shot activation (AI triggers automatically if ready) if (aiPowerShotReady) { aiPowerShotActive = true; aiPowerShotReady = false; aiEnergy = 0; // Power shot: boost ball speed and color var powerShotSpeed = 40; var angle = Math.atan2(ball.vy, ball.vx); ball.vx = Math.cos(angle) * powerShotSpeed; ball.vy = Math.abs(Math.sin(angle) * powerShotSpeed); ball.asset.tint = 0xF1C40F; showInfo("AI Power Shot!", 800); } else { aiPowerShotActive = false; if (!playerPowerShotActive) ball.asset.tint = 0xffffff; } // Clamp speed var speed = Math.sqrt(ball.vx * ball.vx + ball.vy * ball.vy); var maxSpeed = aiPowerShotActive ? 40 : 25; if (speed > maxSpeed) { ball.vx *= maxSpeed / speed; ball.vy *= maxSpeed / speed; } } } // AI movement aiReactTimer++; if (aiReactTimer > (1 - selectedDifficulty.aiReact) * 30) { aiReactTimer = 0; // AI targets ball x, with error var error = (Math.random() - 0.5) * selectedDifficulty.aiError; aiTargetX = clamp(ball.x + error, aiRacket.asset.width / 2, TABLE_WIDTH - aiRacket.asset.width / 2); } // Move AI racket towards target if (Math.abs(aiRacket.x - aiTargetX) > 5) { if (aiRacket.x < aiTargetX) { aiRacket.x += selectedDifficulty.aiSpeed; if (aiRacket.x > aiTargetX) aiRacket.x = aiTargetX; } else { aiRacket.x -= selectedDifficulty.aiSpeed; if (aiRacket.x < aiTargetX) aiRacket.x = aiTargetX; } // Clamp aiRacket.x = clamp(aiRacket.x, aiRacket.asset.width / 2, TABLE_WIDTH - aiRacket.asset.width / 2); } // Clamp player racket (in case of fast drag) playerRacket.x = clamp(playerRacket.x, playerRacket.asset.width / 2, TABLE_WIDTH - playerRacket.asset.width / 2); // Update energy bar UI if (typeof playerEnergyBarBar !== "undefined" && playerEnergyBarBar) { playerEnergyBarBar.width = 400 * (playerEnergy / maxEnergy); if (playerPowerShotReady) playerEnergyBarBar.tint = 0xF1C40F;else playerEnergyBarBar.tint = 0xF39C12; } if (typeof aiEnergyBarBar !== "undefined" && aiEnergyBarBar) { aiEnergyBarBar.width = 400 * (aiEnergy / maxEnergy); if (aiPowerShotReady) aiEnergyBarBar.tint = 0xF1C40F;else aiEnergyBarBar.tint = 0xF39C12; } } // --- Touch/mouse controls --- function gameMove(x, y, obj) { if (dragging) { // Move player racket horizontally only playerRacket.x = clamp(x, playerRacket.asset.width / 2, TABLE_WIDTH - playerRacket.asset.width / 2); } } function gameDown(x, y, obj) { // Only start drag if touch is near player racket var localY = y; if (Math.abs(localY - playerRacket.y) < 120) { dragging = true; // Move immediately playerRacket.x = clamp(x, playerRacket.asset.width / 2, TABLE_WIDTH - playerRacket.asset.width / 2); } } function gameUp(x, y, obj) { dragging = false; } // --- Start with menu --- showMenu(); ; // Allow player to tap energy bar to trigger power shot if ready function energyBarDown(x, y, obj) { if (playerPowerShotReady) { playerPowerShotActive = true; playerPowerShotReady = false; playerEnergy = 0; showInfo("Power Shot!", 800); } } if (typeof playerEnergyBar !== "undefined" && playerEnergyBar) { playerEnergyBar.down = energyBarDown; playerEnergyBarBar.down = energyBarDown; }
===================================================================
--- original.js
+++ change.js
@@ -113,8 +113,16 @@
var aiScore = 0;
var maxScore = 7; // First to 7 wins
var selectedRacketType = RACKET_TYPES[0];
var selectedDifficulty = DIFFICULTIES[1]; // Default: Medium
+// --- Energy bar state ---
+var playerEnergy = 0;
+var aiEnergy = 0;
+var maxEnergy = 100;
+var playerPowerShotReady = false;
+var aiPowerShotReady = false;
+var playerPowerShotActive = false;
+var aiPowerShotActive = false;
// --- UI elements ---
var scoreText = null;
var aiScoreText = null;
var playerScoreText = null;
@@ -252,8 +260,10 @@
if (scoreText) LK.gui.top.removeChild(scoreText);
if (aiScoreText) LK.gui.top.removeChild(aiScoreText);
if (playerScoreText) LK.gui.top.removeChild(playerScoreText);
if (infoText) LK.gui.top.removeChild(infoText);
+ if (typeof playerEnergyBar !== "undefined" && playerEnergyBar) LK.gui.top.removeChild(playerEnergyBar);
+ if (typeof aiEnergyBar !== "undefined" && aiEnergyBar) LK.gui.top.removeChild(aiEnergyBar);
// Table
table = LK.getAsset('table', {
anchorX: 0,
anchorY: 0,
@@ -311,8 +321,57 @@
fill: 0xF1C40F
});
infoText.anchor.set(0.5, 0);
LK.gui.top.addChild(infoText);
+ // Energy bar UI
+ playerEnergy = 0;
+ aiEnergy = 0;
+ playerPowerShotReady = false;
+ aiPowerShotReady = false;
+ playerPowerShotActive = false;
+ aiPowerShotActive = false;
+ // Player energy bar (bottom left, above player label)
+ playerEnergyBar = LK.getAsset('table', {
+ anchorX: 0,
+ anchorY: 0,
+ x: 120,
+ y: 110,
+ width: 400,
+ height: 30,
+ color: 0x333333
+ });
+ playerEnergyBarBar = LK.getAsset('table', {
+ anchorX: 0,
+ anchorY: 0,
+ x: 120,
+ y: 110,
+ width: 0,
+ height: 30,
+ color: 0xF1C40F
+ });
+ LK.gui.top.addChild(playerEnergyBar);
+ LK.gui.top.addChild(playerEnergyBarBar);
+ // AI energy bar (top right, above AI label)
+ aiEnergyBar = LK.getAsset('table', {
+ anchorX: 1,
+ anchorY: 0,
+ x: LK.gui.top.width - 120,
+ y: 110,
+ width: 400,
+ height: 30,
+ color: 0x333333
+ });
+ aiEnergyBarBar = LK.getAsset('table', {
+ anchorX: 1,
+ anchorY: 0,
+ x: LK.gui.top.width - 120,
+ y: 110,
+ width: 0,
+ height: 30,
+ color: 0xF1C40F
+ });
+ LK.gui.top.addChild(aiEnergyBar);
+ LK.gui.top.addChild(aiEnergyBarBar);
// Position GUI
scoreText.x = LK.gui.top.width / 2;
scoreText.y = 20;
playerScoreText.x = 120;
@@ -374,8 +433,17 @@
if (ball.y < 0) {
// Player scores
playerScore++;
updateScoreDisplay();
+ // Reset energy and power shot state
+ playerEnergy = 0;
+ aiEnergy = 0;
+ playerPowerShotReady = false;
+ aiPowerShotReady = false;
+ playerPowerShotActive = false;
+ aiPowerShotActive = false;
+ if (playerEnergyBarBar) playerEnergyBarBar.width = 0;
+ if (aiEnergyBarBar) aiEnergyBarBar.width = 0;
if (playerScore >= maxScore) {
LK.showYouWin();
return;
}
@@ -386,8 +454,17 @@
if (ball.y > TABLE_HEIGHT) {
// AI scores
aiScore++;
updateScoreDisplay();
+ // Reset energy and power shot state
+ playerEnergy = 0;
+ aiEnergy = 0;
+ playerPowerShotReady = false;
+ aiPowerShotReady = false;
+ playerPowerShotActive = false;
+ aiPowerShotActive = false;
+ if (playerEnergyBarBar) playerEnergyBarBar.width = 0;
+ if (aiEnergyBarBar) aiEnergyBarBar.width = 0;
if (aiScore >= maxScore) {
LK.showGameOver();
return;
}
@@ -405,11 +482,36 @@
ball.vy *= -1;
// Add spin based on where hit
var dx = (ball.x - playerRacket.x) / (playerRacket.asset.width / 2);
ball.vx += dx * 10;
+ // Energy gain
+ if (!playerPowerShotReady) {
+ playerEnergy += 20;
+ if (playerEnergy >= maxEnergy) {
+ playerEnergy = maxEnergy;
+ playerPowerShotReady = true;
+ showInfo("Power Shot Ready!", 1000);
+ }
+ }
+ // Power shot activation
+ if (playerPowerShotReady && dragging) {
+ playerPowerShotActive = true;
+ playerPowerShotReady = false;
+ playerEnergy = 0;
+ // Power shot: boost ball speed and color
+ var powerShotSpeed = 40;
+ var angle = Math.atan2(ball.vy, ball.vx);
+ ball.vx = Math.cos(angle) * powerShotSpeed;
+ ball.vy = -Math.abs(Math.sin(angle) * powerShotSpeed);
+ ball.asset.tint = 0xF1C40F;
+ showInfo("Power Shot!", 800);
+ } else {
+ playerPowerShotActive = false;
+ ball.asset.tint = 0xffffff;
+ }
// Clamp speed
var speed = Math.sqrt(ball.vx * ball.vx + ball.vy * ball.vy);
- var maxSpeed = 25;
+ var maxSpeed = playerPowerShotActive ? 40 : 25;
if (speed > maxSpeed) {
ball.vx *= maxSpeed / speed;
ball.vy *= maxSpeed / speed;
}
@@ -425,11 +527,35 @@
ball.vy *= -1;
// Add spin based on where hit
var dx = (ball.x - aiRacket.x) / (aiRacket.asset.width / 2);
ball.vx += dx * 10;
+ // Energy gain
+ if (!aiPowerShotReady) {
+ aiEnergy += 20;
+ if (aiEnergy >= maxEnergy) {
+ aiEnergy = maxEnergy;
+ aiPowerShotReady = true;
+ }
+ }
+ // Power shot activation (AI triggers automatically if ready)
+ if (aiPowerShotReady) {
+ aiPowerShotActive = true;
+ aiPowerShotReady = false;
+ aiEnergy = 0;
+ // Power shot: boost ball speed and color
+ var powerShotSpeed = 40;
+ var angle = Math.atan2(ball.vy, ball.vx);
+ ball.vx = Math.cos(angle) * powerShotSpeed;
+ ball.vy = Math.abs(Math.sin(angle) * powerShotSpeed);
+ ball.asset.tint = 0xF1C40F;
+ showInfo("AI Power Shot!", 800);
+ } else {
+ aiPowerShotActive = false;
+ if (!playerPowerShotActive) ball.asset.tint = 0xffffff;
+ }
// Clamp speed
var speed = Math.sqrt(ball.vx * ball.vx + ball.vy * ball.vy);
- var maxSpeed = 25;
+ var maxSpeed = aiPowerShotActive ? 40 : 25;
if (speed > maxSpeed) {
ball.vx *= maxSpeed / speed;
ball.vy *= maxSpeed / speed;
}
@@ -456,8 +582,17 @@
aiRacket.x = clamp(aiRacket.x, aiRacket.asset.width / 2, TABLE_WIDTH - aiRacket.asset.width / 2);
}
// Clamp player racket (in case of fast drag)
playerRacket.x = clamp(playerRacket.x, playerRacket.asset.width / 2, TABLE_WIDTH - playerRacket.asset.width / 2);
+ // Update energy bar UI
+ if (typeof playerEnergyBarBar !== "undefined" && playerEnergyBarBar) {
+ playerEnergyBarBar.width = 400 * (playerEnergy / maxEnergy);
+ if (playerPowerShotReady) playerEnergyBarBar.tint = 0xF1C40F;else playerEnergyBarBar.tint = 0xF39C12;
+ }
+ if (typeof aiEnergyBarBar !== "undefined" && aiEnergyBarBar) {
+ aiEnergyBarBar.width = 400 * (aiEnergy / maxEnergy);
+ if (aiPowerShotReady) aiEnergyBarBar.tint = 0xF1C40F;else aiEnergyBarBar.tint = 0xF39C12;
+ }
}
// --- Touch/mouse controls ---
function gameMove(x, y, obj) {
if (dragging) {
@@ -477,5 +612,19 @@
function gameUp(x, y, obj) {
dragging = false;
}
// --- Start with menu ---
-showMenu();
\ No newline at end of file
+showMenu();
+;
+// Allow player to tap energy bar to trigger power shot if ready
+function energyBarDown(x, y, obj) {
+ if (playerPowerShotReady) {
+ playerPowerShotActive = true;
+ playerPowerShotReady = false;
+ playerEnergy = 0;
+ showInfo("Power Shot!", 800);
+ }
+}
+if (typeof playerEnergyBar !== "undefined" && playerEnergyBar) {
+ playerEnergyBar.down = energyBarDown;
+ playerEnergyBarBar.down = energyBarDown;
+}
\ No newline at end of file