/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var facekit = LK.import("@upit/facekit.v1"); /**** * Classes ****/ // Bonus class: falls from top, destroys itself when off screen var Bonus = Container.expand(function () { var self = Container.call(this); var gfx = self.attachAsset('bonus', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 10; // Will be increased as game progresses self.update = function () { self.y += self.speed; }; return self; }); // Obstacle class: falls from top, destroys itself when off screen var Obstacle = Container.expand(function () { var self = Container.call(this); var gfx = self.attachAsset('obstacle', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 12; // Will be increased as game progresses 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 gfx = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); // No update needed; position is set by facekit in main game loop return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ // Player: blue ellipse // Bonus: yellow ellipse // Obstacles: gray boxes // Game variables var player = new Player(); game.addChild(player); player.x = 2048 / 2; player.y = 2732 - 350; // Start near bottom var obstacles = []; var bonuses = []; var score = 0; var bonusScore = 0; var gameOver = false; var ticksSurvived = 0; // Score text var scoreTxt = new Text2('0', { size: 120, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // Bonus text var bonusTxt = new Text2('', { size: 80, fill: 0xFFE066 }); bonusTxt.anchor.set(0.5, 0); LK.gui.top.addChild(bonusTxt); bonusTxt.y = 130; // Difficulty progression var obstacleInterval = 60; // ticks between obstacles (start: 1/sec) var bonusInterval = 180; // ticks between bonuses (start: 1/3sec) var minObstacleInterval = 18; // fastest: ~3/sec var minBonusInterval = 240; // slowest: ~1/4sec var lastObstacleTick = 0; var lastBonusTick = 0; var obstacleSpeed = 12; var bonusSpeed = 10; var speedIncreaseEvery = 600; // every 10 seconds // Main update loop game.update = function () { if (gameOver) return; // Update player position from facekit // Clamp to game area var fx = facekit.mouthCenter && facekit.mouthCenter.x ? facekit.mouthCenter.x : 2048 / 2; var fy = facekit.mouthCenter && facekit.mouthCenter.y ? facekit.mouthCenter.y : 2732 - 350; // Keep player inside bounds var px = Math.max(player.width / 2, Math.min(2048 - player.width / 2, fx)); var py = Math.max(player.height / 2 + 100, Math.min(2732 - player.height / 2, fy)); player.x = px; player.y = py; // Spawn obstacles if (LK.ticks - lastObstacleTick >= obstacleInterval) { var obs = new Obstacle(); obs.x = Math.random() * (2048 - 200) + 100; obs.y = -obs.height / 2; obs.speed = obstacleSpeed; obstacles.push(obs); game.addChild(obs); lastObstacleTick = LK.ticks; } // Spawn bonuses if (LK.ticks - lastBonusTick >= bonusInterval) { // 60% chance to spawn a bonus if (Math.random() < 0.6) { var bon = new Bonus(); bon.x = Math.random() * (2048 - 160) + 80; bon.y = -bon.height / 2; bon.speed = bonusSpeed; bonuses.push(bon); game.addChild(bon); } lastBonusTick = LK.ticks; } // Increase difficulty over time if (LK.ticks % speedIncreaseEvery === 0 && LK.ticks > 0) { if (obstacleInterval > minObstacleInterval) obstacleInterval -= 4; if (bonusInterval < minBonusInterval) bonusInterval += 8; obstacleSpeed += 1.5; bonusSpeed += 1; } // Update obstacles for (var i = obstacles.length - 1; i >= 0; i--) { var obs = obstacles[i]; obs.update(); // Remove if off screen if (obs.y - obs.height / 2 > 2732 + 50) { obs.destroy(); obstacles.splice(i, 1); continue; } // Collision with player if (obs.intersects(player)) { // Game over LK.effects.flashScreen(0xff0000, 800); gameOver = true; tween(player, { alpha: 0.2 }, { duration: 400, easing: tween.easeOut }); LK.setTimeout(function () { LK.showGameOver(); }, 900); return; } } // Update bonuses for (var j = bonuses.length - 1; j >= 0; j--) { var bon = bonuses[j]; bon.update(); // Remove if off screen if (bon.y - bon.height / 2 > 2732 + 50) { bon.destroy(); bonuses.splice(j, 1); continue; } // Collision with player if (bon.intersects(player)) { bonusScore += 1; score += 5; scoreTxt.setText(score); bonusTxt.setText('Bonuses: ' + bonusScore); // Flash bonus LK.effects.flashObject(bon, 0xffff00, 300); bon.destroy(); bonuses.splice(j, 1); continue; } } // Score: 1 point per 30 ticks survived ticksSurvived++; if (ticksSurvived % 30 === 0) { score += 1; scoreTxt.setText(score); } }; // Reset game state on restart game.on('reset', function () { // Remove all obstacles and bonuses for (var i = 0; i < obstacles.length; i++) { obstacles[i].destroy(); } for (var j = 0; j < bonuses.length; j++) { bonuses[j].destroy(); } obstacles = []; bonuses = []; score = 0; bonusScore = 0; ticksSurvived = 0; gameOver = false; player.x = 2048 / 2; player.y = 2732 - 350; scoreTxt.setText('0'); bonusTxt.setText(''); obstacleInterval = 60; bonusInterval = 180; obstacleSpeed = 12; bonusSpeed = 10; lastObstacleTick = 0; lastBonusTick = 0; }); // Show camera background game.setBackgroundColor(0x000000); // Camera will show behind game elements // No need to handle music, pause, or leaderboard
===================================================================
--- original.js
+++ change.js