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