User prompt
Make the ball move slower
User prompt
Make it so the ball moves at a consistent speed and once it loses energy it falls
User prompt
Make the ball have realistic physics
User prompt
Remove the rotation
User prompt
Make it so it rotates at the players mouth rotation ↪💡 Consider importing and using the following plugins: @upit/facekit.v1
User prompt
Make it so the paddle can move all around and can rotate based on the players mouth ↪💡 Consider importing and using the following plugins: @upit/facekit.v1
Code edit (1 edits merged)
Please save this source code
User prompt
Mouth Pong: Face-Controlled Paddle
Initial prompt
Make a game where it is a pong game and the players mouth is tracked in real life and that is the paddle to hit the ball
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var facekit = LK.import("@upit/facekit.v1"); /**** * Classes ****/ // Ball class var Ball = Container.expand(function () { var self = Container.call(this); var ballAsset = self.attachAsset('ball', { anchorX: 0.5, anchorY: 0.5 }); // Ball velocity self.vx = 0; self.vy = 0; // Ball radius for collision self.getRadius = function () { return ballAsset.width / 2; }; // Ball update: move and handle wall bounces self.update = function () { self.x += self.vx; self.y += self.vy; }; return self; }); // Paddle class var Paddle = Container.expand(function () { var self = Container.call(this); var paddleAsset = self.attachAsset('paddle', { anchorX: 0.5, anchorY: 0.5 }); // Paddle width/height for collision self.getWidth = function () { return paddleAsset.width; }; self.getHeight = function () { return paddleAsset.height; }; return self; }); // Wall class (for top wall) var Wall = Container.expand(function () { var self = Container.call(this); var wallAsset = self.attachAsset('wall', { anchorX: 0.5, anchorY: 0.5 }); self.getWidth = function () { return wallAsset.width; }; self.getHeight = function () { return wallAsset.height; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ // LK.init.sound('bounce', {volume: 0.5}); // Sound for bounce (optional, but not used as per instructions) // Wall: thin, wide rectangle (for top wall) // Ball: circle // Paddle: wide, short rectangle // Center positions var GAME_WIDTH = 2048; var GAME_HEIGHT = 2732; // Score var score = 0; // Create paddle var paddle = new Paddle(); game.addChild(paddle); // Paddle position: bottom center, above bottom edge paddle.x = GAME_WIDTH / 2; paddle.y = GAME_HEIGHT - 180; // Create ball var ball = new Ball(); game.addChild(ball); // Ball start position: above paddle ball.x = GAME_WIDTH / 2; ball.y = paddle.y - 120; // Ball initial velocity (randomized angle upwards) function resetBallVelocity() { // Angle: between -60 and +60 degrees from vertical var angle = Math.random() * Math.PI / 3 - Math.PI / 6; var speed = 28; ball.vx = Math.sin(angle) * speed; ball.vy = -Math.cos(angle) * speed; } resetBallVelocity(); // Create top wall var topWall = new Wall(); game.addChild(topWall); topWall.x = GAME_WIDTH / 2; topWall.y = 40 / 2 + 10; // 10px margin from top // Score text var scoreTxt = new Text2('0', { size: 120, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // Helper: clamp paddle within game bounds function clampPaddleX(x) { var halfWidth = paddle.getWidth() / 2; if (x < halfWidth) return halfWidth; if (x > GAME_WIDTH - halfWidth) return GAME_WIDTH - halfWidth; return x; } // Face tracking: update paddle position game.update = function () { // Use facekit.mouthCenter.x for paddle X var mouthX = facekit.mouthCenter && typeof facekit.mouthCenter.x === 'number' ? facekit.mouthCenter.x : GAME_WIDTH / 2; paddle.x = clampPaddleX(mouthX); // Ball movement ball.update(); // Ball collision with left/right walls var ballRadius = ball.getRadius(); if (ball.x - ballRadius < 0) { ball.x = ballRadius; ball.vx = -ball.vx; } if (ball.x + ballRadius > GAME_WIDTH) { ball.x = GAME_WIDTH - ballRadius; ball.vx = -ball.vx; } // Ball collision with top wall if (ball.y - ballRadius < topWall.y + topWall.getHeight() / 2) { ball.y = topWall.y + topWall.getHeight() / 2 + ballRadius; ball.vy = -ball.vy; } // Ball collision with paddle // Simple AABB vs circle collision var paddleLeft = paddle.x - paddle.getWidth() / 2; var paddleRight = paddle.x + paddle.getWidth() / 2; var paddleTop = paddle.y - paddle.getHeight() / 2; var paddleBottom = paddle.y + paddle.getHeight() / 2; var closestX = Math.max(paddleLeft, Math.min(ball.x, paddleRight)); var closestY = Math.max(paddleTop, Math.min(ball.y, paddleBottom)); var dx = ball.x - closestX; var dy = ball.y - closestY; var distSq = dx * dx + dy * dy; // Only allow bounce if ball is moving downwards if (distSq < ballRadius * ballRadius && ball.vy > 0) { // Bounce: reflect vy, add some "english" based on where it hit the paddle var hitPos = (ball.x - paddle.x) / (paddle.getWidth() / 2); // -1 (left) to 1 (right) var angle = hitPos * (Math.PI / 3); // up to +/-60deg var speed = Math.sqrt(ball.vx * ball.vx + ball.vy * ball.vy) * 1.04; // speed up a bit ball.vx = Math.sin(angle) * speed; ball.vy = -Math.abs(Math.cos(angle) * speed); // Move ball above paddle to prevent sticking ball.y = paddle.y - paddle.getHeight() / 2 - ballRadius - 2; // Flash paddle LK.effects.flashObject(paddle, 0xffff00, 200); // Increase score score += 1; LK.setScore(score); scoreTxt.setText(score); // Optionally: play sound // LK.getSound('bounce').play(); } // Ball falls below paddle: game over if (ball.y - ballRadius > GAME_HEIGHT) { // Flash screen red LK.effects.flashScreen(0xff0000, 800); // Show game over (auto resets game) LK.showGameOver(); } }; // No dragging or touch controls needed; paddle is controlled by facekit only // Reset score on game start LK.setScore(0); score = 0; scoreTxt.setText('0');
===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,187 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+var facekit = LK.import("@upit/facekit.v1");
+
+/****
+* Classes
+****/
+// Ball class
+var Ball = Container.expand(function () {
+ var self = Container.call(this);
+ var ballAsset = self.attachAsset('ball', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ // Ball velocity
+ self.vx = 0;
+ self.vy = 0;
+ // Ball radius for collision
+ self.getRadius = function () {
+ return ballAsset.width / 2;
+ };
+ // Ball update: move and handle wall bounces
+ self.update = function () {
+ self.x += self.vx;
+ self.y += self.vy;
+ };
+ return self;
+});
+// Paddle class
+var Paddle = Container.expand(function () {
+ var self = Container.call(this);
+ var paddleAsset = self.attachAsset('paddle', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ // Paddle width/height for collision
+ self.getWidth = function () {
+ return paddleAsset.width;
+ };
+ self.getHeight = function () {
+ return paddleAsset.height;
+ };
+ return self;
+});
+// Wall class (for top wall)
+var Wall = Container.expand(function () {
+ var self = Container.call(this);
+ var wallAsset = self.attachAsset('wall', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.getWidth = function () {
+ return wallAsset.width;
+ };
+ self.getHeight = function () {
+ return wallAsset.height;
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
backgroundColor: 0x000000
-});
\ No newline at end of file
+});
+
+/****
+* Game Code
+****/
+// LK.init.sound('bounce', {volume: 0.5});
+// Sound for bounce (optional, but not used as per instructions)
+// Wall: thin, wide rectangle (for top wall)
+// Ball: circle
+// Paddle: wide, short rectangle
+// Center positions
+var GAME_WIDTH = 2048;
+var GAME_HEIGHT = 2732;
+// Score
+var score = 0;
+// Create paddle
+var paddle = new Paddle();
+game.addChild(paddle);
+// Paddle position: bottom center, above bottom edge
+paddle.x = GAME_WIDTH / 2;
+paddle.y = GAME_HEIGHT - 180;
+// Create ball
+var ball = new Ball();
+game.addChild(ball);
+// Ball start position: above paddle
+ball.x = GAME_WIDTH / 2;
+ball.y = paddle.y - 120;
+// Ball initial velocity (randomized angle upwards)
+function resetBallVelocity() {
+ // Angle: between -60 and +60 degrees from vertical
+ var angle = Math.random() * Math.PI / 3 - Math.PI / 6;
+ var speed = 28;
+ ball.vx = Math.sin(angle) * speed;
+ ball.vy = -Math.cos(angle) * speed;
+}
+resetBallVelocity();
+// Create top wall
+var topWall = new Wall();
+game.addChild(topWall);
+topWall.x = GAME_WIDTH / 2;
+topWall.y = 40 / 2 + 10; // 10px margin from top
+// Score text
+var scoreTxt = new Text2('0', {
+ size: 120,
+ fill: 0xFFFFFF
+});
+scoreTxt.anchor.set(0.5, 0);
+LK.gui.top.addChild(scoreTxt);
+// Helper: clamp paddle within game bounds
+function clampPaddleX(x) {
+ var halfWidth = paddle.getWidth() / 2;
+ if (x < halfWidth) return halfWidth;
+ if (x > GAME_WIDTH - halfWidth) return GAME_WIDTH - halfWidth;
+ return x;
+}
+// Face tracking: update paddle position
+game.update = function () {
+ // Use facekit.mouthCenter.x for paddle X
+ var mouthX = facekit.mouthCenter && typeof facekit.mouthCenter.x === 'number' ? facekit.mouthCenter.x : GAME_WIDTH / 2;
+ paddle.x = clampPaddleX(mouthX);
+ // Ball movement
+ ball.update();
+ // Ball collision with left/right walls
+ var ballRadius = ball.getRadius();
+ if (ball.x - ballRadius < 0) {
+ ball.x = ballRadius;
+ ball.vx = -ball.vx;
+ }
+ if (ball.x + ballRadius > GAME_WIDTH) {
+ ball.x = GAME_WIDTH - ballRadius;
+ ball.vx = -ball.vx;
+ }
+ // Ball collision with top wall
+ if (ball.y - ballRadius < topWall.y + topWall.getHeight() / 2) {
+ ball.y = topWall.y + topWall.getHeight() / 2 + ballRadius;
+ ball.vy = -ball.vy;
+ }
+ // Ball collision with paddle
+ // Simple AABB vs circle collision
+ var paddleLeft = paddle.x - paddle.getWidth() / 2;
+ var paddleRight = paddle.x + paddle.getWidth() / 2;
+ var paddleTop = paddle.y - paddle.getHeight() / 2;
+ var paddleBottom = paddle.y + paddle.getHeight() / 2;
+ var closestX = Math.max(paddleLeft, Math.min(ball.x, paddleRight));
+ var closestY = Math.max(paddleTop, Math.min(ball.y, paddleBottom));
+ var dx = ball.x - closestX;
+ var dy = ball.y - closestY;
+ var distSq = dx * dx + dy * dy;
+ // Only allow bounce if ball is moving downwards
+ if (distSq < ballRadius * ballRadius && ball.vy > 0) {
+ // Bounce: reflect vy, add some "english" based on where it hit the paddle
+ var hitPos = (ball.x - paddle.x) / (paddle.getWidth() / 2); // -1 (left) to 1 (right)
+ var angle = hitPos * (Math.PI / 3); // up to +/-60deg
+ var speed = Math.sqrt(ball.vx * ball.vx + ball.vy * ball.vy) * 1.04; // speed up a bit
+ ball.vx = Math.sin(angle) * speed;
+ ball.vy = -Math.abs(Math.cos(angle) * speed);
+ // Move ball above paddle to prevent sticking
+ ball.y = paddle.y - paddle.getHeight() / 2 - ballRadius - 2;
+ // Flash paddle
+ LK.effects.flashObject(paddle, 0xffff00, 200);
+ // Increase score
+ score += 1;
+ LK.setScore(score);
+ scoreTxt.setText(score);
+ // Optionally: play sound
+ // LK.getSound('bounce').play();
+ }
+ // Ball falls below paddle: game over
+ if (ball.y - ballRadius > GAME_HEIGHT) {
+ // Flash screen red
+ LK.effects.flashScreen(0xff0000, 800);
+ // Show game over (auto resets game)
+ LK.showGameOver();
+ }
+};
+// No dragging or touch controls needed; paddle is controlled by facekit only
+// Reset score on game start
+LK.setScore(0);
+score = 0;
+scoreTxt.setText('0');
\ No newline at end of file