/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Ball = Container.expand(function () {
var self = Container.call(this);
var ballGraphics = self.attachAsset('ball', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocityX = 24;
self.velocityY = 12;
self.baseSpeed = 24;
self.reset = function () {
self.x = 200;
self.y = 2732 / 2;
self.velocityX = self.baseSpeed;
self.velocityY = (Math.random() - 0.5) * 18;
self.lastX = self.x; // Initialize last position
};
self.update = function () {
self.x += self.velocityX;
self.y += self.velocityY;
// Bounce off top and bottom walls - using actual ball height (150px)
var ballRadius = 75; // Half of 150px ball height
if (self.y <= ballRadius || self.y >= 2732 - ballRadius) {
self.velocityY = -self.velocityY;
LK.getSound('bounce').play();
}
// Game over if ball hits left wall - using actual ball width (150px)
if (self.x <= ballRadius) {
LK.showGameOver();
}
// Check paddle collision - both intersection and position crossing
// Using actual paddle dimensions: 444x462.05
var paddleHalfWidth = 222; // Half of 444px paddle width
var paddleHalfHeight = 231; // Half of 462.05px paddle height
var paddleLeft = paddle.x - paddleHalfWidth;
var paddleRight = paddle.x + paddleHalfWidth;
var paddleTop = paddle.y - paddleHalfHeight;
var paddleBottom = paddle.y + paddleHalfHeight;
var ballInPaddleY = self.y >= paddleTop && self.y <= paddleBottom;
var ballCrossedPaddle = self.lastX > paddleRight && self.x <= paddleRight;
if (self.velocityX < 0 && ballInPaddleY && (self.intersects(paddle) || ballCrossedPaddle)) {
self.velocityX = -self.velocityX;
// Add some angle based on where it hits the paddle
var paddleCenter = paddle.y;
var ballCenter = self.y;
var diff = ballCenter - paddleCenter;
self.velocityY += diff * 0.05;
// Add friction effect based on paddle movement
var paddleVelocity = paddle.targetY - paddle.y;
self.velocityY += paddleVelocity * 0.08; // Apply reduced friction effect
LK.getSound('bounce').play();
}
// Check wall collision - only if not passing through hole
// Using actual wall position and ball dimensions
var wallX = wall.x;
var ballRadius = 75; // Half of 150px ball width
var ballHitWall = self.lastX < wallX && self.x >= wallX;
if (self.velocityX > 0 && ballHitWall && !wall.checkBallThrough(self)) {
// Ball hit the wall (but not through hole), bounce back
self.velocityX = -self.velocityX;
LK.getSound('bounce').play();
}
// Store last position for next frame collision detection
self.lastX = self.x;
// Reset if ball goes off right side
if (self.x > 2048 + 50) {
self.reset();
}
};
return self;
});
var Paddle = Container.expand(function () {
var self = Container.call(this);
var paddleGraphics = self.attachAsset('paddle', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 12;
self.targetY = 2732 / 2;
self.update = function () {
var diff = self.targetY - self.y;
if (Math.abs(diff) > 2) {
self.y += diff * 0.15;
}
};
return self;
});
var Wall = Container.expand(function () {
var self = Container.call(this);
var wallGraphics = self.attachAsset('wall', {
anchorX: 0,
anchorY: 0
});
var holeGraphics = self.attachAsset('hole', {
anchorX: 0,
anchorY: 0.5
});
self.holeY = 2732 / 2 + 200;
holeGraphics.y = self.holeY;
holeGraphics.scaleY = 1.2;
self.moveHole = function () {
var minY = 300;
var maxY = 2732 - 300;
self.holeY = minY + Math.random() * (maxY - minY);
tween(holeGraphics, {
y: self.holeY
}, {
duration: 500,
easing: tween.easeOut
});
};
self.checkBallThrough = function (ball) {
var holeX = self.x;
var holeY = self.holeY;
var ballX = ball.x;
var ballY = ball.y;
var lastBallX = ball.lastX || ballX;
// Check if ball crossed through the wall horizontally
var crossedWall = lastBallX < holeX && ballX >= holeX;
// Check if ball center is in hole Y range during the crossing
// Using actual hole dimensions: 120x432 (360 * 1.2 scale)
var holeHalfHeight = 216; // Half of 432px scaled hole height
var ballRadius = 75; // Half of 150px ball
// Ball center must be within hole bounds (accounting for ball radius for easier gameplay)
var inHoleY = Math.abs(ballY - holeY) <= holeHalfHeight - ballRadius;
return crossedWall && inHoleY;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x001122
});
/****
* Game Code
****/
// Add background
var background = game.addChild(LK.getAsset('background', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 20.48,
// Scale to fit 2048 width (2048/100)
scaleY: 27.32 // Scale to fit 2732 height (2732/100)
}));
background.x = 2048 / 2;
background.y = 2732 / 2;
var paddle = game.addChild(new Paddle());
paddle.x = 100;
paddle.y = 2732 / 2;
var ball = game.addChild(new Ball());
ball.reset();
var wall = game.addChild(new Wall());
wall.x = 1600;
wall.y = 0;
var scoreTxt = new Text2('0', {
size: 100,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
scoreTxt.y = 50;
var lastBallX = ball.x;
var ballThroughHole = false;
var isLeftPressed = false;
var originalSpeedX = 0;
var originalSpeedY = 0;
// Start playing background music
LK.playMusic('running');
game.move = function (x, y, obj) {
paddle.targetY = y;
};
game.down = function (x, y, obj) {
paddle.targetY = y;
// Apply speed boost on any screen press
isLeftPressed = true;
// Store original speeds
originalSpeedX = ball.velocityX;
originalSpeedY = ball.velocityY;
// Boost ball speed 3x
ball.velocityX *= 3;
ball.velocityY *= 3;
};
game.up = function (x, y, obj) {
// Restore original speed on any screen release
if (isLeftPressed) {
isLeftPressed = false;
ball.velocityX /= 3;
ball.velocityY /= 3;
}
};
game.update = function () {
// Track ball movement for hole detection
var currentBallX = ball.x;
// Check if ball passed through hole
if (!ballThroughHole && wall.checkBallThrough(ball)) {
// Score!
ballThroughHole = true;
LK.setScore(LK.getScore() + 1);
scoreTxt.setText(LK.getScore());
LK.getSound('score').play();
// Move hole to new position
wall.moveHole();
// Increase ball speed slightly
ball.baseSpeed += 0.5;
// Preserve current velocity and just increase it proportionally
var currentSpeed = Math.sqrt(ball.velocityX * ball.velocityX + ball.velocityY * ball.velocityY);
var speedIncrease = ball.baseSpeed / (ball.baseSpeed - 0.5);
ball.velocityX *= speedIncrease;
ball.velocityY *= speedIncrease;
}
// Check if ball hits right wall (off screen) - score regardless of hole passage
if (ball.x > 2048) {
// Score for hitting right wall!
LK.setScore(LK.getScore() + 1);
scoreTxt.setText(LK.getScore());
LK.getSound('score').play();
// Move hole to new position
wall.moveHole();
// Reset ball
ball.reset();
ballThroughHole = false;
}
// Reset ball through hole flag when ball moves away
if (currentBallX < wall.x - 100) {
ballThroughHole = false;
}
lastBallX = currentBallX;
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Ball = Container.expand(function () {
var self = Container.call(this);
var ballGraphics = self.attachAsset('ball', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocityX = 24;
self.velocityY = 12;
self.baseSpeed = 24;
self.reset = function () {
self.x = 200;
self.y = 2732 / 2;
self.velocityX = self.baseSpeed;
self.velocityY = (Math.random() - 0.5) * 18;
self.lastX = self.x; // Initialize last position
};
self.update = function () {
self.x += self.velocityX;
self.y += self.velocityY;
// Bounce off top and bottom walls - using actual ball height (150px)
var ballRadius = 75; // Half of 150px ball height
if (self.y <= ballRadius || self.y >= 2732 - ballRadius) {
self.velocityY = -self.velocityY;
LK.getSound('bounce').play();
}
// Game over if ball hits left wall - using actual ball width (150px)
if (self.x <= ballRadius) {
LK.showGameOver();
}
// Check paddle collision - both intersection and position crossing
// Using actual paddle dimensions: 444x462.05
var paddleHalfWidth = 222; // Half of 444px paddle width
var paddleHalfHeight = 231; // Half of 462.05px paddle height
var paddleLeft = paddle.x - paddleHalfWidth;
var paddleRight = paddle.x + paddleHalfWidth;
var paddleTop = paddle.y - paddleHalfHeight;
var paddleBottom = paddle.y + paddleHalfHeight;
var ballInPaddleY = self.y >= paddleTop && self.y <= paddleBottom;
var ballCrossedPaddle = self.lastX > paddleRight && self.x <= paddleRight;
if (self.velocityX < 0 && ballInPaddleY && (self.intersects(paddle) || ballCrossedPaddle)) {
self.velocityX = -self.velocityX;
// Add some angle based on where it hits the paddle
var paddleCenter = paddle.y;
var ballCenter = self.y;
var diff = ballCenter - paddleCenter;
self.velocityY += diff * 0.05;
// Add friction effect based on paddle movement
var paddleVelocity = paddle.targetY - paddle.y;
self.velocityY += paddleVelocity * 0.08; // Apply reduced friction effect
LK.getSound('bounce').play();
}
// Check wall collision - only if not passing through hole
// Using actual wall position and ball dimensions
var wallX = wall.x;
var ballRadius = 75; // Half of 150px ball width
var ballHitWall = self.lastX < wallX && self.x >= wallX;
if (self.velocityX > 0 && ballHitWall && !wall.checkBallThrough(self)) {
// Ball hit the wall (but not through hole), bounce back
self.velocityX = -self.velocityX;
LK.getSound('bounce').play();
}
// Store last position for next frame collision detection
self.lastX = self.x;
// Reset if ball goes off right side
if (self.x > 2048 + 50) {
self.reset();
}
};
return self;
});
var Paddle = Container.expand(function () {
var self = Container.call(this);
var paddleGraphics = self.attachAsset('paddle', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 12;
self.targetY = 2732 / 2;
self.update = function () {
var diff = self.targetY - self.y;
if (Math.abs(diff) > 2) {
self.y += diff * 0.15;
}
};
return self;
});
var Wall = Container.expand(function () {
var self = Container.call(this);
var wallGraphics = self.attachAsset('wall', {
anchorX: 0,
anchorY: 0
});
var holeGraphics = self.attachAsset('hole', {
anchorX: 0,
anchorY: 0.5
});
self.holeY = 2732 / 2 + 200;
holeGraphics.y = self.holeY;
holeGraphics.scaleY = 1.2;
self.moveHole = function () {
var minY = 300;
var maxY = 2732 - 300;
self.holeY = minY + Math.random() * (maxY - minY);
tween(holeGraphics, {
y: self.holeY
}, {
duration: 500,
easing: tween.easeOut
});
};
self.checkBallThrough = function (ball) {
var holeX = self.x;
var holeY = self.holeY;
var ballX = ball.x;
var ballY = ball.y;
var lastBallX = ball.lastX || ballX;
// Check if ball crossed through the wall horizontally
var crossedWall = lastBallX < holeX && ballX >= holeX;
// Check if ball center is in hole Y range during the crossing
// Using actual hole dimensions: 120x432 (360 * 1.2 scale)
var holeHalfHeight = 216; // Half of 432px scaled hole height
var ballRadius = 75; // Half of 150px ball
// Ball center must be within hole bounds (accounting for ball radius for easier gameplay)
var inHoleY = Math.abs(ballY - holeY) <= holeHalfHeight - ballRadius;
return crossedWall && inHoleY;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x001122
});
/****
* Game Code
****/
// Add background
var background = game.addChild(LK.getAsset('background', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 20.48,
// Scale to fit 2048 width (2048/100)
scaleY: 27.32 // Scale to fit 2732 height (2732/100)
}));
background.x = 2048 / 2;
background.y = 2732 / 2;
var paddle = game.addChild(new Paddle());
paddle.x = 100;
paddle.y = 2732 / 2;
var ball = game.addChild(new Ball());
ball.reset();
var wall = game.addChild(new Wall());
wall.x = 1600;
wall.y = 0;
var scoreTxt = new Text2('0', {
size: 100,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
scoreTxt.y = 50;
var lastBallX = ball.x;
var ballThroughHole = false;
var isLeftPressed = false;
var originalSpeedX = 0;
var originalSpeedY = 0;
// Start playing background music
LK.playMusic('running');
game.move = function (x, y, obj) {
paddle.targetY = y;
};
game.down = function (x, y, obj) {
paddle.targetY = y;
// Apply speed boost on any screen press
isLeftPressed = true;
// Store original speeds
originalSpeedX = ball.velocityX;
originalSpeedY = ball.velocityY;
// Boost ball speed 3x
ball.velocityX *= 3;
ball.velocityY *= 3;
};
game.up = function (x, y, obj) {
// Restore original speed on any screen release
if (isLeftPressed) {
isLeftPressed = false;
ball.velocityX /= 3;
ball.velocityY /= 3;
}
};
game.update = function () {
// Track ball movement for hole detection
var currentBallX = ball.x;
// Check if ball passed through hole
if (!ballThroughHole && wall.checkBallThrough(ball)) {
// Score!
ballThroughHole = true;
LK.setScore(LK.getScore() + 1);
scoreTxt.setText(LK.getScore());
LK.getSound('score').play();
// Move hole to new position
wall.moveHole();
// Increase ball speed slightly
ball.baseSpeed += 0.5;
// Preserve current velocity and just increase it proportionally
var currentSpeed = Math.sqrt(ball.velocityX * ball.velocityX + ball.velocityY * ball.velocityY);
var speedIncrease = ball.baseSpeed / (ball.baseSpeed - 0.5);
ball.velocityX *= speedIncrease;
ball.velocityY *= speedIncrease;
}
// Check if ball hits right wall (off screen) - score regardless of hole passage
if (ball.x > 2048) {
// Score for hitting right wall!
LK.setScore(LK.getScore() + 1);
scoreTxt.setText(LK.getScore());
LK.getSound('score').play();
// Move hole to new position
wall.moveHole();
// Reset ball
ball.reset();
ballThroughHole = false;
}
// Reset ball through hole flag when ball moves away
if (currentBallX < wall.x - 100) {
ballThroughHole = false;
}
lastBallX = currentBallX;
};