User prompt
Make the background new asset
User prompt
Add a background
User prompt
Don't let AI follow us and try to score a goal. Let him try to throw it to the one below.
User prompt
Let the AI try to throw the player red in green
Code edit (1 edits merged)
Please save this source code
User prompt
Car Football Frenzy
Initial prompt
Make me a car football game
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Ball class
var Ball = Container.expand(function () {
var self = Container.call(this);
self.ballSprite = self.attachAsset('football', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = self.ballSprite.width;
self.height = self.ballSprite.height;
self.vx = 0;
self.vy = 0;
self.friction = 0.98;
self.maxSpeed = 38;
self.update = function () {
// Move ball
self.x += self.vx;
self.y += self.vy;
// Friction
self.vx *= self.friction;
self.vy *= self.friction;
// Clamp speed
var speed = Math.sqrt(self.vx * self.vx + self.vy * self.vy);
if (speed > self.maxSpeed) {
self.vx *= self.maxSpeed / speed;
self.vy *= self.maxSpeed / speed;
}
// Bounce off walls
if (self.x < self.width / 2) {
self.x = self.width / 2;
self.vx = -self.vx * 0.7;
}
if (self.x > 2048 - self.width / 2) {
self.x = 2048 - self.width / 2;
self.vx = -self.vx * 0.7;
}
if (self.y < self.height / 2) {
self.y = self.height / 2;
self.vy = -self.vy * 0.7;
}
if (self.y > 2732 - self.height / 2) {
self.y = 2732 - self.height / 2;
self.vy = -self.vy * 0.7;
}
};
return self;
});
// Car class (for both player and AI)
var Car = Container.expand(function () {
var self = Container.call(this);
// Attach car asset (default to player car)
self.carSprite = self.attachAsset('car', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = self.carSprite.width;
self.height = self.carSprite.height;
self.speed = 0;
self.maxSpeed = 32;
self.acceleration = 2.2;
self.friction = 0.95;
self.angle = 0; // radians
self.turnSpeed = 0.09;
self.boosting = false;
self.boostPower = 48;
self.boostCooldown = 0;
self.isAI = false;
// For AI
self.targetX = 0;
self.targetY = 0;
self.update = function () {
// AI logic
if (self.isAI) {
// If the player car is above the halfway line, try to push the player into the green goal
if (playerCar.y > 1366) {
// Target just behind the player car, so AI can push it toward the green goal
var dx = playerCar.x - self.x;
var dy = playerCar.y - self.y;
var dist = Math.sqrt(dx * dx + dy * dy);
// Aim for a point slightly behind the player car (towards the green goal)
var pushDist = 120;
var pushAngle = Math.atan2(playerCar.y - goalPlayer.y, playerCar.x - goalPlayer.x);
self.targetX = playerCar.x + Math.cos(pushAngle) * pushDist;
self.targetY = playerCar.y + Math.sin(pushAngle) * pushDist;
// If close to player and facing, boost
var desiredAngle = Math.atan2(self.targetY - self.y, self.targetX - self.x);
var angleDiff = desiredAngle - self.angle;
while (angleDiff > Math.PI) angleDiff -= Math.PI * 2;
while (angleDiff < -Math.PI) angleDiff += Math.PI * 2;
if (angleDiff > 0.1) self.angle += self.turnSpeed;else if (angleDiff < -0.1) self.angle -= self.turnSpeed;
if (Math.abs(angleDiff) < 0.5) {
self.speed += self.acceleration * 0.7;
}
if (dist < 350 && Math.abs(angleDiff) < 0.3 && self.boostCooldown <= 0) {
self.boosting = true;
}
} else {
// Default: try to push the ball toward the player goal
var dx = ball.x - self.x;
var dy = ball.y - self.y;
var dist = Math.sqrt(dx * dx + dy * dy);
// Target: If ball is on AI's side, go for ball, else defend
if (ball.y < 1366) {
self.targetX = ball.x;
self.targetY = ball.y + 120;
} else {
// Defend goal
self.targetX = 1024;
self.targetY = 220;
}
// Turn towards target
var desiredAngle = Math.atan2(self.targetY - self.y, self.targetX - self.x);
var angleDiff = desiredAngle - self.angle;
while (angleDiff > Math.PI) angleDiff -= Math.PI * 2;
while (angleDiff < -Math.PI) angleDiff += Math.PI * 2;
if (angleDiff > 0.1) self.angle += self.turnSpeed;else if (angleDiff < -0.1) self.angle -= self.turnSpeed;
// Accelerate if facing target
if (Math.abs(angleDiff) < 0.5) {
self.speed += self.acceleration * 0.7;
}
// AI boost if close to ball and facing it
if (dist < 400 && Math.abs(angleDiff) < 0.3 && self.boostCooldown <= 0) {
self.boosting = true;
}
}
}
// Boost logic
if (self.boosting && self.boostCooldown <= 0) {
self.speed = self.boostPower;
self.boostCooldown = 60; // 1 second cooldown
self.boosting = false;
}
if (self.boostCooldown > 0) self.boostCooldown--;
// Clamp speed
if (self.speed > self.maxSpeed) self.speed = self.maxSpeed;
if (self.speed < -self.maxSpeed / 2) self.speed = -self.maxSpeed / 2;
// Move car
self.x += Math.cos(self.angle) * self.speed;
self.y += Math.sin(self.angle) * self.speed;
// Friction
self.speed *= self.friction;
// Keep in bounds
if (self.x < self.width / 2) self.x = self.width / 2;
if (self.x > 2048 - self.width / 2) self.x = 2048 - self.width / 2;
if (self.y < self.height / 2) self.y = self.height / 2;
if (self.y > 2732 - self.height / 2) self.y = 2732 - self.height / 2;
// Rotate sprite
self.carSprite.rotation = self.angle;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x222222
});
/****
* Game Code
****/
// Game state
// Car asset (player)
// Car asset (AI)
// Ball asset
// Goal asset (player)
// Goal asset (AI)
var playerScore = 0;
var aiScore = 0;
var matchTime = 60; // seconds
var timeLeft = matchTime;
var gameActive = true;
// Create goals
var goalPlayer = LK.getAsset('goal_player', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 2732 - 80
});
var goalAI = LK.getAsset('goal_ai', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 80
});
game.addChild(goalPlayer);
game.addChild(goalAI);
// Create ball
var ball = new Ball();
game.addChild(ball);
// Create player car
var playerCar = new Car();
playerCar.x = 1024;
playerCar.y = 2732 - 400;
playerCar.angle = -Math.PI / 2;
game.addChild(playerCar);
// Create AI car
var aiCar = new Car();
aiCar.carSprite.destroy();
aiCar.carSprite = aiCar.attachAsset('car_ai', {
anchorX: 0.5,
anchorY: 0.5
});
aiCar.isAI = true;
aiCar.x = 1024;
aiCar.y = 400;
aiCar.angle = Math.PI / 2;
game.addChild(aiCar);
// Score display
var scoreTxt = new Text2('0 : 0', {
size: 120,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Timer display
var timerTxt = new Text2('60', {
size: 90,
fill: 0xFFFF00
});
timerTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(timerTxt);
timerTxt.y = 120;
// Helper: Reset ball and cars to center
function resetPositions(scoredBy) {
ball.x = 1024;
ball.y = 1366;
ball.vx = 0;
ball.vy = 0;
playerCar.x = 1024;
playerCar.y = 2732 - 400;
playerCar.angle = -Math.PI / 2;
playerCar.speed = 0;
aiCar.x = 1024;
aiCar.y = 400;
aiCar.angle = Math.PI / 2;
aiCar.speed = 0;
// Small pause after goal
gameActive = false;
tween(ball, {
alpha: 0.2
}, {
duration: 200,
onFinish: function onFinish() {
tween(ball, {
alpha: 1
}, {
duration: 200,
onFinish: function onFinish() {
gameActive = true;
}
});
}
});
}
// Touch controls
var touchActive = false;
var touchStartX = 0,
touchStartY = 0;
var touchCurX = 0,
touchCurY = 0;
var boostActive = false;
// Touch: steer by dragging, boost by double tap or long press
game.down = function (x, y, obj) {
// Ignore if not active
if (!gameActive) return;
// Don't allow touch in top left 100x100
if (x < 100 && y < 100) return;
touchActive = true;
touchStartX = x;
touchStartY = y;
touchCurX = x;
touchCurY = y;
boostActive = false;
// Detect long press for boost
playerCar.boosting = false;
playerCar._boostTimeout = LK.setTimeout(function () {
boostActive = true;
playerCar.boosting = true;
}, 400);
};
game.move = function (x, y, obj) {
if (!gameActive) return;
if (!touchActive) return;
touchCurX = x;
touchCurY = y;
// Steer: angle towards drag direction
var dx = touchCurX - playerCar.x;
var dy = touchCurY - playerCar.y;
var desiredAngle = Math.atan2(dy, dx);
var angleDiff = desiredAngle - playerCar.angle;
while (angleDiff > Math.PI) angleDiff -= Math.PI * 2;
while (angleDiff < -Math.PI) angleDiff += Math.PI * 2;
if (angleDiff > 0.1) playerCar.angle += playerCar.turnSpeed;else if (angleDiff < -0.1) playerCar.angle -= playerCar.turnSpeed;
// Accelerate if facing drag direction
if (Math.abs(angleDiff) < 0.5) {
playerCar.speed += playerCar.acceleration;
}
// Clamp
if (playerCar.speed > playerCar.maxSpeed) playerCar.speed = playerCar.maxSpeed;
};
game.up = function (x, y, obj) {
touchActive = false;
if (playerCar._boostTimeout) {
LK.clearTimeout(playerCar._boostTimeout);
playerCar._boostTimeout = null;
}
if (boostActive) {
boostActive = false;
}
};
// Double tap for boost
var lastTap = 0;
game.down = function (origDown) {
return function (x, y, obj) {
var now = Date.now();
if (now - lastTap < 350) {
// Double tap: boost
playerCar.boosting = true;
}
lastTap = now;
origDown.call(game, x, y, obj);
};
}(game.down);
// Physics: Car-ball collision
function carBallCollision(car, ball) {
var dx = ball.x - car.x;
var dy = ball.y - car.y;
var dist = Math.sqrt(dx * dx + dy * dy);
var minDist = (car.width / 2 + ball.width / 2) * 0.8;
if (dist < minDist) {
// Push ball away
var nx = dx / (dist || 1);
var ny = dy / (dist || 1);
var overlap = minDist - dist;
ball.x += nx * overlap / 2;
ball.y += ny * overlap / 2;
// Ball velocity: add car's speed
var impact = Math.max(8, car.speed * 1.2);
ball.vx += nx * impact;
ball.vy += ny * impact;
// Car bounces a bit
car.speed *= 0.7;
}
}
// Physics: Car-car collision
function carCarCollision(car1, car2) {
var dx = car2.x - car1.x;
var dy = car2.y - car1.y;
var dist = Math.sqrt(dx * dx + dy * dy);
var minDist = (car1.width / 2 + car2.width / 2) * 0.9;
if (dist < minDist) {
var nx = dx / (dist || 1);
var ny = dy / (dist || 1);
var overlap = minDist - dist;
car1.x -= nx * overlap / 2;
car1.y -= ny * overlap / 2;
car2.x += nx * overlap / 2;
car2.y += ny * overlap / 2;
// Exchange some speed
var temp = car1.speed;
car1.speed = car2.speed * 0.7;
car2.speed = temp * 0.7;
}
}
// Goal detection
function checkGoal() {
// Player goal (top)
if (ball.y - ball.height / 2 < goalAI.y + goalAI.height / 2 && ball.x > goalAI.x - goalAI.width / 2 && ball.x < goalAI.x + goalAI.width / 2) {
playerScore++;
scoreTxt.setText(playerScore + " : " + aiScore);
LK.effects.flashScreen(0x00ff00, 500);
resetPositions('player');
}
// AI goal (bottom)
if (ball.y + ball.height / 2 > goalPlayer.y - goalPlayer.height / 2 && ball.x > goalPlayer.x - goalPlayer.width / 2 && ball.x < goalPlayer.x + goalPlayer.width / 2) {
aiScore++;
scoreTxt.setText(playerScore + " : " + aiScore);
LK.effects.flashScreen(0xff0000, 500);
resetPositions('ai');
}
}
// Timer
var timerInterval = LK.setInterval(function () {
if (!gameActive) return;
if (timeLeft > 0) {
timeLeft--;
timerTxt.setText(timeLeft + "");
if (timeLeft <= 10) timerTxt.setText(timeLeft + "!");
}
if (timeLeft <= 0) {
// End game
gameActive = false;
if (playerScore > aiScore) {
LK.showYouWin();
} else if (aiScore > playerScore) {
LK.showGameOver();
} else {
// Draw: treat as loss for now
LK.showGameOver();
}
}
}, 1000);
// Main update loop
game.update = function () {
if (!gameActive) return;
// Update cars and ball
playerCar.update();
aiCar.update();
ball.update();
// Collisions
carBallCollision(playerCar, ball);
carBallCollision(aiCar, ball);
carCarCollision(playerCar, aiCar);
// Goal check
checkGoal();
};
// Initial positions
resetPositions();
/* End of game code */ ===================================================================
--- original.js
+++ change.js
@@ -77,35 +77,60 @@
self.targetY = 0;
self.update = function () {
// AI logic
if (self.isAI) {
- // Simple AI: Move towards ball, try to push it to player goal
- var dx = ball.x - self.x;
- var dy = ball.y - self.y;
- var dist = Math.sqrt(dx * dx + dy * dy);
- // Target: If ball is on AI's side, go for ball, else defend
- if (ball.y < 1366) {
- self.targetX = ball.x;
- self.targetY = ball.y + 120;
+ // If the player car is above the halfway line, try to push the player into the green goal
+ if (playerCar.y > 1366) {
+ // Target just behind the player car, so AI can push it toward the green goal
+ var dx = playerCar.x - self.x;
+ var dy = playerCar.y - self.y;
+ var dist = Math.sqrt(dx * dx + dy * dy);
+ // Aim for a point slightly behind the player car (towards the green goal)
+ var pushDist = 120;
+ var pushAngle = Math.atan2(playerCar.y - goalPlayer.y, playerCar.x - goalPlayer.x);
+ self.targetX = playerCar.x + Math.cos(pushAngle) * pushDist;
+ self.targetY = playerCar.y + Math.sin(pushAngle) * pushDist;
+ // If close to player and facing, boost
+ var desiredAngle = Math.atan2(self.targetY - self.y, self.targetX - self.x);
+ var angleDiff = desiredAngle - self.angle;
+ while (angleDiff > Math.PI) angleDiff -= Math.PI * 2;
+ while (angleDiff < -Math.PI) angleDiff += Math.PI * 2;
+ if (angleDiff > 0.1) self.angle += self.turnSpeed;else if (angleDiff < -0.1) self.angle -= self.turnSpeed;
+ if (Math.abs(angleDiff) < 0.5) {
+ self.speed += self.acceleration * 0.7;
+ }
+ if (dist < 350 && Math.abs(angleDiff) < 0.3 && self.boostCooldown <= 0) {
+ self.boosting = true;
+ }
} else {
- // Defend goal
- self.targetX = 1024;
- self.targetY = 220;
+ // Default: try to push the ball toward the player goal
+ var dx = ball.x - self.x;
+ var dy = ball.y - self.y;
+ var dist = Math.sqrt(dx * dx + dy * dy);
+ // Target: If ball is on AI's side, go for ball, else defend
+ if (ball.y < 1366) {
+ self.targetX = ball.x;
+ self.targetY = ball.y + 120;
+ } else {
+ // Defend goal
+ self.targetX = 1024;
+ self.targetY = 220;
+ }
+ // Turn towards target
+ var desiredAngle = Math.atan2(self.targetY - self.y, self.targetX - self.x);
+ var angleDiff = desiredAngle - self.angle;
+ while (angleDiff > Math.PI) angleDiff -= Math.PI * 2;
+ while (angleDiff < -Math.PI) angleDiff += Math.PI * 2;
+ if (angleDiff > 0.1) self.angle += self.turnSpeed;else if (angleDiff < -0.1) self.angle -= self.turnSpeed;
+ // Accelerate if facing target
+ if (Math.abs(angleDiff) < 0.5) {
+ self.speed += self.acceleration * 0.7;
+ }
+ // AI boost if close to ball and facing it
+ if (dist < 400 && Math.abs(angleDiff) < 0.3 && self.boostCooldown <= 0) {
+ self.boosting = true;
+ }
}
- // Turn towards target
- var desiredAngle = Math.atan2(self.targetY - self.y, self.targetX - self.x);
- var angleDiff = desiredAngle - self.angle;
- while (angleDiff > Math.PI) angleDiff -= Math.PI * 2;
- while (angleDiff < -Math.PI) angleDiff += Math.PI * 2;
- if (angleDiff > 0.1) self.angle += self.turnSpeed;else if (angleDiff < -0.1) self.angle -= self.turnSpeed;
- // Accelerate if facing target
- if (Math.abs(angleDiff) < 0.5) {
- self.speed += self.acceleration * 0.7;
- }
- // AI boost if close to ball and facing it
- if (dist < 400 && Math.abs(angleDiff) < 0.3 && self.boostCooldown <= 0) {
- self.boosting = true;
- }
}
// Boost logic
if (self.boosting && self.boostCooldown <= 0) {
self.speed = self.boostPower;
@@ -141,14 +166,14 @@
/****
* Game Code
****/
-// Goal asset (AI)
-// Goal asset (player)
-// Ball asset
-// Car asset (AI)
-// Car asset (player)
// Game state
+// Car asset (player)
+// Car asset (AI)
+// Ball asset
+// Goal asset (player)
+// Goal asset (AI)
var playerScore = 0;
var aiScore = 0;
var matchTime = 60; // seconds
var timeLeft = matchTime;