/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var Fly = Container.expand(function (gridX, gridY) { var self = Container.call(this); self.gridX = gridX; self.gridY = gridY; self.lifespan = 5000; // 5 seconds self.timeAlive = 0; var flyGraphics = self.attachAsset('fly', { anchorX: 0.5, anchorY: 0.5 }); // Buzzing animation function buzzAnimation() { if (self.parent) { tween(flyGraphics, { rotation: Math.random() * 0.3 - 0.15 }, { duration: 100 + Math.random() * 200, onFinish: buzzAnimation }); } } buzzAnimation(); self.update = function () { self.timeAlive += 16.67; // ~60fps if (self.timeAlive > self.lifespan) { self.remove(); } // Fade out near end of life if (self.timeAlive > self.lifespan * 0.7) { var fadeAmount = 1 - (self.timeAlive - self.lifespan * 0.7) / (self.lifespan * 0.3); flyGraphics.alpha = Math.max(0.3, fadeAmount); } }; self.remove = function () { var tile = grid[self.gridX][self.gridY]; tile.hasFly = false; var index = flies.indexOf(self); if (index > -1) { flies.splice(index, 1); } self.destroy(); }; self["catch"] = function () { LK.setScore(LK.getScore() + 10); scoreTxt.setText(LK.getScore()); if (LK.getScore() === 20) { frog.evolveToAdult(); } // Track flies eaten as adult for flycatcher evolution - only if not already stone frog if (frog.isAdult && !frog.isStoneFrog && !frog.isFlycatcherFrog) { frog.fliesEatenAsAdult = (frog.fliesEatenAsAdult || 0) + 1; if (frog.fliesEatenAsAdult === 2) { frog.evolveToFlycatcherFrog(); } } // Track flies eaten as flycatcher for fly frog evolution if (frog.isFlycatcherFrog && !frog.isFlyFrog) { frog.fliesEatenAsFlycatcher = (frog.fliesEatenAsFlycatcher || 0) + 1; if (frog.fliesEatenAsFlycatcher === 5) { frog.evolveToFlyFrog(); } } LK.getSound('catchFly').play(); self.remove(); }; return self; }); var Frog = Container.expand(function () { var self = Container.call(this); self.gridX = 0; self.gridY = 0; self.isMoving = false; self.evolutionLevel = 1; self.isAdult = false; self.isStoneFrog = false; self.isFlycatcherFrog = false; self.isIronFrog = false; self.isFlyFrog = false; self.lizardsEaten = 0; self.fliesEatenAsAdult = 0; self.fliesEatenAsFlycatcher = 0; var frogGraphics = self.attachAsset('frog', { anchorX: 0.5, anchorY: 0.5 }); self.setGridPosition = function (gridX, gridY) { self.gridX = gridX; self.gridY = gridY; var worldPos = gridToWorld(gridX, gridY); self.x = worldPos.x; self.y = worldPos.y; }; self.moveToGrid = function (gridX, gridY, callback) { if (self.isMoving) return; self.isMoving = true; self.gridX = gridX; self.gridY = gridY; var worldPos = gridToWorld(gridX, gridY); // Animate hop tween(self, { y: worldPos.y - 60 }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { tween(self, { x: worldPos.x, y: worldPos.y }, { duration: 200, easing: tween.easeIn, onFinish: function onFinish() { self.isMoving = false; if (callback) callback(); } }); } }); LK.getSound('hop').play(); }; self.evolve = function () { self.evolutionLevel++; var newColor = [0x228b22, 0x32cd32, 0x7fff00, 0xadff2f, 0x9acd32][Math.min(self.evolutionLevel - 1, 4)]; frogGraphics.tint = newColor; // Scale animation for evolution tween(frogGraphics, { scaleX: 1.3, scaleY: 1.3 }, { duration: 300, onFinish: function onFinish() { tween(frogGraphics, { scaleX: 1, scaleY: 1 }, { duration: 300 }); } }); }; self.evolveToAdult = function () { if (self.isAdult) return; self.isAdult = true; self.evolutionLevel = 2; // Remove current frog graphics self.removeChild(frogGraphics); // Add adult frog graphics frogGraphics = self.attachAsset('adultFrog', { anchorX: 0.5, anchorY: 0.5 }); // Evolution animation with dramatic scale effect tween(frogGraphics, { scaleX: 1.5, scaleY: 1.5, tint: 0x228b22 }, { duration: 500, easing: tween.bounceOut, onFinish: function onFinish() { tween(frogGraphics, { scaleX: 1.2, scaleY: 1.2 }, { duration: 300, easing: tween.easeOut }); } }); }; self.evolveToStoneFrog = function () { if (self.isStoneFrog) return; self.isStoneFrog = true; self.evolutionLevel = 3; // Remove current frog graphics self.removeChild(frogGraphics); // Add stone frog graphics frogGraphics = self.attachAsset('stoneFrog', { anchorX: 0.5, anchorY: 0.5 }); // Stone evolution animation tween(frogGraphics, { scaleX: 1.8, scaleY: 1.8, tint: 0x696969 }, { duration: 800, easing: tween.bounceOut, onFinish: function onFinish() { tween(frogGraphics, { scaleX: 1.4, scaleY: 1.4 }, { duration: 400, easing: tween.easeOut }); } }); }; self.evolveToFlycatcherFrog = function () { if (self.isFlycatcherFrog) return; self.isFlycatcherFrog = true; self.evolutionLevel = 4; // Remove current frog graphics self.removeChild(frogGraphics); // Add flycatcher frog graphics frogGraphics = self.attachAsset('flycatcherFrog', { anchorX: 0.5, anchorY: 0.5 }); // Flycatcher evolution animation tween(frogGraphics, { scaleX: 2.0, scaleY: 2.0, tint: 0x32cd32 }, { duration: 1000, easing: tween.elasticOut, onFinish: function onFinish() { tween(frogGraphics, { scaleX: 1.6, scaleY: 1.6 }, { duration: 500, easing: tween.easeOut }); } }); }; self.evolveToIronFrog = function () { if (self.isIronFrog) return; self.isIronFrog = true; self.evolutionLevel = 5; // Remove current frog graphics self.removeChild(frogGraphics); // Add iron frog graphics frogGraphics = self.attachAsset('ironFrog', { anchorX: 0.5, anchorY: 0.5 }); // Iron evolution animation tween(frogGraphics, { scaleX: 2.2, scaleY: 2.2, tint: 0x708090 }, { duration: 1200, easing: tween.bounceOut, onFinish: function onFinish() { tween(frogGraphics, { scaleX: 1.8, scaleY: 1.8 }, { duration: 600, easing: tween.easeOut }); } }); }; self.evolveToFlyFrog = function () { if (self.isFlyFrog) return; self.isFlyFrog = true; self.evolutionLevel = 6; // Remove current frog graphics self.removeChild(frogGraphics); // Add fly frog graphics frogGraphics = self.attachAsset('flyFrog', { anchorX: 0.5, anchorY: 0.5 }); // Fly frog evolution animation tween(frogGraphics, { scaleX: 2.4, scaleY: 2.4, tint: 0x00ff00 }, { duration: 1500, easing: tween.elasticOut, onFinish: function onFinish() { tween(frogGraphics, { scaleX: 2.0, scaleY: 2.0 }, { duration: 750, easing: tween.easeOut }); } }); }; return self; }); var GridTile = Container.expand(function (gridX, gridY) { var self = Container.call(this); self.gridX = gridX; self.gridY = gridY; self.hasFly = false; self.hasLizard = false; self.isValidMove = false; var tileGraphics = self.attachAsset('gridTile', { anchorX: 0.5, anchorY: 0.5 }); var validMoveGraphics = self.attachAsset('validMove', { anchorX: 0.5, anchorY: 0.5, alpha: 0 }); self.showValidMove = function (show) { self.isValidMove = show; tween(validMoveGraphics, { alpha: show ? 0.5 : 0 }, { duration: 200 }); }; self.down = function (x, y, obj) { if (self.isValidMove && !frog.isMoving) { moveFrogTo(self.gridX, self.gridY); } }; return self; }); var Lizard = Container.expand(function (gridX, gridY) { var self = Container.call(this); self.gridX = gridX; self.gridY = gridY; self.lifespan = 8000; // 8 seconds self.timeAlive = 0; var lizardGraphics = self.attachAsset('lizard', { anchorX: 0.5, anchorY: 0.5 }); // Idle animation function idleAnimation() { if (self.parent) { tween(lizardGraphics, { scaleX: 0.9 + Math.random() * 0.2, scaleY: 0.9 + Math.random() * 0.2 }, { duration: 800 + Math.random() * 400, onFinish: idleAnimation }); } } idleAnimation(); self.update = function () { self.timeAlive += 16.67; // ~60fps if (self.timeAlive > self.lifespan) { self.remove(); } // Fade out near end of life if (self.timeAlive > self.lifespan * 0.8) { var fadeAmount = 1 - (self.timeAlive - self.lifespan * 0.8) / (self.lifespan * 0.2); lizardGraphics.alpha = Math.max(0.2, fadeAmount); } }; self.remove = function () { var tile = grid[self.gridX][self.gridY]; tile.hasLizard = false; var index = lizards.indexOf(self); if (index > -1) { lizards.splice(index, 1); } self.destroy(); }; self["catch"] = function () { frog.lizardsEaten = (frog.lizardsEaten || 0) + 1; LK.setScore(LK.getScore() + 5); scoreTxt.setText(LK.getScore()); // Check for stone frog evolution (2 lizards) - only if not already flycatcher frog if (frog.lizardsEaten === 2 && !frog.isStoneFrog && !frog.isFlycatcherFrog) { frog.evolveToStoneFrog(); } // Check for iron frog evolution (3 lizards total) - only if already stone frog if (frog.lizardsEaten === 3 && frog.isStoneFrog && !frog.isIronFrog) { frog.evolveToIronFrog(); } LK.getSound('catchFly').play(); self.remove(); }; return self; }); var Wave = Container.expand(function () { var self = Container.call(this); self.rings = []; self.maxRadius = 300; self.speed = 2; // Create multiple concentric circles for wave effect for (var i = 0; i < 3; i++) { var ring = LK.getAsset('wave_ring_' + i, { width: 20, height: 20, color: 0x87ceeb, shape: 'ellipse' }); ring.alpha = 0.3 - i * 0.1; ring.scaleX = 0.1; ring.scaleY = 0.1; self.rings.push(ring); self.addChild(ring); } self.update = function () { var allFinished = true; for (var i = 0; i < self.rings.length; i++) { var ring = self.rings[i]; if (ring.scaleX < self.maxRadius / 10) { ring.scaleX += self.speed * 0.01; ring.scaleY += self.speed * 0.01; ring.alpha *= 0.995; allFinished = false; } } if (allFinished || self.rings[0].alpha < 0.01) { self.remove(); } }; self.remove = function () { var index = waves.indexOf(self); if (index > -1) { waves.splice(index, 1); } self.destroy(); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x4169e1 }); /**** * Game Code ****/ var GRID_SIZE = 200; var GRID_WIDTH = 10; var GRID_HEIGHT = 12; var GRID_OFFSET_X = (2048 - GRID_WIDTH * GRID_SIZE) / 2; var GRID_OFFSET_Y = 300; var grid = []; var frog; var flies = []; var lizards = []; var flySpawnTimer = 0; var flySpawnInterval = 3000; // 3 seconds initially var lizardSpawnTimer = 0; var lizardSpawnInterval = 6000; // 6 seconds initially var waves = []; var waveTimer = 0; var waveInterval = 2000; // Create waves every 2 seconds // Create score display var scoreTxt = new Text2('0', { size: 80, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // Helper functions function gridToWorld(gridX, gridY) { return { x: GRID_OFFSET_X + gridX * GRID_SIZE + GRID_SIZE / 2, y: GRID_OFFSET_Y + gridY * GRID_SIZE + GRID_SIZE / 2 }; } function isAdjacent(x1, y1, x2, y2) { var dx = Math.abs(x1 - x2); var dy = Math.abs(y1 - y2); var maxDistance = 1; if (frog.isAdult) maxDistance = 2; if (frog.isIronFrog || frog.isFlyFrog) maxDistance = 3; return dx <= maxDistance && dy <= maxDistance && !(dx === 0 && dy === 0); } function clearValidMoves() { for (var x = 0; x < GRID_WIDTH; x++) { for (var y = 0; y < GRID_HEIGHT; y++) { grid[x][y].showValidMove(false); } } } function showValidMoves() { clearValidMoves(); for (var x = 0; x < GRID_WIDTH; x++) { for (var y = 0; y < GRID_HEIGHT; y++) { if (isAdjacent(frog.gridX, frog.gridY, x, y)) { grid[x][y].showValidMove(true); } } } } function moveFrogTo(gridX, gridY) { clearValidMoves(); frog.moveToGrid(gridX, gridY, function () { // Check if frog caught a fly var tile = grid[gridX][gridY]; if (tile.hasFly) { for (var i = 0; i < flies.length; i++) { if (flies[i].gridX === gridX && flies[i].gridY === gridY) { flies[i]["catch"](); break; } } } // Check if frog caught a lizard if (tile.hasLizard) { for (var i = 0; i < lizards.length; i++) { if (lizards[i].gridX === gridX && lizards[i].gridY === gridY) { lizards[i]["catch"](); break; } } } showValidMoves(); }); } function spawnFly() { var attempts = 0; var maxAttempts = 50; while (attempts < maxAttempts) { var x = Math.floor(Math.random() * GRID_WIDTH); var y = Math.floor(Math.random() * GRID_HEIGHT); if (!grid[x][y].hasFly && !(x === frog.gridX && y === frog.gridY)) { var fly = new Fly(x, y); var worldPos = gridToWorld(x, y); fly.x = worldPos.x; fly.y = worldPos.y - 20; // Hover above tile grid[x][y].hasFly = true; flies.push(fly); game.addChild(fly); break; } attempts++; } } function spawnLizard() { // Only spawn lizards if frog is adult if (!frog.isAdult) return; var attempts = 0; var maxAttempts = 50; while (attempts < maxAttempts) { var x = Math.floor(Math.random() * GRID_WIDTH); var y = Math.floor(Math.random() * GRID_HEIGHT); if (!grid[x][y].hasLizard && !grid[x][y].hasFly && !(x === frog.gridX && y === frog.gridY)) { var lizard = new Lizard(x, y); var worldPos = gridToWorld(x, y); lizard.x = worldPos.x; lizard.y = worldPos.y - 10; // Slightly above tile grid[x][y].hasLizard = true; lizards.push(lizard); game.addChild(lizard); break; } attempts++; } } // Initialize grid for (var x = 0; x < GRID_WIDTH; x++) { grid[x] = []; for (var y = 0; y < GRID_HEIGHT; y++) { var tile = new GridTile(x, y); var worldPos = gridToWorld(x, y); tile.x = worldPos.x; tile.y = worldPos.y; grid[x][y] = tile; game.addChild(tile); } } // Initialize frog frog = new Frog(); frog.setGridPosition(GRID_WIDTH / 2, GRID_HEIGHT - 2); game.addChild(frog); // Show initial valid moves showValidMoves(); // Spawn first fly spawnFly(); game.update = function () { // Update flies for (var i = flies.length - 1; i >= 0; i--) { if (flies[i].update) { flies[i].update(); } } // Update waves for (var i = waves.length - 1; i >= 0; i--) { if (waves[i].update) { waves[i].update(); } } // Update lizards for (var i = lizards.length - 1; i >= 0; i--) { if (lizards[i].update) { lizards[i].update(); } } // Spawn waves periodically waveTimer += 16.67; if (waveTimer >= waveInterval) { waveTimer = 0; var wave = new Wave(); // Random position on screen wave.x = Math.random() * 2048; wave.y = Math.random() * 2732; waves.push(wave); game.addChild(wave); // Vary wave spawn timing waveInterval = 1500 + Math.random() * 2000; } // Spawn flies periodically flySpawnTimer += 16.67; if (flySpawnTimer >= flySpawnInterval) { flySpawnTimer = 0; spawnFly(); // Increase difficulty - spawn flies faster as score increases if (LK.getScore() > 0) { flySpawnInterval = Math.max(1500, 3000 - LK.getScore() / 10 * 50); } } // Spawn lizards periodically (only if frog is adult) if (frog.isAdult) { lizardSpawnTimer += 16.67; if (lizardSpawnTimer >= lizardSpawnInterval) { lizardSpawnTimer = 0; spawnLizard(); // Vary lizard spawn timing lizardSpawnInterval = 5000 + Math.random() * 3000; } } // Check win condition if (LK.getScore() >= 100) { LK.showYouWin(); } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Fly = Container.expand(function (gridX, gridY) {
var self = Container.call(this);
self.gridX = gridX;
self.gridY = gridY;
self.lifespan = 5000; // 5 seconds
self.timeAlive = 0;
var flyGraphics = self.attachAsset('fly', {
anchorX: 0.5,
anchorY: 0.5
});
// Buzzing animation
function buzzAnimation() {
if (self.parent) {
tween(flyGraphics, {
rotation: Math.random() * 0.3 - 0.15
}, {
duration: 100 + Math.random() * 200,
onFinish: buzzAnimation
});
}
}
buzzAnimation();
self.update = function () {
self.timeAlive += 16.67; // ~60fps
if (self.timeAlive > self.lifespan) {
self.remove();
}
// Fade out near end of life
if (self.timeAlive > self.lifespan * 0.7) {
var fadeAmount = 1 - (self.timeAlive - self.lifespan * 0.7) / (self.lifespan * 0.3);
flyGraphics.alpha = Math.max(0.3, fadeAmount);
}
};
self.remove = function () {
var tile = grid[self.gridX][self.gridY];
tile.hasFly = false;
var index = flies.indexOf(self);
if (index > -1) {
flies.splice(index, 1);
}
self.destroy();
};
self["catch"] = function () {
LK.setScore(LK.getScore() + 10);
scoreTxt.setText(LK.getScore());
if (LK.getScore() === 20) {
frog.evolveToAdult();
}
// Track flies eaten as adult for flycatcher evolution - only if not already stone frog
if (frog.isAdult && !frog.isStoneFrog && !frog.isFlycatcherFrog) {
frog.fliesEatenAsAdult = (frog.fliesEatenAsAdult || 0) + 1;
if (frog.fliesEatenAsAdult === 2) {
frog.evolveToFlycatcherFrog();
}
}
// Track flies eaten as flycatcher for fly frog evolution
if (frog.isFlycatcherFrog && !frog.isFlyFrog) {
frog.fliesEatenAsFlycatcher = (frog.fliesEatenAsFlycatcher || 0) + 1;
if (frog.fliesEatenAsFlycatcher === 5) {
frog.evolveToFlyFrog();
}
}
LK.getSound('catchFly').play();
self.remove();
};
return self;
});
var Frog = Container.expand(function () {
var self = Container.call(this);
self.gridX = 0;
self.gridY = 0;
self.isMoving = false;
self.evolutionLevel = 1;
self.isAdult = false;
self.isStoneFrog = false;
self.isFlycatcherFrog = false;
self.isIronFrog = false;
self.isFlyFrog = false;
self.lizardsEaten = 0;
self.fliesEatenAsAdult = 0;
self.fliesEatenAsFlycatcher = 0;
var frogGraphics = self.attachAsset('frog', {
anchorX: 0.5,
anchorY: 0.5
});
self.setGridPosition = function (gridX, gridY) {
self.gridX = gridX;
self.gridY = gridY;
var worldPos = gridToWorld(gridX, gridY);
self.x = worldPos.x;
self.y = worldPos.y;
};
self.moveToGrid = function (gridX, gridY, callback) {
if (self.isMoving) return;
self.isMoving = true;
self.gridX = gridX;
self.gridY = gridY;
var worldPos = gridToWorld(gridX, gridY);
// Animate hop
tween(self, {
y: worldPos.y - 60
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
x: worldPos.x,
y: worldPos.y
}, {
duration: 200,
easing: tween.easeIn,
onFinish: function onFinish() {
self.isMoving = false;
if (callback) callback();
}
});
}
});
LK.getSound('hop').play();
};
self.evolve = function () {
self.evolutionLevel++;
var newColor = [0x228b22, 0x32cd32, 0x7fff00, 0xadff2f, 0x9acd32][Math.min(self.evolutionLevel - 1, 4)];
frogGraphics.tint = newColor;
// Scale animation for evolution
tween(frogGraphics, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 300,
onFinish: function onFinish() {
tween(frogGraphics, {
scaleX: 1,
scaleY: 1
}, {
duration: 300
});
}
});
};
self.evolveToAdult = function () {
if (self.isAdult) return;
self.isAdult = true;
self.evolutionLevel = 2;
// Remove current frog graphics
self.removeChild(frogGraphics);
// Add adult frog graphics
frogGraphics = self.attachAsset('adultFrog', {
anchorX: 0.5,
anchorY: 0.5
});
// Evolution animation with dramatic scale effect
tween(frogGraphics, {
scaleX: 1.5,
scaleY: 1.5,
tint: 0x228b22
}, {
duration: 500,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(frogGraphics, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 300,
easing: tween.easeOut
});
}
});
};
self.evolveToStoneFrog = function () {
if (self.isStoneFrog) return;
self.isStoneFrog = true;
self.evolutionLevel = 3;
// Remove current frog graphics
self.removeChild(frogGraphics);
// Add stone frog graphics
frogGraphics = self.attachAsset('stoneFrog', {
anchorX: 0.5,
anchorY: 0.5
});
// Stone evolution animation
tween(frogGraphics, {
scaleX: 1.8,
scaleY: 1.8,
tint: 0x696969
}, {
duration: 800,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(frogGraphics, {
scaleX: 1.4,
scaleY: 1.4
}, {
duration: 400,
easing: tween.easeOut
});
}
});
};
self.evolveToFlycatcherFrog = function () {
if (self.isFlycatcherFrog) return;
self.isFlycatcherFrog = true;
self.evolutionLevel = 4;
// Remove current frog graphics
self.removeChild(frogGraphics);
// Add flycatcher frog graphics
frogGraphics = self.attachAsset('flycatcherFrog', {
anchorX: 0.5,
anchorY: 0.5
});
// Flycatcher evolution animation
tween(frogGraphics, {
scaleX: 2.0,
scaleY: 2.0,
tint: 0x32cd32
}, {
duration: 1000,
easing: tween.elasticOut,
onFinish: function onFinish() {
tween(frogGraphics, {
scaleX: 1.6,
scaleY: 1.6
}, {
duration: 500,
easing: tween.easeOut
});
}
});
};
self.evolveToIronFrog = function () {
if (self.isIronFrog) return;
self.isIronFrog = true;
self.evolutionLevel = 5;
// Remove current frog graphics
self.removeChild(frogGraphics);
// Add iron frog graphics
frogGraphics = self.attachAsset('ironFrog', {
anchorX: 0.5,
anchorY: 0.5
});
// Iron evolution animation
tween(frogGraphics, {
scaleX: 2.2,
scaleY: 2.2,
tint: 0x708090
}, {
duration: 1200,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(frogGraphics, {
scaleX: 1.8,
scaleY: 1.8
}, {
duration: 600,
easing: tween.easeOut
});
}
});
};
self.evolveToFlyFrog = function () {
if (self.isFlyFrog) return;
self.isFlyFrog = true;
self.evolutionLevel = 6;
// Remove current frog graphics
self.removeChild(frogGraphics);
// Add fly frog graphics
frogGraphics = self.attachAsset('flyFrog', {
anchorX: 0.5,
anchorY: 0.5
});
// Fly frog evolution animation
tween(frogGraphics, {
scaleX: 2.4,
scaleY: 2.4,
tint: 0x00ff00
}, {
duration: 1500,
easing: tween.elasticOut,
onFinish: function onFinish() {
tween(frogGraphics, {
scaleX: 2.0,
scaleY: 2.0
}, {
duration: 750,
easing: tween.easeOut
});
}
});
};
return self;
});
var GridTile = Container.expand(function (gridX, gridY) {
var self = Container.call(this);
self.gridX = gridX;
self.gridY = gridY;
self.hasFly = false;
self.hasLizard = false;
self.isValidMove = false;
var tileGraphics = self.attachAsset('gridTile', {
anchorX: 0.5,
anchorY: 0.5
});
var validMoveGraphics = self.attachAsset('validMove', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
});
self.showValidMove = function (show) {
self.isValidMove = show;
tween(validMoveGraphics, {
alpha: show ? 0.5 : 0
}, {
duration: 200
});
};
self.down = function (x, y, obj) {
if (self.isValidMove && !frog.isMoving) {
moveFrogTo(self.gridX, self.gridY);
}
};
return self;
});
var Lizard = Container.expand(function (gridX, gridY) {
var self = Container.call(this);
self.gridX = gridX;
self.gridY = gridY;
self.lifespan = 8000; // 8 seconds
self.timeAlive = 0;
var lizardGraphics = self.attachAsset('lizard', {
anchorX: 0.5,
anchorY: 0.5
});
// Idle animation
function idleAnimation() {
if (self.parent) {
tween(lizardGraphics, {
scaleX: 0.9 + Math.random() * 0.2,
scaleY: 0.9 + Math.random() * 0.2
}, {
duration: 800 + Math.random() * 400,
onFinish: idleAnimation
});
}
}
idleAnimation();
self.update = function () {
self.timeAlive += 16.67; // ~60fps
if (self.timeAlive > self.lifespan) {
self.remove();
}
// Fade out near end of life
if (self.timeAlive > self.lifespan * 0.8) {
var fadeAmount = 1 - (self.timeAlive - self.lifespan * 0.8) / (self.lifespan * 0.2);
lizardGraphics.alpha = Math.max(0.2, fadeAmount);
}
};
self.remove = function () {
var tile = grid[self.gridX][self.gridY];
tile.hasLizard = false;
var index = lizards.indexOf(self);
if (index > -1) {
lizards.splice(index, 1);
}
self.destroy();
};
self["catch"] = function () {
frog.lizardsEaten = (frog.lizardsEaten || 0) + 1;
LK.setScore(LK.getScore() + 5);
scoreTxt.setText(LK.getScore());
// Check for stone frog evolution (2 lizards) - only if not already flycatcher frog
if (frog.lizardsEaten === 2 && !frog.isStoneFrog && !frog.isFlycatcherFrog) {
frog.evolveToStoneFrog();
}
// Check for iron frog evolution (3 lizards total) - only if already stone frog
if (frog.lizardsEaten === 3 && frog.isStoneFrog && !frog.isIronFrog) {
frog.evolveToIronFrog();
}
LK.getSound('catchFly').play();
self.remove();
};
return self;
});
var Wave = Container.expand(function () {
var self = Container.call(this);
self.rings = [];
self.maxRadius = 300;
self.speed = 2;
// Create multiple concentric circles for wave effect
for (var i = 0; i < 3; i++) {
var ring = LK.getAsset('wave_ring_' + i, {
width: 20,
height: 20,
color: 0x87ceeb,
shape: 'ellipse'
});
ring.alpha = 0.3 - i * 0.1;
ring.scaleX = 0.1;
ring.scaleY = 0.1;
self.rings.push(ring);
self.addChild(ring);
}
self.update = function () {
var allFinished = true;
for (var i = 0; i < self.rings.length; i++) {
var ring = self.rings[i];
if (ring.scaleX < self.maxRadius / 10) {
ring.scaleX += self.speed * 0.01;
ring.scaleY += self.speed * 0.01;
ring.alpha *= 0.995;
allFinished = false;
}
}
if (allFinished || self.rings[0].alpha < 0.01) {
self.remove();
}
};
self.remove = function () {
var index = waves.indexOf(self);
if (index > -1) {
waves.splice(index, 1);
}
self.destroy();
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x4169e1
});
/****
* Game Code
****/
var GRID_SIZE = 200;
var GRID_WIDTH = 10;
var GRID_HEIGHT = 12;
var GRID_OFFSET_X = (2048 - GRID_WIDTH * GRID_SIZE) / 2;
var GRID_OFFSET_Y = 300;
var grid = [];
var frog;
var flies = [];
var lizards = [];
var flySpawnTimer = 0;
var flySpawnInterval = 3000; // 3 seconds initially
var lizardSpawnTimer = 0;
var lizardSpawnInterval = 6000; // 6 seconds initially
var waves = [];
var waveTimer = 0;
var waveInterval = 2000; // Create waves every 2 seconds
// Create score display
var scoreTxt = new Text2('0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Helper functions
function gridToWorld(gridX, gridY) {
return {
x: GRID_OFFSET_X + gridX * GRID_SIZE + GRID_SIZE / 2,
y: GRID_OFFSET_Y + gridY * GRID_SIZE + GRID_SIZE / 2
};
}
function isAdjacent(x1, y1, x2, y2) {
var dx = Math.abs(x1 - x2);
var dy = Math.abs(y1 - y2);
var maxDistance = 1;
if (frog.isAdult) maxDistance = 2;
if (frog.isIronFrog || frog.isFlyFrog) maxDistance = 3;
return dx <= maxDistance && dy <= maxDistance && !(dx === 0 && dy === 0);
}
function clearValidMoves() {
for (var x = 0; x < GRID_WIDTH; x++) {
for (var y = 0; y < GRID_HEIGHT; y++) {
grid[x][y].showValidMove(false);
}
}
}
function showValidMoves() {
clearValidMoves();
for (var x = 0; x < GRID_WIDTH; x++) {
for (var y = 0; y < GRID_HEIGHT; y++) {
if (isAdjacent(frog.gridX, frog.gridY, x, y)) {
grid[x][y].showValidMove(true);
}
}
}
}
function moveFrogTo(gridX, gridY) {
clearValidMoves();
frog.moveToGrid(gridX, gridY, function () {
// Check if frog caught a fly
var tile = grid[gridX][gridY];
if (tile.hasFly) {
for (var i = 0; i < flies.length; i++) {
if (flies[i].gridX === gridX && flies[i].gridY === gridY) {
flies[i]["catch"]();
break;
}
}
}
// Check if frog caught a lizard
if (tile.hasLizard) {
for (var i = 0; i < lizards.length; i++) {
if (lizards[i].gridX === gridX && lizards[i].gridY === gridY) {
lizards[i]["catch"]();
break;
}
}
}
showValidMoves();
});
}
function spawnFly() {
var attempts = 0;
var maxAttempts = 50;
while (attempts < maxAttempts) {
var x = Math.floor(Math.random() * GRID_WIDTH);
var y = Math.floor(Math.random() * GRID_HEIGHT);
if (!grid[x][y].hasFly && !(x === frog.gridX && y === frog.gridY)) {
var fly = new Fly(x, y);
var worldPos = gridToWorld(x, y);
fly.x = worldPos.x;
fly.y = worldPos.y - 20; // Hover above tile
grid[x][y].hasFly = true;
flies.push(fly);
game.addChild(fly);
break;
}
attempts++;
}
}
function spawnLizard() {
// Only spawn lizards if frog is adult
if (!frog.isAdult) return;
var attempts = 0;
var maxAttempts = 50;
while (attempts < maxAttempts) {
var x = Math.floor(Math.random() * GRID_WIDTH);
var y = Math.floor(Math.random() * GRID_HEIGHT);
if (!grid[x][y].hasLizard && !grid[x][y].hasFly && !(x === frog.gridX && y === frog.gridY)) {
var lizard = new Lizard(x, y);
var worldPos = gridToWorld(x, y);
lizard.x = worldPos.x;
lizard.y = worldPos.y - 10; // Slightly above tile
grid[x][y].hasLizard = true;
lizards.push(lizard);
game.addChild(lizard);
break;
}
attempts++;
}
}
// Initialize grid
for (var x = 0; x < GRID_WIDTH; x++) {
grid[x] = [];
for (var y = 0; y < GRID_HEIGHT; y++) {
var tile = new GridTile(x, y);
var worldPos = gridToWorld(x, y);
tile.x = worldPos.x;
tile.y = worldPos.y;
grid[x][y] = tile;
game.addChild(tile);
}
}
// Initialize frog
frog = new Frog();
frog.setGridPosition(GRID_WIDTH / 2, GRID_HEIGHT - 2);
game.addChild(frog);
// Show initial valid moves
showValidMoves();
// Spawn first fly
spawnFly();
game.update = function () {
// Update flies
for (var i = flies.length - 1; i >= 0; i--) {
if (flies[i].update) {
flies[i].update();
}
}
// Update waves
for (var i = waves.length - 1; i >= 0; i--) {
if (waves[i].update) {
waves[i].update();
}
}
// Update lizards
for (var i = lizards.length - 1; i >= 0; i--) {
if (lizards[i].update) {
lizards[i].update();
}
}
// Spawn waves periodically
waveTimer += 16.67;
if (waveTimer >= waveInterval) {
waveTimer = 0;
var wave = new Wave();
// Random position on screen
wave.x = Math.random() * 2048;
wave.y = Math.random() * 2732;
waves.push(wave);
game.addChild(wave);
// Vary wave spawn timing
waveInterval = 1500 + Math.random() * 2000;
}
// Spawn flies periodically
flySpawnTimer += 16.67;
if (flySpawnTimer >= flySpawnInterval) {
flySpawnTimer = 0;
spawnFly();
// Increase difficulty - spawn flies faster as score increases
if (LK.getScore() > 0) {
flySpawnInterval = Math.max(1500, 3000 - LK.getScore() / 10 * 50);
}
}
// Spawn lizards periodically (only if frog is adult)
if (frog.isAdult) {
lizardSpawnTimer += 16.67;
if (lizardSpawnTimer >= lizardSpawnInterval) {
lizardSpawnTimer = 0;
spawnLizard();
// Vary lizard spawn timing
lizardSpawnInterval = 5000 + Math.random() * 3000;
}
}
// Check win condition
if (LK.getScore() >= 100) {
LK.showYouWin();
}
};