User prompt
make the obstacles little slower
User prompt
start this game a little slower, make it speed up a little every time you get a powerup, and sometimes add the ability to pass through rare obstacles ↪💡 Consider importing and using the following plugins: @upit/tween.v1
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
Please continue polishing my design document.
User prompt
Please continue polishing my design document.
Initial prompt
make me roblox
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var facekit = LK.import("@upit/facekit.v1"); /**** * Classes ****/ // Obstacle class: moves downward, destroys itself off-screen var Obstacle = Container.expand(function () { var self = Container.call(this); var obsGfx = self.attachAsset('obstacle', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 18 + Math.random() * 10; // pixels per frame, increases with time self.update = function () { self.y += self.speed; }; return self; }); // Player class: follows face position var Player = Container.expand(function () { var self = Container.call(this); var playerGfx = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); // For possible future effects self.flash = function () { tween(self, { alpha: 0.3 }, { duration: 80, onFinish: function onFinish() { tween(self, { alpha: 1 }, { duration: 120 }); } }); }; return self; }); // Powerup class: moves downward, destroys itself off-screen var Powerup = Container.expand(function () { var self = Container.call(this); var powGfx = self.attachAsset('powerup', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 14 + Math.random() * 6; self.update = function () { self.y += self.speed; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x181c2c }); /**** * Game Code ****/ // Powerup: Green ellipse // Obstacle: Red box // Character: Player avatar (ellipse, bright color) // Game area margins (to avoid top-left menu) var marginTop = 100; var marginLeft = 100; var marginRight = 100; var marginBottom = 100; // Player setup var player = new Player(); game.addChild(player); // Start in center player.x = 2048 / 2; player.y = 2732 - 400; // Score display var scoreTxt = new Text2('0', { size: 120, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // Powerup timer display (hidden by default) var powerupTxt = new Text2('', { size: 80, fill: 0xFFE066 }); powerupTxt.anchor.set(0.5, 0); LK.gui.top.addChild(powerupTxt); powerupTxt.visible = false; // Game state var obstacles = []; var powerups = []; var powerupActive = false; var powerupTimer = 0; var powerupDuration = 180; // frames (3 seconds) var score = 0; var ticks = 0; var gameOver = false; // Helper: clamp value function clamp(val, min, max) { return Math.max(min, Math.min(max, val)); } // Main update loop game.update = function () { if (gameOver) return; ticks++; // --- Face tracking: update player position --- // Use mouth center if available, else fallback to noseTip var faceX = facekit.mouthCenter && facekit.mouthCenter.x ? facekit.mouthCenter.x : facekit.noseTip && facekit.noseTip.x ? facekit.noseTip.x : 2048 / 2; var faceY = facekit.mouthCenter && facekit.mouthCenter.y ? facekit.mouthCenter.y : facekit.noseTip && facekit.noseTip.y ? facekit.noseTip.y : 2732 - 400; // Clamp to game area (avoid top-left menu and screen edges) var px = clamp(faceX, marginLeft + player.width / 2, 2048 - marginRight - player.width / 2); var py = clamp(faceY, marginTop + player.height / 2, 2732 - marginBottom - player.height / 2); // Smooth movement (lerp) player.x += (px - player.x) * 0.35; player.y += (py - player.y) * 0.35; // --- Spawn obstacles --- // Increase spawn rate over time var spawnInterval = Math.max(32, 80 - Math.floor(ticks / 600)); if (ticks % spawnInterval === 0) { var obs = new Obstacle(); // Random X, avoid edges obs.x = clamp(180 + Math.random() * (2048 - 360), marginLeft + 90, 2048 - marginRight - 90); obs.y = -80; // Speed up as score increases obs.speed += Math.floor(score / 10) * 2; obstacles.push(obs); game.addChild(obs); } // --- Spawn powerups --- if (!powerupActive && ticks > 120 && ticks % 420 === 0) { var pow = new Powerup(); pow.x = clamp(180 + Math.random() * (2048 - 360), marginLeft + 90, 2048 - marginRight - 90); pow.y = -60; powerups.push(pow); game.addChild(pow); } // --- Update obstacles --- for (var i = obstacles.length - 1; i >= 0; i--) { var obs = obstacles[i]; obs.update(); // Off-screen if (obs.y - obs.height / 2 > 2732 + 40) { obs.destroy(); obstacles.splice(i, 1); continue; } // Collision with player if (!powerupActive && player.intersects(obs)) { player.flash(); LK.effects.flashScreen(0xff0000, 600); gameOver = true; LK.setTimeout(function () { LK.showGameOver(); }, 600); return; } } // --- Update powerups --- for (var j = powerups.length - 1; j >= 0; j--) { var pow = powerups[j]; pow.update(); // Off-screen if (pow.y - pow.height / 2 > 2732 + 40) { pow.destroy(); powerups.splice(j, 1); continue; } // Collect if (player.intersects(pow)) { pow.destroy(); powerups.splice(j, 1); powerupActive = true; powerupTimer = powerupDuration; powerupTxt.visible = true; // Visual feedback tween(player, { scaleX: 1.3, scaleY: 1.3 }, { duration: 200, onFinish: function onFinish() { tween(player, { scaleX: 1, scaleY: 1 }, { duration: 200 }); } }); } } // --- Powerup effect --- if (powerupActive) { powerupTimer--; powerupTxt.setText("Invincible: " + Math.ceil(powerupTimer / 60) + "s"); if (powerupTimer <= 0) { powerupActive = false; powerupTxt.visible = false; } } // --- Score --- if (ticks % 6 === 0 && !gameOver) { score++; LK.setScore(score); scoreTxt.setText(score); } }; // Reset state on game restart game.on('reset', function () { // Remove all obstacles and powerups for (var i = 0; i < obstacles.length; i++) obstacles[i].destroy(); for (var j = 0; j < powerups.length; j++) powerups[j].destroy(); obstacles = []; powerups = []; score = 0; LK.setScore(0); scoreTxt.setText('0'); powerupActive = false; powerupTimer = 0; powerupTxt.visible = false; player.x = 2048 / 2; player.y = 2732 - 400; gameOver = false; ticks = 0; }); // No touch controls: face only, but allow drag fallback for debug var dragNode = null; game.down = function (x, y, obj) { // For debug: allow dragging player if facekit not available if (!facekit.mouthCenter) dragNode = player; }; game.move = function (x, y, obj) { if (dragNode) { player.x = clamp(x, marginLeft + player.width / 2, 2048 - marginRight - player.width / 2); player.y = clamp(y, marginTop + player.height / 2, 2732 - marginBottom - player.height / 2); } }; game.up = function (x, y, obj) { dragNode = null; };
===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,251 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+var facekit = LK.import("@upit/facekit.v1");
+
+/****
+* Classes
+****/
+// Obstacle class: moves downward, destroys itself off-screen
+var Obstacle = Container.expand(function () {
+ var self = Container.call(this);
+ var obsGfx = self.attachAsset('obstacle', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.speed = 18 + Math.random() * 10; // pixels per frame, increases with time
+ self.update = function () {
+ self.y += self.speed;
+ };
+ return self;
+});
+// Player class: follows face position
+var Player = Container.expand(function () {
+ var self = Container.call(this);
+ var playerGfx = self.attachAsset('player', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ // For possible future effects
+ self.flash = function () {
+ tween(self, {
+ alpha: 0.3
+ }, {
+ duration: 80,
+ onFinish: function onFinish() {
+ tween(self, {
+ alpha: 1
+ }, {
+ duration: 120
+ });
+ }
+ });
+ };
+ return self;
+});
+// Powerup class: moves downward, destroys itself off-screen
+var Powerup = Container.expand(function () {
+ var self = Container.call(this);
+ var powGfx = self.attachAsset('powerup', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.speed = 14 + Math.random() * 6;
+ self.update = function () {
+ self.y += self.speed;
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0x181c2c
+});
+
+/****
+* Game Code
+****/
+// Powerup: Green ellipse
+// Obstacle: Red box
+// Character: Player avatar (ellipse, bright color)
+// Game area margins (to avoid top-left menu)
+var marginTop = 100;
+var marginLeft = 100;
+var marginRight = 100;
+var marginBottom = 100;
+// Player setup
+var player = new Player();
+game.addChild(player);
+// Start in center
+player.x = 2048 / 2;
+player.y = 2732 - 400;
+// Score display
+var scoreTxt = new Text2('0', {
+ size: 120,
+ fill: 0xFFFFFF
+});
+scoreTxt.anchor.set(0.5, 0);
+LK.gui.top.addChild(scoreTxt);
+// Powerup timer display (hidden by default)
+var powerupTxt = new Text2('', {
+ size: 80,
+ fill: 0xFFE066
+});
+powerupTxt.anchor.set(0.5, 0);
+LK.gui.top.addChild(powerupTxt);
+powerupTxt.visible = false;
+// Game state
+var obstacles = [];
+var powerups = [];
+var powerupActive = false;
+var powerupTimer = 0;
+var powerupDuration = 180; // frames (3 seconds)
+var score = 0;
+var ticks = 0;
+var gameOver = false;
+// Helper: clamp value
+function clamp(val, min, max) {
+ return Math.max(min, Math.min(max, val));
+}
+// Main update loop
+game.update = function () {
+ if (gameOver) return;
+ ticks++;
+ // --- Face tracking: update player position ---
+ // Use mouth center if available, else fallback to noseTip
+ var faceX = facekit.mouthCenter && facekit.mouthCenter.x ? facekit.mouthCenter.x : facekit.noseTip && facekit.noseTip.x ? facekit.noseTip.x : 2048 / 2;
+ var faceY = facekit.mouthCenter && facekit.mouthCenter.y ? facekit.mouthCenter.y : facekit.noseTip && facekit.noseTip.y ? facekit.noseTip.y : 2732 - 400;
+ // Clamp to game area (avoid top-left menu and screen edges)
+ var px = clamp(faceX, marginLeft + player.width / 2, 2048 - marginRight - player.width / 2);
+ var py = clamp(faceY, marginTop + player.height / 2, 2732 - marginBottom - player.height / 2);
+ // Smooth movement (lerp)
+ player.x += (px - player.x) * 0.35;
+ player.y += (py - player.y) * 0.35;
+ // --- Spawn obstacles ---
+ // Increase spawn rate over time
+ var spawnInterval = Math.max(32, 80 - Math.floor(ticks / 600));
+ if (ticks % spawnInterval === 0) {
+ var obs = new Obstacle();
+ // Random X, avoid edges
+ obs.x = clamp(180 + Math.random() * (2048 - 360), marginLeft + 90, 2048 - marginRight - 90);
+ obs.y = -80;
+ // Speed up as score increases
+ obs.speed += Math.floor(score / 10) * 2;
+ obstacles.push(obs);
+ game.addChild(obs);
+ }
+ // --- Spawn powerups ---
+ if (!powerupActive && ticks > 120 && ticks % 420 === 0) {
+ var pow = new Powerup();
+ pow.x = clamp(180 + Math.random() * (2048 - 360), marginLeft + 90, 2048 - marginRight - 90);
+ pow.y = -60;
+ powerups.push(pow);
+ game.addChild(pow);
+ }
+ // --- Update obstacles ---
+ for (var i = obstacles.length - 1; i >= 0; i--) {
+ var obs = obstacles[i];
+ obs.update();
+ // Off-screen
+ if (obs.y - obs.height / 2 > 2732 + 40) {
+ obs.destroy();
+ obstacles.splice(i, 1);
+ continue;
+ }
+ // Collision with player
+ if (!powerupActive && player.intersects(obs)) {
+ player.flash();
+ LK.effects.flashScreen(0xff0000, 600);
+ gameOver = true;
+ LK.setTimeout(function () {
+ LK.showGameOver();
+ }, 600);
+ return;
+ }
+ }
+ // --- Update powerups ---
+ for (var j = powerups.length - 1; j >= 0; j--) {
+ var pow = powerups[j];
+ pow.update();
+ // Off-screen
+ if (pow.y - pow.height / 2 > 2732 + 40) {
+ pow.destroy();
+ powerups.splice(j, 1);
+ continue;
+ }
+ // Collect
+ if (player.intersects(pow)) {
+ pow.destroy();
+ powerups.splice(j, 1);
+ powerupActive = true;
+ powerupTimer = powerupDuration;
+ powerupTxt.visible = true;
+ // Visual feedback
+ tween(player, {
+ scaleX: 1.3,
+ scaleY: 1.3
+ }, {
+ duration: 200,
+ onFinish: function onFinish() {
+ tween(player, {
+ scaleX: 1,
+ scaleY: 1
+ }, {
+ duration: 200
+ });
+ }
+ });
+ }
+ }
+ // --- Powerup effect ---
+ if (powerupActive) {
+ powerupTimer--;
+ powerupTxt.setText("Invincible: " + Math.ceil(powerupTimer / 60) + "s");
+ if (powerupTimer <= 0) {
+ powerupActive = false;
+ powerupTxt.visible = false;
+ }
+ }
+ // --- Score ---
+ if (ticks % 6 === 0 && !gameOver) {
+ score++;
+ LK.setScore(score);
+ scoreTxt.setText(score);
+ }
+};
+// Reset state on game restart
+game.on('reset', function () {
+ // Remove all obstacles and powerups
+ for (var i = 0; i < obstacles.length; i++) obstacles[i].destroy();
+ for (var j = 0; j < powerups.length; j++) powerups[j].destroy();
+ obstacles = [];
+ powerups = [];
+ score = 0;
+ LK.setScore(0);
+ scoreTxt.setText('0');
+ powerupActive = false;
+ powerupTimer = 0;
+ powerupTxt.visible = false;
+ player.x = 2048 / 2;
+ player.y = 2732 - 400;
+ gameOver = false;
+ ticks = 0;
+});
+// No touch controls: face only, but allow drag fallback for debug
+var dragNode = null;
+game.down = function (x, y, obj) {
+ // For debug: allow dragging player if facekit not available
+ if (!facekit.mouthCenter) dragNode = player;
+};
+game.move = function (x, y, obj) {
+ if (dragNode) {
+ player.x = clamp(x, marginLeft + player.width / 2, 2048 - marginRight - player.width / 2);
+ player.y = clamp(y, marginTop + player.height / 2, 2732 - marginBottom - player.height / 2);
+ }
+};
+game.up = function (x, y, obj) {
+ dragNode = null;
+};
\ No newline at end of file