/**** * 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