/****
* Classes
****/
// BigMosquito class: represents a large mosquito
var BigMosquito = Container.expand(function () {
var self = Container.call(this);
// If this is the special big bee (arı), use blue box asset, else use mosquito
var mosquitoGfx;
if (self.isBigBee) {
mosquitoGfx = self.attachAsset('bigbee', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1,
scaleY: 1
});
} else {
mosquitoGfx = self.attachAsset('mosquito', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.2,
scaleY: 2.2
});
}
// Big mosquito speed (slower for regular, faster for big bee)
if (self.isBigBee) {
self.speed = 8 + Math.random() * 4; // 8-12 px/tick for big bee (arı)
} else {
self.speed = 4 + Math.random() * 2; // 4-6 px/tick for regular big mosquito
}
// Direction in radians (random)
self.direction = Math.random() * Math.PI * 2;
self.changeDirTimer = 40 + Math.floor(Math.random() * 60);
self.alive = true;
// Big mosquito dies in 1 hit (default)
self.update = function () {
// If racket exists, home in on racket
if (typeof racket !== "undefined" && racket !== null && racket.x !== undefined && racket.y !== undefined) {
var dx = racket.x - self.x;
var dy = racket.y - self.y;
var angleToRacket = Math.atan2(dy, dx);
// Smoothly turn toward racket
var angleDiff = angleToRacket - self.direction;
// Normalize angleDiff to [-PI, PI]
while (angleDiff > Math.PI) {
angleDiff -= 2 * Math.PI;
}
while (angleDiff < -Math.PI) {
angleDiff += 2 * Math.PI;
}
// Turn speed: bigger = more aggressive
var turnSpeed = 0.07;
if (Math.abs(angleDiff) < turnSpeed) {
self.direction = angleToRacket;
} else {
self.direction += turnSpeed * Math.sign(angleDiff);
}
}
self.x += Math.cos(self.direction) * self.speed;
self.y += Math.sin(self.direction) * self.speed;
var margin = mosquitoGfx.width / 2 + 10;
if (self.x < margin) {
self.x = margin;
self.direction = Math.PI - self.direction + (Math.random() - 0.5) * 0.5;
}
if (self.x > 2048 - margin) {
self.x = 2048 - margin;
self.direction = Math.PI - self.direction + (Math.random() - 0.5) * 0.5;
}
if (self.y < margin + 100) {
self.y = margin + 100;
self.direction = -self.direction + (Math.random() - 0.5) * 0.5;
}
if (self.y > 2732 - margin) {
self.y = 2732 - margin;
self.direction = -self.direction + (Math.random() - 0.5) * 0.5;
}
self.changeDirTimer--;
if (self.changeDirTimer <= 0) {
self.direction += (Math.random() - 0.5) * Math.PI / 1.5;
self.changeDirTimer = 40 + Math.floor(Math.random() * 60);
}
};
// When hit, play animation and destroy
self.squash = function (_onFinish) {
self.alive = false;
self.scaleX = 2.5;
self.scaleY = 0.7;
self.alpha = 0;
if (_onFinish) {
_onFinish();
}
};
return self;
});
//var tween = LK.import("@upit/tween.v1");
// Mosquito class: represents a single mosquito
var Mosquito = Container.expand(function () {
var self = Container.call(this);
// Attach mosquito asset (ellipse, small, dark color)
var mosquitoGfx = self.attachAsset('mosquito', {
anchorX: 0.5,
anchorY: 0.5
});
// Mosquito speed (pixels per tick)
self.speed = 6 + Math.random() * 4; // 6-10 px/tick
// Direction in radians (random)
self.direction = Math.random() * Math.PI * 2;
// Time until next direction change
self.changeDirTimer = 30 + Math.floor(Math.random() * 60);
// Mark as alive
self.alive = true;
// Update method: called every tick
self.update = function () {
// If racket exists and is close, move away from racket
if (typeof racket !== "undefined" && racket !== null && racket.x !== undefined && racket.y !== undefined) {
var dx = self.x - racket.x;
var dy = self.y - racket.y;
var dist = Math.sqrt(dx * dx + dy * dy);
var fleeRadius = 400; // px, how close before fleeing
if (dist < fleeRadius) {
// Move away from racket: set direction away, with some random jitter
var angleFromRacket = Math.atan2(dy, dx);
// Add a little randomness so they don't all flee in a straight line
self.direction = angleFromRacket + (Math.random() - 0.5) * 0.5;
// Optional: speed up a bit when fleeing
self.x += Math.cos(self.direction) * (self.speed + 2);
self.y += Math.sin(self.direction) * (self.speed + 2);
} else {
self.x += Math.cos(self.direction) * self.speed;
self.y += Math.sin(self.direction) * self.speed;
}
} else {
self.x += Math.cos(self.direction) * self.speed;
self.y += Math.sin(self.direction) * self.speed;
}
// Bounce off walls (game area: 0,0 to 2048,2732)
var margin = mosquitoGfx.width / 2 + 10;
if (self.x < margin) {
self.x = margin;
self.direction = Math.PI - self.direction + (Math.random() - 0.5) * 0.5;
}
if (self.x > 2048 - margin) {
self.x = 2048 - margin;
self.direction = Math.PI - self.direction + (Math.random() - 0.5) * 0.5;
}
if (self.y < margin + 100) {
// leave top 100px for menu
self.y = margin + 100;
self.direction = -self.direction + (Math.random() - 0.5) * 0.5;
}
if (self.y > 2732 - margin) {
self.y = 2732 - margin;
self.direction = -self.direction + (Math.random() - 0.5) * 0.5;
}
// Change direction randomly
self.changeDirTimer--;
if (self.changeDirTimer <= 0) {
self.direction += (Math.random() - 0.5) * Math.PI / 1.5;
self.changeDirTimer = 30 + Math.floor(Math.random() * 60);
}
};
// When hit, play animation and destroy
self.squash = function (_onFinish) {
self.alive = false;
// Instantly squash and fade out (no tween)
self.scaleX = 1.7;
self.scaleY = 0.5;
self.alpha = 0;
if (_onFinish) {
_onFinish();
}
};
return self;
});
// Racket class: represents the player's racket
var Racket = Container.expand(function () {
var self = Container.call(this);
// Attach racket asset (rectangle, bright color)
var racketGfx = self.attachAsset('racket', {
anchorX: 0.5,
anchorY: 0.5
});
// Optionally, add a little shadow for visibility
racketGfx.alpha = 0.95;
// Racket size for collision
self.radius = racketGfx.width * 0.5;
// For touch feedback
self.flash = function () {
// Instantly flash racket (no tween)
racketGfx.tint = 0xffff00;
LK.setTimeout(function () {
racketGfx.tint = 0xffffff;
}, 80);
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x888888 // Gray background
});
/****
* Game Code
****/
// --- Game Variables ---
// --- Game Variables ---
// --- Asset Initialization ---
var mosquitoes = [];
var racket = null;
var score = 0;
var scoreTxt = null;
// Player health (3 lives)
var playerHealth = 3;
var healthTxt = null;
// Timer removed: no time limit
var maxMosquitoes = 5; // Start value, will increase over time
var mosquitoRampTick = 0; // Track ticks for ramping up
// Removed mosquitoesEscaped and maxEscaped (kaçan sayısı) as requested
var gameActive = true;
var dragNode = null;
game.bigMosquitoSpawned = false;
// Track big mosquito approach timers
var bigMosquitoApproachTimers = [];
// --- UI Elements ---
// Skor text
scoreTxt = new Text2('0', {
size: 120,
fill: "#222"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Health text (hearts)
healthTxt = new Text2('❤❤❤', {
size: 100,
fill: "#c00"
});
// Anchor to center-top, so it aligns with score
healthTxt.anchor.set(0.5, 0);
// Position health exactly centered below score
healthTxt.x = LK.gui.top.width / 2;
healthTxt.y = scoreTxt.height + 10;
LK.gui.top.addChild(healthTxt);
function updateHealthUI() {
var hearts = "";
for (var i = 0; i < playerHealth; i++) {
hearts += "❤";
}
healthTxt.setText(hearts);
}
// --- Helper Functions ---
function spawnMosquito() {
if (!gameActive) {
return;
}
var m = new Mosquito();
// Random position, not too close to top (menu)
var margin = 80;
m.x = margin + Math.random() * (2048 - 2 * margin);
m.y = 150 + Math.random() * (2732 - 250);
mosquitoes.push(m);
game.addChild(m);
}
function updateScore() {
scoreTxt.setText(score);
}
// updateTimer removed: no timer to update
// Removed updateMissed function (kaçan sayısı)
function endGame(win) {
gameActive = false;
// Show win or game over
if (win) {
LK.showYouWin();
} else {
LK.showGameOver();
}
}
// --- Racket Setup ---
racket = new Racket();
game.addChild(racket);
// Start racket in center, lower half
racket.x = 2048 / 2;
racket.y = 2732 * 0.7;
// --- Touch/Drag Controls ---
game.down = function (x, y, obj) {
// Don't allow drag in top left 100x100
if (x < 100 && y < 100) {
return;
}
dragNode = racket;
// Move racket instantly to touch
racket.x = x;
racket.y = y;
};
game.move = function (x, y, obj) {
if (!gameActive) {
return;
}
if (dragNode) {
// Clamp racket inside game area (leave top 100px)
var rw = racket.width * 0.5;
var rh = racket.height * 0.5;
var nx = Math.max(rw, Math.min(2048 - rw, x));
var ny = Math.max(100 + rh, Math.min(2732 - rh, y));
racket.x = nx;
racket.y = ny;
}
};
game.up = function (x, y, obj) {
dragNode = null;
};
// --- Main Game Loop ---
game.update = function () {
if (!gameActive) {
return;
}
// Update mosquitoes
for (var i = mosquitoes.length - 1; i >= 0; i--) {
var m = mosquitoes[i];
if (!m.alive) {
continue;
}
m.update();
// Check collision with racket
var dx = m.x - racket.x;
var dy = m.y - racket.y;
var dist = Math.sqrt(dx * dx + dy * dy);
var hitRadius = m.width * 0.5 + racket.width * 0.5 * 0.7;
// --- Big Mosquito Approach Logic ---
if (m instanceof BigMosquito) {
// Track last and current approach state
if (typeof m.lastApproaching === "undefined") {
m.lastApproaching = false;
}
if (typeof m.sticking === "undefined") {
m.sticking = false;
}
var approachRadius = m.width * 0.5 + racket.width * 0.5 * 1.1; // slightly larger than hit
var isApproaching = dist < approachRadius;
// If just started approaching, stick to racket and start timer
if (!m.lastApproaching && isApproaching) {
// Stick to racket
m.sticking = true;
m.stickOffsetX = m.x - racket.x;
m.stickOffsetY = m.y - racket.y;
// Start a 1s timer for this mosquito if not already started
if (!m._approachTimerActive) {
m._approachTimerActive = true;
m._approachTimerId = LK.setTimeout(function (mosq, idx) {
return function () {
// Only lose health if still alive, still close, and still sticking
if (mosq.alive && mosquitoes.indexOf(mosq) !== -1 && mosq.sticking) {
var dx2 = mosq.x - racket.x;
var dy2 = mosq.y - racket.y;
var dist2 = Math.sqrt(dx2 * dx2 + dy2 * dy2);
if (dist2 < approachRadius) {
playerHealth -= 1;
updateHealthUI();
racket.flash();
if (playerHealth <= 0) {
endGame(false);
return;
}
}
}
mosq._approachTimerActive = false;
mosq._approachTimerId = null;
mosq.sticking = false;
};
}(m, i), 1000);
bigMosquitoApproachTimers.push(m._approachTimerId);
}
}
// If moved away, cancel timer if running and unstick
if (m.lastApproaching && !isApproaching) {
if (m._approachTimerActive && m._approachTimerId) {
LK.clearTimeout(m._approachTimerId);
m._approachTimerActive = false;
m._approachTimerId = null;
}
m.sticking = false;
}
// If sticking, follow racket
if (m.sticking) {
m.x = racket.x + (typeof m.stickOffsetX === "number" ? m.stickOffsetX : 0);
m.y = racket.y + (typeof m.stickOffsetY === "number" ? m.stickOffsetY : 0);
}
m.lastApproaching = isApproaching;
}
// --- End Big Mosquito Approach Logic ---
if (dist < hitRadius) {
// If big mosquito, destroy on first hit
if (m instanceof BigMosquito) {
// If this is the special big bee (arı) at score 50
if (m.isBigBee) {
// Remove the scheduled timeout to auto-remove the bee
if (m._removeTimeout) {
LK.clearTimeout(m._removeTimeout);
m._removeTimeout = null;
}
// Reduce player health by 5
playerHealth -= 5;
updateHealthUI();
racket.flash();
if (playerHealth <= 0) {
endGame(false);
return;
}
}
// Cancel any pending approach timer
if (m._approachTimerActive && m._approachTimerId) {
LK.clearTimeout(m._approachTimerId);
m._approachTimerActive = false;
m._approachTimerId = null;
}
// Cancel any pending approach timer and unstick
if (m._approachTimerActive && m._approachTimerId) {
LK.clearTimeout(m._approachTimerId);
m._approachTimerActive = false;
m._approachTimerId = null;
}
m.sticking = false;
racket.flash();
m.squash(function () {
m.destroy();
});
mosquitoes.splice(i, 1);
continue;
}
// Hit!
m.squash(function () {
m.destroy();
});
mosquitoes.splice(i, 1);
score += 1;
updateScore();
racket.flash();
// Spawn big bee (arı) every time score increases by 30 (i.e., at 30, 60, 90, ...)
if (score > 0 && score % 30 === 0) {
// Prevent multiple spawns for the same score
if (typeof game.lastBigBeeScore === "undefined" || game.lastBigBeeScore !== score) {
game.lastBigBeeScore = score;
var bigBee = new BigMosquito();
bigBee.isBigBee = true; // Mark as special bee BEFORE asset attach
// Re-attach blue box asset for big bee
if (typeof bigBee.children !== "undefined" && bigBee.children.length > 0) {
for (var i = bigBee.children.length - 1; i >= 0; i--) {
bigBee.removeChild(bigBee.children[i]);
}
}
bigBee.attachAsset('bigbee', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1,
scaleY: 1
});
// Random position, not too close to top (menu)
var margin = 120;
bigBee.x = margin + Math.random() * (2048 - 2 * margin);
bigBee.y = 200 + Math.random() * (2732 - 400);
mosquitoes.push(bigBee);
game.addChild(bigBee);
// Show info text for 5 seconds
if (typeof game.bigBeeInfoTxt !== "undefined" && game.bigBeeInfoTxt) {
LK.gui.top.removeChild(game.bigBeeInfoTxt);
game.bigBeeInfoTxt = null;
}
game.bigBeeInfoTxt = new Text2("The bee will disappear after 5 seconds", {
size: 50,
fill: 0x0055FF
});
// Center anchor both horizontally and vertically
game.bigBeeInfoTxt.anchor.set(0.5, 0.5);
// Pause the game when big bee appears
gameActive = false;
LK.setTimeout(function () {
// Center in the middle of the screen (LK.gui.top is overlay, so use its width/height)
game.bigBeeInfoTxt.x = LK.gui.top.width / 2 - 120;
game.bigBeeInfoTxt.y = LK.gui.top.height / 2;
// Ensure the text is fully visible and not clipped
// If the text is too wide or tall, adjust size or position to fit
// Defensive: get current size from .style or fallback to 50
var currentSize = game.bigBeeInfoTxt && game.bigBeeInfoTxt.style && typeof game.bigBeeInfoTxt.style.size === "number" ? game.bigBeeInfoTxt.style.size : 50;
if (game.bigBeeInfoTxt.width > LK.gui.top.width - 100) {
game.bigBeeInfoTxt.setStyle({
size: Math.floor(currentSize * (LK.gui.top.width - 100) / game.bigBeeInfoTxt.width)
});
game.bigBeeInfoTxt.x = LK.gui.top.width / 2 - 120;
}
if (game.bigBeeInfoTxt.height > LK.gui.top.height - 100) {
// Re-fetch current size in case it changed above
var currentSize2 = game.bigBeeInfoTxt && game.bigBeeInfoTxt.style && typeof game.bigBeeInfoTxt.style.size === "number" ? game.bigBeeInfoTxt.style.size : 50;
game.bigBeeInfoTxt.setStyle({
size: Math.floor(currentSize2 * (LK.gui.top.height - 100) / game.bigBeeInfoTxt.height)
});
game.bigBeeInfoTxt.y = LK.gui.top.height / 2;
}
// After resizing, re-center to ensure perfect centering
game.bigBeeInfoTxt.x = LK.gui.top.width / 2 - 120;
game.bigBeeInfoTxt.y = LK.gui.top.height / 2;
}, 0);
LK.gui.top.addChild(game.bigBeeInfoTxt);
// Remove the big bee after 5 seconds if still alive, and resume the game
bigBee._removeTimeout = LK.setTimeout(function () {
var idx = mosquitoes.indexOf(bigBee);
if (idx !== -1 && bigBee.alive) {
bigBee.squash(function () {
bigBee.destroy();
});
mosquitoes.splice(idx, 1);
}
// Remove info text
if (typeof game.bigBeeInfoTxt !== "undefined" && game.bigBeeInfoTxt) {
LK.gui.top.removeChild(game.bigBeeInfoTxt);
game.bigBeeInfoTxt = null;
}
// Resume the game after big bee disappears
gameActive = true;
}, 5000);
}
}
// For other multiples of 5 (except 10), spawn big mosquito as before
if (score > 0 && score % 5 === 0 && score !== 10) {
var bigM = new BigMosquito();
// Random position, not too close to top (menu)
var margin = 120;
bigM.x = margin + Math.random() * (2048 - 2 * margin);
bigM.y = 200 + Math.random() * (2732 - 400);
mosquitoes.push(bigM);
game.addChild(bigM);
}
// Show shop at score 35
// Win condition
if (score >= 10000000000000000000000000000000000000000000000000000000) {
endGame(true);
return;
}
continue;
}
// Removed mosquito escape logic: mosquitoes no longer get destroyed at the edge
}
// End game if there are more than 20 mosquitoes on screen
if (mosquitoes.length > 20 && gameActive) {
endGame(false);
return;
}
// Gradually increase maxMosquitoes every 300 ticks (about every 5 seconds)
mosquitoRampTick = typeof mosquitoRampTick === "number" ? mosquitoRampTick + 1 : 1;
if (mosquitoRampTick % 300 === 0 && maxMosquitoes < 20) {
maxMosquitoes += 1;
}
// Spawn exactly 2 mosquitoes every 1 second using a timer
if (typeof mosquitoSpawnTimer === "undefined") {
var mosquitoSpawnTimer = LK.setInterval(function () {
if (!gameActive) {
return;
}
// Always spawn 2 mosquitoes every second, regardless of current count (unless at or above maxMosquitoes)
var canSpawn = Math.max(0, maxMosquitoes - mosquitoes.length);
var toSpawn = Math.min(2, canSpawn);
for (var i = 0; i < toSpawn; i++) {
spawnMosquito();
}
}, 1000);
}
};
// Timer removed: no time-based lose condition
// --- Game Start ---
score = 0;
updateScore();
playerHealth = 3;
if (typeof updateHealthUI === "function") {
updateHealthUI();
}
for (var i = 0; i < maxMosquitoes; i++) {
spawnMosquito();
} /****
* Classes
****/
// BigMosquito class: represents a large mosquito
var BigMosquito = Container.expand(function () {
var self = Container.call(this);
// If this is the special big bee (arı), use blue box asset, else use mosquito
var mosquitoGfx;
if (self.isBigBee) {
mosquitoGfx = self.attachAsset('bigbee', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1,
scaleY: 1
});
} else {
mosquitoGfx = self.attachAsset('mosquito', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.2,
scaleY: 2.2
});
}
// Big mosquito speed (slower for regular, faster for big bee)
if (self.isBigBee) {
self.speed = 8 + Math.random() * 4; // 8-12 px/tick for big bee (arı)
} else {
self.speed = 4 + Math.random() * 2; // 4-6 px/tick for regular big mosquito
}
// Direction in radians (random)
self.direction = Math.random() * Math.PI * 2;
self.changeDirTimer = 40 + Math.floor(Math.random() * 60);
self.alive = true;
// Big mosquito dies in 1 hit (default)
self.update = function () {
// If racket exists, home in on racket
if (typeof racket !== "undefined" && racket !== null && racket.x !== undefined && racket.y !== undefined) {
var dx = racket.x - self.x;
var dy = racket.y - self.y;
var angleToRacket = Math.atan2(dy, dx);
// Smoothly turn toward racket
var angleDiff = angleToRacket - self.direction;
// Normalize angleDiff to [-PI, PI]
while (angleDiff > Math.PI) {
angleDiff -= 2 * Math.PI;
}
while (angleDiff < -Math.PI) {
angleDiff += 2 * Math.PI;
}
// Turn speed: bigger = more aggressive
var turnSpeed = 0.07;
if (Math.abs(angleDiff) < turnSpeed) {
self.direction = angleToRacket;
} else {
self.direction += turnSpeed * Math.sign(angleDiff);
}
}
self.x += Math.cos(self.direction) * self.speed;
self.y += Math.sin(self.direction) * self.speed;
var margin = mosquitoGfx.width / 2 + 10;
if (self.x < margin) {
self.x = margin;
self.direction = Math.PI - self.direction + (Math.random() - 0.5) * 0.5;
}
if (self.x > 2048 - margin) {
self.x = 2048 - margin;
self.direction = Math.PI - self.direction + (Math.random() - 0.5) * 0.5;
}
if (self.y < margin + 100) {
self.y = margin + 100;
self.direction = -self.direction + (Math.random() - 0.5) * 0.5;
}
if (self.y > 2732 - margin) {
self.y = 2732 - margin;
self.direction = -self.direction + (Math.random() - 0.5) * 0.5;
}
self.changeDirTimer--;
if (self.changeDirTimer <= 0) {
self.direction += (Math.random() - 0.5) * Math.PI / 1.5;
self.changeDirTimer = 40 + Math.floor(Math.random() * 60);
}
};
// When hit, play animation and destroy
self.squash = function (_onFinish) {
self.alive = false;
self.scaleX = 2.5;
self.scaleY = 0.7;
self.alpha = 0;
if (_onFinish) {
_onFinish();
}
};
return self;
});
//var tween = LK.import("@upit/tween.v1");
// Mosquito class: represents a single mosquito
var Mosquito = Container.expand(function () {
var self = Container.call(this);
// Attach mosquito asset (ellipse, small, dark color)
var mosquitoGfx = self.attachAsset('mosquito', {
anchorX: 0.5,
anchorY: 0.5
});
// Mosquito speed (pixels per tick)
self.speed = 6 + Math.random() * 4; // 6-10 px/tick
// Direction in radians (random)
self.direction = Math.random() * Math.PI * 2;
// Time until next direction change
self.changeDirTimer = 30 + Math.floor(Math.random() * 60);
// Mark as alive
self.alive = true;
// Update method: called every tick
self.update = function () {
// If racket exists and is close, move away from racket
if (typeof racket !== "undefined" && racket !== null && racket.x !== undefined && racket.y !== undefined) {
var dx = self.x - racket.x;
var dy = self.y - racket.y;
var dist = Math.sqrt(dx * dx + dy * dy);
var fleeRadius = 400; // px, how close before fleeing
if (dist < fleeRadius) {
// Move away from racket: set direction away, with some random jitter
var angleFromRacket = Math.atan2(dy, dx);
// Add a little randomness so they don't all flee in a straight line
self.direction = angleFromRacket + (Math.random() - 0.5) * 0.5;
// Optional: speed up a bit when fleeing
self.x += Math.cos(self.direction) * (self.speed + 2);
self.y += Math.sin(self.direction) * (self.speed + 2);
} else {
self.x += Math.cos(self.direction) * self.speed;
self.y += Math.sin(self.direction) * self.speed;
}
} else {
self.x += Math.cos(self.direction) * self.speed;
self.y += Math.sin(self.direction) * self.speed;
}
// Bounce off walls (game area: 0,0 to 2048,2732)
var margin = mosquitoGfx.width / 2 + 10;
if (self.x < margin) {
self.x = margin;
self.direction = Math.PI - self.direction + (Math.random() - 0.5) * 0.5;
}
if (self.x > 2048 - margin) {
self.x = 2048 - margin;
self.direction = Math.PI - self.direction + (Math.random() - 0.5) * 0.5;
}
if (self.y < margin + 100) {
// leave top 100px for menu
self.y = margin + 100;
self.direction = -self.direction + (Math.random() - 0.5) * 0.5;
}
if (self.y > 2732 - margin) {
self.y = 2732 - margin;
self.direction = -self.direction + (Math.random() - 0.5) * 0.5;
}
// Change direction randomly
self.changeDirTimer--;
if (self.changeDirTimer <= 0) {
self.direction += (Math.random() - 0.5) * Math.PI / 1.5;
self.changeDirTimer = 30 + Math.floor(Math.random() * 60);
}
};
// When hit, play animation and destroy
self.squash = function (_onFinish) {
self.alive = false;
// Instantly squash and fade out (no tween)
self.scaleX = 1.7;
self.scaleY = 0.5;
self.alpha = 0;
if (_onFinish) {
_onFinish();
}
};
return self;
});
// Racket class: represents the player's racket
var Racket = Container.expand(function () {
var self = Container.call(this);
// Attach racket asset (rectangle, bright color)
var racketGfx = self.attachAsset('racket', {
anchorX: 0.5,
anchorY: 0.5
});
// Optionally, add a little shadow for visibility
racketGfx.alpha = 0.95;
// Racket size for collision
self.radius = racketGfx.width * 0.5;
// For touch feedback
self.flash = function () {
// Instantly flash racket (no tween)
racketGfx.tint = 0xffff00;
LK.setTimeout(function () {
racketGfx.tint = 0xffffff;
}, 80);
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x888888 // Gray background
});
/****
* Game Code
****/
// --- Game Variables ---
// --- Game Variables ---
// --- Asset Initialization ---
var mosquitoes = [];
var racket = null;
var score = 0;
var scoreTxt = null;
// Player health (3 lives)
var playerHealth = 3;
var healthTxt = null;
// Timer removed: no time limit
var maxMosquitoes = 5; // Start value, will increase over time
var mosquitoRampTick = 0; // Track ticks for ramping up
// Removed mosquitoesEscaped and maxEscaped (kaçan sayısı) as requested
var gameActive = true;
var dragNode = null;
game.bigMosquitoSpawned = false;
// Track big mosquito approach timers
var bigMosquitoApproachTimers = [];
// --- UI Elements ---
// Skor text
scoreTxt = new Text2('0', {
size: 120,
fill: "#222"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Health text (hearts)
healthTxt = new Text2('❤❤❤', {
size: 100,
fill: "#c00"
});
// Anchor to center-top, so it aligns with score
healthTxt.anchor.set(0.5, 0);
// Position health exactly centered below score
healthTxt.x = LK.gui.top.width / 2;
healthTxt.y = scoreTxt.height + 10;
LK.gui.top.addChild(healthTxt);
function updateHealthUI() {
var hearts = "";
for (var i = 0; i < playerHealth; i++) {
hearts += "❤";
}
healthTxt.setText(hearts);
}
// --- Helper Functions ---
function spawnMosquito() {
if (!gameActive) {
return;
}
var m = new Mosquito();
// Random position, not too close to top (menu)
var margin = 80;
m.x = margin + Math.random() * (2048 - 2 * margin);
m.y = 150 + Math.random() * (2732 - 250);
mosquitoes.push(m);
game.addChild(m);
}
function updateScore() {
scoreTxt.setText(score);
}
// updateTimer removed: no timer to update
// Removed updateMissed function (kaçan sayısı)
function endGame(win) {
gameActive = false;
// Show win or game over
if (win) {
LK.showYouWin();
} else {
LK.showGameOver();
}
}
// --- Racket Setup ---
racket = new Racket();
game.addChild(racket);
// Start racket in center, lower half
racket.x = 2048 / 2;
racket.y = 2732 * 0.7;
// --- Touch/Drag Controls ---
game.down = function (x, y, obj) {
// Don't allow drag in top left 100x100
if (x < 100 && y < 100) {
return;
}
dragNode = racket;
// Move racket instantly to touch
racket.x = x;
racket.y = y;
};
game.move = function (x, y, obj) {
if (!gameActive) {
return;
}
if (dragNode) {
// Clamp racket inside game area (leave top 100px)
var rw = racket.width * 0.5;
var rh = racket.height * 0.5;
var nx = Math.max(rw, Math.min(2048 - rw, x));
var ny = Math.max(100 + rh, Math.min(2732 - rh, y));
racket.x = nx;
racket.y = ny;
}
};
game.up = function (x, y, obj) {
dragNode = null;
};
// --- Main Game Loop ---
game.update = function () {
if (!gameActive) {
return;
}
// Update mosquitoes
for (var i = mosquitoes.length - 1; i >= 0; i--) {
var m = mosquitoes[i];
if (!m.alive) {
continue;
}
m.update();
// Check collision with racket
var dx = m.x - racket.x;
var dy = m.y - racket.y;
var dist = Math.sqrt(dx * dx + dy * dy);
var hitRadius = m.width * 0.5 + racket.width * 0.5 * 0.7;
// --- Big Mosquito Approach Logic ---
if (m instanceof BigMosquito) {
// Track last and current approach state
if (typeof m.lastApproaching === "undefined") {
m.lastApproaching = false;
}
if (typeof m.sticking === "undefined") {
m.sticking = false;
}
var approachRadius = m.width * 0.5 + racket.width * 0.5 * 1.1; // slightly larger than hit
var isApproaching = dist < approachRadius;
// If just started approaching, stick to racket and start timer
if (!m.lastApproaching && isApproaching) {
// Stick to racket
m.sticking = true;
m.stickOffsetX = m.x - racket.x;
m.stickOffsetY = m.y - racket.y;
// Start a 1s timer for this mosquito if not already started
if (!m._approachTimerActive) {
m._approachTimerActive = true;
m._approachTimerId = LK.setTimeout(function (mosq, idx) {
return function () {
// Only lose health if still alive, still close, and still sticking
if (mosq.alive && mosquitoes.indexOf(mosq) !== -1 && mosq.sticking) {
var dx2 = mosq.x - racket.x;
var dy2 = mosq.y - racket.y;
var dist2 = Math.sqrt(dx2 * dx2 + dy2 * dy2);
if (dist2 < approachRadius) {
playerHealth -= 1;
updateHealthUI();
racket.flash();
if (playerHealth <= 0) {
endGame(false);
return;
}
}
}
mosq._approachTimerActive = false;
mosq._approachTimerId = null;
mosq.sticking = false;
};
}(m, i), 1000);
bigMosquitoApproachTimers.push(m._approachTimerId);
}
}
// If moved away, cancel timer if running and unstick
if (m.lastApproaching && !isApproaching) {
if (m._approachTimerActive && m._approachTimerId) {
LK.clearTimeout(m._approachTimerId);
m._approachTimerActive = false;
m._approachTimerId = null;
}
m.sticking = false;
}
// If sticking, follow racket
if (m.sticking) {
m.x = racket.x + (typeof m.stickOffsetX === "number" ? m.stickOffsetX : 0);
m.y = racket.y + (typeof m.stickOffsetY === "number" ? m.stickOffsetY : 0);
}
m.lastApproaching = isApproaching;
}
// --- End Big Mosquito Approach Logic ---
if (dist < hitRadius) {
// If big mosquito, destroy on first hit
if (m instanceof BigMosquito) {
// If this is the special big bee (arı) at score 50
if (m.isBigBee) {
// Remove the scheduled timeout to auto-remove the bee
if (m._removeTimeout) {
LK.clearTimeout(m._removeTimeout);
m._removeTimeout = null;
}
// Reduce player health by 5
playerHealth -= 5;
updateHealthUI();
racket.flash();
if (playerHealth <= 0) {
endGame(false);
return;
}
}
// Cancel any pending approach timer
if (m._approachTimerActive && m._approachTimerId) {
LK.clearTimeout(m._approachTimerId);
m._approachTimerActive = false;
m._approachTimerId = null;
}
// Cancel any pending approach timer and unstick
if (m._approachTimerActive && m._approachTimerId) {
LK.clearTimeout(m._approachTimerId);
m._approachTimerActive = false;
m._approachTimerId = null;
}
m.sticking = false;
racket.flash();
m.squash(function () {
m.destroy();
});
mosquitoes.splice(i, 1);
continue;
}
// Hit!
m.squash(function () {
m.destroy();
});
mosquitoes.splice(i, 1);
score += 1;
updateScore();
racket.flash();
// Spawn big bee (arı) every time score increases by 30 (i.e., at 30, 60, 90, ...)
if (score > 0 && score % 30 === 0) {
// Prevent multiple spawns for the same score
if (typeof game.lastBigBeeScore === "undefined" || game.lastBigBeeScore !== score) {
game.lastBigBeeScore = score;
var bigBee = new BigMosquito();
bigBee.isBigBee = true; // Mark as special bee BEFORE asset attach
// Re-attach blue box asset for big bee
if (typeof bigBee.children !== "undefined" && bigBee.children.length > 0) {
for (var i = bigBee.children.length - 1; i >= 0; i--) {
bigBee.removeChild(bigBee.children[i]);
}
}
bigBee.attachAsset('bigbee', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1,
scaleY: 1
});
// Random position, not too close to top (menu)
var margin = 120;
bigBee.x = margin + Math.random() * (2048 - 2 * margin);
bigBee.y = 200 + Math.random() * (2732 - 400);
mosquitoes.push(bigBee);
game.addChild(bigBee);
// Show info text for 5 seconds
if (typeof game.bigBeeInfoTxt !== "undefined" && game.bigBeeInfoTxt) {
LK.gui.top.removeChild(game.bigBeeInfoTxt);
game.bigBeeInfoTxt = null;
}
game.bigBeeInfoTxt = new Text2("The bee will disappear after 5 seconds", {
size: 50,
fill: 0x0055FF
});
// Center anchor both horizontally and vertically
game.bigBeeInfoTxt.anchor.set(0.5, 0.5);
// Pause the game when big bee appears
gameActive = false;
LK.setTimeout(function () {
// Center in the middle of the screen (LK.gui.top is overlay, so use its width/height)
game.bigBeeInfoTxt.x = LK.gui.top.width / 2 - 120;
game.bigBeeInfoTxt.y = LK.gui.top.height / 2;
// Ensure the text is fully visible and not clipped
// If the text is too wide or tall, adjust size or position to fit
// Defensive: get current size from .style or fallback to 50
var currentSize = game.bigBeeInfoTxt && game.bigBeeInfoTxt.style && typeof game.bigBeeInfoTxt.style.size === "number" ? game.bigBeeInfoTxt.style.size : 50;
if (game.bigBeeInfoTxt.width > LK.gui.top.width - 100) {
game.bigBeeInfoTxt.setStyle({
size: Math.floor(currentSize * (LK.gui.top.width - 100) / game.bigBeeInfoTxt.width)
});
game.bigBeeInfoTxt.x = LK.gui.top.width / 2 - 120;
}
if (game.bigBeeInfoTxt.height > LK.gui.top.height - 100) {
// Re-fetch current size in case it changed above
var currentSize2 = game.bigBeeInfoTxt && game.bigBeeInfoTxt.style && typeof game.bigBeeInfoTxt.style.size === "number" ? game.bigBeeInfoTxt.style.size : 50;
game.bigBeeInfoTxt.setStyle({
size: Math.floor(currentSize2 * (LK.gui.top.height - 100) / game.bigBeeInfoTxt.height)
});
game.bigBeeInfoTxt.y = LK.gui.top.height / 2;
}
// After resizing, re-center to ensure perfect centering
game.bigBeeInfoTxt.x = LK.gui.top.width / 2 - 120;
game.bigBeeInfoTxt.y = LK.gui.top.height / 2;
}, 0);
LK.gui.top.addChild(game.bigBeeInfoTxt);
// Remove the big bee after 5 seconds if still alive, and resume the game
bigBee._removeTimeout = LK.setTimeout(function () {
var idx = mosquitoes.indexOf(bigBee);
if (idx !== -1 && bigBee.alive) {
bigBee.squash(function () {
bigBee.destroy();
});
mosquitoes.splice(idx, 1);
}
// Remove info text
if (typeof game.bigBeeInfoTxt !== "undefined" && game.bigBeeInfoTxt) {
LK.gui.top.removeChild(game.bigBeeInfoTxt);
game.bigBeeInfoTxt = null;
}
// Resume the game after big bee disappears
gameActive = true;
}, 5000);
}
}
// For other multiples of 5 (except 10), spawn big mosquito as before
if (score > 0 && score % 5 === 0 && score !== 10) {
var bigM = new BigMosquito();
// Random position, not too close to top (menu)
var margin = 120;
bigM.x = margin + Math.random() * (2048 - 2 * margin);
bigM.y = 200 + Math.random() * (2732 - 400);
mosquitoes.push(bigM);
game.addChild(bigM);
}
// Show shop at score 35
// Win condition
if (score >= 10000000000000000000000000000000000000000000000000000000) {
endGame(true);
return;
}
continue;
}
// Removed mosquito escape logic: mosquitoes no longer get destroyed at the edge
}
// End game if there are more than 20 mosquitoes on screen
if (mosquitoes.length > 20 && gameActive) {
endGame(false);
return;
}
// Gradually increase maxMosquitoes every 300 ticks (about every 5 seconds)
mosquitoRampTick = typeof mosquitoRampTick === "number" ? mosquitoRampTick + 1 : 1;
if (mosquitoRampTick % 300 === 0 && maxMosquitoes < 20) {
maxMosquitoes += 1;
}
// Spawn exactly 2 mosquitoes every 1 second using a timer
if (typeof mosquitoSpawnTimer === "undefined") {
var mosquitoSpawnTimer = LK.setInterval(function () {
if (!gameActive) {
return;
}
// Always spawn 2 mosquitoes every second, regardless of current count (unless at or above maxMosquitoes)
var canSpawn = Math.max(0, maxMosquitoes - mosquitoes.length);
var toSpawn = Math.min(2, canSpawn);
for (var i = 0; i < toSpawn; i++) {
spawnMosquito();
}
}, 1000);
}
};
// Timer removed: no time-based lose condition
// --- Game Start ---
score = 0;
updateScore();
playerHealth = 3;
if (typeof updateHealthUI === "function") {
updateHealthUI();
}
for (var i = 0; i < maxMosquitoes; i++) {
spawnMosquito();
}
sivrisinek. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
racket sivriseinek için . No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
arı. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat