/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Cloud obstacle
var Cloud = Container.expand(function () {
var self = Container.call(this);
var sprite = self.attachAsset('cloud', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = sprite.width / 2;
self.vx = -10;
self.update = function () {
self.x += self.vx;
};
return self;
});
// Ember collectible
var Ember = Container.expand(function () {
var self = Container.call(this);
var sprite = self.attachAsset('ember', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = sprite.width / 2;
self.vx = -12;
self.update = function () {
self.x += self.vx;
};
return self;
});
// Falcon (Richard) class
var Falcon = Container.expand(function () {
var self = Container.call(this);
var sprite = self.attachAsset('falcon', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = sprite.width / 2;
self.vx = 18;
self.update = function () {
self.x += self.vx;
};
return self;
});
// Phoenix (Vixen) class
var Phoenix = Container.expand(function () {
var self = Container.call(this);
var sprite = self.attachAsset('phoenix', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = sprite.width / 2;
self.energy = 0; // 0-1
self.isTransformed = false;
self.update = function () {
// No auto-movement; movement is handled by drag/touch
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1e2a44
});
/****
* Game Code
****/
// Energy bar fill
// Energy bar background
// Dark cloud (obstacle)
// Ember collectible
// Falcon (Richard)
// Phoenix (Vixen)
// Game state
var phoenix, falcon;
var embers = [];
var clouds = [];
var dragNode = null;
var energyBarBg, energyBarFill;
var score = 0;
var scoreTxt;
var energy = 0; // 0-1
var inBonusStage = false;
var bonusTimer = 0;
var lastPhoenixPos = {
x: 0,
y: 0
};
// Place Phoenix at start
phoenix = new Phoenix();
phoenix.x = 400;
phoenix.y = 1366;
game.addChild(phoenix);
// Energy bar UI
energyBarBg = LK.getAsset('energyBarBg', {
anchorX: 0,
anchorY: 0.5,
x: 724,
y: 120
});
energyBarFill = LK.getAsset('energyBarFill', {
anchorX: 0,
anchorY: 0.5,
x: 724,
y: 120
});
energyBarFill.width = 0;
LK.gui.top.addChild(energyBarBg);
LK.gui.top.addChild(energyBarFill);
// Score UI
scoreTxt = new Text2('0', {
size: 100,
fill: '#fff'
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
scoreTxt.x = 2048 / 2;
scoreTxt.y = 30;
// Helper: spawn ember
function spawnEmber() {
var ember = new Ember();
ember.x = 2048 + 80;
ember.y = 300 + Math.floor(Math.random() * (2732 - 600));
embers.push(ember);
game.addChild(ember);
}
// Helper: spawn cloud
function spawnCloud() {
var cloud = new Cloud();
cloud.x = 2048 + 120;
cloud.y = 200 + Math.floor(Math.random() * (2732 - 400));
clouds.push(cloud);
game.addChild(cloud);
}
// Dragging Phoenix
function handleMove(x, y, obj) {
if (dragNode && !inBonusStage) {
// Clamp to screen, avoid top left 100x100
var nx = Math.max(phoenix.radius + 100, Math.min(2048 - phoenix.radius, x));
var ny = Math.max(phoenix.radius, Math.min(2732 - phoenix.radius, y));
dragNode.x = nx;
dragNode.y = ny;
}
}
game.move = handleMove;
game.down = function (x, y, obj) {
// Only allow drag if not in bonus
if (!inBonusStage) {
dragNode = phoenix;
handleMove(x, y, obj);
}
};
game.up = function (x, y, obj) {
dragNode = null;
};
// Main update loop
game.update = function () {
// Phoenix stage
if (!inBonusStage) {
// Spawn embers
if (LK.ticks % 45 === 0) {
spawnEmber();
}
// Spawn clouds
if (LK.ticks % 90 === 0) {
spawnCloud();
}
// Update embers
for (var i = embers.length - 1; i >= 0; i--) {
var ember = embers[i];
ember.update();
// Off screen
if (ember.x < -80) {
ember.destroy();
embers.splice(i, 1);
continue;
}
// Collect
if (phoenix.intersects(ember)) {
ember.destroy();
embers.splice(i, 1);
score += 1;
if (energy < 1) {
energy += 0.08;
if (energy > 1) energy = 1;
}
scoreTxt.setText(score);
// Animate energy bar
tween(energyBarFill, {
width: 600 * energy
}, {
duration: 200,
easing: tween.cubicOut
});
}
}
// Update clouds
for (var j = clouds.length - 1; j >= 0; j--) {
var cloud = clouds[j];
cloud.update();
if (cloud.x < -120) {
cloud.destroy();
clouds.splice(j, 1);
continue;
}
// Hit
if (phoenix.intersects(cloud)) {
// Flash, game over
LK.effects.flashScreen(0x222244, 900);
LK.showGameOver();
return;
}
}
// Energy full: transform!
if (energy >= 1 && !phoenix.isTransformed) {
phoenix.isTransformed = true;
// Animate: fade out phoenix, fade in falcon
tween(phoenix, {
alpha: 0
}, {
duration: 600,
easing: tween.linear,
onFinish: function onFinish() {
phoenix.visible = false;
startBonusStage();
}
});
}
}
// Bonus stage: Falcon
if (inBonusStage && falcon) {
falcon.update();
// End bonus after 4 seconds or off screen
bonusTimer++;
if (falcon.x > 2048 + 200 || bonusTimer > 240) {
LK.showYouWin();
return;
}
}
};
// Start bonus stage: Falcon
function startBonusStage() {
inBonusStage = true;
// Remove embers/clouds
for (var i = 0; i < embers.length; i++) embers[i].destroy();
for (var j = 0; j < clouds.length; j++) clouds[j].destroy();
embers = [];
clouds = [];
// Place Falcon at Phoenix's last position
falcon = new Falcon();
falcon.x = phoenix.x;
falcon.y = phoenix.y;
game.addChild(falcon);
bonusTimer = 0;
// Animate falcon in
falcon.alpha = 0;
tween(falcon, {
alpha: 1
}, {
duration: 400,
easing: tween.linear
});
// Animate energy bar out
tween(energyBarBg, {
alpha: 0
}, {
duration: 400
});
tween(energyBarFill, {
alpha: 0
}, {
duration: 400
});
}
// Set initial energy bar width
energyBarFill.width = 0;
// Place UI elements
energyBarBg.y = 120;
energyBarFill.y = 120;
energyBarBg.x = 724;
energyBarFill.x = 724;
// Make sure phoenix is above clouds/embers
phoenix.zIndex = 10;
// Initial score
scoreTxt.setText(score);
// Ensure all elements are visible and not in top left 100x100
phoenix.x = Math.max(phoenix.radius + 100, phoenix.x);
phoenix.y = Math.max(phoenix.radius, phoenix.y); ===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,297 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+
+/****
+* Classes
+****/
+// Cloud obstacle
+var Cloud = Container.expand(function () {
+ var self = Container.call(this);
+ var sprite = self.attachAsset('cloud', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.radius = sprite.width / 2;
+ self.vx = -10;
+ self.update = function () {
+ self.x += self.vx;
+ };
+ return self;
+});
+// Ember collectible
+var Ember = Container.expand(function () {
+ var self = Container.call(this);
+ var sprite = self.attachAsset('ember', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.radius = sprite.width / 2;
+ self.vx = -12;
+ self.update = function () {
+ self.x += self.vx;
+ };
+ return self;
+});
+// Falcon (Richard) class
+var Falcon = Container.expand(function () {
+ var self = Container.call(this);
+ var sprite = self.attachAsset('falcon', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.radius = sprite.width / 2;
+ self.vx = 18;
+ self.update = function () {
+ self.x += self.vx;
+ };
+ return self;
+});
+// Phoenix (Vixen) class
+var Phoenix = Container.expand(function () {
+ var self = Container.call(this);
+ var sprite = self.attachAsset('phoenix', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.radius = sprite.width / 2;
+ self.energy = 0; // 0-1
+ self.isTransformed = false;
+ self.update = function () {
+ // No auto-movement; movement is handled by drag/touch
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0x1e2a44
+});
+
+/****
+* Game Code
+****/
+// Energy bar fill
+// Energy bar background
+// Dark cloud (obstacle)
+// Ember collectible
+// Falcon (Richard)
+// Phoenix (Vixen)
+// Game state
+var phoenix, falcon;
+var embers = [];
+var clouds = [];
+var dragNode = null;
+var energyBarBg, energyBarFill;
+var score = 0;
+var scoreTxt;
+var energy = 0; // 0-1
+var inBonusStage = false;
+var bonusTimer = 0;
+var lastPhoenixPos = {
+ x: 0,
+ y: 0
+};
+// Place Phoenix at start
+phoenix = new Phoenix();
+phoenix.x = 400;
+phoenix.y = 1366;
+game.addChild(phoenix);
+// Energy bar UI
+energyBarBg = LK.getAsset('energyBarBg', {
+ anchorX: 0,
+ anchorY: 0.5,
+ x: 724,
+ y: 120
+});
+energyBarFill = LK.getAsset('energyBarFill', {
+ anchorX: 0,
+ anchorY: 0.5,
+ x: 724,
+ y: 120
+});
+energyBarFill.width = 0;
+LK.gui.top.addChild(energyBarBg);
+LK.gui.top.addChild(energyBarFill);
+// Score UI
+scoreTxt = new Text2('0', {
+ size: 100,
+ fill: '#fff'
+});
+scoreTxt.anchor.set(0.5, 0);
+LK.gui.top.addChild(scoreTxt);
+scoreTxt.x = 2048 / 2;
+scoreTxt.y = 30;
+// Helper: spawn ember
+function spawnEmber() {
+ var ember = new Ember();
+ ember.x = 2048 + 80;
+ ember.y = 300 + Math.floor(Math.random() * (2732 - 600));
+ embers.push(ember);
+ game.addChild(ember);
+}
+// Helper: spawn cloud
+function spawnCloud() {
+ var cloud = new Cloud();
+ cloud.x = 2048 + 120;
+ cloud.y = 200 + Math.floor(Math.random() * (2732 - 400));
+ clouds.push(cloud);
+ game.addChild(cloud);
+}
+// Dragging Phoenix
+function handleMove(x, y, obj) {
+ if (dragNode && !inBonusStage) {
+ // Clamp to screen, avoid top left 100x100
+ var nx = Math.max(phoenix.radius + 100, Math.min(2048 - phoenix.radius, x));
+ var ny = Math.max(phoenix.radius, Math.min(2732 - phoenix.radius, y));
+ dragNode.x = nx;
+ dragNode.y = ny;
+ }
+}
+game.move = handleMove;
+game.down = function (x, y, obj) {
+ // Only allow drag if not in bonus
+ if (!inBonusStage) {
+ dragNode = phoenix;
+ handleMove(x, y, obj);
+ }
+};
+game.up = function (x, y, obj) {
+ dragNode = null;
+};
+// Main update loop
+game.update = function () {
+ // Phoenix stage
+ if (!inBonusStage) {
+ // Spawn embers
+ if (LK.ticks % 45 === 0) {
+ spawnEmber();
+ }
+ // Spawn clouds
+ if (LK.ticks % 90 === 0) {
+ spawnCloud();
+ }
+ // Update embers
+ for (var i = embers.length - 1; i >= 0; i--) {
+ var ember = embers[i];
+ ember.update();
+ // Off screen
+ if (ember.x < -80) {
+ ember.destroy();
+ embers.splice(i, 1);
+ continue;
+ }
+ // Collect
+ if (phoenix.intersects(ember)) {
+ ember.destroy();
+ embers.splice(i, 1);
+ score += 1;
+ if (energy < 1) {
+ energy += 0.08;
+ if (energy > 1) energy = 1;
+ }
+ scoreTxt.setText(score);
+ // Animate energy bar
+ tween(energyBarFill, {
+ width: 600 * energy
+ }, {
+ duration: 200,
+ easing: tween.cubicOut
+ });
+ }
+ }
+ // Update clouds
+ for (var j = clouds.length - 1; j >= 0; j--) {
+ var cloud = clouds[j];
+ cloud.update();
+ if (cloud.x < -120) {
+ cloud.destroy();
+ clouds.splice(j, 1);
+ continue;
+ }
+ // Hit
+ if (phoenix.intersects(cloud)) {
+ // Flash, game over
+ LK.effects.flashScreen(0x222244, 900);
+ LK.showGameOver();
+ return;
+ }
+ }
+ // Energy full: transform!
+ if (energy >= 1 && !phoenix.isTransformed) {
+ phoenix.isTransformed = true;
+ // Animate: fade out phoenix, fade in falcon
+ tween(phoenix, {
+ alpha: 0
+ }, {
+ duration: 600,
+ easing: tween.linear,
+ onFinish: function onFinish() {
+ phoenix.visible = false;
+ startBonusStage();
+ }
+ });
+ }
+ }
+ // Bonus stage: Falcon
+ if (inBonusStage && falcon) {
+ falcon.update();
+ // End bonus after 4 seconds or off screen
+ bonusTimer++;
+ if (falcon.x > 2048 + 200 || bonusTimer > 240) {
+ LK.showYouWin();
+ return;
+ }
+ }
+};
+// Start bonus stage: Falcon
+function startBonusStage() {
+ inBonusStage = true;
+ // Remove embers/clouds
+ for (var i = 0; i < embers.length; i++) embers[i].destroy();
+ for (var j = 0; j < clouds.length; j++) clouds[j].destroy();
+ embers = [];
+ clouds = [];
+ // Place Falcon at Phoenix's last position
+ falcon = new Falcon();
+ falcon.x = phoenix.x;
+ falcon.y = phoenix.y;
+ game.addChild(falcon);
+ bonusTimer = 0;
+ // Animate falcon in
+ falcon.alpha = 0;
+ tween(falcon, {
+ alpha: 1
+ }, {
+ duration: 400,
+ easing: tween.linear
+ });
+ // Animate energy bar out
+ tween(energyBarBg, {
+ alpha: 0
+ }, {
+ duration: 400
+ });
+ tween(energyBarFill, {
+ alpha: 0
+ }, {
+ duration: 400
+ });
+}
+// Set initial energy bar width
+energyBarFill.width = 0;
+// Place UI elements
+energyBarBg.y = 120;
+energyBarFill.y = 120;
+energyBarBg.x = 724;
+energyBarFill.x = 724;
+// Make sure phoenix is above clouds/embers
+phoenix.zIndex = 10;
+// Initial score
+scoreTxt.setText(score);
+// Ensure all elements are visible and not in top left 100x100
+phoenix.x = Math.max(phoenix.radius + 100, phoenix.x);
+phoenix.y = Math.max(phoenix.radius, phoenix.y);
\ No newline at end of file