/****
* 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
@@ -1,6 +1,223 @@
-/****
+/****
+* 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
-});
\ No newline at end of file
+});
+
+/****
+* 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
\ No newline at end of file