/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var facekit = LK.import("@upit/facekit.v1");
/****
* Classes
****/
// Enemy class
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyAsset = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 12 + Math.random() * 8; // Downward, randomize a bit
self.update = function () {
self.y += self.speed;
};
return self;
});
// Bullet class
var HeroBullet = Container.expand(function () {
var self = Container.call(this);
var bulletAsset = self.attachAsset('heroBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -40; // Fast upward
self.update = function () {
self.y += self.speed;
};
return self;
});
// Hero Ship class
var HeroShip = Container.expand(function () {
var self = Container.call(this);
var shipAsset = self.attachAsset('heroShip', {
anchorX: 0.5,
anchorY: 0.5
});
// For possible future effects
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Sound for shooting
// Enemy: red ellipse
// Bullet: small yellow box
// Hero ship: ellipse, blue
// Score display
var scoreTxt = new Text2('0', {
size: 120,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Create hero ship
var heroShip = new HeroShip();
game.addChild(heroShip);
// Start at center bottom
heroShip.x = 2048 / 2;
heroShip.y = 2732 - 350;
// Bullets and enemies arrays
var heroBullets = [];
var enemies = [];
// Bullet cooldown
var bulletCooldown = 0;
var bulletCooldownFrames = 12; // ~0.2s at 60fps
// Enemy spawn timer
var enemySpawnFrames = 36; // ~0.6s at 60fps
// For mouth open detection
var lastMouthOpen = false;
// For game over state
var isGameOver = false;
// Main update loop
game.update = function () {
// Move hero ship to facekit mouth position (if available)
if (facekit.mouthCenter && typeof facekit.mouthCenter.x === 'number' && typeof facekit.mouthCenter.y === 'number') {
// Clamp to game area, keep ship fully visible
var shipW = heroShip.width || 140;
var shipH = heroShip.height || 140;
var targetX = Math.max(shipW / 2, Math.min(2048 - shipW / 2, facekit.mouthCenter.x));
var targetY = Math.max(shipH / 2 + 100, Math.min(2732 - shipH / 2, facekit.mouthCenter.y));
// Tween for smoothness
tween(heroShip, {
x: targetX,
y: targetY
}, {
duration: 80,
easing: tween.easeOut
});
}
// Handle shooting (mouth open)
var mouthOpen = !!facekit.mouthOpen;
if (mouthOpen && !lastMouthOpen && bulletCooldown <= 0) {
// Fire bullet
var bullet = new HeroBullet();
bullet.x = heroShip.x;
bullet.y = heroShip.y - (heroShip.height ? heroShip.height / 2 : 70) - 30;
heroBullets.push(bullet);
game.addChild(bullet);
bulletCooldown = bulletCooldownFrames;
LK.getSound('shoot').play();
}
lastMouthOpen = mouthOpen;
if (bulletCooldown > 0) bulletCooldown--;
// Update bullets
for (var i = heroBullets.length - 1; i >= 0; i--) {
var b = heroBullets[i];
b.update();
// Remove if off screen
if (b.y < -100) {
b.destroy();
heroBullets.splice(i, 1);
continue;
}
}
// Spawn enemies
if (LK.ticks % enemySpawnFrames === 0) {
var enemy = new Enemy();
// Random X, avoid edges
var ew = enemy.width || 120;
enemy.x = ew / 2 + 80 + Math.random() * (2048 - ew - 160);
enemy.y = -ew / 2 - 40;
enemies.push(enemy);
game.addChild(enemy);
}
// Update enemies
for (var j = enemies.length - 1; j >= 0; j--) {
var e = enemies[j];
e.update();
// Remove if off screen
if (e.y > 2732 + 100) {
e.destroy();
enemies.splice(j, 1);
continue;
}
}
// Bullet-enemy collisions
for (var k = enemies.length - 1; k >= 0; k--) {
var enemyObj = enemies[k];
for (var l = heroBullets.length - 1; l >= 0; l--) {
var bulletObj = heroBullets[l];
if (enemyObj.intersects(bulletObj)) {
// Destroy both
enemyObj.destroy();
bulletObj.destroy();
enemies.splice(k, 1);
heroBullets.splice(l, 1);
// Score up
LK.setScore(LK.getScore() + 1);
scoreTxt.setText(LK.getScore());
break;
}
}
}
// Enemy-hero collision (game over)
for (var m = 0; m < enemies.length; m++) {
var enemyObj2 = enemies[m];
if (enemyObj2.intersects(heroShip)) {
if (!isGameOver) {
isGameOver = true;
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
}
break;
}
}
};
// No touch controls needed; all control is via facekit
// Reset state on game over (handled by LK, but clear local state)
game.onDestroy = function () {
heroBullets = [];
enemies = [];
isGameOver = false;
lastMouthOpen = false;
bulletCooldown = 0;
scoreTxt.setText('0');
}; ===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,190 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+var facekit = LK.import("@upit/facekit.v1");
+
+/****
+* Classes
+****/
+// Enemy class
+var Enemy = Container.expand(function () {
+ var self = Container.call(this);
+ var enemyAsset = self.attachAsset('enemy', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.speed = 12 + Math.random() * 8; // Downward, randomize a bit
+ self.update = function () {
+ self.y += self.speed;
+ };
+ return self;
+});
+// Bullet class
+var HeroBullet = Container.expand(function () {
+ var self = Container.call(this);
+ var bulletAsset = self.attachAsset('heroBullet', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.speed = -40; // Fast upward
+ self.update = function () {
+ self.y += self.speed;
+ };
+ return self;
+});
+// Hero Ship class
+var HeroShip = Container.expand(function () {
+ var self = Container.call(this);
+ var shipAsset = self.attachAsset('heroShip', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ // For possible future effects
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
backgroundColor: 0x000000
-});
\ No newline at end of file
+});
+
+/****
+* Game Code
+****/
+// Sound for shooting
+// Enemy: red ellipse
+// Bullet: small yellow box
+// Hero ship: ellipse, blue
+// Score display
+var scoreTxt = new Text2('0', {
+ size: 120,
+ fill: 0xFFFFFF
+});
+scoreTxt.anchor.set(0.5, 0);
+LK.gui.top.addChild(scoreTxt);
+// Create hero ship
+var heroShip = new HeroShip();
+game.addChild(heroShip);
+// Start at center bottom
+heroShip.x = 2048 / 2;
+heroShip.y = 2732 - 350;
+// Bullets and enemies arrays
+var heroBullets = [];
+var enemies = [];
+// Bullet cooldown
+var bulletCooldown = 0;
+var bulletCooldownFrames = 12; // ~0.2s at 60fps
+// Enemy spawn timer
+var enemySpawnFrames = 36; // ~0.6s at 60fps
+// For mouth open detection
+var lastMouthOpen = false;
+// For game over state
+var isGameOver = false;
+// Main update loop
+game.update = function () {
+ // Move hero ship to facekit mouth position (if available)
+ if (facekit.mouthCenter && typeof facekit.mouthCenter.x === 'number' && typeof facekit.mouthCenter.y === 'number') {
+ // Clamp to game area, keep ship fully visible
+ var shipW = heroShip.width || 140;
+ var shipH = heroShip.height || 140;
+ var targetX = Math.max(shipW / 2, Math.min(2048 - shipW / 2, facekit.mouthCenter.x));
+ var targetY = Math.max(shipH / 2 + 100, Math.min(2732 - shipH / 2, facekit.mouthCenter.y));
+ // Tween for smoothness
+ tween(heroShip, {
+ x: targetX,
+ y: targetY
+ }, {
+ duration: 80,
+ easing: tween.easeOut
+ });
+ }
+ // Handle shooting (mouth open)
+ var mouthOpen = !!facekit.mouthOpen;
+ if (mouthOpen && !lastMouthOpen && bulletCooldown <= 0) {
+ // Fire bullet
+ var bullet = new HeroBullet();
+ bullet.x = heroShip.x;
+ bullet.y = heroShip.y - (heroShip.height ? heroShip.height / 2 : 70) - 30;
+ heroBullets.push(bullet);
+ game.addChild(bullet);
+ bulletCooldown = bulletCooldownFrames;
+ LK.getSound('shoot').play();
+ }
+ lastMouthOpen = mouthOpen;
+ if (bulletCooldown > 0) bulletCooldown--;
+ // Update bullets
+ for (var i = heroBullets.length - 1; i >= 0; i--) {
+ var b = heroBullets[i];
+ b.update();
+ // Remove if off screen
+ if (b.y < -100) {
+ b.destroy();
+ heroBullets.splice(i, 1);
+ continue;
+ }
+ }
+ // Spawn enemies
+ if (LK.ticks % enemySpawnFrames === 0) {
+ var enemy = new Enemy();
+ // Random X, avoid edges
+ var ew = enemy.width || 120;
+ enemy.x = ew / 2 + 80 + Math.random() * (2048 - ew - 160);
+ enemy.y = -ew / 2 - 40;
+ enemies.push(enemy);
+ game.addChild(enemy);
+ }
+ // Update enemies
+ for (var j = enemies.length - 1; j >= 0; j--) {
+ var e = enemies[j];
+ e.update();
+ // Remove if off screen
+ if (e.y > 2732 + 100) {
+ e.destroy();
+ enemies.splice(j, 1);
+ continue;
+ }
+ }
+ // Bullet-enemy collisions
+ for (var k = enemies.length - 1; k >= 0; k--) {
+ var enemyObj = enemies[k];
+ for (var l = heroBullets.length - 1; l >= 0; l--) {
+ var bulletObj = heroBullets[l];
+ if (enemyObj.intersects(bulletObj)) {
+ // Destroy both
+ enemyObj.destroy();
+ bulletObj.destroy();
+ enemies.splice(k, 1);
+ heroBullets.splice(l, 1);
+ // Score up
+ LK.setScore(LK.getScore() + 1);
+ scoreTxt.setText(LK.getScore());
+ break;
+ }
+ }
+ }
+ // Enemy-hero collision (game over)
+ for (var m = 0; m < enemies.length; m++) {
+ var enemyObj2 = enemies[m];
+ if (enemyObj2.intersects(heroShip)) {
+ if (!isGameOver) {
+ isGameOver = true;
+ LK.effects.flashScreen(0xff0000, 1000);
+ LK.showGameOver();
+ }
+ break;
+ }
+ }
+};
+// No touch controls needed; all control is via facekit
+// Reset state on game over (handled by LK, but clear local state)
+game.onDestroy = function () {
+ heroBullets = [];
+ enemies = [];
+ isGameOver = false;
+ lastMouthOpen = false;
+ bulletCooldown = 0;
+ scoreTxt.setText('0');
+};
\ No newline at end of file