User prompt
add move command
User prompt
Let the ball be a little slower
User prompt
ortada yuvarlak olsun
User prompt
çizgiler ekle
User prompt
make the background more realistic
Code edit (1 edits merged)
Please save this source code
User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'length')' in or related to this line: 'self.attachAsset(self.assetId, {' Line Number: 22
Code edit (1 edits merged)
Please save this source code
User prompt
Neon Table Hockey Sparkle
Initial prompt
Create a table hockey game against an AI opponent with colorful neon lights, and have the puck sparkle whenever it bounces to the left or right.
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Paddle class (for both player and AI)
var Paddle = Container.expand(function () {
var self = Container.call(this);
self.radius = 130; // for collision
self.attachAsset(self.assetId, {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
// Puck class
var Puck = Container.expand(function () {
var self = Container.call(this);
var puckGfx = self.attachAsset('puck', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = 40;
self.vx = 0;
self.vy = 0;
self.maxSpeed = 38;
self.minSpeed = 18;
self.update = function () {
self.x += self.vx;
self.y += self.vy;
// 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;
}
if (speed < self.minSpeed && speed > 0) {
self.vx *= self.minSpeed / speed;
self.vy *= self.minSpeed / speed;
}
};
return self;
});
// Sparkle effect class
var Sparkle = Container.expand(function () {
var self = Container.call(this);
var sparkleGfx = self.attachAsset('sparkle', {
anchorX: 0.5,
anchorY: 0.5
});
self.life = 18 + Math.floor(Math.random() * 10);
self.vx = (Math.random() - 0.5) * 32;
self.vy = (Math.random() - 0.5) * 32;
self.update = function () {
self.x += self.vx;
self.y += self.vy;
self.life--;
self.alpha = self.life / 24;
if (self.life <= 0) {
self.destroy();
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x0a0020
});
/****
* Game Code
****/
// Neon paddles and puck, sparkles, and goal lines
// Game constants
var FIELD_WIDTH = 2048;
var FIELD_HEIGHT = 2732;
var GOAL_HEIGHT = 32;
var PADDLE_Y_OFFSET = 220;
var AI_Y = FIELD_HEIGHT - PADDLE_Y_OFFSET;
var PLAYER_Y = PADDLE_Y_OFFSET;
var PUCK_START_Y = FIELD_HEIGHT / 2;
var PUCK_START_X = FIELD_WIDTH / 2;
var GOAL_LINE_Y_TOP = GOAL_HEIGHT;
var GOAL_LINE_Y_BOT = FIELD_HEIGHT - GOAL_HEIGHT;
// Game state
var playerScore = 0;
var aiScore = 0;
var maxScore = 7;
var dragging = false;
var dragOffsetX = 0,
dragOffsetY = 0;
var lastTouchX = 0,
lastTouchY = 0;
var sparkles = [];
var lastGoal = null;
// Create paddles
var playerPaddle = new Paddle();
playerPaddle.assetId = 'paddlePlayer';
playerPaddle.x = FIELD_WIDTH / 2;
playerPaddle.y = PLAYER_Y;
game.addChild(playerPaddle);
var aiPaddle = new Paddle();
aiPaddle.assetId = 'paddleAI';
aiPaddle.x = FIELD_WIDTH / 2;
aiPaddle.y = AI_Y;
game.addChild(aiPaddle);
// Create puck
var puck = new Puck();
puck.x = PUCK_START_X;
puck.y = PUCK_START_Y;
resetPuck();
game.addChild(puck);
// Goal lines
var goalLineTop = LK.getAsset('goalLine', {
anchorX: 0.5,
anchorY: 0.5,
x: FIELD_WIDTH / 2,
y: GOAL_LINE_Y_TOP
});
game.addChild(goalLineTop);
var goalLineBot = LK.getAsset('goalLine', {
anchorX: 0.5,
anchorY: 0.5,
x: FIELD_WIDTH / 2,
y: GOAL_LINE_Y_BOT
});
game.addChild(goalLineBot);
// Score display
var scoreTxt = new Text2('0 : 0', {
size: 120,
fill: 0x00FFF7
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Helper: reset puck to center, random direction
function resetPuck(scoredBy) {
puck.x = PUCK_START_X;
puck.y = PUCK_START_Y;
var angle = Math.random() * Math.PI * 2;
// If scoredBy, send puck toward the other player
if (scoredBy === 'player') {
angle = Math.PI / 2 + (Math.random() - 0.5) * 0.7;
} else if (scoredBy === 'ai') {
angle = -Math.PI / 2 + (Math.random() - 0.5) * 0.7;
}
var speed = 24 + Math.random() * 8;
puck.vx = Math.cos(angle) * speed;
puck.vy = Math.sin(angle) * speed;
}
// Helper: clamp paddle inside field
function clampPaddle(paddle, isPlayer) {
var minX = paddle.radius + 12;
var maxX = FIELD_WIDTH - paddle.radius - 12;
var minY = isPlayer ? GOAL_LINE_Y_TOP + paddle.radius + 12 : FIELD_HEIGHT / 2 + paddle.radius + 12;
var maxY = isPlayer ? FIELD_HEIGHT / 2 - paddle.radius - 12 : GOAL_LINE_Y_BOT - paddle.radius - 12;
if (paddle.x < minX) paddle.x = minX;
if (paddle.x > maxX) paddle.x = maxX;
if (paddle.y < minY) paddle.y = minY;
if (paddle.y > maxY) paddle.y = maxY;
}
// Helper: paddle-puck collision
function checkPaddleCollision(paddle) {
var dx = puck.x - paddle.x;
var dy = puck.y - paddle.y;
var dist = Math.sqrt(dx * dx + dy * dy);
var minDist = paddle.radius + puck.radius;
if (dist < minDist) {
// Move puck out of paddle
var overlap = minDist - dist + 2;
var nx = dx / (dist || 1);
var ny = dy / (dist || 1);
puck.x += nx * overlap;
puck.y += ny * overlap;
// Reflect puck velocity
var dot = puck.vx * nx + puck.vy * ny;
puck.vx = puck.vx - 2 * dot * nx;
puck.vy = puck.vy - 2 * dot * ny;
// Add paddle movement to puck
if (paddle === playerPaddle && dragging) {
puck.vx += (paddle.x - lastTouchX) * 0.4;
puck.vy += (paddle.y - lastTouchY) * 0.4;
}
// Clamp puck speed
var speed = Math.sqrt(puck.vx * puck.vx + puck.vy * puck.vy);
if (speed < puck.minSpeed) {
puck.vx *= puck.minSpeed / (speed || 1);
puck.vy *= puck.minSpeed / (speed || 1);
}
// Neon flash effect
LK.effects.flashObject(paddle, 0xffffff, 120);
}
}
// Helper: wall collision and sparkle
function checkWallCollision() {
// Left/right walls
if (puck.x - puck.radius < 0) {
puck.x = puck.radius + 2;
puck.vx = -puck.vx;
spawnSparkles(puck.x, puck.y, 1);
}
if (puck.x + puck.radius > FIELD_WIDTH) {
puck.x = FIELD_WIDTH - puck.radius - 2;
puck.vx = -puck.vx;
spawnSparkles(puck.x, puck.y, 1);
}
// Top/bottom: check for goals
if (puck.y - puck.radius < GOAL_LINE_Y_TOP) {
// AI scores
if (puck.x > FIELD_WIDTH * 0.25 && puck.x < FIELD_WIDTH * 0.75) {
aiScore++;
updateScore();
LK.effects.flashScreen(0xff00e1, 400);
lastGoal = 'ai';
if (aiScore >= maxScore) {
LK.showGameOver();
return;
}
resetPuck('ai');
} else {
puck.y = GOAL_LINE_Y_TOP + puck.radius + 2;
puck.vy = -puck.vy;
}
}
if (puck.y + puck.radius > GOAL_LINE_Y_BOT) {
// Player scores
if (puck.x > FIELD_WIDTH * 0.25 && puck.x < FIELD_WIDTH * 0.75) {
playerScore++;
updateScore();
LK.effects.flashScreen(0x00fff7, 400);
lastGoal = 'player';
if (playerScore >= maxScore) {
LK.showYouWin();
return;
}
resetPuck('player');
} else {
puck.y = GOAL_LINE_Y_BOT - puck.radius - 2;
puck.vy = -puck.vy;
}
}
}
// Helper: update score text
function updateScore() {
scoreTxt.setText(playerScore + ' : ' + aiScore);
}
// Helper: spawn sparkles at (x, y)
function spawnSparkles(x, y, count) {
for (var i = 0; i < 8 + Math.floor(Math.random() * 4); i++) {
var s = new Sparkle();
s.x = x;
s.y = y;
s.alpha = 1;
sparkles.push(s);
game.addChild(s);
// Animate color
tween(s, {
tint: Math.random() > 0.5 ? 0x00fff7 : 0xff00e1
}, {
duration: 200
});
}
}
// AI logic
function aiMove() {
// Only move if puck is on AI's side or moving toward AI
var targetX = puck.x;
var targetY = AI_Y;
// Defensive: if puck is coming toward AI, track it
if (puck.vy > 0 && puck.y > FIELD_HEIGHT / 2 - 200) {
targetX = puck.x;
} else {
// Center
targetX = FIELD_WIDTH / 2;
}
// Add some reaction delay and error
var dx = targetX - aiPaddle.x;
var maxMove = 32 + Math.random() * 12;
if (Math.abs(dx) > maxMove) dx = maxMove * (dx > 0 ? 1 : -1);
aiPaddle.x += dx * 0.18;
clampPaddle(aiPaddle, false);
}
// Touch/mouse controls for player paddle
game.down = function (x, y, obj) {
// Only allow drag if touch is on player's half
if (y < FIELD_HEIGHT / 2) return;
// Check if touch is on paddle
var dx = x - playerPaddle.x;
var dy = y - playerPaddle.y;
if (dx * dx + dy * dy < playerPaddle.radius * playerPaddle.radius * 1.2) {
dragging = true;
dragOffsetX = playerPaddle.x - x;
dragOffsetY = playerPaddle.y - y;
lastTouchX = playerPaddle.x;
lastTouchY = playerPaddle.y;
}
};
game.move = function (x, y, obj) {
if (dragging) {
// Only allow paddle in player's half
playerPaddle.x = x + dragOffsetX;
playerPaddle.y = y + dragOffsetY;
clampPaddle(playerPaddle, true);
}
};
game.up = function (x, y, obj) {
dragging = false;
};
// Main update loop
game.update = function () {
// Update puck
puck.update();
// Update sparkles
for (var i = sparkles.length - 1; i >= 0; i--) {
var s = sparkles[i];
if (s.parent) s.update();
if (!s.parent) sparkles.splice(i, 1);
}
// AI move
aiMove();
// Paddle collision
checkPaddleCollision(playerPaddle);
checkPaddleCollision(aiPaddle);
// Wall and goal collision
checkWallCollision();
// Clamp paddles
clampPaddle(playerPaddle, true);
clampPaddle(aiPaddle, false);
// Save last touch for paddle velocity
if (dragging) {
lastTouchX = playerPaddle.x;
lastTouchY = playerPaddle.y;
}
};
// Set background color to deep neon blue
game.setBackgroundColor(0x0a0020); ===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,341 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+
+/****
+* Classes
+****/
+// Paddle class (for both player and AI)
+var Paddle = Container.expand(function () {
+ var self = Container.call(this);
+ self.radius = 130; // for collision
+ self.attachAsset(self.assetId, {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ return self;
+});
+// Puck class
+var Puck = Container.expand(function () {
+ var self = Container.call(this);
+ var puckGfx = self.attachAsset('puck', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.radius = 40;
+ self.vx = 0;
+ self.vy = 0;
+ self.maxSpeed = 38;
+ self.minSpeed = 18;
+ self.update = function () {
+ self.x += self.vx;
+ self.y += self.vy;
+ // 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;
+ }
+ if (speed < self.minSpeed && speed > 0) {
+ self.vx *= self.minSpeed / speed;
+ self.vy *= self.minSpeed / speed;
+ }
+ };
+ return self;
+});
+// Sparkle effect class
+var Sparkle = Container.expand(function () {
+ var self = Container.call(this);
+ var sparkleGfx = self.attachAsset('sparkle', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.life = 18 + Math.floor(Math.random() * 10);
+ self.vx = (Math.random() - 0.5) * 32;
+ self.vy = (Math.random() - 0.5) * 32;
+ self.update = function () {
+ self.x += self.vx;
+ self.y += self.vy;
+ self.life--;
+ self.alpha = self.life / 24;
+ if (self.life <= 0) {
+ self.destroy();
+ }
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0x0a0020
+});
+
+/****
+* Game Code
+****/
+// Neon paddles and puck, sparkles, and goal lines
+// Game constants
+var FIELD_WIDTH = 2048;
+var FIELD_HEIGHT = 2732;
+var GOAL_HEIGHT = 32;
+var PADDLE_Y_OFFSET = 220;
+var AI_Y = FIELD_HEIGHT - PADDLE_Y_OFFSET;
+var PLAYER_Y = PADDLE_Y_OFFSET;
+var PUCK_START_Y = FIELD_HEIGHT / 2;
+var PUCK_START_X = FIELD_WIDTH / 2;
+var GOAL_LINE_Y_TOP = GOAL_HEIGHT;
+var GOAL_LINE_Y_BOT = FIELD_HEIGHT - GOAL_HEIGHT;
+// Game state
+var playerScore = 0;
+var aiScore = 0;
+var maxScore = 7;
+var dragging = false;
+var dragOffsetX = 0,
+ dragOffsetY = 0;
+var lastTouchX = 0,
+ lastTouchY = 0;
+var sparkles = [];
+var lastGoal = null;
+// Create paddles
+var playerPaddle = new Paddle();
+playerPaddle.assetId = 'paddlePlayer';
+playerPaddle.x = FIELD_WIDTH / 2;
+playerPaddle.y = PLAYER_Y;
+game.addChild(playerPaddle);
+var aiPaddle = new Paddle();
+aiPaddle.assetId = 'paddleAI';
+aiPaddle.x = FIELD_WIDTH / 2;
+aiPaddle.y = AI_Y;
+game.addChild(aiPaddle);
+// Create puck
+var puck = new Puck();
+puck.x = PUCK_START_X;
+puck.y = PUCK_START_Y;
+resetPuck();
+game.addChild(puck);
+// Goal lines
+var goalLineTop = LK.getAsset('goalLine', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: FIELD_WIDTH / 2,
+ y: GOAL_LINE_Y_TOP
+});
+game.addChild(goalLineTop);
+var goalLineBot = LK.getAsset('goalLine', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: FIELD_WIDTH / 2,
+ y: GOAL_LINE_Y_BOT
+});
+game.addChild(goalLineBot);
+// Score display
+var scoreTxt = new Text2('0 : 0', {
+ size: 120,
+ fill: 0x00FFF7
+});
+scoreTxt.anchor.set(0.5, 0);
+LK.gui.top.addChild(scoreTxt);
+// Helper: reset puck to center, random direction
+function resetPuck(scoredBy) {
+ puck.x = PUCK_START_X;
+ puck.y = PUCK_START_Y;
+ var angle = Math.random() * Math.PI * 2;
+ // If scoredBy, send puck toward the other player
+ if (scoredBy === 'player') {
+ angle = Math.PI / 2 + (Math.random() - 0.5) * 0.7;
+ } else if (scoredBy === 'ai') {
+ angle = -Math.PI / 2 + (Math.random() - 0.5) * 0.7;
+ }
+ var speed = 24 + Math.random() * 8;
+ puck.vx = Math.cos(angle) * speed;
+ puck.vy = Math.sin(angle) * speed;
+}
+// Helper: clamp paddle inside field
+function clampPaddle(paddle, isPlayer) {
+ var minX = paddle.radius + 12;
+ var maxX = FIELD_WIDTH - paddle.radius - 12;
+ var minY = isPlayer ? GOAL_LINE_Y_TOP + paddle.radius + 12 : FIELD_HEIGHT / 2 + paddle.radius + 12;
+ var maxY = isPlayer ? FIELD_HEIGHT / 2 - paddle.radius - 12 : GOAL_LINE_Y_BOT - paddle.radius - 12;
+ if (paddle.x < minX) paddle.x = minX;
+ if (paddle.x > maxX) paddle.x = maxX;
+ if (paddle.y < minY) paddle.y = minY;
+ if (paddle.y > maxY) paddle.y = maxY;
+}
+// Helper: paddle-puck collision
+function checkPaddleCollision(paddle) {
+ var dx = puck.x - paddle.x;
+ var dy = puck.y - paddle.y;
+ var dist = Math.sqrt(dx * dx + dy * dy);
+ var minDist = paddle.radius + puck.radius;
+ if (dist < minDist) {
+ // Move puck out of paddle
+ var overlap = minDist - dist + 2;
+ var nx = dx / (dist || 1);
+ var ny = dy / (dist || 1);
+ puck.x += nx * overlap;
+ puck.y += ny * overlap;
+ // Reflect puck velocity
+ var dot = puck.vx * nx + puck.vy * ny;
+ puck.vx = puck.vx - 2 * dot * nx;
+ puck.vy = puck.vy - 2 * dot * ny;
+ // Add paddle movement to puck
+ if (paddle === playerPaddle && dragging) {
+ puck.vx += (paddle.x - lastTouchX) * 0.4;
+ puck.vy += (paddle.y - lastTouchY) * 0.4;
+ }
+ // Clamp puck speed
+ var speed = Math.sqrt(puck.vx * puck.vx + puck.vy * puck.vy);
+ if (speed < puck.minSpeed) {
+ puck.vx *= puck.minSpeed / (speed || 1);
+ puck.vy *= puck.minSpeed / (speed || 1);
+ }
+ // Neon flash effect
+ LK.effects.flashObject(paddle, 0xffffff, 120);
+ }
+}
+// Helper: wall collision and sparkle
+function checkWallCollision() {
+ // Left/right walls
+ if (puck.x - puck.radius < 0) {
+ puck.x = puck.radius + 2;
+ puck.vx = -puck.vx;
+ spawnSparkles(puck.x, puck.y, 1);
+ }
+ if (puck.x + puck.radius > FIELD_WIDTH) {
+ puck.x = FIELD_WIDTH - puck.radius - 2;
+ puck.vx = -puck.vx;
+ spawnSparkles(puck.x, puck.y, 1);
+ }
+ // Top/bottom: check for goals
+ if (puck.y - puck.radius < GOAL_LINE_Y_TOP) {
+ // AI scores
+ if (puck.x > FIELD_WIDTH * 0.25 && puck.x < FIELD_WIDTH * 0.75) {
+ aiScore++;
+ updateScore();
+ LK.effects.flashScreen(0xff00e1, 400);
+ lastGoal = 'ai';
+ if (aiScore >= maxScore) {
+ LK.showGameOver();
+ return;
+ }
+ resetPuck('ai');
+ } else {
+ puck.y = GOAL_LINE_Y_TOP + puck.radius + 2;
+ puck.vy = -puck.vy;
+ }
+ }
+ if (puck.y + puck.radius > GOAL_LINE_Y_BOT) {
+ // Player scores
+ if (puck.x > FIELD_WIDTH * 0.25 && puck.x < FIELD_WIDTH * 0.75) {
+ playerScore++;
+ updateScore();
+ LK.effects.flashScreen(0x00fff7, 400);
+ lastGoal = 'player';
+ if (playerScore >= maxScore) {
+ LK.showYouWin();
+ return;
+ }
+ resetPuck('player');
+ } else {
+ puck.y = GOAL_LINE_Y_BOT - puck.radius - 2;
+ puck.vy = -puck.vy;
+ }
+ }
+}
+// Helper: update score text
+function updateScore() {
+ scoreTxt.setText(playerScore + ' : ' + aiScore);
+}
+// Helper: spawn sparkles at (x, y)
+function spawnSparkles(x, y, count) {
+ for (var i = 0; i < 8 + Math.floor(Math.random() * 4); i++) {
+ var s = new Sparkle();
+ s.x = x;
+ s.y = y;
+ s.alpha = 1;
+ sparkles.push(s);
+ game.addChild(s);
+ // Animate color
+ tween(s, {
+ tint: Math.random() > 0.5 ? 0x00fff7 : 0xff00e1
+ }, {
+ duration: 200
+ });
+ }
+}
+// AI logic
+function aiMove() {
+ // Only move if puck is on AI's side or moving toward AI
+ var targetX = puck.x;
+ var targetY = AI_Y;
+ // Defensive: if puck is coming toward AI, track it
+ if (puck.vy > 0 && puck.y > FIELD_HEIGHT / 2 - 200) {
+ targetX = puck.x;
+ } else {
+ // Center
+ targetX = FIELD_WIDTH / 2;
+ }
+ // Add some reaction delay and error
+ var dx = targetX - aiPaddle.x;
+ var maxMove = 32 + Math.random() * 12;
+ if (Math.abs(dx) > maxMove) dx = maxMove * (dx > 0 ? 1 : -1);
+ aiPaddle.x += dx * 0.18;
+ clampPaddle(aiPaddle, false);
+}
+// Touch/mouse controls for player paddle
+game.down = function (x, y, obj) {
+ // Only allow drag if touch is on player's half
+ if (y < FIELD_HEIGHT / 2) return;
+ // Check if touch is on paddle
+ var dx = x - playerPaddle.x;
+ var dy = y - playerPaddle.y;
+ if (dx * dx + dy * dy < playerPaddle.radius * playerPaddle.radius * 1.2) {
+ dragging = true;
+ dragOffsetX = playerPaddle.x - x;
+ dragOffsetY = playerPaddle.y - y;
+ lastTouchX = playerPaddle.x;
+ lastTouchY = playerPaddle.y;
+ }
+};
+game.move = function (x, y, obj) {
+ if (dragging) {
+ // Only allow paddle in player's half
+ playerPaddle.x = x + dragOffsetX;
+ playerPaddle.y = y + dragOffsetY;
+ clampPaddle(playerPaddle, true);
+ }
+};
+game.up = function (x, y, obj) {
+ dragging = false;
+};
+// Main update loop
+game.update = function () {
+ // Update puck
+ puck.update();
+ // Update sparkles
+ for (var i = sparkles.length - 1; i >= 0; i--) {
+ var s = sparkles[i];
+ if (s.parent) s.update();
+ if (!s.parent) sparkles.splice(i, 1);
+ }
+ // AI move
+ aiMove();
+ // Paddle collision
+ checkPaddleCollision(playerPaddle);
+ checkPaddleCollision(aiPaddle);
+ // Wall and goal collision
+ checkWallCollision();
+ // Clamp paddles
+ clampPaddle(playerPaddle, true);
+ clampPaddle(aiPaddle, false);
+ // Save last touch for paddle velocity
+ if (dragging) {
+ lastTouchX = playerPaddle.x;
+ lastTouchY = playerPaddle.y;
+ }
+};
+// Set background color to deep neon blue
+game.setBackgroundColor(0x0a0020);
\ No newline at end of file