/****
* Classes
****/
//<Assets used in the game will automatically appear here>
// Ball class
var Ball = Container.expand(function () {
var self = Container.call(this);
var ballGraphics = self.attachAsset('ball', {
anchorX: 0.5,
anchorY: 0.5
});
self.speedY = 4.0;
self.speedX = 0;
self.update = function () {
self.y += self.speedY;
self.x += self.speedX;
if (self.y <= 50 || self.y >= 2682) {
self.speedY *= -1;
LK.getSound('ballsound').play();
}
if (self.x <= 150 || self.x >= 1898) {
self.speedX *= -1;
LK.getSound('ballsound').play();
if ((self.y <= 200 || self.y >= 2532) && (lastCornerHit === null || Date.now() - lastCornerHit > 1000)) {
cornerHits++;
lastCornerHit = Date.now();
if (cornerHits >= 3) {
opponentPaddle.y -= 50; // Move opponent closer to iceGateTop
cornerHits = 0; // Reset counter
}
}
}
// Removed redundant check for ball going out sideways
if (self.y >= 2732 || self.y <= 0) {
self.speedY *= -1; // Bounce back vertically
LK.getSound('ballsound').play();
} else if (self.speedX === 0 && self.speedY === 0) {
// If the ball stops, move the paddle to iceGateTop and push the ball
paddle.y = topGoal.y + 50; // Move paddle to iceGateTop
self.speedY = 4; // Push the ball away
}
// Removed redundant check for ball going out sideways
if (self.y >= 2732) {
self.speedY *= -1;
}
// Removed redundant check for ball going out sideways
if (self.y >= 2732) {
self.speedY *= -1;
}
// Removed redundant check for ball going out sideways
if (self.y >= 2732) {
self.speedY *= -1;
}
// Removed redundant check for ball going out sideways
if (self.y >= 2732) {
self.speedY *= -1;
}
if (self.x <= 0 || self.x >= 2048) {
self.speedX *= -1; // Bounce back horizontally
}
if (self.y >= 2732) {
self.speedY *= -1;
}
if (self.x <= 0 || self.x >= 2048) {
self.speedX *= -1;
}
if (self.x <= 0 || self.x >= 2048) {
self.speedX *= -1;
}
// Check for collision with player paddle
if (self.intersects(paddle)) {
LK.getSound('paddles').play();
// Calculate the angle of incidence based on where the ball hits the paddle
var relativeIntersectX = (paddle.x - self.x) / (paddle.width / 2);
var bounceAngle = relativeIntersectX * Math.PI / 4; // Max bounce angle of 45 degrees
// Calculate paddle movement speed
var paddleSpeed = Math.sqrt(Math.pow(paddle.x - paddle.prevX, 2) + Math.pow(paddle.y - paddle.prevY, 2));
// Update ball speed and direction, adding paddle speed influence
self.speedX = self.speedY * Math.sin(bounceAngle) + paddleSpeed * 0.2; // Increase influence factor
self.speedY = -Math.abs(self.speedY * Math.cos(bounceAngle)) - paddleSpeed * 0.1; // Add vertical influence
self.speedX = self.speedX === 0 ? 1 : self.speedX; // Ensure non-zero speed
self.speedY = self.speedY === 0 ? 1 : self.speedY; // Ensure non-zero speed
}
// Check for collision with opponent paddle
if (self.intersects(opponentPaddle)) {
LK.getSound('paddles').play();
// Calculate the angle of incidence based on where the ball hits the paddle
var relativeIntersectX = (opponentPaddle.x - self.x) / (opponentPaddle.width / 2);
var bounceAngle = relativeIntersectX * Math.PI / 4; // Max bounce angle of 45 degrees
// Update ball speed and direction
self.speedX = self.speedY * Math.sin(bounceAngle);
self.speedY = Math.abs(self.speedY * Math.cos(bounceAngle));
self.speedX = self.speedX === 0 ? 1 : self.speedX; // Ensure non-zero speed
self.speedY = self.speedY === 0 ? 1 : self.speedY; // Ensure non-zero speed
}
};
});
var IceGate = Container.expand(function (color) {
var self = Container.call(this);
var gateGraphics = self.attachAsset(color === 'top' ? 'iceGateTop' : 'iceGateBottom', {
anchorX: 0.5,
anchorY: 0.5
});
});
// Opponent Paddle class
var OpponentPaddle = Container.expand(function () {
var self = Container.call(this);
var paddleGraphics = self.attachAsset('playerPaddle', {
anchorX: 0.5,
anchorY: 0.5
});
self.idleTime = 0;
self.update = function () {
if (self.prevX === self.x && self.prevY === self.y) {
self.idleTime += 1 / 60; // Increment idle time by 1/60th of a second
} else {
self.idleTime = 0; // Reset idle time if paddle has moved
}
self.prevX = self.x;
self.prevY = self.y;
if (self.idleTime > 1) {
// Retreat towards the center of the track
if (self.x < 2048 / 2) {
self.x += 5;
} else if (self.x > 2048 / 2) {
self.x -= 5;
}
if (self.y < 1366 / 2) {
self.y += 5;
} else if (self.y > 1366 / 2) {
self.y -= 5;
}
}
// Opponent paddle AI logic with adjusted target
var targetY = ball.y - 100; // Aim closer to the ball for more aggressive tracking
var targetX = ball.x;
// Move vertically towards the target position with increased speed
self.y += (targetY - self.y) * 0.2; // Increase speed for more aggressive movement
// Move horizontally towards the target position with increased speed
self.x += (targetX - self.x) * 0.2; // Increase speed for more aggressive movement
// Removed opponent paddle intersection logic to prevent blocking the ball
// Check if ball is in the corner of the field
if (ball.x <= 200 && ball.y <= 200 || ball.x >= 1848 && ball.y <= 200) {
// Pull opponent paddle towards its own goal
if (self.y < 200) {
self.y += 5;
}
}
// Apply damping to reduce jitter
self.y = Math.max(200 + self.height / 2, Math.min(self.y, 1366 - 200 - self.height / 2));
self.x = Math.max(200 + self.width / 2, Math.min(self.x, 2048 - 200 - self.width / 2));
self.y *= 0.95; // Apply damping to vertical movement
self.x *= 0.95; // Apply damping to horizontal movement
// Ensure opponent paddle does not overlap with the ball
if (self.intersects(ball)) {
if (self.y < ball.y) {
self.y = ball.y - self.height - 1; // Add a small buffer to prevent squeezing
} else {
self.y = ball.y + ball.height + 1; // Add a small buffer to prevent squeezing
}
}
// Prevent overlap with player paddle
if (self.intersects(paddle)) {
if (self.y < paddle.y) {
self.y = paddle.y - self.height;
} else {
self.y = paddle.y + paddle.height;
}
}
// Ensure opponent paddle stays within the screen bounds
if (self.y < 200) {
self.y = 200;
}
};
});
// Paddle class
var Paddle = Container.expand(function () {
var self = Container.call(this);
var paddleGraphics = self.attachAsset('paddle', {
anchorX: 0.5,
anchorY: 0.5
});
self.update = function () {
// Store previous position
self.prevX = self.x;
self.prevY = self.y;
// Ensure player paddle does not overlap with opponent paddle
if (self.intersects(opponentPaddle)) {
if (self.y < opponentPaddle.y) {
self.y = opponentPaddle.y - self.height;
} else {
self.y = opponentPaddle.y + opponentPaddle.height;
}
}
// Ensure the paddle stays within the screen bounds
self.y = Math.max(self.height / 2, Math.min(self.y, 2732 - self.height / 2));
self.x = Math.max(self.width / 2, Math.min(self.x, 2048 - self.width / 2));
// Ensure player paddle does not overlap with the ball
if (self.intersects(ball)) {
if (self.y < ball.y) {
self.y = ball.y - self.height - 1; // Add a small buffer to prevent squeezing
} else {
self.y = ball.y + ball.height + 1; // Add a small buffer to prevent squeezing
}
}
};
});
var ResetButton = Container.expand(function () {
var self = Container.call(this);
var buttonGraphics = self.attachAsset('resetButton', {
anchorX: 0.5,
anchorY: 0.5
});
self.down = function (x, y, obj) {
ball.x = 2048 / 2;
ball.y = 1366;
ball.speedX = 0;
ball.speedY = 4.0;
};
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000,
//Init game with black background
scaleMode: 'fullScreen' // Enable full screen scaling for smartphones
});
/****
* Game Code
****/
// Attach white background asset
var cornerHits = 0;
var lastCornerHit = null;
var background = LK.getAsset('background', {
anchorX: 0.0,
anchorY: 0.0,
x: -1765,
y: -690
});
game.addChild(background);
// Initialize ice hockey goals
var topGoal = game.addChild(new IceGate('top'));
topGoal.x = 2048 / 2 - 10;
topGoal.y = 50 - 45;
var bottomGoal = game.addChild(new IceGate('bottom'));
bottomGoal.x = 2048 / 2 - 10;
bottomGoal.y = 2732 - 50 + 40;
// Initialize ball and paddles
var ball = game.addChild(new Ball());
ball.x = 2048 / 2;
ball.y = 1366; // Center of the field
var paddle = game.addChild(new Paddle());
paddle.x = 2048 / 2;
paddle.y = 2500 + 500;
var opponentPaddle = game.addChild(new OpponentPaddle());
opponentPaddle.prevX = opponentPaddle.x;
opponentPaddle.prevY = opponentPaddle.y;
opponentPaddle.x = 2048 / 2;
opponentPaddle.y = 200;
opponentPaddle.x = 2048 / 2;
// Score display
var playerScore = 0;
var opponentScore = 0;
var scoreTxt = new Text2('0-0', {
size: 150,
fill: "#FFD700" // Golden yellow color
});
scoreTxt.anchor.set(0.5, 0.5);
scoreTxt.rotation = -Math.PI / 2; // Rotate 180 degrees to the left
scoreTxt.x = 2048 - 100; // Position 100 units from the right edge of the screen
scoreTxt.y = 1366 - 25; // Move up by 25 units
game.addChild(scoreTxt);
// Add reset button to the game
var resetButton = game.addChild(new ResetButton());
resetButton.x = 2048 - resetButton.width / 2;
resetButton.y = 2732 - resetButton.height / 2;
// Handle paddle movement
game.move = function (x, y, obj) {
paddle.x = x;
paddle.y = y;
};
// Update game logic
game.update = function () {
ball.update();
paddle.update();
opponentPaddle.update();
// Check for collision between ball and iceGateTop
if (ball.intersects(topGoal)) {
playerScore++;
scoreTxt.setText(playerScore + '-' + opponentScore);
LK.getSound('scoreSound').play();
LK.getSound('scoreSound').play();
LK.getSound('scoreSound').play();
ball.x = 2048 / 2;
ball.y = 1366; // Center of the field
ball.speedX = 0; // Reset horizontal speed
ball.speedY = 4.0; // Reset vertical speed
}
// Check if ball hits the bottom of the screen
if (ball.y >= 2732 || ball.y <= 0) {}
// Check for collision between ball and iceGateBottom
if (ball.intersects(bottomGoal)) {
opponentScore++;
scoreTxt.setText(playerScore + '-' + opponentScore);
LK.getSound('scoreSound').play();
ball.x = 2048 / 2;
ball.y = 1366; // Center of the field
ball.speedX = 0;
ball.speedY = 4.0;
cornerHits = 0; // Reset cornerHits counter
lastCornerHit = null; // Reset lastCornerHit timestamp
}
};
amusement arcade Air hockey table. Top view.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
Air hockey puck. Top view..
change colour from red to blue
Air hockey logo.
Reset ball button retro style. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.