/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Eagle (goal) class
var Eagle = Container.expand(function () {
var self = Container.call(this);
var eagleSprite = self.attachAsset('eagle', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = eagleSprite.width / 2;
return self;
});
// Enemy class (moves horizontally)
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemySprite = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = enemySprite.width / 2;
self.dir = 1;
self.speed = 7 + Math.random() * 4;
self.minX = 0;
self.maxX = 2048;
self.update = function () {
self.x += self.dir * self.speed;
if (self.x < self.minX + self.radius) {
self.x = self.minX + self.radius;
self.dir = 1;
}
if (self.x > self.maxX - self.radius) {
self.x = self.maxX - self.radius;
self.dir = -1;
}
};
return self;
});
// Falcon (player) class
var Falcon = Container.expand(function () {
var self = Container.call(this);
var falconSprite = self.attachAsset('falcon', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = falconSprite.width / 2;
self.speed = 0;
self.maxSpeed = 22;
self.vx = 0;
self.vy = 0;
self.update = function () {
self.x += self.vx;
self.y += self.vy;
};
return self;
});
// On-screen joystick class
var Joystick = Container.expand(function () {
var self = Container.call(this);
var base = self.attachAsset('joystickBase', {
anchorX: 0.5,
anchorY: 0.5
});
var knob = self.attachAsset('joystickKnob', {
anchorX: 0.5,
anchorY: 0.5
});
knob.x = 0;
knob.y = 0;
self.knob = knob;
self.baseRadius = base.width / 2;
self.knobRadius = knob.width / 2;
self.active = false;
self.value = {
x: 0,
y: 0
};
self.startX = 0;
self.startY = 0;
self.pointerId = null;
// Touch down on joystick
self.down = function (x, y, obj) {
self.active = true;
self.startX = x;
self.startY = y;
self.pointerId = obj.event && obj.event.pointerId !== undefined ? obj.event.pointerId : null;
self.move(x, y, obj);
};
// Touch move on joystick
self.move = function (x, y, obj) {
if (!self.active) return;
var dx = x - self.startX;
var dy = y - self.startY;
var dist = Math.sqrt(dx * dx + dy * dy);
var maxDist = self.baseRadius - self.knobRadius;
if (dist > maxDist) {
dx = dx * maxDist / dist;
dy = dy * maxDist / dist;
dist = maxDist;
}
self.knob.x = dx;
self.knob.y = dy;
self.value.x = dx / maxDist;
self.value.y = dy / maxDist;
};
// Touch up on joystick
self.up = function (x, y, obj) {
self.active = false;
self.knob.x = 0;
self.knob.y = 0;
self.value.x = 0;
self.value.y = 0;
self.pointerId = null;
};
return self;
});
// Obstacle class
var Obstacle = Container.expand(function () {
var self = Container.call(this);
var obs = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = obs.width;
self.height = obs.height;
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x6ec6f2 // Light blue sky
});
/****
* Game Code
****/
// On-screen joystick knob
// On-screen joystick base
// Enemy
// Obstacle
// Eagle (goal)
// Falcon (player)
// Level data: Each level defines obstacles, enemies, falcon start, eagle goal
var levels = [
// Level 1: Simple, no enemies
{
falcon: {
x: 300,
y: 2300
},
eagle: {
x: 1800,
y: 400
},
obstacles: [{
x: 1024,
y: 1400,
w: 800,
h: 60
}, {
x: 1024,
y: 800,
w: 400,
h: 60
}],
enemies: []
},
// Level 2: Add one enemy
{
falcon: {
x: 300,
y: 2300
},
eagle: {
x: 1800,
y: 400
},
obstacles: [{
x: 1024,
y: 1400,
w: 800,
h: 60
}, {
x: 1024,
y: 800,
w: 400,
h: 60
}],
enemies: [{
x: 600,
y: 1200,
minX: 400,
maxX: 1648
}]
},
// Level 3: More obstacles, two enemies
{
falcon: {
x: 300,
y: 2300
},
eagle: {
x: 1800,
y: 400
},
obstacles: [{
x: 1024,
y: 1800,
w: 800,
h: 60
}, {
x: 1024,
y: 1400,
w: 600,
h: 60
}, {
x: 1024,
y: 1000,
w: 400,
h: 60
}],
enemies: [{
x: 400,
y: 1700,
minX: 300,
maxX: 1720
}, {
x: 1600,
y: 1200,
minX: 1200,
maxX: 2000
}]
},
// Level 4: Narrow path, one fast enemy
{
falcon: {
x: 300,
y: 2300
},
eagle: {
x: 1800,
y: 400
},
obstacles: [{
x: 1024,
y: 2000,
w: 1200,
h: 60
}, {
x: 1024,
y: 1600,
w: 400,
h: 60
}, {
x: 1024,
y: 1200,
w: 1200,
h: 60
}, {
x: 1024,
y: 800,
w: 400,
h: 60
}],
enemies: [{
x: 1024,
y: 1600,
minX: 400,
maxX: 1648
}]
},
// Level 5: Zig-zag obstacles, two enemies
{
falcon: {
x: 300,
y: 2300
},
eagle: {
x: 1800,
y: 400
},
obstacles: [{
x: 600,
y: 2000,
w: 600,
h: 60
}, {
x: 1448,
y: 1600,
w: 600,
h: 60
}, {
x: 600,
y: 1200,
w: 600,
h: 60
}, {
x: 1448,
y: 800,
w: 600,
h: 60
}],
enemies: [{
x: 1024,
y: 1800,
minX: 400,
maxX: 1648
}, {
x: 1024,
y: 1000,
minX: 400,
maxX: 1648
}]
}
// ... Add up to 19 levels as needed
];
// For MVP, repeat last level for levels 6-19
while (levels.length < 19) {
var last = levels[levels.length - 1];
// Slightly increase enemy speed and add a new obstacle for each new level
var newLevel = {
falcon: {
x: last.falcon.x,
y: last.falcon.y
},
eagle: {
x: last.eagle.x,
y: last.eagle.y
},
obstacles: last.obstacles.slice(0),
enemies: []
};
for (var i = 0; i < last.enemies.length; i++) {
var e = last.enemies[i];
newLevel.enemies.push({
x: e.x,
y: e.y,
minX: e.minX,
maxX: e.maxX
});
}
// Add a new obstacle
newLevel.obstacles.push({
x: 400 + Math.random() * 1200,
y: 600 + Math.random() * 1600,
w: 400 + Math.random() * 400,
h: 60
});
// Add a new enemy every 2 levels
if (levels.length % 2 === 0) {
newLevel.enemies.push({
x: 400 + Math.random() * 1200,
y: 600 + Math.random() * 1600,
minX: 200,
maxX: 1848
});
}
levels.push(newLevel);
}
// Game state
var currentLevel = 0;
var falcon = null;
var eagle = null;
var obstacles = [];
var enemies = [];
var joystick = null;
var levelText = null;
var winText = null;
var dragJoystick = false;
// Score display (level number)
levelText = new Text2('Level 1', {
size: 100,
fill: 0xFFFFFF
});
levelText.anchor.set(0.5, 0);
LK.gui.top.addChild(levelText);
// Helper: load a level
function loadLevel(levelIdx) {
// Remove old objects
if (falcon) {
falcon.destroy();
falcon = null;
}
if (eagle) {
eagle.destroy();
eagle = null;
}
for (var i = 0; i < obstacles.length; i++) obstacles[i].destroy();
for (var i = 0; i < enemies.length; i++) enemies[i].destroy();
obstacles = [];
enemies = [];
// Clamp level
if (levelIdx < 0) levelIdx = 0;
if (levelIdx >= levels.length) levelIdx = levels.length - 1;
currentLevel = levelIdx;
var data = levels[levelIdx];
// Create falcon
falcon = new Falcon();
falcon.x = data.falcon.x;
falcon.y = data.falcon.y;
game.addChild(falcon);
// Create eagle
eagle = new Eagle();
eagle.x = data.eagle.x;
eagle.y = data.eagle.y;
game.addChild(eagle);
// Create obstacles
for (var i = 0; i < data.obstacles.length; i++) {
var o = data.obstacles[i];
var obs = new Obstacle();
obs.x = o.x;
obs.y = o.y;
// Scale obstacle to match w/h
obs.children[0].width = o.w;
obs.children[0].height = o.h;
obs.width = o.w;
obs.height = o.h;
obstacles.push(obs);
game.addChild(obs);
}
// Create enemies
for (var i = 0; i < data.enemies.length; i++) {
var e = data.enemies[i];
var enemy = new Enemy();
enemy.x = e.x;
enemy.y = e.y;
enemy.minX = e.minX;
enemy.maxX = e.maxX;
enemies.push(enemy);
game.addChild(enemy);
}
// Update level text
levelText.setText('Level ' + (levelIdx + 1));
}
// Helper: collision detection (circle-rectangle)
function circleRectIntersect(cx, cy, cr, rx, ry, rw, rh) {
// Find closest point to circle within rectangle
var closestX = Math.max(rx - rw / 2, Math.min(cx, rx + rw / 2));
var closestY = Math.max(ry - rh / 2, Math.min(cy, ry + rh / 2));
var dx = cx - closestX;
var dy = cy - closestY;
return dx * dx + dy * dy < cr * cr;
}
// Helper: collision detection (circle-circle)
function circleCircleIntersect(x1, y1, r1, x2, y2, r2) {
var dx = x1 - x2;
var dy = y1 - y2;
var dist = dx * dx + dy * dy;
var r = r1 + r2;
return dist < r * r;
}
// Helper: clamp position inside game area
function clampPosition(obj) {
var r = obj.radius || 60;
if (obj.x < r) obj.x = r;
if (obj.x > 2048 - r) obj.x = 2048 - r;
if (obj.y < r) obj.y = r;
if (obj.y > 2732 - r) obj.y = 2732 - r;
}
// Show win text
function showWin() {
LK.showYouWin();
}
// Show game over
function showGameOver() {
LK.effects.flashScreen(0xff0000, 800);
LK.showGameOver();
}
// Joystick setup
joystick = new Joystick();
joystick.x = 300;
joystick.y = 2732 - 300;
LK.gui.bottomLeft.addChild(joystick);
// Joystick event handling
var joystickActive = false;
var joystickPointerId = null;
LK.gui.bottomLeft.down = function (x, y, obj) {
// Only activate if inside joystick area
var dx = x - joystick.x;
var dy = y - joystick.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < joystick.baseRadius) {
joystick.down(x, y, obj);
joystickActive = true;
joystickPointerId = obj.event && obj.event.pointerId !== undefined ? obj.event.pointerId : null;
}
};
LK.gui.bottomLeft.move = function (x, y, obj) {
if (joystickActive) {
joystick.move(x, y, obj);
}
};
LK.gui.bottomLeft.up = function (x, y, obj) {
if (joystickActive) {
joystick.up(x, y, obj);
joystickActive = false;
joystickPointerId = null;
}
};
// Prevent game area from handling joystick touches
game.down = function (x, y, obj) {
// No drag for falcon; only joystick controls
};
game.move = function (x, y, obj) {
// No drag for falcon; only joystick controls
};
game.up = function (x, y, obj) {
// No drag for falcon; only joystick controls
};
// Main game update loop
game.update = function () {
// Move falcon by joystick
if (falcon && joystick) {
var jx = joystick.value.x;
var jy = joystick.value.y;
var speed = falcon.maxSpeed;
falcon.vx = jx * speed;
falcon.vy = jy * speed;
falcon.update();
clampPosition(falcon);
}
// Move enemies
for (var i = 0; i < enemies.length; i++) {
enemies[i].update();
}
// Check falcon-obstacle collision
for (var i = 0; i < obstacles.length; i++) {
var obs = obstacles[i];
if (circleRectIntersect(falcon.x, falcon.y, falcon.radius, obs.x, obs.y, obs.width, obs.height)) {
// Push falcon out of obstacle
// Find minimal direction to push out
var dx = falcon.x - obs.x;
var dy = falcon.y - obs.y;
var px = 0,
py = 0;
if (Math.abs(dx) > Math.abs(dy)) {
px = dx > 0 ? obs.x + obs.width / 2 + falcon.radius : obs.x - obs.width / 2 - falcon.radius;
falcon.x = px;
} else {
py = dy > 0 ? obs.y + obs.height / 2 + falcon.radius : obs.y - obs.height / 2 - falcon.radius;
falcon.y = py;
}
clampPosition(falcon);
}
}
// Check falcon-enemy collision
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
if (circleCircleIntersect(falcon.x, falcon.y, falcon.radius, enemy.x, enemy.y, enemy.radius)) {
showGameOver();
return;
}
}
// Check falcon-eagle collision (win)
if (circleCircleIntersect(falcon.x, falcon.y, falcon.radius, eagle.x, eagle.y, eagle.radius)) {
// Next level or win
if (currentLevel < levels.length - 1) {
// Flash green, load next level after short delay
LK.effects.flashScreen(0x00ff00, 400);
var nextLevel = currentLevel + 1;
LK.setTimeout(function () {
loadLevel(nextLevel);
}, 600);
} else {
// All levels complete
showWin();
}
}
};
// Start first level
loadLevel(0); ===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,578 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+
+/****
+* Classes
+****/
+// Eagle (goal) class
+var Eagle = Container.expand(function () {
+ var self = Container.call(this);
+ var eagleSprite = self.attachAsset('eagle', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.radius = eagleSprite.width / 2;
+ return self;
+});
+// Enemy class (moves horizontally)
+var Enemy = Container.expand(function () {
+ var self = Container.call(this);
+ var enemySprite = self.attachAsset('enemy', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.radius = enemySprite.width / 2;
+ self.dir = 1;
+ self.speed = 7 + Math.random() * 4;
+ self.minX = 0;
+ self.maxX = 2048;
+ self.update = function () {
+ self.x += self.dir * self.speed;
+ if (self.x < self.minX + self.radius) {
+ self.x = self.minX + self.radius;
+ self.dir = 1;
+ }
+ if (self.x > self.maxX - self.radius) {
+ self.x = self.maxX - self.radius;
+ self.dir = -1;
+ }
+ };
+ return self;
+});
+// Falcon (player) class
+var Falcon = Container.expand(function () {
+ var self = Container.call(this);
+ var falconSprite = self.attachAsset('falcon', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.radius = falconSprite.width / 2;
+ self.speed = 0;
+ self.maxSpeed = 22;
+ self.vx = 0;
+ self.vy = 0;
+ self.update = function () {
+ self.x += self.vx;
+ self.y += self.vy;
+ };
+ return self;
+});
+// On-screen joystick class
+var Joystick = Container.expand(function () {
+ var self = Container.call(this);
+ var base = self.attachAsset('joystickBase', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ var knob = self.attachAsset('joystickKnob', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ knob.x = 0;
+ knob.y = 0;
+ self.knob = knob;
+ self.baseRadius = base.width / 2;
+ self.knobRadius = knob.width / 2;
+ self.active = false;
+ self.value = {
+ x: 0,
+ y: 0
+ };
+ self.startX = 0;
+ self.startY = 0;
+ self.pointerId = null;
+ // Touch down on joystick
+ self.down = function (x, y, obj) {
+ self.active = true;
+ self.startX = x;
+ self.startY = y;
+ self.pointerId = obj.event && obj.event.pointerId !== undefined ? obj.event.pointerId : null;
+ self.move(x, y, obj);
+ };
+ // Touch move on joystick
+ self.move = function (x, y, obj) {
+ if (!self.active) return;
+ var dx = x - self.startX;
+ var dy = y - self.startY;
+ var dist = Math.sqrt(dx * dx + dy * dy);
+ var maxDist = self.baseRadius - self.knobRadius;
+ if (dist > maxDist) {
+ dx = dx * maxDist / dist;
+ dy = dy * maxDist / dist;
+ dist = maxDist;
+ }
+ self.knob.x = dx;
+ self.knob.y = dy;
+ self.value.x = dx / maxDist;
+ self.value.y = dy / maxDist;
+ };
+ // Touch up on joystick
+ self.up = function (x, y, obj) {
+ self.active = false;
+ self.knob.x = 0;
+ self.knob.y = 0;
+ self.value.x = 0;
+ self.value.y = 0;
+ self.pointerId = null;
+ };
+ return self;
+});
+// Obstacle class
+var Obstacle = Container.expand(function () {
+ var self = Container.call(this);
+ var obs = self.attachAsset('obstacle', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.width = obs.width;
+ self.height = obs.height;
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0x6ec6f2 // Light blue sky
+});
+
+/****
+* Game Code
+****/
+// On-screen joystick knob
+// On-screen joystick base
+// Enemy
+// Obstacle
+// Eagle (goal)
+// Falcon (player)
+// Level data: Each level defines obstacles, enemies, falcon start, eagle goal
+var levels = [
+// Level 1: Simple, no enemies
+{
+ falcon: {
+ x: 300,
+ y: 2300
+ },
+ eagle: {
+ x: 1800,
+ y: 400
+ },
+ obstacles: [{
+ x: 1024,
+ y: 1400,
+ w: 800,
+ h: 60
+ }, {
+ x: 1024,
+ y: 800,
+ w: 400,
+ h: 60
+ }],
+ enemies: []
+},
+// Level 2: Add one enemy
+{
+ falcon: {
+ x: 300,
+ y: 2300
+ },
+ eagle: {
+ x: 1800,
+ y: 400
+ },
+ obstacles: [{
+ x: 1024,
+ y: 1400,
+ w: 800,
+ h: 60
+ }, {
+ x: 1024,
+ y: 800,
+ w: 400,
+ h: 60
+ }],
+ enemies: [{
+ x: 600,
+ y: 1200,
+ minX: 400,
+ maxX: 1648
+ }]
+},
+// Level 3: More obstacles, two enemies
+{
+ falcon: {
+ x: 300,
+ y: 2300
+ },
+ eagle: {
+ x: 1800,
+ y: 400
+ },
+ obstacles: [{
+ x: 1024,
+ y: 1800,
+ w: 800,
+ h: 60
+ }, {
+ x: 1024,
+ y: 1400,
+ w: 600,
+ h: 60
+ }, {
+ x: 1024,
+ y: 1000,
+ w: 400,
+ h: 60
+ }],
+ enemies: [{
+ x: 400,
+ y: 1700,
+ minX: 300,
+ maxX: 1720
+ }, {
+ x: 1600,
+ y: 1200,
+ minX: 1200,
+ maxX: 2000
+ }]
+},
+// Level 4: Narrow path, one fast enemy
+{
+ falcon: {
+ x: 300,
+ y: 2300
+ },
+ eagle: {
+ x: 1800,
+ y: 400
+ },
+ obstacles: [{
+ x: 1024,
+ y: 2000,
+ w: 1200,
+ h: 60
+ }, {
+ x: 1024,
+ y: 1600,
+ w: 400,
+ h: 60
+ }, {
+ x: 1024,
+ y: 1200,
+ w: 1200,
+ h: 60
+ }, {
+ x: 1024,
+ y: 800,
+ w: 400,
+ h: 60
+ }],
+ enemies: [{
+ x: 1024,
+ y: 1600,
+ minX: 400,
+ maxX: 1648
+ }]
+},
+// Level 5: Zig-zag obstacles, two enemies
+{
+ falcon: {
+ x: 300,
+ y: 2300
+ },
+ eagle: {
+ x: 1800,
+ y: 400
+ },
+ obstacles: [{
+ x: 600,
+ y: 2000,
+ w: 600,
+ h: 60
+ }, {
+ x: 1448,
+ y: 1600,
+ w: 600,
+ h: 60
+ }, {
+ x: 600,
+ y: 1200,
+ w: 600,
+ h: 60
+ }, {
+ x: 1448,
+ y: 800,
+ w: 600,
+ h: 60
+ }],
+ enemies: [{
+ x: 1024,
+ y: 1800,
+ minX: 400,
+ maxX: 1648
+ }, {
+ x: 1024,
+ y: 1000,
+ minX: 400,
+ maxX: 1648
+ }]
+}
+// ... Add up to 19 levels as needed
+];
+// For MVP, repeat last level for levels 6-19
+while (levels.length < 19) {
+ var last = levels[levels.length - 1];
+ // Slightly increase enemy speed and add a new obstacle for each new level
+ var newLevel = {
+ falcon: {
+ x: last.falcon.x,
+ y: last.falcon.y
+ },
+ eagle: {
+ x: last.eagle.x,
+ y: last.eagle.y
+ },
+ obstacles: last.obstacles.slice(0),
+ enemies: []
+ };
+ for (var i = 0; i < last.enemies.length; i++) {
+ var e = last.enemies[i];
+ newLevel.enemies.push({
+ x: e.x,
+ y: e.y,
+ minX: e.minX,
+ maxX: e.maxX
+ });
+ }
+ // Add a new obstacle
+ newLevel.obstacles.push({
+ x: 400 + Math.random() * 1200,
+ y: 600 + Math.random() * 1600,
+ w: 400 + Math.random() * 400,
+ h: 60
+ });
+ // Add a new enemy every 2 levels
+ if (levels.length % 2 === 0) {
+ newLevel.enemies.push({
+ x: 400 + Math.random() * 1200,
+ y: 600 + Math.random() * 1600,
+ minX: 200,
+ maxX: 1848
+ });
+ }
+ levels.push(newLevel);
+}
+// Game state
+var currentLevel = 0;
+var falcon = null;
+var eagle = null;
+var obstacles = [];
+var enemies = [];
+var joystick = null;
+var levelText = null;
+var winText = null;
+var dragJoystick = false;
+// Score display (level number)
+levelText = new Text2('Level 1', {
+ size: 100,
+ fill: 0xFFFFFF
+});
+levelText.anchor.set(0.5, 0);
+LK.gui.top.addChild(levelText);
+// Helper: load a level
+function loadLevel(levelIdx) {
+ // Remove old objects
+ if (falcon) {
+ falcon.destroy();
+ falcon = null;
+ }
+ if (eagle) {
+ eagle.destroy();
+ eagle = null;
+ }
+ for (var i = 0; i < obstacles.length; i++) obstacles[i].destroy();
+ for (var i = 0; i < enemies.length; i++) enemies[i].destroy();
+ obstacles = [];
+ enemies = [];
+ // Clamp level
+ if (levelIdx < 0) levelIdx = 0;
+ if (levelIdx >= levels.length) levelIdx = levels.length - 1;
+ currentLevel = levelIdx;
+ var data = levels[levelIdx];
+ // Create falcon
+ falcon = new Falcon();
+ falcon.x = data.falcon.x;
+ falcon.y = data.falcon.y;
+ game.addChild(falcon);
+ // Create eagle
+ eagle = new Eagle();
+ eagle.x = data.eagle.x;
+ eagle.y = data.eagle.y;
+ game.addChild(eagle);
+ // Create obstacles
+ for (var i = 0; i < data.obstacles.length; i++) {
+ var o = data.obstacles[i];
+ var obs = new Obstacle();
+ obs.x = o.x;
+ obs.y = o.y;
+ // Scale obstacle to match w/h
+ obs.children[0].width = o.w;
+ obs.children[0].height = o.h;
+ obs.width = o.w;
+ obs.height = o.h;
+ obstacles.push(obs);
+ game.addChild(obs);
+ }
+ // Create enemies
+ for (var i = 0; i < data.enemies.length; i++) {
+ var e = data.enemies[i];
+ var enemy = new Enemy();
+ enemy.x = e.x;
+ enemy.y = e.y;
+ enemy.minX = e.minX;
+ enemy.maxX = e.maxX;
+ enemies.push(enemy);
+ game.addChild(enemy);
+ }
+ // Update level text
+ levelText.setText('Level ' + (levelIdx + 1));
+}
+// Helper: collision detection (circle-rectangle)
+function circleRectIntersect(cx, cy, cr, rx, ry, rw, rh) {
+ // Find closest point to circle within rectangle
+ var closestX = Math.max(rx - rw / 2, Math.min(cx, rx + rw / 2));
+ var closestY = Math.max(ry - rh / 2, Math.min(cy, ry + rh / 2));
+ var dx = cx - closestX;
+ var dy = cy - closestY;
+ return dx * dx + dy * dy < cr * cr;
+}
+// Helper: collision detection (circle-circle)
+function circleCircleIntersect(x1, y1, r1, x2, y2, r2) {
+ var dx = x1 - x2;
+ var dy = y1 - y2;
+ var dist = dx * dx + dy * dy;
+ var r = r1 + r2;
+ return dist < r * r;
+}
+// Helper: clamp position inside game area
+function clampPosition(obj) {
+ var r = obj.radius || 60;
+ if (obj.x < r) obj.x = r;
+ if (obj.x > 2048 - r) obj.x = 2048 - r;
+ if (obj.y < r) obj.y = r;
+ if (obj.y > 2732 - r) obj.y = 2732 - r;
+}
+// Show win text
+function showWin() {
+ LK.showYouWin();
+}
+// Show game over
+function showGameOver() {
+ LK.effects.flashScreen(0xff0000, 800);
+ LK.showGameOver();
+}
+// Joystick setup
+joystick = new Joystick();
+joystick.x = 300;
+joystick.y = 2732 - 300;
+LK.gui.bottomLeft.addChild(joystick);
+// Joystick event handling
+var joystickActive = false;
+var joystickPointerId = null;
+LK.gui.bottomLeft.down = function (x, y, obj) {
+ // Only activate if inside joystick area
+ var dx = x - joystick.x;
+ var dy = y - joystick.y;
+ var dist = Math.sqrt(dx * dx + dy * dy);
+ if (dist < joystick.baseRadius) {
+ joystick.down(x, y, obj);
+ joystickActive = true;
+ joystickPointerId = obj.event && obj.event.pointerId !== undefined ? obj.event.pointerId : null;
+ }
+};
+LK.gui.bottomLeft.move = function (x, y, obj) {
+ if (joystickActive) {
+ joystick.move(x, y, obj);
+ }
+};
+LK.gui.bottomLeft.up = function (x, y, obj) {
+ if (joystickActive) {
+ joystick.up(x, y, obj);
+ joystickActive = false;
+ joystickPointerId = null;
+ }
+};
+// Prevent game area from handling joystick touches
+game.down = function (x, y, obj) {
+ // No drag for falcon; only joystick controls
+};
+game.move = function (x, y, obj) {
+ // No drag for falcon; only joystick controls
+};
+game.up = function (x, y, obj) {
+ // No drag for falcon; only joystick controls
+};
+// Main game update loop
+game.update = function () {
+ // Move falcon by joystick
+ if (falcon && joystick) {
+ var jx = joystick.value.x;
+ var jy = joystick.value.y;
+ var speed = falcon.maxSpeed;
+ falcon.vx = jx * speed;
+ falcon.vy = jy * speed;
+ falcon.update();
+ clampPosition(falcon);
+ }
+ // Move enemies
+ for (var i = 0; i < enemies.length; i++) {
+ enemies[i].update();
+ }
+ // Check falcon-obstacle collision
+ for (var i = 0; i < obstacles.length; i++) {
+ var obs = obstacles[i];
+ if (circleRectIntersect(falcon.x, falcon.y, falcon.radius, obs.x, obs.y, obs.width, obs.height)) {
+ // Push falcon out of obstacle
+ // Find minimal direction to push out
+ var dx = falcon.x - obs.x;
+ var dy = falcon.y - obs.y;
+ var px = 0,
+ py = 0;
+ if (Math.abs(dx) > Math.abs(dy)) {
+ px = dx > 0 ? obs.x + obs.width / 2 + falcon.radius : obs.x - obs.width / 2 - falcon.radius;
+ falcon.x = px;
+ } else {
+ py = dy > 0 ? obs.y + obs.height / 2 + falcon.radius : obs.y - obs.height / 2 - falcon.radius;
+ falcon.y = py;
+ }
+ clampPosition(falcon);
+ }
+ }
+ // Check falcon-enemy collision
+ for (var i = 0; i < enemies.length; i++) {
+ var enemy = enemies[i];
+ if (circleCircleIntersect(falcon.x, falcon.y, falcon.radius, enemy.x, enemy.y, enemy.radius)) {
+ showGameOver();
+ return;
+ }
+ }
+ // Check falcon-eagle collision (win)
+ if (circleCircleIntersect(falcon.x, falcon.y, falcon.radius, eagle.x, eagle.y, eagle.radius)) {
+ // Next level or win
+ if (currentLevel < levels.length - 1) {
+ // Flash green, load next level after short delay
+ LK.effects.flashScreen(0x00ff00, 400);
+ var nextLevel = currentLevel + 1;
+ LK.setTimeout(function () {
+ loadLevel(nextLevel);
+ }, 600);
+ } else {
+ // All levels complete
+ showWin();
+ }
+ }
+};
+// Start first level
+loadLevel(0);
\ No newline at end of file