/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var Cat = Container.expand(function () { var self = Container.call(this); var catGraphics = self.attachAsset('cat', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 6; self.baseSpeed = 6; self.targetX = 0; self.targetY = 0; self.adaptationLevel = 0; self.stuckCounter = 0; self.lastX = 0; self.lastY = 0; self.jumpTimer = 0; self.isJumping = false; self.jumpCooldown = 300; // 5 seconds at 60fps self.hasJumpedForObstacle = false; self.update = function () { // Update jump timer self.jumpTimer++; if (self.jumpTimer >= self.jumpCooldown) { self.jumpTimer = 0; } // Check if cat is stuck if (Math.abs(self.x - self.lastX) < 1 && Math.abs(self.y - self.lastY) < 1) { self.stuckCounter++; if (self.stuckCounter > 30) { // Try alternative path when stuck self.targetX = mouse.x + (Math.random() - 0.5) * 200; self.targetY = mouse.y + (Math.random() - 0.5) * 200; self.stuckCounter = 0; } } else { self.stuckCounter = 0; } // Update cat rotation based on movement direction var dx = self.x - self.lastX; var dy = self.y - self.lastY; if (Math.abs(dx) > 0.1 || Math.abs(dy) > 0.1) { var angle = Math.atan2(dy, dx); catGraphics.rotation = angle; } self.lastX = self.x; self.lastY = self.y; // AI pathfinding with adaptation var dx = self.targetX - self.x; var dy = self.targetY - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 5) { var moveX = dx / distance * self.speed; var moveY = dy / distance * self.speed; var newX = self.x + moveX; var newY = self.y + moveY; // Simple collision avoidance - unless jumping var canMove = true; var obstacleDetected = false; if (!self.isJumping) { for (var i = 0; i < obstacles.length; i++) { var obstacle = obstacles[i]; if (newX > obstacle.x - obstacle.width / 2 - 60 && newX < obstacle.x + obstacle.width / 2 + 60 && newY > obstacle.y - obstacle.height / 2 - 60 && newY < obstacle.y + obstacle.height / 2 + 60) { canMove = false; obstacleDetected = true; // Jump immediately when obstacle is detected, but only once if (!self.hasJumpedForObstacle) { self.performJump(); self.hasJumpedForObstacle = true; } canMove = true; break; } } // Reset jump flag when no obstacle is detected if (!obstacleDetected) { self.hasJumpedForObstacle = false; } } if (canMove) { self.x = newX; self.y = newY; } } }; self.performJump = function () { if (self.isJumping) return; self.isJumping = true; self.jumpTimer = 0; // Calculate jump destination - move towards mouse position over obstacles var dx = mouse.x - self.x; var dy = mouse.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); var jumpDistance = 300; // Distance to jump var jumpX = self.x + dx / distance * jumpDistance; var jumpY = self.y + dy / distance * jumpDistance; // Keep jump within bounds jumpX = Math.max(50, Math.min(1998, jumpX)); jumpY = Math.max(50, Math.min(2682, jumpY)); // Create jump animation - scale up and add slight tint tween(catGraphics, { scaleX: 1.3, scaleY: 1.3, tint: 0xFFFF99 }, { duration: 300, easing: tween.easeOut, onFinish: function onFinish() { // Scale back down after jump tween(catGraphics, { scaleX: 1, scaleY: 1, tint: 0xFFFFFF }, { duration: 200, easing: tween.easeIn, onFinish: function onFinish() { self.isJumping = false; } }); } }); // Actually move the cat over obstacles tween(self, { x: jumpX, y: jumpY }, { duration: 500, easing: tween.easeInOut }); }; self.adaptBehavior = function () { self.adaptationLevel++; self.speed = self.baseSpeed + self.adaptationLevel * 0.5; }; return self; }); var Cheese = Container.expand(function () { var self = Container.call(this); var cheeseGraphics = self.attachAsset('cheese', { anchorX: 0.5, anchorY: 0.5 }); self.collected = false; self.update = function () { if (!self.collected) { cheeseGraphics.rotation += 0.1; } }; return self; }); var ExitZone = Container.expand(function () { var self = Container.call(this); var exitGraphics = self.attachAsset('exitZone', { anchorX: 0.5, anchorY: 0.5, alpha: 0.6 }); self.update = function () { exitGraphics.alpha = 0.4 + Math.sin(LK.ticks * 0.1) * 0.2; }; return self; }); var Mouse = Container.expand(function () { var self = Container.call(this); var mouseGraphics = self.attachAsset('mouse', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 8; self.speedBoost = 1; self.boostTimer = 0; self.isStuck = false; self.stuckInTunnel = null; self.lastX = 0; self.lastY = 0; self.update = function () { if (self.boostTimer > 0) { self.boostTimer--; if (self.boostTimer === 0) { self.speedBoost = 1; if (!ghostMode) { mouseGraphics.tint = 0xFFFFFF; } } } // Handle ghost mode visuals if (ghostMode) { mouseGraphics.alpha = 0.5 + Math.sin(LK.ticks * 0.2) * 0.3; mouseGraphics.tint = 0x00FFFF; } else { mouseGraphics.alpha = 1; if (self.boostTimer === 0) { mouseGraphics.tint = 0xFFFFFF; } } // Update mouse rotation based on movement direction var dx = self.x - self.lastX; var dy = self.y - self.lastY; if (Math.abs(dx) > 0.1 || Math.abs(dy) > 0.1) { var angle = Math.atan2(dy, dx); mouseGraphics.rotation = angle; } self.lastX = self.x; self.lastY = self.y; }; self.applySpeedBoost = function () { self.speedBoost = 2; self.boostTimer = 180; // 3 seconds at 60fps if (!ghostMode) { mouseGraphics.tint = 0xFFFF00; } }; self.activateGhostMode = function () { ghostMode = true; ghostModeTimer = ghostModeDuration; mouseGraphics.tint = 0x00FFFF; mouseGraphics.alpha = 0.7; }; return self; }); var Obstacle = Container.expand(function () { var self = Container.call(this); var obstacleGraphics = self.attachAsset('obstacle', { anchorX: 0.5, anchorY: 0.5 }); return self; }); var SpecialCheese = Container.expand(function () { var self = Container.call(this); var cheeseGraphics = self.attachAsset('specialCheese', { anchorX: 0.5, anchorY: 0.5, tint: 0xFFD700 }); self.collected = false; self.update = function () { if (!self.collected) { cheeseGraphics.rotation += 0.2; // Pulse effect cheeseGraphics.scaleX = 1 + Math.sin(LK.ticks * 0.1) * 0.2; cheeseGraphics.scaleY = 1 + Math.sin(LK.ticks * 0.1) * 0.2; } }; return self; }); var Tunnel = Container.expand(function () { var self = Container.call(this); var tunnelGraphics = self.attachAsset('tunnel', { anchorX: 0.5, anchorY: 0.5 }); return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x2F4F2F }); /**** * Game Code ****/ // Add ground var ground = game.addChild(LK.getAsset('ground', { anchorX: 0, anchorY: 0, x: 0, y: 0 })); var mouse; var cat; var obstacles = []; var tunnels = []; var cheeses = []; var specialCheeses = []; var ghostMode = false; var ghostModeTimer = 0; var ghostModeDuration = 300; // 5 seconds at 60fps var exitZone; var level = 1; var gameStarted = false; var escapeTimer = 0; var maxEscapeTime = 1800; // 30 seconds at 60fps // UI Elements var levelTxt = new Text2('Level: 1', { size: 80, fill: 0xFFFFFF }); levelTxt.anchor.set(0.5, 0); LK.gui.top.addChild(levelTxt); var timerTxt = new Text2('Time: 30', { size: 60, fill: 0xFFFF00 }); timerTxt.anchor.set(1, 0); LK.gui.topRight.addChild(timerTxt); var instructionTxt = new Text2('Touch to move the mouse!\nAvoid the cat and reach the green exit!', { size: 50, fill: 0xFFFFFF }); instructionTxt.anchor.set(0.5, 0.5); instructionTxt.x = 1024; instructionTxt.y = 1366; game.addChild(instructionTxt); // Create mouse mouse = game.addChild(new Mouse()); mouse.x = 200; mouse.y = 2500; // Create cat cat = game.addChild(new Cat()); cat.x = 1800; cat.y = 2500; cat.targetX = mouse.x; cat.targetY = mouse.y; // Create level function createLevel() { // Clear existing level elements for (var i = obstacles.length - 1; i >= 0; i--) { obstacles[i].destroy(); obstacles.splice(i, 1); } for (var i = tunnels.length - 1; i >= 0; i--) { tunnels[i].destroy(); tunnels.splice(i, 1); } for (var i = cheeses.length - 1; i >= 0; i--) { cheeses[i].destroy(); cheeses.splice(i, 1); } for (var i = specialCheeses.length - 1; i >= 0; i--) { specialCheeses[i].destroy(); specialCheeses.splice(i, 1); } if (exitZone) { exitZone.destroy(); } // Create obstacles - more frequent but ensure path to exit var numObstacles = 8 + level * 3; // Increased from 5 + level * 2 for (var i = 0; i < numObstacles; i++) { var obstacle = game.addChild(new Obstacle()); var validPosition = false; var attempts = 0; // Try to find a valid position that doesn't block the path while (!validPosition && attempts < 50) { obstacle.x = Math.random() * 1800 + 200; obstacle.y = Math.random() * 2000 + 400; // Check if obstacle would be too close to mouse start position var distToMouse = Math.sqrt((obstacle.x - 200) * (obstacle.x - 200) + (obstacle.y - 2500) * (obstacle.y - 2500)); // Check if obstacle would be too close to exit zone (if it exists) var distToExit = exitZone ? Math.sqrt((obstacle.x - exitZone.x) * (obstacle.x - exitZone.x) + (obstacle.y - exitZone.y) * (obstacle.y - exitZone.y)) : 1000; // Ensure minimum distance from mouse start and exit if (distToMouse > 300 && distToExit > 250) { validPosition = true; } attempts++; } obstacles.push(obstacle); } // Create tunnels (mouse can pass through, cat cannot) var numTunnels = 3 + level; for (var i = 0; i < numTunnels; i++) { var tunnel = game.addChild(new Tunnel()); tunnel.x = Math.random() * 1800 + 200; tunnel.y = Math.random() * 2000 + 400; tunnels.push(tunnel); } // Create cheese power-ups var numCheeses = 2 + Math.floor(level / 2); for (var i = 0; i < numCheeses; i++) { var cheese = game.addChild(new Cheese()); cheese.x = Math.random() * 1600 + 300; cheese.y = Math.random() * 1800 + 600; cheeses.push(cheese); } // Create special cheese (very rare - 20% chance per level) if (Math.random() < 0.2) { var specialCheese = game.addChild(new SpecialCheese()); specialCheese.x = Math.random() * 1600 + 300; specialCheese.y = Math.random() * 1800 + 600; specialCheeses.push(specialCheese); } // Create exit zone exitZone = game.addChild(new ExitZone()); exitZone.x = Math.random() * 1000 + 500; exitZone.y = Math.random() * 800 + 200; // Reset positions mouse.x = 200; mouse.y = 2500; cat.x = 1800; cat.y = 2500; // Reset mouse stuck state mouse.isStuck = false; mouse.stuckInTunnel = null; // Reset timer escapeTimer = 0; // Update UI levelTxt.setText('Level: ' + level); } // Initialize first level createLevel(); // Game controls var targetX = mouse.x; var targetY = mouse.y; var isMoving = false; game.down = function (x, y, obj) { if (!gameStarted) { gameStarted = true; instructionTxt.visible = false; } targetX = x; targetY = y; isMoving = true; }; game.move = function (x, y, obj) { if (isMoving) { targetX = x; targetY = y; } }; game.up = function (x, y, obj) { isMoving = false; }; game.update = function () { if (!gameStarted) return; // Update ghost mode timer if (ghostMode) { ghostModeTimer--; if (ghostModeTimer <= 0) { ghostMode = false; mouse.attachAsset('mouse', { anchorX: 0.5, anchorY: 0.5 }).alpha = 1; } } // Update timer escapeTimer++; var timeLeft = Math.max(0, Math.ceil((maxEscapeTime - escapeTimer) / 60)); timerTxt.setText('Time: ' + timeLeft); // Check if time is up if (escapeTimer >= maxEscapeTime) { LK.getSound('caught').play(); LK.showGameOver(); return; } // Move mouse towards target with collision prevention if (isMoving && !mouse.isStuck) { var dx = targetX - mouse.x; var dy = targetY - mouse.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 5) { var moveSpeed = mouse.speed * mouse.speedBoost; var newX = mouse.x + dx / distance * moveSpeed; var newY = mouse.y + dy / distance * moveSpeed; // Check if new position would collide with obstacles (unless in ghost mode) var canMoveX = true; var canMoveY = true; if (!ghostMode) { for (var i = 0; i < obstacles.length; i++) { var obstacle = obstacles[i]; // Check X movement if (newX > obstacle.x - obstacle.width / 2 - 50 && newX < obstacle.x + obstacle.width / 2 + 50 && mouse.y > obstacle.y - obstacle.height / 2 - 50 && mouse.y < obstacle.y + obstacle.height / 2 + 50) { canMoveX = false; } // Check Y movement if (mouse.x > obstacle.x - obstacle.width / 2 - 50 && mouse.x < obstacle.x + obstacle.width / 2 + 50 && newY > obstacle.y - obstacle.height / 2 - 50 && newY < obstacle.y + obstacle.height / 2 + 50) { canMoveY = false; } } } // Apply movement only if no collision if (canMoveX) { mouse.x = newX; } if (canMoveY) { mouse.y = newY; } } } // Update cat AI target cat.targetX = mouse.x; cat.targetY = mouse.y; // Check mouse collision with obstacles - prevent movement into obstacles (unless in ghost mode) if (!ghostMode) { var newMouseX = mouse.x; var newMouseY = mouse.y; var collisionDetected = false; for (var i = 0; i < obstacles.length; i++) { var obstacle = obstacles[i]; // Check if mouse would collide with obstacle if (newMouseX > obstacle.x - obstacle.width / 2 - 50 && newMouseX < obstacle.x + obstacle.width / 2 + 50 && newMouseY > obstacle.y - obstacle.height / 2 - 50 && newMouseY < obstacle.y + obstacle.height / 2 + 50) { collisionDetected = true; // Find the closest edge to push mouse away var leftDist = Math.abs(newMouseX - (obstacle.x - obstacle.width / 2 - 50)); var rightDist = Math.abs(newMouseX - (obstacle.x + obstacle.width / 2 + 50)); var topDist = Math.abs(newMouseY - (obstacle.y - obstacle.height / 2 - 50)); var bottomDist = Math.abs(newMouseY - (obstacle.y + obstacle.height / 2 + 50)); var minDist = Math.min(leftDist, rightDist, topDist, bottomDist); if (minDist === leftDist) { mouse.x = obstacle.x - obstacle.width / 2 - 50; } else if (minDist === rightDist) { mouse.x = obstacle.x + obstacle.width / 2 + 50; } else if (minDist === topDist) { mouse.y = obstacle.y - obstacle.height / 2 - 50; } else { mouse.y = obstacle.y + obstacle.height / 2 + 50; } break; } } } // Tunnels are mouse traps - if mouse enters, it gets stuck for (var i = 0; i < tunnels.length; i++) { var tunnel = tunnels[i]; // Use smaller hitbox for tunnel detection (50% of original size) var tunnelHitboxSize = 75; // Reduced from 150 to 75 if (mouse.x > tunnel.x - tunnelHitboxSize / 2 && mouse.x < tunnel.x + tunnelHitboxSize / 2 && mouse.y > tunnel.y - tunnelHitboxSize / 2 && mouse.y < tunnel.y + tunnelHitboxSize / 2 && !mouse.isStuck) { // Mouse gets stuck in tunnel mouse.isStuck = true; mouse.stuckInTunnel = tunnel; mouse.x = tunnel.x; mouse.y = tunnel.y; LK.effects.flashObject(mouse, 0xFF0000, 1000); break; } } // Cats can pass through tunnels freely (no collision detection) // Check cheese collection for (var i = cheeses.length - 1; i >= 0; i--) { var cheese = cheeses[i]; if (!cheese.collected && mouse.intersects(cheese)) { cheese.collected = true; cheese.visible = false; mouse.applySpeedBoost(); LK.getSound('collect').play(); LK.setScore(LK.getScore() + 10); cheeses.splice(i, 1); cheese.destroy(); } } // Check special cheese collection for (var i = specialCheeses.length - 1; i >= 0; i--) { var specialCheese = specialCheeses[i]; if (!specialCheese.collected && mouse.intersects(specialCheese)) { specialCheese.collected = true; specialCheese.visible = false; mouse.activateGhostMode(); LK.getSound('collect').play(); LK.setScore(LK.getScore() + 50); LK.effects.flashScreen(0x00FFFF, 500); specialCheeses.splice(i, 1); specialCheese.destroy(); } } // Check if mouse reached exit if (mouse.intersects(exitZone)) { LK.getSound('escape').play(); LK.setScore(LK.getScore() + 100 * level); level++; if (level > 10) { LK.showYouWin(); } else { cat.adaptBehavior(); createLevel(); } return; } // Check if cat caught mouse if (cat.intersects(mouse)) { LK.getSound('caught').play(); LK.effects.flashScreen(0xFF0000, 500); LK.showGameOver(); } // Keep entities within bounds mouse.x = Math.max(50, Math.min(1998, mouse.x)); mouse.y = Math.max(50, Math.min(2682, mouse.y)); cat.x = Math.max(50, Math.min(1998, cat.x)); cat.y = Math.max(50, Math.min(2682, cat.y)); };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Cat = Container.expand(function () {
var self = Container.call(this);
var catGraphics = self.attachAsset('cat', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 6;
self.baseSpeed = 6;
self.targetX = 0;
self.targetY = 0;
self.adaptationLevel = 0;
self.stuckCounter = 0;
self.lastX = 0;
self.lastY = 0;
self.jumpTimer = 0;
self.isJumping = false;
self.jumpCooldown = 300; // 5 seconds at 60fps
self.hasJumpedForObstacle = false;
self.update = function () {
// Update jump timer
self.jumpTimer++;
if (self.jumpTimer >= self.jumpCooldown) {
self.jumpTimer = 0;
}
// Check if cat is stuck
if (Math.abs(self.x - self.lastX) < 1 && Math.abs(self.y - self.lastY) < 1) {
self.stuckCounter++;
if (self.stuckCounter > 30) {
// Try alternative path when stuck
self.targetX = mouse.x + (Math.random() - 0.5) * 200;
self.targetY = mouse.y + (Math.random() - 0.5) * 200;
self.stuckCounter = 0;
}
} else {
self.stuckCounter = 0;
}
// Update cat rotation based on movement direction
var dx = self.x - self.lastX;
var dy = self.y - self.lastY;
if (Math.abs(dx) > 0.1 || Math.abs(dy) > 0.1) {
var angle = Math.atan2(dy, dx);
catGraphics.rotation = angle;
}
self.lastX = self.x;
self.lastY = self.y;
// AI pathfinding with adaptation
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 5) {
var moveX = dx / distance * self.speed;
var moveY = dy / distance * self.speed;
var newX = self.x + moveX;
var newY = self.y + moveY;
// Simple collision avoidance - unless jumping
var canMove = true;
var obstacleDetected = false;
if (!self.isJumping) {
for (var i = 0; i < obstacles.length; i++) {
var obstacle = obstacles[i];
if (newX > obstacle.x - obstacle.width / 2 - 60 && newX < obstacle.x + obstacle.width / 2 + 60 && newY > obstacle.y - obstacle.height / 2 - 60 && newY < obstacle.y + obstacle.height / 2 + 60) {
canMove = false;
obstacleDetected = true;
// Jump immediately when obstacle is detected, but only once
if (!self.hasJumpedForObstacle) {
self.performJump();
self.hasJumpedForObstacle = true;
}
canMove = true;
break;
}
}
// Reset jump flag when no obstacle is detected
if (!obstacleDetected) {
self.hasJumpedForObstacle = false;
}
}
if (canMove) {
self.x = newX;
self.y = newY;
}
}
};
self.performJump = function () {
if (self.isJumping) return;
self.isJumping = true;
self.jumpTimer = 0;
// Calculate jump destination - move towards mouse position over obstacles
var dx = mouse.x - self.x;
var dy = mouse.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
var jumpDistance = 300; // Distance to jump
var jumpX = self.x + dx / distance * jumpDistance;
var jumpY = self.y + dy / distance * jumpDistance;
// Keep jump within bounds
jumpX = Math.max(50, Math.min(1998, jumpX));
jumpY = Math.max(50, Math.min(2682, jumpY));
// Create jump animation - scale up and add slight tint
tween(catGraphics, {
scaleX: 1.3,
scaleY: 1.3,
tint: 0xFFFF99
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
// Scale back down after jump
tween(catGraphics, {
scaleX: 1,
scaleY: 1,
tint: 0xFFFFFF
}, {
duration: 200,
easing: tween.easeIn,
onFinish: function onFinish() {
self.isJumping = false;
}
});
}
});
// Actually move the cat over obstacles
tween(self, {
x: jumpX,
y: jumpY
}, {
duration: 500,
easing: tween.easeInOut
});
};
self.adaptBehavior = function () {
self.adaptationLevel++;
self.speed = self.baseSpeed + self.adaptationLevel * 0.5;
};
return self;
});
var Cheese = Container.expand(function () {
var self = Container.call(this);
var cheeseGraphics = self.attachAsset('cheese', {
anchorX: 0.5,
anchorY: 0.5
});
self.collected = false;
self.update = function () {
if (!self.collected) {
cheeseGraphics.rotation += 0.1;
}
};
return self;
});
var ExitZone = Container.expand(function () {
var self = Container.call(this);
var exitGraphics = self.attachAsset('exitZone', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.6
});
self.update = function () {
exitGraphics.alpha = 0.4 + Math.sin(LK.ticks * 0.1) * 0.2;
};
return self;
});
var Mouse = Container.expand(function () {
var self = Container.call(this);
var mouseGraphics = self.attachAsset('mouse', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
self.speedBoost = 1;
self.boostTimer = 0;
self.isStuck = false;
self.stuckInTunnel = null;
self.lastX = 0;
self.lastY = 0;
self.update = function () {
if (self.boostTimer > 0) {
self.boostTimer--;
if (self.boostTimer === 0) {
self.speedBoost = 1;
if (!ghostMode) {
mouseGraphics.tint = 0xFFFFFF;
}
}
}
// Handle ghost mode visuals
if (ghostMode) {
mouseGraphics.alpha = 0.5 + Math.sin(LK.ticks * 0.2) * 0.3;
mouseGraphics.tint = 0x00FFFF;
} else {
mouseGraphics.alpha = 1;
if (self.boostTimer === 0) {
mouseGraphics.tint = 0xFFFFFF;
}
}
// Update mouse rotation based on movement direction
var dx = self.x - self.lastX;
var dy = self.y - self.lastY;
if (Math.abs(dx) > 0.1 || Math.abs(dy) > 0.1) {
var angle = Math.atan2(dy, dx);
mouseGraphics.rotation = angle;
}
self.lastX = self.x;
self.lastY = self.y;
};
self.applySpeedBoost = function () {
self.speedBoost = 2;
self.boostTimer = 180; // 3 seconds at 60fps
if (!ghostMode) {
mouseGraphics.tint = 0xFFFF00;
}
};
self.activateGhostMode = function () {
ghostMode = true;
ghostModeTimer = ghostModeDuration;
mouseGraphics.tint = 0x00FFFF;
mouseGraphics.alpha = 0.7;
};
return self;
});
var Obstacle = Container.expand(function () {
var self = Container.call(this);
var obstacleGraphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
var SpecialCheese = Container.expand(function () {
var self = Container.call(this);
var cheeseGraphics = self.attachAsset('specialCheese', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFD700
});
self.collected = false;
self.update = function () {
if (!self.collected) {
cheeseGraphics.rotation += 0.2;
// Pulse effect
cheeseGraphics.scaleX = 1 + Math.sin(LK.ticks * 0.1) * 0.2;
cheeseGraphics.scaleY = 1 + Math.sin(LK.ticks * 0.1) * 0.2;
}
};
return self;
});
var Tunnel = Container.expand(function () {
var self = Container.call(this);
var tunnelGraphics = self.attachAsset('tunnel', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2F4F2F
});
/****
* Game Code
****/
// Add ground
var ground = game.addChild(LK.getAsset('ground', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
}));
var mouse;
var cat;
var obstacles = [];
var tunnels = [];
var cheeses = [];
var specialCheeses = [];
var ghostMode = false;
var ghostModeTimer = 0;
var ghostModeDuration = 300; // 5 seconds at 60fps
var exitZone;
var level = 1;
var gameStarted = false;
var escapeTimer = 0;
var maxEscapeTime = 1800; // 30 seconds at 60fps
// UI Elements
var levelTxt = new Text2('Level: 1', {
size: 80,
fill: 0xFFFFFF
});
levelTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(levelTxt);
var timerTxt = new Text2('Time: 30', {
size: 60,
fill: 0xFFFF00
});
timerTxt.anchor.set(1, 0);
LK.gui.topRight.addChild(timerTxt);
var instructionTxt = new Text2('Touch to move the mouse!\nAvoid the cat and reach the green exit!', {
size: 50,
fill: 0xFFFFFF
});
instructionTxt.anchor.set(0.5, 0.5);
instructionTxt.x = 1024;
instructionTxt.y = 1366;
game.addChild(instructionTxt);
// Create mouse
mouse = game.addChild(new Mouse());
mouse.x = 200;
mouse.y = 2500;
// Create cat
cat = game.addChild(new Cat());
cat.x = 1800;
cat.y = 2500;
cat.targetX = mouse.x;
cat.targetY = mouse.y;
// Create level
function createLevel() {
// Clear existing level elements
for (var i = obstacles.length - 1; i >= 0; i--) {
obstacles[i].destroy();
obstacles.splice(i, 1);
}
for (var i = tunnels.length - 1; i >= 0; i--) {
tunnels[i].destroy();
tunnels.splice(i, 1);
}
for (var i = cheeses.length - 1; i >= 0; i--) {
cheeses[i].destroy();
cheeses.splice(i, 1);
}
for (var i = specialCheeses.length - 1; i >= 0; i--) {
specialCheeses[i].destroy();
specialCheeses.splice(i, 1);
}
if (exitZone) {
exitZone.destroy();
}
// Create obstacles - more frequent but ensure path to exit
var numObstacles = 8 + level * 3; // Increased from 5 + level * 2
for (var i = 0; i < numObstacles; i++) {
var obstacle = game.addChild(new Obstacle());
var validPosition = false;
var attempts = 0;
// Try to find a valid position that doesn't block the path
while (!validPosition && attempts < 50) {
obstacle.x = Math.random() * 1800 + 200;
obstacle.y = Math.random() * 2000 + 400;
// Check if obstacle would be too close to mouse start position
var distToMouse = Math.sqrt((obstacle.x - 200) * (obstacle.x - 200) + (obstacle.y - 2500) * (obstacle.y - 2500));
// Check if obstacle would be too close to exit zone (if it exists)
var distToExit = exitZone ? Math.sqrt((obstacle.x - exitZone.x) * (obstacle.x - exitZone.x) + (obstacle.y - exitZone.y) * (obstacle.y - exitZone.y)) : 1000;
// Ensure minimum distance from mouse start and exit
if (distToMouse > 300 && distToExit > 250) {
validPosition = true;
}
attempts++;
}
obstacles.push(obstacle);
}
// Create tunnels (mouse can pass through, cat cannot)
var numTunnels = 3 + level;
for (var i = 0; i < numTunnels; i++) {
var tunnel = game.addChild(new Tunnel());
tunnel.x = Math.random() * 1800 + 200;
tunnel.y = Math.random() * 2000 + 400;
tunnels.push(tunnel);
}
// Create cheese power-ups
var numCheeses = 2 + Math.floor(level / 2);
for (var i = 0; i < numCheeses; i++) {
var cheese = game.addChild(new Cheese());
cheese.x = Math.random() * 1600 + 300;
cheese.y = Math.random() * 1800 + 600;
cheeses.push(cheese);
}
// Create special cheese (very rare - 20% chance per level)
if (Math.random() < 0.2) {
var specialCheese = game.addChild(new SpecialCheese());
specialCheese.x = Math.random() * 1600 + 300;
specialCheese.y = Math.random() * 1800 + 600;
specialCheeses.push(specialCheese);
}
// Create exit zone
exitZone = game.addChild(new ExitZone());
exitZone.x = Math.random() * 1000 + 500;
exitZone.y = Math.random() * 800 + 200;
// Reset positions
mouse.x = 200;
mouse.y = 2500;
cat.x = 1800;
cat.y = 2500;
// Reset mouse stuck state
mouse.isStuck = false;
mouse.stuckInTunnel = null;
// Reset timer
escapeTimer = 0;
// Update UI
levelTxt.setText('Level: ' + level);
}
// Initialize first level
createLevel();
// Game controls
var targetX = mouse.x;
var targetY = mouse.y;
var isMoving = false;
game.down = function (x, y, obj) {
if (!gameStarted) {
gameStarted = true;
instructionTxt.visible = false;
}
targetX = x;
targetY = y;
isMoving = true;
};
game.move = function (x, y, obj) {
if (isMoving) {
targetX = x;
targetY = y;
}
};
game.up = function (x, y, obj) {
isMoving = false;
};
game.update = function () {
if (!gameStarted) return;
// Update ghost mode timer
if (ghostMode) {
ghostModeTimer--;
if (ghostModeTimer <= 0) {
ghostMode = false;
mouse.attachAsset('mouse', {
anchorX: 0.5,
anchorY: 0.5
}).alpha = 1;
}
}
// Update timer
escapeTimer++;
var timeLeft = Math.max(0, Math.ceil((maxEscapeTime - escapeTimer) / 60));
timerTxt.setText('Time: ' + timeLeft);
// Check if time is up
if (escapeTimer >= maxEscapeTime) {
LK.getSound('caught').play();
LK.showGameOver();
return;
}
// Move mouse towards target with collision prevention
if (isMoving && !mouse.isStuck) {
var dx = targetX - mouse.x;
var dy = targetY - mouse.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 5) {
var moveSpeed = mouse.speed * mouse.speedBoost;
var newX = mouse.x + dx / distance * moveSpeed;
var newY = mouse.y + dy / distance * moveSpeed;
// Check if new position would collide with obstacles (unless in ghost mode)
var canMoveX = true;
var canMoveY = true;
if (!ghostMode) {
for (var i = 0; i < obstacles.length; i++) {
var obstacle = obstacles[i];
// Check X movement
if (newX > obstacle.x - obstacle.width / 2 - 50 && newX < obstacle.x + obstacle.width / 2 + 50 && mouse.y > obstacle.y - obstacle.height / 2 - 50 && mouse.y < obstacle.y + obstacle.height / 2 + 50) {
canMoveX = false;
}
// Check Y movement
if (mouse.x > obstacle.x - obstacle.width / 2 - 50 && mouse.x < obstacle.x + obstacle.width / 2 + 50 && newY > obstacle.y - obstacle.height / 2 - 50 && newY < obstacle.y + obstacle.height / 2 + 50) {
canMoveY = false;
}
}
}
// Apply movement only if no collision
if (canMoveX) {
mouse.x = newX;
}
if (canMoveY) {
mouse.y = newY;
}
}
}
// Update cat AI target
cat.targetX = mouse.x;
cat.targetY = mouse.y;
// Check mouse collision with obstacles - prevent movement into obstacles (unless in ghost mode)
if (!ghostMode) {
var newMouseX = mouse.x;
var newMouseY = mouse.y;
var collisionDetected = false;
for (var i = 0; i < obstacles.length; i++) {
var obstacle = obstacles[i];
// Check if mouse would collide with obstacle
if (newMouseX > obstacle.x - obstacle.width / 2 - 50 && newMouseX < obstacle.x + obstacle.width / 2 + 50 && newMouseY > obstacle.y - obstacle.height / 2 - 50 && newMouseY < obstacle.y + obstacle.height / 2 + 50) {
collisionDetected = true;
// Find the closest edge to push mouse away
var leftDist = Math.abs(newMouseX - (obstacle.x - obstacle.width / 2 - 50));
var rightDist = Math.abs(newMouseX - (obstacle.x + obstacle.width / 2 + 50));
var topDist = Math.abs(newMouseY - (obstacle.y - obstacle.height / 2 - 50));
var bottomDist = Math.abs(newMouseY - (obstacle.y + obstacle.height / 2 + 50));
var minDist = Math.min(leftDist, rightDist, topDist, bottomDist);
if (minDist === leftDist) {
mouse.x = obstacle.x - obstacle.width / 2 - 50;
} else if (minDist === rightDist) {
mouse.x = obstacle.x + obstacle.width / 2 + 50;
} else if (minDist === topDist) {
mouse.y = obstacle.y - obstacle.height / 2 - 50;
} else {
mouse.y = obstacle.y + obstacle.height / 2 + 50;
}
break;
}
}
}
// Tunnels are mouse traps - if mouse enters, it gets stuck
for (var i = 0; i < tunnels.length; i++) {
var tunnel = tunnels[i];
// Use smaller hitbox for tunnel detection (50% of original size)
var tunnelHitboxSize = 75; // Reduced from 150 to 75
if (mouse.x > tunnel.x - tunnelHitboxSize / 2 && mouse.x < tunnel.x + tunnelHitboxSize / 2 && mouse.y > tunnel.y - tunnelHitboxSize / 2 && mouse.y < tunnel.y + tunnelHitboxSize / 2 && !mouse.isStuck) {
// Mouse gets stuck in tunnel
mouse.isStuck = true;
mouse.stuckInTunnel = tunnel;
mouse.x = tunnel.x;
mouse.y = tunnel.y;
LK.effects.flashObject(mouse, 0xFF0000, 1000);
break;
}
}
// Cats can pass through tunnels freely (no collision detection)
// Check cheese collection
for (var i = cheeses.length - 1; i >= 0; i--) {
var cheese = cheeses[i];
if (!cheese.collected && mouse.intersects(cheese)) {
cheese.collected = true;
cheese.visible = false;
mouse.applySpeedBoost();
LK.getSound('collect').play();
LK.setScore(LK.getScore() + 10);
cheeses.splice(i, 1);
cheese.destroy();
}
}
// Check special cheese collection
for (var i = specialCheeses.length - 1; i >= 0; i--) {
var specialCheese = specialCheeses[i];
if (!specialCheese.collected && mouse.intersects(specialCheese)) {
specialCheese.collected = true;
specialCheese.visible = false;
mouse.activateGhostMode();
LK.getSound('collect').play();
LK.setScore(LK.getScore() + 50);
LK.effects.flashScreen(0x00FFFF, 500);
specialCheeses.splice(i, 1);
specialCheese.destroy();
}
}
// Check if mouse reached exit
if (mouse.intersects(exitZone)) {
LK.getSound('escape').play();
LK.setScore(LK.getScore() + 100 * level);
level++;
if (level > 10) {
LK.showYouWin();
} else {
cat.adaptBehavior();
createLevel();
}
return;
}
// Check if cat caught mouse
if (cat.intersects(mouse)) {
LK.getSound('caught').play();
LK.effects.flashScreen(0xFF0000, 500);
LK.showGameOver();
}
// Keep entities within bounds
mouse.x = Math.max(50, Math.min(1998, mouse.x));
mouse.y = Math.max(50, Math.min(2682, mouse.y));
cat.x = Math.max(50, Math.min(1998, cat.x));
cat.y = Math.max(50, Math.min(2682, cat.y));
};
çizgi film peyniri. In-Game asset. 2d. High contrast. No shadows
çizgi film fare yuvası. In-Game asset. 2d. High contrast. No shadows
çizgi filmdeki fare jerry kaçıyor. In-Game asset. 2d. High contrast. No shadows
çizgi film fare tuzağı. In-Game asset. 2d. High contrast. No shadows
just a green field viewed from above. In-Game asset. 2d. High contrast. No shadows
rainbow cartoon cheese. In-Game asset. 2d. High contrast. No shadows