/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Bullet class var Bullet = Container.expand(function () { var self = Container.call(this); self.asset = self.attachAsset('bullet', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 48; self.dir = 0; self.owner = null; // 'player' or 'police' self.update = function () { self.x += Math.cos(self.dir) * self.speed; self.y += Math.sin(self.dir) * self.speed; }; return self; }); // Car (stealable) var Car = Container.expand(function () { var self = Container.call(this); self.asset = self.attachAsset('car', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 0; self.maxSpeed = 5; // much slower self.acceleration = 0.2; // slower acceleration self.deceleration = 0.3; // slower deceleration self.direction = 0; // radians self.driver = null; // player if inside self.isPolice = false; self.targetDir = 0; // for smooth steering self.update = function () { if (self.driver) { // Smoothly turn toward target direction (set by dragDir) var diff = self.targetDir - self.direction; // Normalize angle to [-PI, PI] while (diff > Math.PI) diff -= 2 * Math.PI; while (diff < -Math.PI) diff += 2 * Math.PI; self.direction += diff * 0.2; // smooth steering // Gradually accelerate to maxSpeed if (self.speed < self.maxSpeed) { self.speed += self.acceleration; if (self.speed > self.maxSpeed) self.speed = self.maxSpeed; } // Move in direction self.x += Math.cos(self.direction) * self.speed; self.y += Math.sin(self.direction) * self.speed; } else { // If no driver, slow down to stop if (self.speed > 0) { self.speed -= self.deceleration; if (self.speed < 0) self.speed = 0; self.x += Math.cos(self.direction) * self.speed; self.y += Math.sin(self.direction) * self.speed; } } }; return self; }); // CityBlock: road or building var CityBlock = Container.expand(function () { var self = Container.call(this); self.type = 'road'; // or 'building' self.setType = function (type) { self.type = type; if (self.asset) { self.removeChild(self.asset); } if (type === 'road') { self.asset = self.attachAsset('road', { anchorX: 0.5, anchorY: 0.5 }); } else { self.asset = self.attachAsset('building', { anchorX: 0.5, anchorY: 0.5 }); } }; return self; }); var Civilian = Container.expand(function () { var self = Container.call(this); // Pick a random color asset for this civilian var civAssetIdx = 1 + Math.floor(Math.random() * 6); var civAssetName = 'civilian' + civAssetIdx; self.asset = self.attachAsset(civAssetName, { anchorX: 0.5, anchorY: 0.5 }); self.asset.alpha = 0.7; // Add 'npc' label above the civilian self.npcLabel = new Text2('npc', { size: 38, fill: 0xFFFFFF }); self.npcLabel.anchor.set(0.5, 1); self.npcLabel.y = -40; self.addChild(self.npcLabel); self.speed = 2 + Math.random() * 2; self.direction = Math.random() * Math.PI * 2; self.update = function () { // Move in direction, bounce off buildings var nx = self.x + Math.cos(self.direction) * self.speed; var ny = self.y + Math.sin(self.direction) * self.speed; var onRoad = false; for (var i = 0; i < cityBlocks.length; i++) { var b = cityBlocks[i]; if (b.type === 'road') { var left = b.x - blockSize / 2; var right = b.x + blockSize / 2; var top = b.y - blockSize / 2; var bottom = b.y + blockSize / 2; if (nx >= left && nx <= right && ny >= top && ny <= bottom) { onRoad = true; break; } } } if (onRoad) { self.x = nx; self.y = ny; } else { self.direction = Math.random() * Math.PI * 2; } }; return self; }); // Spawn 6 civilians at random road blocks (not near player or police) // Mission marker var Mission = Container.expand(function () { var self = Container.call(this); self.asset = self.attachAsset('mission', { anchorX: 0.5, anchorY: 0.5 }); self.active = true; return self; }); // Player character var Player = Container.expand(function () { var self = Container.call(this); self.asset = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); // Add 'you' label above the player self.youLabel = new Text2('you', { size: 38, fill: 0xFFFFFF }); self.youLabel.anchor.set(0.5, 1); self.youLabel.y = -80; self.addChild(self.youLabel); self.speed = 16; self.inCar = null; // reference to car if inside self.direction = 0; // radians, 0 = right // Add gun to player's hand self.gun = self.attachAsset('gun', { anchorX: 0.1, anchorY: 0.5 }); self.gun.x = 60; // offset from player center self.gun.y = 0; self.gun.visible = true; self.lastShotDir = 0; // radians self.update = function () { // If in car, follow car and hide player sprite if (self.inCar) { self.x = self.inCar.x; self.y = self.inCar.y; self.visible = false; self.gun.visible = false; self.youLabel.visible = false; } else { self.visible = true; self.gun.visible = true; self.youLabel.visible = true; // Gun follows player hand and points at last shot direction self.gun.x = 60 * Math.cos(self.lastShotDir); self.gun.y = 60 * Math.sin(self.lastShotDir); self.gun.rotation = self.lastShotDir; } }; return self; }); // Police car var PoliceCar = Container.expand(function () { var self = Container.call(this); self.asset = self.attachAsset('police', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 0; self.maxSpeed = 2.5; // much slower (reduced for slower police) self.acceleration = 0.08; // slower acceleration self.deceleration = 0.15; // slower deceleration self.direction = 0; self.target = null; // player or car self.isPolice = true; self.targetDir = 0; self.update = function () { if (self.target) { // Simple chase logic var dx = self.target.x - self.x; var dy = self.target.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 10) { self.targetDir = Math.atan2(dy, dx); // Smoothly turn toward target direction var diff = self.targetDir - self.direction; while (diff > Math.PI) diff -= 2 * Math.PI; while (diff < -Math.PI) diff += 2 * Math.PI; self.direction += diff * 0.2; // Accelerate to maxSpeed if (self.speed < self.maxSpeed) { self.speed += self.acceleration; if (self.speed > self.maxSpeed) self.speed = self.maxSpeed; } self.x += Math.cos(self.direction) * self.speed; self.y += Math.sin(self.direction) * self.speed; } else { self.speed = 0; } } else { // If no target, slow down to stop if (self.speed > 0) { self.speed -= self.deceleration; if (self.speed < 0) self.speed = 0; self.x += Math.cos(self.direction) * self.speed; self.y += Math.sin(self.direction) * self.speed; } } }; return self; }); // Police shooter class (policeman on foot) var PoliceShooter = Container.expand(function () { var self = Container.call(this); self.asset = self.attachAsset('police', { anchorX: 0.5, anchorY: 0.5 }); // Add 'POLIS' label above the police shooter self.polisLabel = new Text2('POLIS', { size: 38, fill: 0xFFFFFF }); self.polisLabel.anchor.set(0.5, 1); self.polisLabel.y = -80; self.addChild(self.polisLabel); // Add gun to police shooter's hand self.gun = self.attachAsset('gun', { anchorX: 0.1, anchorY: 0.5 }); self.gun.x = 60; self.gun.y = 0; self.gun.visible = true; self.addChild(self.gun); self.speed = 5; // reduced for slower police self.target = null; self.lastShotTick = 0; self.lastShotDir = 0; // direction of last shot self.update = function () { // If not aggro (no target), patrol randomly on roads if (!self.target) { if (typeof self.patrolTarget === "undefined" || !self.patrolTarget) { // Pick a random road block as patrol target var roadBlocks = []; for (var k = 0; k < cityBlocks.length; k++) { if (cityBlocks[k].type === 'road') roadBlocks.push(cityBlocks[k]); } if (roadBlocks.length > 0) { var idx = Math.floor(Math.random() * roadBlocks.length); self.patrolTarget = { x: roadBlocks[idx].x + (Math.random() - 0.5) * 100, y: roadBlocks[idx].y + (Math.random() - 0.5) * 100 }; } } if (self.patrolTarget) { var dx = self.patrolTarget.x - self.x; var dy = self.patrolTarget.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 10) { self.direction = Math.atan2(dy, dx); self.x += Math.cos(self.direction) * self.speed * 0.5; self.y += Math.sin(self.direction) * self.speed * 0.5; } else { // Arrived at patrol target, pick a new one next frame self.patrolTarget = null; } // Gun points in patrol direction self.lastShotDir = self.direction; self.gun.x = 60 * Math.cos(self.lastShotDir); self.gun.y = 60 * Math.sin(self.lastShotDir); self.gun.rotation = self.lastShotDir; } } else { // Move toward player if target exists var dx = self.target.x - self.x; var dy = self.target.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 120) { self.x += dx / dist * self.speed; self.y += dy / dist * self.speed; } // Gun points at player self.lastShotDir = Math.atan2(dy, dx); self.gun.x = 60 * Math.cos(self.lastShotDir); self.gun.y = 60 * Math.sin(self.lastShotDir); self.gun.rotation = self.lastShotDir; } // Firing handled in game.update }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ // No title, no description // Set backgroundColor to vibrant green for lush map backgroundColor: 0x1ecb2a }); /**** * Game Code ****/ // --- Market Setup --- var marketEntrance = new Container(); marketEntrance.asset = marketEntrance.attachAsset('building', { anchorX: 0.5, anchorY: 0.5 }); marketEntrance.asset.width = 300; marketEntrance.asset.height = 300; marketEntrance.x = (gridCols - 1) / 2 * blockSize + blockSize / 2 + 300; // rightmost road col + offset marketEntrance.y = 0 * blockSize + blockSize / 2; marketEntrance.isMarketEntrance = true; // Add 'MARKET' label above the market entrance marketEntrance.marketLabel = new Text2('MARKET', { size: 90, fill: "#fff" }); marketEntrance.marketLabel.anchor.set(0.5, 1); marketEntrance.marketLabel.x = 0; marketEntrance.marketLabel.y = -170; marketEntrance.addChild(marketEntrance.marketLabel); game.addChild(marketEntrance); // Market interior (hidden until entered) var marketInterior = new Container(); marketInterior.asset = marketInterior.attachAsset('building', { anchorX: 0.5, anchorY: 0.5 }); marketInterior.asset.width = 800; marketInterior.asset.height = 800; marketInterior.x = 2048 / 2; marketInterior.y = 2732 / 2; marketInterior.visible = false; game.addChild(marketInterior); // Market buy ammo button var marketBuyBtn = new Text2("₺50'ye 100 mermi al", { size: 120, fill: "#fff" }); marketBuyBtn.anchor.set(0.5, 0.5); marketBuyBtn.x = marketInterior.x; marketBuyBtn.y = marketInterior.y + 100; marketBuyBtn.visible = false; game.addChild(marketBuyBtn); // Market exit (door) var marketExit = new Container(); marketExit.asset = marketExit.attachAsset('road', { anchorX: 0.5, anchorY: 0.5 }); marketExit.asset.width = 200; marketExit.asset.height = 100; marketExit.x = marketInterior.x; marketExit.y = marketInterior.y + 350; marketExit.visible = false; marketExit.isMarketExit = true; game.addChild(marketExit); // Track if player is in market var playerInMarket = false; // marketStartPos will be initialized after player is created var marketStartPos; // --- Money on ground --- // Police car - white box with blue // Car - yellow box // Player (hero) - red ellipse // Building - blue box // City block (road) - gray box // --- Fixed City Map Setup --- var blockSize = 400; var cityBlocks = []; var cityBlockMap = {}; // key: "col,row" -> CityBlock // Fixed grid size var gridCols = 9; var gridRows = 13; // Use a simple procedural pattern: every even col/row is road, others are building function getBlockType(col, row) { // Make a simple city: roads every 2 blocks, rest are buildings if (col % 2 === 0 || row % 2 === 0) return 'road'; return 'building'; } // Helper to get or create a city block at (col, row) function getOrCreateCityBlock(col, row) { // Clamp to fixed grid if (col < -Math.floor(gridCols / 2) || col > Math.floor(gridCols / 2) || row < -Math.floor(gridRows / 2) || row > Math.floor(gridRows / 2)) { return null; } var key = col + ',' + row; if (cityBlockMap[key]) return cityBlockMap[key]; var block = new CityBlock(); var type = getBlockType(col, row); block.setType(type); block.x = col * blockSize + blockSize / 2; block.y = row * blockSize + blockSize / 2; cityBlockMap[key] = block; cityBlocks.push(block); game.addChild(block); return block; } // Generate fixed grid (centered at 0,0) var initialCols = gridCols, initialRows = gridRows; var centerCol = 0, centerRow = 0; for (var row = -Math.floor(initialRows / 2); row <= Math.floor(initialRows / 2); row++) { for (var col = -Math.floor(initialCols / 2); col <= Math.floor(initialCols / 2); col++) { getOrCreateCityBlock(col, row); } } // Helper to get all road blocks in a region (for spawning) function getRoadBlocksInRegion(colMin, colMax, rowMin, rowMax) { var blocks = []; for (var row = rowMin; row <= rowMax; row++) { for (var col = colMin; col <= colMax; col++) { var block = getOrCreateCityBlock(col, row); if (block && block.type === 'road') blocks.push(block); } } return blocks; } // Helper to get nearest road block col/row for a given x/y function getColRowForXY(x, y) { var col = Math.round((x - blockSize / 2) / blockSize); var row = Math.round((y - blockSize / 2) / blockSize); // Clamp to grid col = Math.max(-Math.floor(gridCols / 2), Math.min(Math.floor(gridCols / 2), col)); row = Math.max(-Math.floor(gridRows / 2), Math.min(Math.floor(gridRows / 2), row)); return { col: col, row: row }; } // --- Player Setup --- // Spawn player at center of the infinite world (col=0, row=0) var player = new Player(); player.x = 0 * blockSize + blockSize / 2; player.y = 0 * blockSize + blockSize / 2; game.addChild(player); // Now that player is defined, initialize marketStartPos marketStartPos = { x: player.x, y: player.y }; // --- Civilians Setup --- var civilians = []; // Spawn 6 civilians at random road blocks (not near player or police) for (var i = 0; i < 6; i++) { // Use a region around player for infinite world var playerColRow = getColRowForXY(player.x, player.y); var roadBlocks = getRoadBlocksInRegion(playerColRow.col - 7, playerColRow.col + 7, playerColRow.row - 7, playerColRow.row + 7); // Avoid spawn near player var filtered = []; for (var j = 0; j < roadBlocks.length; j++) { var b = roadBlocks[j]; var distToPlayer = Math.sqrt(Math.pow(b.x - player.x, 2) + Math.pow(b.y - player.y, 2)); if (distToPlayer > 400) filtered.push(b); } if (filtered.length > 0) { var idx = Math.floor(Math.random() * filtered.length); var civ = new Civilian(); civ.x = filtered[idx].x + (Math.random() - 0.5) * 100; civ.y = filtered[idx].y + (Math.random() - 0.5) * 100; civilians.push(civ); game.addChild(civ); } } // --- Cars Setup --- var cars = []; function spawnCar(x, y) { var car = new Car(); car.x = x; car.y = y; car.direction = Math.random() * Math.PI * 2; cars.push(car); game.addChild(car); return car; } // Place a few cars on roads using fixed world var roadBlocksForCars = []; for (var i = 0; i < cityBlocks.length; i++) { if (cityBlocks[i].type === 'road') { // Remove player's starting block if (!(cityBlocks[i].x === player.x && cityBlocks[i].y === player.y)) { roadBlocksForCars.push(cityBlocks[i]); } } } // Shuffle for (var k = roadBlocksForCars.length - 1; k > 0; k--) { var j = Math.floor(Math.random() * (k + 1)); var temp = roadBlocksForCars[k]; roadBlocksForCars[k] = roadBlocksForCars[j]; roadBlocksForCars[j] = temp; } // Spawn up to 4 cars in distinct available road blocks var carsToSpawn = 4; for (var i = 0; i < Math.min(carsToSpawn, roadBlocksForCars.length); i++) { var block = roadBlocksForCars[i]; spawnCar(block.x, block.y); } // --- Police Setup --- var policeCars = []; function spawnPolice(x, y) { var police = new PoliceCar(); police.x = x; police.y = y; police.direction = 0; // Police do not chase the player anymore police.target = null; policeCars.push(police); game.addChild(police); return police; } // Start with three police cars at different road blocks var policeStartBlocks = []; for (var i = 0; i < cityBlocks.length; i++) { if (cityBlocks[i].type === 'road') { policeStartBlocks.push(cityBlocks[i]); } } if (policeStartBlocks.length > 0) { // Always spawn one at the top left of region var policeStartX = cityBlocks[0].x; var policeStartY = cityBlocks[0].y; spawnPolice(policeStartX, policeStartY); // Pick two more random road blocks (not the same as above) var used = {}; used[policeStartX + ',' + policeStartY] = true; for (var p = 0; p < 2; p++) { var idx = Math.floor(Math.random() * policeStartBlocks.length); var b = policeStartBlocks[idx]; var key = b.x + ',' + b.y; if (!used[key]) { spawnPolice(b.x, b.y); used[key] = true; } } } // --- Mission Setup --- var mission = new Mission(); // Place mission at far corner of grid mission.x = cityBlocks[cityBlocks.length - 1].x; mission.y = cityBlocks[cityBlocks.length - 1].y; game.addChild(mission); // --- Money on ground --- var moneyPickups = []; function spawnMoney(x, y) { var m = new Container(); m.asset = m.attachAsset('mission', { anchorX: 0.5, anchorY: 0.5 }); m.x = x; m.y = y; m.value = 50; moneyPickups.push(m); game.addChild(m); return m; } // Place 15 money pickups at random road blocks in grid var roadBlocksForMoney = []; for (var i = 0; i < cityBlocks.length; i++) { if (cityBlocks[i].type === 'road') { roadBlocksForMoney.push(cityBlocks[i]); } } for (var i = 0; i < 15; i++) { if (roadBlocksForMoney.length > 0) { var idx = Math.floor(Math.random() * roadBlocksForMoney.length); var b = roadBlocksForMoney[idx]; var mx = b.x + (Math.random() - 0.5) * (blockSize - 100); var my = b.y + (Math.random() - 0.5) * (blockSize - 100); spawnMoney(mx, my); } } // --- Score and Wanted Level --- var score = 0; var wantedLevel = 1; // 1-5 var scoreTxt = new Text2('Score: 0', { size: 90, fill: "#fff" }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); var wantedTxt = new Text2('★', { size: 80, fill: "#ff0" }); wantedTxt.anchor.set(1, 0); // anchor to top right wantedTxt.x = 0; wantedTxt.y = 0; LK.gui.topRight.addChild(wantedTxt); // (Removed 'elinde akm var' text below the wanted stars) // --- Timer --- var timeLeft = 60; // seconds var timerTxt = new Text2('60', { size: 80, fill: "#fff" }); timerTxt.anchor.set(0.5, 0); LK.gui.top.addChild(timerTxt); // --- Touch Controls --- var dragDir = null; // {dx,dy} var dragStart = null; var dragNode = null; var lastTouchX = 0, lastTouchY = 0; // --- Shooting & Health --- var bullets = []; var policeBullets = []; var playerHealth = 5; // --- Ammo system --- var playerAmmo = 100; var ammoTxt = new Text2('Ammo: 100', { size: 80, fill: "#fff" }); // Anchor to top right (same as wanted stars) ammoTxt.anchor.set(1, 0); // Place just below the wanted stars (wantedTxt is at y=0, height ~80) ammoTxt.x = 0; ammoTxt.y = wantedTxt.y + wantedTxt.height + 10; // 10px below stars LK.gui.topRight.addChild(ammoTxt); function updateAmmoDisplay() { ammoTxt.setText('Ammo: ' + playerAmmo); } // Money system var playerMoney = 0; var moneyTxt = new Text2('₺ 0', { size: 120, fill: 0x44FF44 }); moneyTxt.anchor.set(0, 0); moneyTxt.x = 100; moneyTxt.y = 90; LK.gui.addChild(moneyTxt); var healthTxt = new Text2('♥♥♥♥♥', { size: 80, fill: 0xFF4444 }); healthTxt.anchor.set(0, 0); // anchor top left // Place health bar at (100,0) to avoid platform menu healthTxt.x = 100; healthTxt.y = 0; LK.gui.addChild(healthTxt); // Track if police are aggressive (chasing) or passive var policeAggro = false; // Helper to update health display function updateHealthDisplay() { var hearts = ''; for (var i = 0; i < playerHealth; i++) hearts += '♥'; healthTxt.setText(hearts); } function updateMoneyDisplay() { moneyTxt.setText('₺ ' + playerMoney); } var policeShooters = []; // Spawn a few police shooters at random road blocks, not near player (fixed world) for (var i = 0; i < 8; i++) { var roadBlocks = []; for (var j = 0; j < cityBlocks.length; j++) { if (cityBlocks[j].type === 'road') { var b = cityBlocks[j]; var distToPlayer = Math.sqrt(Math.pow(b.x - player.x, 2) + Math.pow(b.y - player.y, 2)); if (distToPlayer > 600) roadBlocks.push(b); } } if (roadBlocks.length > 0) { var idx = Math.floor(Math.random() * roadBlocks.length); var shooter = new PoliceShooter(); shooter.x = roadBlocks[idx].x + (Math.random() - 0.5) * 100; shooter.y = roadBlocks[idx].y + (Math.random() - 0.5) * 100; shooter.target = null; // Do not target player at start shooter.wasShotAt = false; // Only shoot if player shoots at them policeShooters.push(shooter); game.addChild(shooter); } } // --- Helper Functions --- function isOnRoad(x, y) { // Returns true if (x,y) is on a road block (fixed world) var colRow = getColRowForXY(x, y); var block = getOrCreateCityBlock(colRow.col, colRow.row); if (block && block.type === 'road') { var left = block.x - blockSize / 2; var right = block.x + blockSize / 2; var top = block.y - blockSize / 2; var bottom = block.y + blockSize / 2; if (x >= left && x <= right && y >= top && y <= bottom) { return true; } } return false; } function clampToRoad(x, y) { // Snap to nearest road block center (fixed world) var colRow = getColRowForXY(x, y); var block = getOrCreateCityBlock(colRow.col, colRow.row); if (block && block.type === 'road') { return { x: block.x, y: block.y }; } // If not road, search nearby for (var r = -1; r <= 1; r++) { for (var c = -1; c <= 1; c++) { var b = getOrCreateCityBlock(colRow.col + c, colRow.row + r); if (b && b.type === 'road') return { x: b.x, y: b.y }; } } // Fallback: return original return { x: x, y: y }; } function updateWantedDisplay() { var stars = ''; for (var i = 0; i < wantedLevel; i++) stars += '★'; wantedTxt.setText(stars); // Default color var color = "#ff0"; // If 5 stars, flash red/blue if (wantedLevel === 5) { // Show "wandet" text for 3 seconds only on the frame wantedLevel becomes 5 if (typeof wandetTextShown === "undefined") wandetTextShown = false; if (!wandetTextShown) { // Remove previous if exists if (typeof wandetText !== "undefined" && wandetText.parent) { wandetText.parent.removeChild(wandetText); wandetText = undefined; } wandetText = new Text2("wandet", { size: 160, fill: 0xFF2222 }); wandetText.anchor.set(0.5, 0); wandetText.x = 2048 / 2; wandetText.y = 500; LK.gui.addChild(wandetText); wandetTextShown = true; LK.setTimeout(function () { if (wandetText && wandetText.parent) { wandetText.parent.removeChild(wandetText); wandetText = undefined; } wandetTextShown = false; }, 3000); } // Alternate color every 20 ticks (about 1/3 second at 60fps) if (LK.ticks % 40 < 20) { color = "#ff2222"; // red } else { color = "#2288ff"; // blue } } if (wantedTxt && wantedTxt.style && typeof wantedTxt.style.fill !== "undefined") { wantedTxt.style.fill = color; } } function addScore(amt) { score += amt; scoreTxt.setText('Score: ' + score); LK.setScore(score); } function resetMission() { // Place mission at random road block (fixed world) var roadBlocks = []; for (var i = 0; i < cityBlocks.length; i++) { if (cityBlocks[i].type === 'road') { var b = cityBlocks[i]; var distToPlayer = Math.sqrt(Math.pow(b.x - player.x, 2) + Math.pow(b.y - player.y, 2)); if (distToPlayer > 400) roadBlocks.push(b); } } if (roadBlocks.length > 0) { var idx = Math.floor(Math.random() * roadBlocks.length); mission.x = roadBlocks[idx].x; mission.y = roadBlocks[idx].y; mission.active = true; mission.visible = true; } } // --- Game Touch Controls --- // Drag to move (swipe in direction to move) game.down = function (x, y, obj) { // Don't allow drag from top left 100x100 if (x < 100 && y < 100) return; // --- SHOOTING LOGIC --- // If not dragging, treat as tap to shoot if (!dragNode && !dragDir && !player.inCar) { if (typeof playerAmmo === "undefined") playerAmmo = 0; if (playerAmmo > 0) { // Player shoots toward (x, y) var b = new Bullet(); b.x = player.x; b.y = player.y; b.dir = Math.atan2(y - b.y, x - b.x); b.owner = 'player'; bullets.push(b); game.addChild(b); // Update player's gun direction to point at shot player.lastShotDir = b.dir; playerAmmo--; if (typeof updateAmmoDisplay === "function") updateAmmoDisplay(); } else { // Out of ammo: show "mermi bitti" for 1 second at center-top if (typeof ammoEmptyText !== "undefined" && ammoEmptyText.parent) { ammoEmptyText.parent.removeChild(ammoEmptyText); ammoEmptyText = undefined; } ammoEmptyText = new Text2("mermi bitti", { size: 120, fill: 0xFF2222 }); ammoEmptyText.anchor.set(0.5, 0); ammoEmptyText.x = 2048 / 2; ammoEmptyText.y = 320; LK.gui.addChild(ammoEmptyText); LK.setTimeout(function () { if (ammoEmptyText && ammoEmptyText.parent) { ammoEmptyText.parent.removeChild(ammoEmptyText); ammoEmptyText = undefined; } }, 1000); } // No police aggro or wanted level increase when shooting police } // --- DRAG LOGIC (movement) --- dragStart = { x: x, y: y }; lastTouchX = x; lastTouchY = y; dragDir = null; dragNode = player; }; game.move = function (x, y, obj) { if (!dragNode) return; var dx = x - dragStart.x; var dy = y - dragStart.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 30) { dragDir = { dx: dx, dy: dy }; } lastTouchX = x; lastTouchY = y; }; game.up = function (x, y, obj) { dragNode = null; dragDir = null; dragStart = null; }; // --- Car Enter/Exit Logic --- // Track tap times for triple-tap exit var carTapTimes = []; game.on('down', function (x, y, obj) { // If player is not in car, check if tap is on car and player is close enough if (!player.inCar) { for (var i = 0; i < cars.length; i++) { var car = cars[i]; var dx = car.x - x; var dy = car.y - y; // Tap must be on car if (Math.abs(dx) < 80 && Math.abs(dy) < 50) { // Player must be close to car to enter if (Math.abs(player.x - car.x) < 120 && Math.abs(player.y - car.y) < 80) { player.inCar = car; car.driver = player; // Do not set car.speed here; Car.update will handle acceleration car.direction = 0; // Increase wanted level wantedLevel = Math.min(5, wantedLevel + 1); updateWantedDisplay(); // Police target car for (var j = 0; j < policeCars.length; j++) { policeCars[j].target = car; } // Reset tap times for exit carTapTimes = []; break; } } } } else { // Player is in car: require triple-tap within 1 second to exit var now = Date.now(); carTapTimes.push(now); // Only keep last 3 taps if (carTapTimes.length > 3) carTapTimes.shift(); if (carTapTimes.length === 3) { // Check if 3 taps are within 1 second if (carTapTimes[2] - carTapTimes[0] < 1000) { var car = player.inCar; player.inCar = null; car.driver = null; // Do not set car.speed to 0; Car.update will handle deceleration // Place player next to car player.x = car.x + 80; player.y = car.y; // Police target player for (var j = 0; j < policeCars.length; j++) { policeCars[j].target = player; } carTapTimes = []; } } } }); // --- Game Update Loop --- game.update = function () { // Timer if (LK.ticks % 60 === 0 && timeLeft > 0) { timeLeft--; timerTxt.setText(timeLeft + ''); // Do not end the game when timer reaches zero } // --- Market logic --- // If not in market, check for market entrance if (!playerInMarket) { // Check if player is at market entrance (right edge) if (Math.abs(player.x - marketEntrance.x) < 120 && Math.abs(player.y - marketEntrance.y) < 120) { // Teleport to market interior playerInMarket = true; marketStartPos.x = player.x; marketStartPos.y = player.y; player.x = marketInterior.x; player.y = marketInterior.y - 100; marketInterior.visible = true; marketBuyBtn.visible = true; marketExit.visible = true; // Hide city elements for (var i = 0; i < cityBlocks.length; i++) cityBlocks[i].visible = false; for (var i = 0; i < cars.length; i++) cars[i].visible = false; for (var i = 0; i < civilians.length; i++) civilians[i].visible = false; for (var i = 0; i < policeCars.length; i++) policeCars[i].visible = false; for (var i = 0; i < policeShooters.length; i++) policeShooters[i].visible = false; for (var i = 0; i < moneyPickups.length; i++) moneyPickups[i].visible = false; if (typeof gunPickups !== "undefined") for (var i = 0; i < gunPickups.length; i++) gunPickups[i].visible = false; mission.visible = false; marketEntrance.visible = false; } } else { // In market: only allow movement inside market area if (dragDir) { var angle = Math.atan2(dragDir.dy, dragDir.dx); var nx = player.x + Math.cos(angle) * player.speed; var ny = player.y + Math.sin(angle) * player.speed; // Clamp to market interior bounds var left = marketInterior.x - 350, right = marketInterior.x + 350; var top = marketInterior.y - 350, bottom = marketInterior.y + 350; if (nx > left && nx < right && ny > top && ny < bottom) { player.x = nx; player.y = ny; } } // Check for ammo buy (touch on buy button) if (Math.abs(player.x - marketBuyBtn.x) < 200 && Math.abs(player.y - marketBuyBtn.y) < 100) { if (playerMoney >= 50 && playerAmmo < 100) { playerMoney -= 50; playerAmmo = 100; updateMoneyDisplay(); updateAmmoDisplay(); // Show "100 mermi alındı" text if (typeof marketBuyText !== "undefined" && marketBuyText.parent) { marketBuyText.parent.removeChild(marketBuyText); marketBuyText = undefined; } marketBuyText = new Text2("100 mermi alındı", { size: 120, fill: 0x44FF44 }); marketBuyText.anchor.set(0.5, 0); marketBuyText.x = 2048 / 2; marketBuyText.y = 320; LK.gui.addChild(marketBuyText); LK.setTimeout(function () { if (marketBuyText && marketBuyText.parent) { marketBuyText.parent.removeChild(marketBuyText); marketBuyText = undefined; } }, 1000); } } // Check for exit (touch on exit door) if (Math.abs(player.x - marketExit.x) < 120 && Math.abs(player.y - marketExit.y) < 80) { // Teleport back to start player.x = marketStartPos.x; player.y = marketStartPos.y; playerInMarket = false; marketInterior.visible = false; marketBuyBtn.visible = false; marketExit.visible = false; // Show city elements again for (var i = 0; i < cityBlocks.length; i++) cityBlocks[i].visible = true; for (var i = 0; i < cars.length; i++) cars[i].visible = true; for (var i = 0; i < civilians.length; i++) civilians[i].visible = true; for (var i = 0; i < policeCars.length; i++) policeCars[i].visible = true; for (var i = 0; i < policeShooters.length; i++) policeShooters[i].visible = true; for (var i = 0; i < moneyPickups.length; i++) moneyPickups[i].visible = true; if (typeof gunPickups !== "undefined") for (var i = 0; i < gunPickups.length; i++) gunPickups[i].visible = true; mission.visible = true; marketEntrance.visible = true; } } // Player movement if (!player.inCar && dragDir && !playerInMarket) { // Move player in drag direction, but only on road var angle = Math.atan2(dragDir.dy, dragDir.dx); var nx = player.x + Math.cos(angle) * player.speed; var ny = player.y + Math.sin(angle) * player.speed; if (isOnRoad(nx, ny)) { player.x = nx; player.y = ny; } // No infinite world: no need to generate new blocks in update } // Car movement (if player in car) for (var i = 0; i < cars.length; i++) { var car = cars[i]; // If player is driving this car, set car's targetDir to drag direction if (car.driver === player && dragDir) { var angle = Math.atan2(dragDir.dy, dragDir.dx); car.targetDir = angle; } car.update(); // Clamp car to road if (car.driver) { if (!isOnRoad(car.x, car.y)) { // Stop car at edge car.speed = 0; } } } // Police movement for (var i = 0; i < policeCars.length; i++) { var police = policeCars[i]; // Police patrol logic: move randomly on roads if not chasing if (!policeAggro) { if (typeof police.patrolTarget === "undefined" || !police.patrolTarget) { // Pick a random road block as patrol target var roadBlocks = []; for (var k = 0; k < cityBlocks.length; k++) { if (cityBlocks[k].type === 'road') roadBlocks.push(cityBlocks[k]); } if (roadBlocks.length > 0) { var idx = Math.floor(Math.random() * roadBlocks.length); police.patrolTarget = { x: roadBlocks[idx].x + (Math.random() - 0.5) * 100, y: roadBlocks[idx].y + (Math.random() - 0.5) * 100 }; } } if (police.patrolTarget) { var dx = police.patrolTarget.x - police.x; var dy = police.patrolTarget.y - police.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 10) { police.direction = Math.atan2(dy, dx); police.speed = police.maxSpeed * 0.5; police.x += Math.cos(police.direction) * police.speed; police.y += Math.sin(police.direction) * police.speed; } else { // Arrived at patrol target, pick a new one next frame police.patrolTarget = null; police.speed = 0; } } } else { police.update(); } // Clamp police to road if (!isOnRoad(police.x, police.y)) { police.speed = 0; } // Police catch player var target = police.target; if (policeAggro && target && Math.abs(police.x - target.x) < 80 && Math.abs(police.y - target.y) < 80) { LK.effects.flashScreen(0xff0000, 1000); LK.showGameOver(); return; } } // Police shooters update for (var i = policeShooters.length - 1; i >= 0; i--) { var shooter = policeShooters[i]; shooter.update(); // Remove if off map if (shooter.x < 0 || shooter.x > 2048 || shooter.y < 0 || shooter.y > 2732) { shooter.destroy(); policeShooters.splice(i, 1); continue; } // --- Police shooter fires at player only if aggro (wasShotAt or policeAggro) --- // Only fire if player is within 700px, not in car, and shooter is aggro if (shooter.wasShotAt || policeAggro) { var px = player.inCar ? player.inCar.x : player.x; var py = player.inCar ? player.inCar.y : player.y; var dx = px - shooter.x; var dy = py - shooter.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < 700 && LK.ticks - shooter.lastShotTick > 60) { // Fire bullet toward player var b = new Bullet(); b.x = shooter.x; b.y = shooter.y; b.dir = Math.atan2(dy, dx); b.owner = 'police'; policeBullets.push(b); game.addChild(b); shooter.lastShotTick = LK.ticks; } } } // Bullets update (player) for (var i = bullets.length - 1; i >= 0; i--) { var b = bullets[i]; if (b && typeof b.update === "function") { b.update(); } // Remove if off screen if (b && typeof b.x === "number" && typeof b.y === "number" && (b.x < 0 || b.x > 2048 || b.y < 0 || b.y > 2732)) { b.destroy(); bullets.splice(i, 1); continue; } // --- Police car kill check --- for (var j = policeCars.length - 1; j >= 0; j--) { var police = policeCars[j]; // --- Car bullet hit logic --- if (police && b && typeof police.x === "number" && typeof police.y === "number" && typeof b.x === "number" && typeof b.y === "number" && Math.abs(police.x - b.x) < 60 && Math.abs(police.y - b.y) < 60) { // Track bullet hits on this car if (typeof police.bulletHitCount === "undefined") police.bulletHitCount = 0; police.bulletHitCount++; // Remove bullet b.destroy(); bullets.splice(i, 1); // If hit 30 times, destroy car and show "arba patladı" if (police.bulletHitCount >= 30) { // Drop a gun at police car's position var gunDrop = new Container(); gunDrop.asset = gunDrop.attachAsset('gun', { anchorX: 0.5, anchorY: 0.5 }); // Add 'gun' label above the dropped gun gunDrop.gunLabel = new Text2('gun', { size: 38, fill: 0xFFFFFF }); gunDrop.gunLabel.anchor.set(0.5, 1); gunDrop.gunLabel.y = -30; gunDrop.addChild(gunDrop.gunLabel); gunDrop.x = police.x; gunDrop.y = police.y; gunDrop.isGunPickup = true; game.addChild(gunDrop); if (typeof gunPickups === "undefined") gunPickups = []; gunPickups.push(gunDrop); police.destroy(); policeCars.splice(j, 1); // Show "arba patladı" text for 2 seconds at center of screen if (typeof carExplodedText !== "undefined" && carExplodedText.parent) { carExplodedText.parent.removeChild(carExplodedText); carExplodedText = undefined; } carExplodedText = new Text2("arba patladı", { size: 160, fill: 0xFF2222 }); carExplodedText.anchor.set(0.5, 0.5); carExplodedText.x = 2048 / 2; carExplodedText.y = 2732 / 2; LK.gui.addChild(carExplodedText); LK.setTimeout(function () { if (carExplodedText && carExplodedText.parent) { carExplodedText.parent.removeChild(carExplodedText); carExplodedText = undefined; } }, 2000); addScore(20); // Increase wanted level by 1 (max 5) when police car is killed wantedLevel = Math.min(5, wantedLevel + 1); updateWantedDisplay(); // Only aggro police if wantedLevel is 5 if (wantedLevel === 5 && typeof spawned5StarPolice === "undefined") { for (var p = 0; p < policeShooters.length; p++) { policeShooters[p].wasShotAt = true; policeShooters[p].target = player; } for (var p = 0; p < policeCars.length; p++) { policeCars[p].target = player; } policeAggro = true; // Spawn 20 police cars at random road blocks (not near player) var roadBlocks = []; for (var i = 0; i < cityBlocks.length; i++) { if (cityBlocks[i].type === 'road') { var distToPlayer = Math.sqrt(Math.pow(cityBlocks[i].x - player.x, 2) + Math.pow(cityBlocks[i].y - player.y, 2)); if (distToPlayer > 400) { roadBlocks.push(cityBlocks[i]); } } } for (var s = 0; s < 20; s++) { if (roadBlocks.length > 0) { var idx = Math.floor(Math.random() * roadBlocks.length); var b = roadBlocks[idx]; var newPolice = spawnPolice(b.x, b.y); newPolice.target = player; // Remove this block from roadBlocks to avoid double-spawn at same spot roadBlocks.splice(idx, 1); } } // --- Spawn 40 police shooters at random road blocks, not near player --- for (var spawnCount = 0; spawnCount < 40; spawnCount++) { var shooterBlocks = []; for (var k = 0; k < cityBlocks.length; k++) { var b2 = cityBlocks[k]; if (b2.type === 'road') { var distToPlayer = Math.sqrt(Math.pow(b2.x - player.x, 2) + Math.pow(b2.y - player.y, 2)); if (distToPlayer > 600) { shooterBlocks.push(b2); } } } if (shooterBlocks.length > 0) { var idx2 = Math.floor(Math.random() * shooterBlocks.length); var newShooter = new PoliceShooter(); newShooter.x = shooterBlocks[idx2].x + (Math.random() - 0.5) * 100; newShooter.y = shooterBlocks[idx2].y + (Math.random() - 0.5) * 100; newShooter.target = player; newShooter.wasShotAt = true; policeShooters.push(newShooter); game.addChild(newShooter); shooterBlocks.splice(idx2, 1); } } spawned5StarPolice = true; } break; } // If not destroyed, do not break, allow other cars to be checked continue; } // --- END Car bullet hit logic --- } // --- Police shooter kill check --- for (var j = policeShooters.length - 1; j >= 0; j--) { var shooter = policeShooters[j]; if (shooter && b && typeof shooter.x === "number" && typeof shooter.y === "number" && typeof b.x === "number" && typeof b.y === "number" && Math.abs(shooter.x - b.x) < 60 && Math.abs(shooter.y - b.y) < 60) { // Mark this shooter as shot at, so it will shoot back shooter.wasShotAt = true; // --- Police shooter health logic --- // Instantly kill police shooter with one bullet b.destroy(); bullets.splice(i, 1); // Police shooter killed! // Drop a gun at police shooter's position var gunDrop = new Container(); gunDrop.asset = gunDrop.attachAsset('gun', { anchorX: 0.5, anchorY: 0.5 }); // Add 'gun' label above the dropped gun gunDrop.gunLabel = new Text2('gun', { size: 38, fill: 0xFFFFFF }); gunDrop.gunLabel.anchor.set(0.5, 1); gunDrop.gunLabel.y = -30; gunDrop.addChild(gunDrop.gunLabel); gunDrop.x = shooter.x; gunDrop.y = shooter.y; gunDrop.isGunPickup = true; game.addChild(gunDrop); if (typeof gunPickups === "undefined") gunPickups = []; gunPickups.push(gunDrop); shooter.destroy(); policeShooters.splice(j, 1); // --- Spawn TWO new police shooters at random road blocks, not near player --- for (var spawnCount = 0; spawnCount < 2; spawnCount++) { var roadBlocks = []; for (var k = 0; k < cityBlocks.length; k++) { var b2 = cityBlocks[k]; if (b2.type === 'road') { var distToPlayer = Math.sqrt(Math.pow(b2.x - player.x, 2) + Math.pow(b2.y - player.y, 2)); if (distToPlayer > 600) { roadBlocks.push(b2); } } } if (roadBlocks.length > 0) { var idx2 = Math.floor(Math.random() * roadBlocks.length); var newShooter = new PoliceShooter(); newShooter.x = roadBlocks[idx2].x + (Math.random() - 0.5) * 100; newShooter.y = roadBlocks[idx2].y + (Math.random() - 0.5) * 100; if (policeAggro) { newShooter.target = player; newShooter.wasShotAt = true; } else { newShooter.target = null; newShooter.wasShotAt = false; } policeShooters.push(newShooter); game.addChild(newShooter); } } addScore(15); // Increase wanted level by 1 (max 5) when police shooter is killed wantedLevel = Math.min(5, wantedLevel + 1); updateWantedDisplay(); break; // If not dead, do not break, allow other shooters to be checked } } } // Bullets update (police) for (var i = policeBullets.length - 1; i >= 0; i--) { var b = policeBullets[i]; if (b && typeof b.update === "function") { b.update(); } // Remove if off screen if (b && typeof b.x === "number" && typeof b.y === "number" && (b.x < 0 || b.x > 2048 || b.y < 0 || b.y > 2732)) { b.destroy(); policeBullets.splice(i, 1); continue; } // Check hit player var px = player.inCar ? player.inCar.x : player.x; var py = player.inCar ? player.inCar.y : player.y; if (Math.abs(px - b.x) < 60 && Math.abs(py - b.y) < 60) { // Police bullet hits player: decrease health if not in car if (!player.inCar && playerHealth > 0) { playerHealth--; updateHealthDisplay(); // Optional: flash screen on hit LK.effects.flashScreen(0xff0000, 200); // Game over if health reaches 0 if (playerHealth <= 0) { LK.showGameOver(); return; } } // If player is in car, do not take damage b.destroy(); policeBullets.splice(i, 1); } } // Player update player.update(); // Civilians update and check for being shot by player or run over by car for (var i = civilians.length - 1; i >= 0; i--) { var civ = civilians[i]; if (civ && typeof civ.update === "function") { civ.update(); } var killed = false; // Check if hit by any player bullet for (var j = bullets.length - 1; j >= 0; j--) { var b = bullets[j]; if (Math.abs(civ.x - b.x) < 60 && Math.abs(civ.y - b.y) < 60) { killed = true; // Remove bullet b.destroy(); bullets.splice(j, 1); break; } } // Check if run over by any car driven by player if (!killed) { for (var c = 0; c < cars.length; c++) { var car = cars[c]; if (car.driver === player) { // Use a slightly larger hitbox for car if (Math.abs(civ.x - car.x) < 90 && Math.abs(civ.y - car.y) < 70) { killed = true; break; } } } } if (killed) { // Civilian killed // Drop money at civilian's position spawnMoney(civ.x, civ.y); // Respawn civilian at random road block (fixed world) var roadBlocks = []; for (var k = 0; k < cityBlocks.length; k++) { if (cityBlocks[k].type === 'road') { var b = cityBlocks[k]; var distToPlayer = Math.sqrt(Math.pow(b.x - player.x, 2) + Math.pow(b.y - player.y, 2)); if (distToPlayer > 400) roadBlocks.push(b); } } if (roadBlocks.length > 0) { var idx = Math.floor(Math.random() * roadBlocks.length); var newCiv = new Civilian(); newCiv.x = roadBlocks[idx].x + (Math.random() - 0.5) * 100; newCiv.y = roadBlocks[idx].y + (Math.random() - 0.5) * 100; civilians.push(newCiv); game.addChild(newCiv); } civ.destroy(); civilians.splice(i, 1); addScore(10); // Increase wanted level by 1 every time player kills an NPC, max 5 wantedLevel = Math.min(5, wantedLevel + 1); updateWantedDisplay(); // Only aggro police if wantedLevel is 5 if (wantedLevel === 5) { for (var p = 0; p < policeShooters.length; p++) { policeShooters[p].wasShotAt = true; policeShooters[p].target = player; } for (var p = 0; p < policeCars.length; p++) { policeCars[p].target = player; } policeAggro = true; } // No break here: allow this to happen every time an NPC is killed continue; } // --- Police run over by car logic --- // Player can run over police shooters and police cars when driving a car for (var c = 0; c < cars.length; c++) { var car = cars[c]; if (car.driver === player) { // Run over police shooters for (var s = policeShooters.length - 1; s >= 0; s--) { var shooter = policeShooters[s]; if (Math.abs(shooter.x - car.x) < 90 && Math.abs(shooter.y - car.y) < 70) { // Police shooter killed by car // Drop a gun at police shooter's position var gunDrop = new Container(); gunDrop.asset = gunDrop.attachAsset('gun', { anchorX: 0.5, anchorY: 0.5 }); gunDrop.gunLabel = new Text2('gun', { size: 38, fill: 0xFFFFFF }); gunDrop.gunLabel.anchor.set(0.5, 1); gunDrop.gunLabel.y = -30; gunDrop.addChild(gunDrop.gunLabel); gunDrop.x = shooter.x; gunDrop.y = shooter.y; gunDrop.isGunPickup = true; game.addChild(gunDrop); if (typeof gunPickups === "undefined") gunPickups = []; gunPickups.push(gunDrop); shooter.destroy(); policeShooters.splice(s, 1); // Spawn TWO new police shooters at random road blocks, not near player for (var spawnCount = 0; spawnCount < 2; spawnCount++) { var roadBlocks = []; for (var k = 0; k < cityBlocks.length; k++) { var b2 = cityBlocks[k]; if (b2.type === 'road') { var distToPlayer = Math.sqrt(Math.pow(b2.x - player.x, 2) + Math.pow(b2.y - player.y, 2)); if (distToPlayer > 600) { roadBlocks.push(b2); } } } if (roadBlocks.length > 0) { var idx2 = Math.floor(Math.random() * roadBlocks.length); var newShooter = new PoliceShooter(); newShooter.x = roadBlocks[idx2].x + (Math.random() - 0.5) * 100; newShooter.y = roadBlocks[idx2].y + (Math.random() - 0.5) * 100; if (policeAggro) { newShooter.target = player; newShooter.wasShotAt = true; } else { newShooter.target = null; newShooter.wasShotAt = false; } policeShooters.push(newShooter); game.addChild(newShooter); } } addScore(15); // Increase wanted level by 1 (max 5) when police shooter is killed wantedLevel = Math.min(5, wantedLevel + 1); updateWantedDisplay(); // Only aggro police if wantedLevel is 5 if (wantedLevel === 5) { for (var p = 0; p < policeShooters.length; p++) { policeShooters[p].wasShotAt = true; policeShooters[p].target = player; } for (var p = 0; p < policeCars.length; p++) { policeCars[p].target = player; } policeAggro = true; } // Only allow one run over per car per frame break; } } // Run over police cars for (var pc = policeCars.length - 1; pc >= 0; pc--) { var police = policeCars[pc]; if (Math.abs(police.x - car.x) < 90 && Math.abs(police.y - car.y) < 70) { // Police car killed by car // Drop a gun at police car's position var gunDrop = new Container(); gunDrop.asset = gunDrop.attachAsset('gun', { anchorX: 0.5, anchorY: 0.5 }); gunDrop.gunLabel = new Text2('gun', { size: 38, fill: 0xFFFFFF }); gunDrop.gunLabel.anchor.set(0.5, 1); gunDrop.gunLabel.y = -30; gunDrop.addChild(gunDrop.gunLabel); gunDrop.x = police.x; gunDrop.y = police.y; gunDrop.isGunPickup = true; game.addChild(gunDrop); if (typeof gunPickups === "undefined") gunPickups = []; gunPickups.push(gunDrop); police.destroy(); policeCars.splice(pc, 1); addScore(20); // Increase wanted level by 1 (max 5) when police car is killed wantedLevel = Math.min(5, wantedLevel + 1); updateWantedDisplay(); // Only aggro police if wantedLevel is 5 if (wantedLevel === 5 && typeof spawned5StarPolice === "undefined") { for (var p = 0; p < policeShooters.length; p++) { policeShooters[p].wasShotAt = true; policeShooters[p].target = player; } for (var p = 0; p < policeCars.length; p++) { policeCars[p].target = player; } policeAggro = true; // Spawn 5 police cars at random road blocks (not near player) var roadBlocks = []; for (var i = 0; i < cityBlocks.length; i++) { if (cityBlocks[i].type === 'road') { var distToPlayer = Math.sqrt(Math.pow(cityBlocks[i].x - player.x, 2) + Math.pow(cityBlocks[i].y - player.y, 2)); if (distToPlayer > 400) { roadBlocks.push(cityBlocks[i]); } } } for (var s = 0; s < 5; s++) { if (roadBlocks.length > 0) { var idx = Math.floor(Math.random() * roadBlocks.length); var b = roadBlocks[idx]; var newPolice = spawnPolice(b.x, b.y); newPolice.target = player; // Remove this block from roadBlocks to avoid double-spawn at same spot roadBlocks.splice(idx, 1); } } spawned5StarPolice = true; } // Only allow one run over per car per frame break; } } } } } // Money pickup check var px = player.inCar ? player.inCar.x : player.x; var py = player.inCar ? player.inCar.y : player.y; for (var i = moneyPickups.length - 1; i >= 0; i--) { var m = moneyPickups[i]; if (Math.abs(m.x - px) < 60 && Math.abs(m.y - py) < 60) { playerMoney += m.value; updateMoneyDisplay(); m.destroy(); moneyPickups.splice(i, 1); // Show "+50 money" text for 1 second at center-top of screen if (typeof moneyPickupText !== "undefined" && moneyPickupText.parent) { moneyPickupText.parent.removeChild(moneyPickupText); moneyPickupText = undefined; } moneyPickupText = new Text2("+50 money", { size: 120, fill: 0x44FF44 }); moneyPickupText.anchor.set(0.5, 0); moneyPickupText.x = 2048 / 2; moneyPickupText.y = 320; LK.gui.addChild(moneyPickupText); LK.setTimeout(function () { if (moneyPickupText && moneyPickupText.parent) { moneyPickupText.parent.removeChild(moneyPickupText); moneyPickupText = undefined; } }, 1000); } } // Gun pickup check if (typeof gunPickups === "undefined") gunPickups = []; for (var i = gunPickups.length - 1; i >= 0; i--) { var g = gunPickups[i]; if (Math.abs(g.x - px) < 60 && Math.abs(g.y - py) < 60) { // Player picks up gun: restore ammo to 100 playerAmmo = 100; if (typeof updateAmmoDisplay === "function") updateAmmoDisplay(); g.destroy(); gunPickups.splice(i, 1); // Show "+1 gun" text for 1 second at center-top of screen if (typeof gunPickupText !== "undefined" && gunPickupText.parent) { gunPickupText.parent.removeChild(gunPickupText); gunPickupText = undefined; } gunPickupText = new Text2("+1 gun", { size: 120, fill: 0xFFF700 }); gunPickupText.anchor.set(0.5, 0); // Place at top center, but not in top left 100x100 gunPickupText.x = 2048 / 2; gunPickupText.y = 180; LK.gui.addChild(gunPickupText); // Remove after 1 second LK.setTimeout(function () { if (gunPickupText && gunPickupText.parent) { gunPickupText.parent.removeChild(gunPickupText); gunPickupText = undefined; } }, 1000); // Optionally: add logic for ammo, weapon upgrade, etc. } } // Mission check if (mission.active) { var px = player.inCar ? player.inCar.x : player.x; var py = player.inCar ? player.inCar.y : player.y; if (Math.abs(mission.x - px) < 80 && Math.abs(mission.y - py) < 80) { // Complete mission addScore(10 * wantedLevel); mission.active = false; mission.visible = false; // Increase wanted level, spawn more police wantedLevel = Math.min(5, wantedLevel + 1); updateWantedDisplay(); if (wantedLevel > policeCars.length) { // Spawn new police at random road var roadBlocks = []; for (var i = 0; i < cityBlocks.length; i++) { if (cityBlocks[i].type === 'road') roadBlocks.push(cityBlocks[i]); } var idx = Math.floor(Math.random() * roadBlocks.length); var b = roadBlocks[idx]; spawnPolice(b.x, b.y); } // Next mission after short delay LK.setTimeout(function () { resetMission(); }, 1200); } } // Win condition removed: game never ends when score >= 100 }; // --- Start State --- addScore(0); updateWantedDisplay(); timerTxt.setText(timeLeft + ''); resetMission(); playerHealth = 5; updateHealthDisplay(); playerMoney = 0; updateMoneyDisplay(); policeAggro = false; var policeHitCount = 0; ; ;
===================================================================
--- original.js
+++ change.js
@@ -348,8 +348,17 @@
marketEntrance.asset.height = 300;
marketEntrance.x = (gridCols - 1) / 2 * blockSize + blockSize / 2 + 300; // rightmost road col + offset
marketEntrance.y = 0 * blockSize + blockSize / 2;
marketEntrance.isMarketEntrance = true;
+// Add 'MARKET' label above the market entrance
+marketEntrance.marketLabel = new Text2('MARKET', {
+ size: 90,
+ fill: "#fff"
+});
+marketEntrance.marketLabel.anchor.set(0.5, 1);
+marketEntrance.marketLabel.x = 0;
+marketEntrance.marketLabel.y = -170;
+marketEntrance.addChild(marketEntrance.marketLabel);
game.addChild(marketEntrance);
// Market interior (hidden until entered)
var marketInterior = new Container();
marketInterior.asset = marketInterior.attachAsset('building', {