Code edit (1 edits merged)
Please save this source code
User prompt
Face Dash: Smile Runner
User prompt
Please continue polishing my design document.
User prompt
Make a poop clicker where you click poop. every time you click the poop you get one extra fly. every time you get 5 flies you can upgrade and get twice as much clicks
Initial prompt
hi
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var facekit = LK.import("@upit/facekit.v1"); /**** * Classes ****/ // Player character controlled by face var FaceChar = Container.expand(function () { var self = Container.call(this); var _char = self.attachAsset('faceChar', { anchorX: 0.5, anchorY: 0.5 }); // For hit flash self.flash = function () { tween(self, { alpha: 0.3 }, { duration: 80, onFinish: function onFinish() { tween(self, { alpha: 1 }, { duration: 120 }); } }); }; return self; }); // Obstacle class var Obstacle = Container.expand(function () { var self = Container.call(this); var obs = self.attachAsset('obstacle', { anchorX: 0.5, anchorY: 0.5 }); // For possible future animation self.update = function () { self.y += self.speed; }; return self; }); // Point collectible class var PointItem = Container.expand(function () { var self = Container.call(this); var pt = self.attachAsset('point', { anchorX: 0.5, anchorY: 0.5 }); self.update = function () { self.y += self.speed; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x181c2c }); /**** * Game Code ****/ /* We use simple shapes for the character, obstacles, and points. - character: ellipse, bright color - obstacle: box, dark color - point: ellipse, gold color */ // Game constants var GAME_WIDTH = 2048; var GAME_HEIGHT = 2732; var CHAR_START_X = GAME_WIDTH / 2; var CHAR_START_Y = GAME_HEIGHT * 0.8; var OBSTACLE_MIN_X = 180; var OBSTACLE_MAX_X = GAME_WIDTH - 180; var OBSTACLE_MIN_GAP = 400; var OBSTACLE_MAX_GAP = 900; var OBSTACLE_MIN_SPEED = 12; var OBSTACLE_MAX_SPEED = 32; var POINT_MIN_GAP = 600; var POINT_MAX_GAP = 1400; var POINT_SPEED_FACTOR = 1.0; // Game state var faceChar; var obstacles = []; var points = []; var score = 0; var scoreTxt; var lastObstacleY = 0; var lastPointY = 0; var gameSpeed = 1.0; var ticksSinceStart = 0; var isGameOver = false; // Score display scoreTxt = new Text2('0', { size: 140, fill: "#fff" }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // Create player character faceChar = new FaceChar(); game.addChild(faceChar); faceChar.x = CHAR_START_X; faceChar.y = CHAR_START_Y; // Helper: Clamp value function clamp(val, min, max) { return Math.max(min, Math.min(max, val)); } // Helper: Generate random integer in [min, max] function randInt(min, max) { return min + Math.floor(Math.random() * (max - min + 1)); } // Helper: Place new obstacle at top function spawnObstacle() { var obs = new Obstacle(); obs.x = randInt(OBSTACLE_MIN_X, OBSTACLE_MAX_X); obs.y = -100; obs.speed = OBSTACLE_MIN_SPEED + (OBSTACLE_MAX_SPEED - OBSTACLE_MIN_SPEED) * Math.min(1, gameSpeed / 3); obstacles.push(obs); game.addChild(obs); } // Helper: Place new point at top function spawnPoint() { var pt = new PointItem(); pt.x = randInt(OBSTACLE_MIN_X, OBSTACLE_MAX_X); pt.y = -80; pt.speed = (OBSTACLE_MIN_SPEED + (OBSTACLE_MAX_SPEED - OBSTACLE_MIN_SPEED) * Math.min(1, gameSpeed / 3)) * POINT_SPEED_FACTOR; points.push(pt); game.addChild(pt); } // Main update loop game.update = function () { if (isGameOver) return; ticksSinceStart++; // Increase speed over time if (ticksSinceStart % 120 === 0) { gameSpeed += 0.08; } // Face tracking: Use mouth center if available, else nose tip var fx = facekit.mouthCenter && facekit.mouthCenter.x ? facekit.mouthCenter.x : facekit.noseTip && facekit.noseTip.x ? facekit.noseTip.x : CHAR_START_X; var fy = facekit.mouthCenter && facekit.mouthCenter.y ? facekit.mouthCenter.y : facekit.noseTip && facekit.noseTip.y ? facekit.noseTip.y : CHAR_START_Y; // Clamp to game area, avoid top 100px (menu) faceChar.x = clamp(fx, 100 + faceChar.width / 2, GAME_WIDTH - faceChar.width / 2); faceChar.y = clamp(fy, 200 + faceChar.height / 2, GAME_HEIGHT - faceChar.height / 2); // Spawn obstacles if (obstacles.length === 0 || obstacles[obstacles.length - 1].y > randInt(OBSTACLE_MIN_GAP, OBSTACLE_MAX_GAP)) { spawnObstacle(); } // Spawn points if (points.length === 0 || points[points.length - 1].y > randInt(POINT_MIN_GAP, POINT_MAX_GAP)) { spawnPoint(); } // Update obstacles for (var i = obstacles.length - 1; i >= 0; i--) { var obs = obstacles[i]; obs.y += obs.speed * gameSpeed; if (obs.y > GAME_HEIGHT + 100) { obs.destroy(); obstacles.splice(i, 1); continue; } // Collision with player if (faceChar.intersects(obs)) { isGameOver = true; faceChar.flash(); LK.effects.flashScreen(0xff2222, 800); LK.showGameOver(); return; } } // Update points for (var j = points.length - 1; j >= 0; j--) { var pt = points[j]; pt.y += pt.speed * gameSpeed; if (pt.y > GAME_HEIGHT + 80) { pt.destroy(); points.splice(j, 1); continue; } // Collect point if (faceChar.intersects(pt)) { score += 1; scoreTxt.setText(score); // Flash effect LK.effects.flashObject(faceChar, 0xffd700, 200); pt.destroy(); points.splice(j, 1); continue; } } }; // Reset state on game restart game.on('reset', function () { // Remove all obstacles and points for (var i = 0; i < obstacles.length; i++) { obstacles[i].destroy(); } for (var j = 0; j < points.length; j++) { points[j].destroy(); } obstacles = []; points = []; score = 0; scoreTxt.setText(score); faceChar.x = CHAR_START_X; faceChar.y = CHAR_START_Y; gameSpeed = 1.0; ticksSinceStart = 0; isGameOver = false; });
===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,218 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+var facekit = LK.import("@upit/facekit.v1");
+
+/****
+* Classes
+****/
+// Player character controlled by face
+var FaceChar = Container.expand(function () {
+ var self = Container.call(this);
+ var _char = self.attachAsset('faceChar', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ // For hit flash
+ self.flash = function () {
+ tween(self, {
+ alpha: 0.3
+ }, {
+ duration: 80,
+ onFinish: function onFinish() {
+ tween(self, {
+ alpha: 1
+ }, {
+ duration: 120
+ });
+ }
+ });
+ };
+ return self;
+});
+// Obstacle class
+var Obstacle = Container.expand(function () {
+ var self = Container.call(this);
+ var obs = self.attachAsset('obstacle', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ // For possible future animation
+ self.update = function () {
+ self.y += self.speed;
+ };
+ return self;
+});
+// Point collectible class
+var PointItem = Container.expand(function () {
+ var self = Container.call(this);
+ var pt = self.attachAsset('point', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.update = function () {
+ self.y += self.speed;
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
+ backgroundColor: 0x181c2c
+});
+
+/****
+* Game Code
+****/
+/*
+We use simple shapes for the character, obstacles, and points.
+- character: ellipse, bright color
+- obstacle: box, dark color
+- point: ellipse, gold color
+*/
+// Game constants
+var GAME_WIDTH = 2048;
+var GAME_HEIGHT = 2732;
+var CHAR_START_X = GAME_WIDTH / 2;
+var CHAR_START_Y = GAME_HEIGHT * 0.8;
+var OBSTACLE_MIN_X = 180;
+var OBSTACLE_MAX_X = GAME_WIDTH - 180;
+var OBSTACLE_MIN_GAP = 400;
+var OBSTACLE_MAX_GAP = 900;
+var OBSTACLE_MIN_SPEED = 12;
+var OBSTACLE_MAX_SPEED = 32;
+var POINT_MIN_GAP = 600;
+var POINT_MAX_GAP = 1400;
+var POINT_SPEED_FACTOR = 1.0;
+// Game state
+var faceChar;
+var obstacles = [];
+var points = [];
+var score = 0;
+var scoreTxt;
+var lastObstacleY = 0;
+var lastPointY = 0;
+var gameSpeed = 1.0;
+var ticksSinceStart = 0;
+var isGameOver = false;
+// Score display
+scoreTxt = new Text2('0', {
+ size: 140,
+ fill: "#fff"
+});
+scoreTxt.anchor.set(0.5, 0);
+LK.gui.top.addChild(scoreTxt);
+// Create player character
+faceChar = new FaceChar();
+game.addChild(faceChar);
+faceChar.x = CHAR_START_X;
+faceChar.y = CHAR_START_Y;
+// Helper: Clamp value
+function clamp(val, min, max) {
+ return Math.max(min, Math.min(max, val));
+}
+// Helper: Generate random integer in [min, max]
+function randInt(min, max) {
+ return min + Math.floor(Math.random() * (max - min + 1));
+}
+// Helper: Place new obstacle at top
+function spawnObstacle() {
+ var obs = new Obstacle();
+ obs.x = randInt(OBSTACLE_MIN_X, OBSTACLE_MAX_X);
+ obs.y = -100;
+ obs.speed = OBSTACLE_MIN_SPEED + (OBSTACLE_MAX_SPEED - OBSTACLE_MIN_SPEED) * Math.min(1, gameSpeed / 3);
+ obstacles.push(obs);
+ game.addChild(obs);
+}
+// Helper: Place new point at top
+function spawnPoint() {
+ var pt = new PointItem();
+ pt.x = randInt(OBSTACLE_MIN_X, OBSTACLE_MAX_X);
+ pt.y = -80;
+ pt.speed = (OBSTACLE_MIN_SPEED + (OBSTACLE_MAX_SPEED - OBSTACLE_MIN_SPEED) * Math.min(1, gameSpeed / 3)) * POINT_SPEED_FACTOR;
+ points.push(pt);
+ game.addChild(pt);
+}
+// Main update loop
+game.update = function () {
+ if (isGameOver) return;
+ ticksSinceStart++;
+ // Increase speed over time
+ if (ticksSinceStart % 120 === 0) {
+ gameSpeed += 0.08;
+ }
+ // Face tracking: Use mouth center if available, else nose tip
+ var fx = facekit.mouthCenter && facekit.mouthCenter.x ? facekit.mouthCenter.x : facekit.noseTip && facekit.noseTip.x ? facekit.noseTip.x : CHAR_START_X;
+ var fy = facekit.mouthCenter && facekit.mouthCenter.y ? facekit.mouthCenter.y : facekit.noseTip && facekit.noseTip.y ? facekit.noseTip.y : CHAR_START_Y;
+ // Clamp to game area, avoid top 100px (menu)
+ faceChar.x = clamp(fx, 100 + faceChar.width / 2, GAME_WIDTH - faceChar.width / 2);
+ faceChar.y = clamp(fy, 200 + faceChar.height / 2, GAME_HEIGHT - faceChar.height / 2);
+ // Spawn obstacles
+ if (obstacles.length === 0 || obstacles[obstacles.length - 1].y > randInt(OBSTACLE_MIN_GAP, OBSTACLE_MAX_GAP)) {
+ spawnObstacle();
+ }
+ // Spawn points
+ if (points.length === 0 || points[points.length - 1].y > randInt(POINT_MIN_GAP, POINT_MAX_GAP)) {
+ spawnPoint();
+ }
+ // Update obstacles
+ for (var i = obstacles.length - 1; i >= 0; i--) {
+ var obs = obstacles[i];
+ obs.y += obs.speed * gameSpeed;
+ if (obs.y > GAME_HEIGHT + 100) {
+ obs.destroy();
+ obstacles.splice(i, 1);
+ continue;
+ }
+ // Collision with player
+ if (faceChar.intersects(obs)) {
+ isGameOver = true;
+ faceChar.flash();
+ LK.effects.flashScreen(0xff2222, 800);
+ LK.showGameOver();
+ return;
+ }
+ }
+ // Update points
+ for (var j = points.length - 1; j >= 0; j--) {
+ var pt = points[j];
+ pt.y += pt.speed * gameSpeed;
+ if (pt.y > GAME_HEIGHT + 80) {
+ pt.destroy();
+ points.splice(j, 1);
+ continue;
+ }
+ // Collect point
+ if (faceChar.intersects(pt)) {
+ score += 1;
+ scoreTxt.setText(score);
+ // Flash effect
+ LK.effects.flashObject(faceChar, 0xffd700, 200);
+ pt.destroy();
+ points.splice(j, 1);
+ continue;
+ }
+ }
+};
+// Reset state on game restart
+game.on('reset', function () {
+ // Remove all obstacles and points
+ for (var i = 0; i < obstacles.length; i++) {
+ obstacles[i].destroy();
+ }
+ for (var j = 0; j < points.length; j++) {
+ points[j].destroy();
+ }
+ obstacles = [];
+ points = [];
+ score = 0;
+ scoreTxt.setText(score);
+ faceChar.x = CHAR_START_X;
+ faceChar.y = CHAR_START_Y;
+ gameSpeed = 1.0;
+ ticksSinceStart = 0;
+ isGameOver = false;
});
\ No newline at end of file