User prompt
add animation to both players when they hit the ball ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
audience should bounce for 3 seconds up and down. The stand should be still ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
make audience bounce whenever someone wins a point, game or match ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
well it doesn't
User prompt
add winning music when someone wins the whole match
User prompt
add sound asset for when someone wins the whole match and ref speaks
User prompt
add sound effects for audience cheering when someone wins the whole match
User prompt
add sound effects for every type of result. 15 - 0, 15 -15, 15 - 30 etc
User prompt
add sound effects for when ai hits the ball, when player hits the ball, audience cheering any time someone wins a ball, audience cheering extra when someone wins a game.
User prompt
When ball goes out right AI gets point, when ball goes out left player gets point
User prompt
Can you put the score board under the court instead of above
User prompt
put the referee closer to the court
User prompt
remove referee shirt asset
User prompt
the white line should be as wide as the court
User prompt
bring back white line around court
User prompt
remove the middle line
User prompt
remove horisontal white line from court
User prompt
make the net a vertical white line
User prompt
make the stand as wide as the court
User prompt
make the stand as wide as the court
User prompt
Add a stand with an audience behind the referee
User prompt
around the court. Not on the court. Make it one big one that goes around the court
User prompt
Add stands around the field with advertising boards and an audience watching.
User prompt
Add an official/referee looking at the game. He should be placed above the field in the middle
User prompt
make the "net" go trough the hole field vertically
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var AIPaddle = Container.expand(function () {
var self = Container.call(this);
var paddleGraphics = self.attachAsset('aiPaddle', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
self.difficulty = 0.7;
self.update = function () {
if (ball && ball.velocityX < 0) {
// Ball coming towards AI (left side)
var targetY = ball.y + (Math.random() - 0.5) * 80 * (1 - self.difficulty);
var diff = targetY - self.y;
var moveSpeed = self.speed * self.difficulty;
if (Math.abs(diff) > 8) {
if (diff > 0) {
self.y += moveSpeed;
} else {
self.y -= moveSpeed;
}
}
}
// Keep AI paddle within court bounds
if (self.y < courtTop + 60) self.y = courtTop + 60;
if (self.y > courtBottom - 60) self.y = courtBottom - 60;
};
return self;
});
var PlayerPaddle = Container.expand(function () {
var self = Container.call(this);
var paddleGraphics = self.attachAsset('playerPaddle', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 15;
self.targetY = 0;
self.update = function () {
var diff = self.targetY - self.y;
if (Math.abs(diff) > 5) {
self.y += diff * 0.15;
}
};
return self;
});
var Referee = Container.expand(function () {
var self = Container.call(this);
// Main body (black)
var refereeBody = self.attachAsset('referee', {
anchorX: 0.5,
anchorY: 0.5
});
// White shirt
var refereeShirt = self.attachAsset('refereeShirt', {
anchorX: 0.5,
anchorY: 0.5,
y: -10
});
return self;
});
var Stand = Container.expand(function () {
var self = Container.call(this);
// Main stand structure
var standStructure = self.attachAsset('stand', {
anchorX: 0.5,
anchorY: 0.5
});
// Create multiple rows of seats
for (var row = 0; row < 5; row++) {
var seat = self.attachAsset('standSeat', {
anchorX: 0.5,
anchorY: 0.5,
y: -120 + row * 50
});
// Add audience members to each row
for (var i = 0; i < 30; i++) {
var audienceMember = self.attachAsset('audience', {
anchorX: 0.5,
anchorY: 0.5,
x: -375 + i * 25,
y: -120 + row * 50
});
}
}
return self;
});
var TennisBall = Container.expand(function () {
var self = Container.call(this);
var ballGraphics = self.attachAsset('ball', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocityX = 0;
self.velocityY = 0;
self.speed = 12;
self.lastPlayerHit = null;
self.reset = function () {
self.x = 1024;
self.y = 1366;
self.velocityX = (Math.random() > 0.5 ? 1 : -1) * self.speed;
self.velocityY = (Math.random() - 0.5) * 8;
self.lastPlayerHit = null;
};
self.update = function () {
self.x += self.velocityX;
self.y += self.velocityY;
// Ball collision with top and bottom court boundaries
if (self.y <= courtTop || self.y >= courtBottom) {
self.velocityY = -self.velocityY;
self.y = self.y <= courtTop ? courtTop : courtBottom;
}
// Ball collision with player paddle (right side) - prevent tunneling
if (self.velocityX > 0 && self.x >= playerPaddle.x - 40 && self.x <= playerPaddle.x + 40 && self.y >= playerPaddle.y - 60 && self.y <= playerPaddle.y + 60 && self.lastPlayerHit !== 'player') {
self.velocityX = -Math.abs(self.velocityX) * 1.05; // Ensure ball goes left
self.velocityY += (self.y - playerPaddle.y) * 0.1;
self.x = playerPaddle.x - 40; // Position ball at paddle edge to prevent tunneling
self.lastPlayerHit = 'player';
LK.getSound('hitBall').play();
rallyCount++;
}
// Ball collision with AI paddle (left side) - prevent tunneling
if (self.velocityX < 0 && self.x >= aiPaddle.x - 40 && self.x <= aiPaddle.x + 40 && self.y >= aiPaddle.y - 60 && self.y <= aiPaddle.y + 60 && self.lastPlayerHit !== 'ai') {
self.velocityX = Math.abs(self.velocityX) * 1.05; // Ensure ball goes right
self.velocityY += (self.y - aiPaddle.y) * 0.1;
self.x = aiPaddle.x + 40; // Position ball at paddle edge to prevent tunneling
self.lastPlayerHit = 'ai';
LK.getSound('hitBall').play();
rallyCount++;
}
// Ball out of bounds - score point
if (self.x < courtLeft - 50) {
scorePoint('ai');
} else if (self.x > courtRight + 50) {
scorePoint('player');
}
// Limit ball speed
var maxSpeed = 20;
if (Math.abs(self.velocityX) > maxSpeed) {
self.velocityX = self.velocityX > 0 ? maxSpeed : -maxSpeed;
}
if (Math.abs(self.velocityY) > maxSpeed) {
self.velocityY = self.velocityY > 0 ? maxSpeed : -maxSpeed;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x228B22
});
/****
* Game Code
****/
// Game variables
var playerScore = 0;
var aiScore = 0;
var playerGames = 0;
var aiGames = 0;
var rallyCount = 0;
var gameInProgress = true;
// Court dimensions
var courtLeft = 124;
var courtRight = 1924;
var courtTop = 766;
var courtBottom = 1966;
// Create court
var court = game.addChild(LK.getAsset('court', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366
}));
// Create net
var net = game.addChild(LK.getAsset('net', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366
}));
// Court lines removed - only side lines and service lines remain
var leftLine = game.addChild(LK.getAsset('sideLine', {
anchorX: 0.5,
anchorY: 0.5,
x: courtLeft,
y: 1366
}));
var rightLine = game.addChild(LK.getAsset('sideLine', {
anchorX: 0.5,
anchorY: 0.5,
x: courtRight,
y: 1366
}));
// Service lines
var leftServiceLine = game.addChild(LK.getAsset('serviceLine', {
anchorX: 0.5,
anchorY: 0.5,
x: 574,
y: 1366
}));
var rightServiceLine = game.addChild(LK.getAsset('serviceLine', {
anchorX: 0.5,
anchorY: 0.5,
x: 1474,
y: 1366
}));
// Center service line
var centerServiceLine = game.addChild(LK.getAsset('centerLine', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1216
}));
// Create paddles
var aiPaddle = game.addChild(new AIPaddle());
aiPaddle.x = 200; // AI on the left
aiPaddle.y = 1366;
var playerPaddle = game.addChild(new PlayerPaddle());
playerPaddle.x = 1848; // Human player on the right
playerPaddle.y = 1366;
// Create stand with audience
var stand = game.addChild(new Stand());
stand.x = 1024; // Center of court horizontally
stand.y = 400; // Behind the referee
// Create referee
var referee = game.addChild(new Referee());
referee.x = 1024; // Center of court horizontally
referee.y = 600; // Above the court
// Create ball
var ball = game.addChild(new TennisBall());
ball.reset();
// Score display
var scoreText = new Text2('0 - 0', {
size: 80,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
var gameScoreText = new Text2('Games: AI 0 - 0 Player', {
size: 60,
fill: 0xFFFFFF
});
gameScoreText.anchor.set(0.5, 0);
gameScoreText.y = 100;
LK.gui.top.addChild(gameScoreText);
// Touch controls
var dragActive = false;
game.down = function (x, y, obj) {
if (gameInProgress) {
dragActive = true;
playerPaddle.targetY = y;
}
};
game.move = function (x, y, obj) {
if (dragActive && gameInProgress) {
playerPaddle.targetY = y;
// Keep paddle within court bounds
if (playerPaddle.targetY < courtTop + 60) playerPaddle.targetY = courtTop + 60;
if (playerPaddle.targetY > courtBottom - 60) playerPaddle.targetY = courtBottom - 60;
}
};
game.up = function (x, y, obj) {
dragActive = false;
};
// Tennis scoring system
var scoreNames = ['0', '15', '30', '40'];
function getScoreText() {
var playerScoreStr, aiScoreStr;
if (playerScore >= 3 && aiScore >= 3) {
// Deuce situation
if (playerScore === aiScore) {
return 'Deuce';
} else if (playerScore > aiScore) {
return 'Player Advantage';
} else {
return 'AI Advantage';
}
} else {
playerScoreStr = playerScore >= 4 ? '40' : scoreNames[playerScore];
aiScoreStr = aiScore >= 4 ? '40' : scoreNames[aiScore];
return 'AI ' + aiScoreStr + ' - ' + playerScoreStr + ' Player';
}
}
function scorePoint(winner) {
if (!gameInProgress) return;
LK.getSound('scorePoint').play();
if (winner === 'player') {
playerScore++;
} else {
aiScore++;
}
// Check if game is won
var gameWon = false;
if ((playerScore >= 4 || aiScore >= 4) && Math.abs(playerScore - aiScore) >= 2) {
gameWon = true;
if (playerScore > aiScore) {
playerGames++;
} else {
aiGames++;
}
// Reset point scores
playerScore = 0;
aiScore = 0;
}
// Check if set is won
if (gameWon) {
if ((playerGames >= 6 || aiGames >= 6) && Math.abs(playerGames - aiGames) >= 2) {
// Set won
gameInProgress = false;
if (playerGames > aiGames) {
LK.showYouWin();
} else {
LK.showGameOver();
}
} else if (playerGames === 6 && aiGames === 6) {
// Tiebreaker (simplified - first to 7 points wins)
// For simplicity, we'll just continue normal game scoring
}
}
// Update score displays
scoreText.setText(getScoreText());
gameScoreText.setText('Games: AI ' + aiGames + ' - ' + playerGames + ' Player');
// Reset ball and adjust AI difficulty
rallyCount = 0;
aiPaddle.difficulty = Math.min(0.9, 0.5 + (playerGames + aiGames) * 0.05);
ball.reset();
}
game.update = function () {
if (!gameInProgress) return;
// Update score display
scoreText.setText(getScoreText());
gameScoreText.setText('Games: AI ' + aiGames + ' - ' + playerGames + ' Player');
}; ===================================================================
--- original.js
+++ change.js
@@ -187,21 +187,9 @@
anchorY: 0.5,
x: 1024,
y: 1366
}));
-// Create court lines
-var topLine = game.addChild(LK.getAsset('courtLine', {
- anchorX: 0.5,
- anchorY: 0.5,
- x: 1024,
- y: courtTop
-}));
-var bottomLine = game.addChild(LK.getAsset('courtLine', {
- anchorX: 0.5,
- anchorY: 0.5,
- x: 1024,
- y: courtBottom
-}));
+// Court lines removed - only side lines and service lines remain
var leftLine = game.addChild(LK.getAsset('sideLine', {
anchorX: 0.5,
anchorY: 0.5,
x: courtLeft,
pixel art tennis ball. In-Game asset. 2d. High contrast. No shadows
tennis referee, Top-down perspective, pixelart. In-Game asset. 2d. High contrast. No shadows
pixelart tennis player looking to the right. In-Game asset. 2d. High contrast. No shadows
pixelart tennis player looking to the left. In-Game asset. 2d. High contrast. No shadows
pixelart tennis audience, looking down. In-Game asset. 2d. High contrast. No shadows
playerHit
Sound effect
aiHit
Sound effect
audienceCheer
Sound effect
audienceCheerExtra
Sound effect
scoreDeuce
Sound effect
scorePlayerAdvantage
Sound effect
scoreAIAdvantage
Sound effect
scorePoint
Sound effect
audienceCheerMatch
Sound effect
refMatchWin
Sound effect
victoryMusic
Music