User prompt
Oyun neden açılmıyor?
User prompt
Hatalı kodları düzenle
Code edit (1 edits merged)
Please save this source code
User prompt
City Chaos: Open World Adventure
Initial prompt
Oynum GTA tarzı olsun arabalar olsun onların içine gire bilelim ve çıka bilelim ve arabaları sürelim ayrıca rasgele yapay zekalı adamlar olsun yolda yürüsünler ama bize saldırmasınlar biz saldırırsak bize saldırsınlar adamların can barı olsun bizim bir silahımız olsun şehir açık dünya olsun büyük şehir olsun yol olsun ve kaldırım da adamlar kaldırımda yürüsün ve yol olsun yolda arabalar olsun o arabalarda ancak yolda gitsin yolun kenarında arabalar olsun biz ona bine bilelim ayrıca arabalara ve kaldırıma carpal bilelim arabanın benzini bitince araba dursun arabanın benzinin benzin barı OLSUN bar bitince araba dursun çalışmasın ve binalarda olsun şehir büyük olsun ve oyunda haritada olsun ve bölgeler olsun bölgelerin isimini Sen ver o bölgelerin isimi haritada da olsun
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { defaults: { highScore: 0, lastDistrict: "downtown" } }); /**** * Classes ****/ var Building = Container.expand(function (width, height) { var self = Container.call(this); width = width || 200; height = height || 200; var buildingGraphics = self.attachAsset('building', { anchorX: 0.5, anchorY: 0.5, width: width, height: height }); return self; }); var District = Container.expand(function (name, color, x, y, width, height) { var self = Container.call(this); self.name = name; self.color = color; self.bounds = { x: x, y: y, width: width, height: height }; // Create district text label self.label = new Text2(name, { size: 40, fill: 0xFFFFFF }); self.label.anchor.set(0.5, 0.5); self.label.x = x + width / 2; self.label.y = y + height / 2; self.addChild(self.label); // Check if a point is inside this district self.contains = function (px, py) { return px >= self.bounds.x && px <= self.bounds.x + self.bounds.width && py >= self.bounds.y && py <= self.bounds.y + self.bounds.height; }; return self; }); var FuelGauge = Container.expand(function () { var self = Container.call(this); // Create fuel gauge background var gaugeBackground = self.attachAsset('fuel_bar_background', { anchorX: 0, anchorY: 0 }); // Create fuel bar self.fuelBar = LK.getAsset('fuel_bar', { anchorX: 0, anchorY: 0 }); self.addChild(self.fuelBar); // Create fuel text self.fuelText = new Text2('FUEL', { size: 20, fill: 0xFFFFFF }); self.fuelText.anchor.set(0.5, 0.5); self.fuelText.x = 100; self.fuelText.y = 15; self.addChild(self.fuelText); self.update = function (fuelLevel) { // Update fuel bar width based on fuel level (0-100) var fuelPercentage = Math.max(0, Math.min(100, fuelLevel)) / 100; self.fuelBar.width = 200 * fuelPercentage; // Update color based on fuel level if (fuelPercentage < 0.3) { self.fuelBar.tint = 0xff0000; // Red when low } else if (fuelPercentage < 0.6) { self.fuelBar.tint = 0xffff00; // Yellow when medium } else { self.fuelBar.tint = 0x00ff00; // Green when high } }; return self; }); var GameObject = Container.expand(function () { var self = Container.call(this); self.velocity = { x: 0, y: 0 }; self.speed = 0; self.maxSpeed = 5; self.direction = 0; self.active = true; self.move = function () { if (!self.active) { return; } self.x += self.velocity.x; self.y += self.velocity.y; }; self.setVelocity = function (speed, direction) { self.speed = Math.min(speed, self.maxSpeed); self.direction = direction; self.velocity.x = Math.cos(direction) * self.speed; self.velocity.y = Math.sin(direction) * self.speed; }; self.checkBoundaries = function () { // Basic boundary checking to keep objects in the game world var buffer = 50; if (self.x < buffer) { self.x = buffer; self.velocity.x = 0; } else if (self.x > worldWidth - buffer) { self.x = worldWidth - buffer; self.velocity.x = 0; } if (self.y < buffer) { self.y = buffer; self.velocity.y = 0; } else if (self.y > worldHeight - buffer) { self.y = worldHeight - buffer; self.velocity.y = 0; } }; return self; }); var Vehicle = GameObject.expand(function (type) { var self = GameObject.call(this); self.type = type || 'car'; self.isOccupied = false; self.fuel = 100; self.maxFuel = 100; // Configure vehicle based on type switch (self.type) { case 'car': self.maxSpeed = 8; self.fuelConsumption = 0.1; var vehicleGraphics = self.attachAsset('car', { anchorX: 0.5, anchorY: 0.5 }); break; case 'truck': self.maxSpeed = 6; self.fuelConsumption = 0.15; var vehicleGraphics = self.attachAsset('truck', { anchorX: 0.5, anchorY: 0.5 }); break; case 'motorcycle': self.maxSpeed = 10; self.fuelConsumption = 0.08; var vehicleGraphics = self.attachAsset('motorcycle', { anchorX: 0.5, anchorY: 0.5 }); break; } self.update = function () { if (self.isOccupied) { // When occupied, update fuel if (self.fuel > 0 && (self.velocity.x !== 0 || self.velocity.y !== 0)) { self.fuel -= self.fuelConsumption; if (self.fuel <= 0) { self.fuel = 0; self.velocity.x = 0; self.velocity.y = 0; } } } else { // AI behavior when not occupied if (Math.random() < 0.01) { var angle = Math.random() * Math.PI * 2; self.setVelocity(self.maxSpeed * 0.5, angle); } } self.move(); self.checkBoundaries(); // Update rotation based on movement direction if (self.velocity.x !== 0 || self.velocity.y !== 0) { self.rotation = Math.atan2(self.velocity.y, self.velocity.x); } }; return self; }); var Player = GameObject.expand(function () { var self = GameObject.call(this); var playerGraphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); self.health = 100; self.maxSpeed = 6; self.inVehicle = null; self.hasWeapon = true; self.score = 0; self.update = function () { if (self.inVehicle) { return; } self.move(); self.checkBoundaries(); }; self.takeDamage = function (amount) { self.health -= amount; LK.effects.flashObject(self, 0xff0000, 300); if (self.health <= 0) { self.health = 0; LK.showGameOver(); } }; self.exitVehicle = function () { if (!self.inVehicle) { return; } // Position player next to vehicle self.x = self.inVehicle.x + 80; self.y = self.inVehicle.y; self.inVehicle.isOccupied = false; self.inVehicle = null; self.visible = true; }; self.shootBullet = function () { if (!self.hasWeapon || self.inVehicle) { return; } var bullet = new Bullet(); bullet.x = self.x; bullet.y = self.y; bullet.lastWasIntersecting = false; bullet.setVelocity(10, self.direction); bullets.push(bullet); gameWorld.addChild(bullet); LK.getSound('gun_shot').play(); }; return self; }); var Pedestrian = GameObject.expand(function () { var self = GameObject.call(this); var pedestrianGraphics = self.attachAsset('pedestrian', { anchorX: 0.5, anchorY: 0.5 }); self.health = 50; self.maxSpeed = 2; self.isAggressive = false; self.targetX = self.x; self.targetY = self.y; self.decisionCooldown = 0; self.update = function () { self.decisionCooldown--; if (self.decisionCooldown <= 0) { // Make new decision about movement if (Math.random() < 0.7) { // Random movement self.targetX = self.x + (Math.random() * 400 - 200); self.targetY = self.y + (Math.random() * 400 - 200); // Ensure target is within bounds self.targetX = Math.max(100, Math.min(worldWidth - 100, self.targetX)); self.targetY = Math.max(100, Math.min(worldHeight - 100, self.targetY)); // Calculate direction to target var dx = self.targetX - self.x; var dy = self.targetY - self.y; var angle = Math.atan2(dy, dx); self.setVelocity(self.maxSpeed * 0.5 + Math.random() * self.maxSpeed * 0.5, angle); } else { // Stop and idle self.velocity.x = 0; self.velocity.y = 0; } // Set cooldown before next decision self.decisionCooldown = 60 + Math.floor(Math.random() * 120); } // If aggressive, chase player if (self.isAggressive && player && !player.inVehicle) { var dx = player.x - self.x; var dy = player.y - self.y; var distanceToPlayer = Math.sqrt(dx * dx + dy * dy); if (distanceToPlayer < 500) { var angle = Math.atan2(dy, dx); self.setVelocity(self.maxSpeed, angle); // Attack player if close enough if (distanceToPlayer < 60 && Math.random() < 0.02) { player.takeDamage(5); } } } self.move(); self.checkBoundaries(); // Update rotation based on movement direction if (self.velocity.x !== 0 || self.velocity.y !== 0) { self.rotation = Math.atan2(self.velocity.y, self.velocity.x); } }; self.takeDamage = function (amount) { self.health -= amount; LK.effects.flashObject(self, 0xff0000, 300); LK.getSound('pedestrian_hurt').play(); // Turn aggressive when damaged if (!self.isAggressive && self.health > 0) { self.isAggressive = true; } if (self.health <= 0) { self.health = 0; self.active = false; self.visible = false; // Add score for defeating pedestrian if (player) { player.score += 10; updateScore(); } // Remove from game var index = pedestrians.indexOf(self); if (index > -1) { pedestrians.splice(index, 1); } self.destroy(); } }; return self; }); var Bullet = GameObject.expand(function () { var self = GameObject.call(this); var bulletGraphics = self.attachAsset('bullet', { anchorX: 0.5, anchorY: 0.5 }); self.damage = 20; self.lifespan = 60; // frames alive before auto-destruction self.update = function () { self.move(); self.lifespan--; // Check if bullet has expired if (self.lifespan <= 0) { self.active = false; return; } // Ensure lastIntersecting is initialized if (self.lastIntersecting === undefined) { self.lastIntersecting = false; } }; return self; }); var MiniMap = Container.expand(function () { var self = Container.call(this); // Create minimap background var mapBackground = self.attachAsset('minimap_background', { anchorX: 0, anchorY: 0, alpha: 0.7 }); // Player indicator on minimap self.playerIndicator = LK.getAsset('minimap_player', { anchorX: 0.5, anchorY: 0.5 }); self.addChild(self.playerIndicator); // Elements collection for buildings and roads self.elements = []; self.addElement = function (type, x, y, width, height, rotation) { var element; if (type === 'building') { element = LK.getAsset('minimap_building', { anchorX: 0.5, anchorY: 0.5, width: width / 10, // Scale down for minimap height: height / 10 }); } else if (type === 'road') { element = LK.getAsset('minimap_road', { anchorX: 0.5, anchorY: 0.5, width: width / 10, height: height / 10 }); } if (element) { element.x = x / 10; // Scale to minimap coordinates element.y = y / 10; if (rotation !== undefined) { element.rotation = rotation; } self.addChild(element); self.elements.push(element); } }; self.update = function () { if (player) { // Update player indicator position on minimap self.playerIndicator.x = player.x / 10; self.playerIndicator.y = player.y / 10; } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x222222 }); /**** * Game Code ****/ // World dimensions var worldWidth = 4000; var worldHeight = 4000; // Game objects var player = null; var gameWorld = null; var camera = null; var minimap = null; var fuelGauge = null; var scoreText = null; var districtText = null; // Collections var vehicles = []; var pedestrians = []; var buildings = []; var roads = []; var bullets = []; var districts = []; // Game state var currentDistrict = null; var dragMode = false; // Initialize the game world function initGameWorld() { // Create world container gameWorld = new Container(); game.addChild(gameWorld); // Create districts createDistricts(); // Create city layout createCityLayout(); // Create player player = new Player(); player.x = worldWidth / 2; player.y = worldHeight / 2; gameWorld.addChild(player); // Create vehicles createVehicles(); // Create pedestrians createPedestrians(); // Setup camera camera = { x: 0, y: 0, update: function update() { // Center camera on player if (player) { var targetX = -player.x + 2048 / 2; var targetY = -player.y + 2732 / 2; // Smooth camera movement camera.x += (targetX - camera.x) * 0.1; camera.y += (targetY - camera.y) * 0.1; // Apply camera position to game world gameWorld.x = camera.x; gameWorld.y = camera.y; } } }; // Create minimap minimap = new MiniMap(); minimap.x = 2048 - 420; minimap.y = 20; LK.gui.addChild(minimap); // Add buildings and roads to minimap for (var i = 0; i < buildings.length; i++) { minimap.addElement('building', buildings[i].x, buildings[i].y, buildings[i].width, buildings[i].height); } for (var i = 0; i < roads.length; i++) { minimap.addElement('road', roads[i].x, roads[i].y, roads[i].width, roads[i].height, roads[i].rotation); } // Create fuel gauge fuelGauge = new FuelGauge(); fuelGauge.x = 20; fuelGauge.y = 20; fuelGauge.visible = false; // Only visible when in vehicle LK.gui.addChild(fuelGauge); // Create score display scoreText = new Text2('SCORE: 0', { size: 40, fill: 0xFFFFFF }); scoreText.anchor.set(0.5, 0); LK.gui.top.addChild(scoreText); // Create district display districtText = new Text2('', { size: 30, fill: 0xFFFFFF }); districtText.anchor.set(0, 0); districtText.x = 20; districtText.y = 70; LK.gui.addChild(districtText); // Play background music LK.playMusic('city_ambience'); } function createDistricts() { // Create different city districts districts.push(new District('Downtown', 0xff3333, 0, 0, worldWidth / 3, worldHeight / 3)); districts.push(new District('Suburbs', 0x33cc33, worldWidth / 3, 0, worldWidth / 3, worldHeight / 3)); districts.push(new District('Industrial', 0x3366ff, 2 * worldWidth / 3, 0, worldWidth / 3, worldHeight / 3)); districts.push(new District('Harbor', 0xffcc00, 0, worldHeight / 3, worldWidth / 3, worldHeight / 3)); districts.push(new District('Business', 0x9933ff, worldWidth / 3, worldHeight / 3, worldWidth / 3, worldHeight / 3)); districts.push(new District('Park', 0x33cccc, 2 * worldWidth / 3, worldHeight / 3, worldWidth / 3, worldHeight / 3)); districts.push(new District('Shopping', 0xff9933, 0, 2 * worldHeight / 3, worldWidth / 3, worldHeight / 3)); districts.push(new District('Residential', 0xcc33cc, worldWidth / 3, 2 * worldHeight / 3, worldWidth / 3, worldHeight / 3)); districts.push(new District('Entertainment', 0xffff33, 2 * worldWidth / 3, 2 * worldHeight / 3, worldWidth / 3, worldHeight / 3)); // Add district boundaries for (var i = 0; i < districts.length; i++) { gameWorld.addChild(districts[i]); // Create visual boundaries between districts if (i % 3 !== 2) { // Vertical boundaries (except last column) var boundary = LK.getAsset('district_boundary', { anchorX: 0.5, anchorY: 0.5 }); boundary.x = districts[i].bounds.x + districts[i].bounds.width; boundary.y = districts[i].bounds.y + districts[i].bounds.height / 2; boundary.height = districts[i].bounds.height; gameWorld.addChild(boundary); } if (i < 6) { // Horizontal boundaries (except last row) var boundary = LK.getAsset('district_boundary', { anchorX: 0.5, anchorY: 0.5 }); boundary.x = districts[i].bounds.x + districts[i].bounds.width / 2; boundary.y = districts[i].bounds.y + districts[i].bounds.height; boundary.rotation = Math.PI / 2; boundary.height = districts[i].bounds.width; gameWorld.addChild(boundary); } } } function createCityLayout() { // Create buildings for (var i = 0; i < 200; i++) { var building = new Building(100 + Math.random() * 300, // Random width 100 + Math.random() * 300 // Random height ); // Position building randomly within the world building.x = Math.random() * worldWidth; building.y = Math.random() * worldHeight; // Prevent overlapping with existing buildings (simplified) var overlapping = false; for (var j = 0; j < buildings.length; j++) { var other = buildings[j]; var distance = Math.sqrt(Math.pow(building.x - other.x, 2) + Math.pow(building.y - other.y, 2)); if (distance < 350) { overlapping = true; break; } } if (!overlapping) { buildings.push(building); gameWorld.addChild(building); } } // Create roads for (var i = 0; i < 40; i++) { // Horizontal roads var roadH = LK.getAsset('road', { anchorX: 0.5, anchorY: 0.5, width: worldWidth - 200, height: 120 }); roadH.x = worldWidth / 2; roadH.y = (i + 1) * (worldHeight / 41); roads.push(roadH); gameWorld.addChild(roadH); // Add sidewalks alongside roads var sidewalkH1 = LK.getAsset('sidewalk', { anchorX: 0.5, anchorY: 0.5, width: worldWidth - 200, height: 50 }); sidewalkH1.x = worldWidth / 2; sidewalkH1.y = roadH.y - 85; gameWorld.addChild(sidewalkH1); var sidewalkH2 = LK.getAsset('sidewalk', { anchorX: 0.5, anchorY: 0.5, width: worldWidth - 200, height: 50 }); sidewalkH2.x = worldWidth / 2; sidewalkH2.y = roadH.y + 85; gameWorld.addChild(sidewalkH2); } for (var i = 0; i < 30; i++) { // Vertical roads var roadV = LK.getAsset('road', { anchorX: 0.5, anchorY: 0.5, width: 120, height: worldHeight - 200 }); roadV.rotation = Math.PI / 2; roadV.x = (i + 1) * (worldWidth / 31); roadV.y = worldHeight / 2; roads.push(roadV); gameWorld.addChild(roadV); // Add sidewalks alongside roads var sidewalkV1 = LK.getAsset('sidewalk', { anchorX: 0.5, anchorY: 0.5, width: 50, height: worldHeight - 200 }); sidewalkV1.x = roadV.x - 85; sidewalkV1.y = worldHeight / 2; sidewalkV1.rotation = Math.PI / 2; gameWorld.addChild(sidewalkV1); var sidewalkV2 = LK.getAsset('sidewalk', { anchorX: 0.5, anchorY: 0.5, width: 50, height: worldHeight - 200 }); sidewalkV2.x = roadV.x + 85; sidewalkV2.y = worldHeight / 2; sidewalkV2.rotation = Math.PI / 2; gameWorld.addChild(sidewalkV2); } } function createVehicles() { // Vehicle types var types = ['car', 'truck', 'motorcycle']; // Create a variety of vehicles for (var i = 0; i < 30; i++) { var type = types[Math.floor(Math.random() * types.length)]; var vehicle = new Vehicle(type); // Position vehicle on roads var onVerticalRoad = Math.random() < 0.5; if (onVerticalRoad) { vehicle.x = (Math.floor(Math.random() * 30) + 1) * (worldWidth / 31); vehicle.y = Math.random() * worldHeight; } else { vehicle.x = Math.random() * worldWidth; vehicle.y = (Math.floor(Math.random() * 40) + 1) * (worldHeight / 41); } vehicles.push(vehicle); gameWorld.addChild(vehicle); } } function createPedestrians() { // Create pedestrians for (var i = 0; i < 50; i++) { var pedestrian = new Pedestrian(); // Position pedestrian randomly on sidewalks pedestrian.x = Math.random() * worldWidth; pedestrian.y = Math.random() * worldHeight; pedestrians.push(pedestrian); gameWorld.addChild(pedestrian); } } function updateScore() { if (player) { scoreText.setText('SCORE: ' + player.score); // Update high score if needed if (player.score > storage.highScore) { storage.highScore = player.score; } } } function checkCollisions() { // Player with vehicles (for entering) if (player && !player.inVehicle) { for (var i = 0; i < vehicles.length; i++) { var vehicle = vehicles[i]; if (!vehicle.isOccupied && player.intersects(vehicle)) { // Player can enter vehicle if (dragMode) { // Enter vehicle player.inVehicle = vehicle; vehicle.isOccupied = true; player.visible = false; // Play sound LK.getSound('car_start').play(); // Show fuel gauge fuelGauge.visible = true; fuelGauge.update(vehicle.fuel); break; } } } } // Bullets with pedestrians and vehicles for (var i = bullets.length - 1; i >= 0; i--) { var bullet = bullets[i]; // Initialize lastWasIntersecting if not present if (bullet.lastWasIntersecting === undefined) { bullet.lastWasIntersecting = false; } // Check collision with pedestrians for (var j = 0; j < pedestrians.length; j++) { if (bullet.active && !bullet.lastWasIntersecting && bullet.intersects(pedestrians[j])) { pedestrians[j].takeDamage(bullet.damage); bullet.active = false; break; } } // Check collision with vehicles for (var j = 0; j < vehicles.length; j++) { if (bullet.active && bullet.intersects(vehicles[j])) { // Damage vehicle or make it explode LK.effects.flashObject(vehicles[j], 0xff0000, 300); LK.getSound('collision').play(); // Bullets stop when hitting vehicles bullet.active = false; break; } } // Check collision with buildings for (var j = 0; j < buildings.length; j++) { if (bullet.active && bullet.intersects(buildings[j])) { bullet.active = false; break; } } // Remove inactive bullets if (!bullet.active) { bullet.destroy(); bullets.splice(i, 1); } } // Vehicle with vehicle collisions for (var i = 0; i < vehicles.length; i++) { for (var j = i + 1; j < vehicles.length; j++) { if (vehicles[i].intersects(vehicles[j])) { // Simplified collision response - just reverse direction vehicles[i].velocity.x *= -0.5; vehicles[i].velocity.y *= -0.5; vehicles[j].velocity.x *= -0.5; vehicles[j].velocity.y *= -0.5; LK.getSound('collision').play(); } } } // Vehicle with building collisions for (var i = 0; i < vehicles.length; i++) { for (var j = 0; j < buildings.length; j++) { if (vehicles[i].intersects(buildings[j])) { // Simplified collision response - just stop vehicles[i].velocity.x = 0; vehicles[i].velocity.y = 0; // Move away from building var dx = vehicles[i].x - buildings[j].x; var dy = vehicles[i].y - buildings[j].y; var angle = Math.atan2(dy, dx); vehicles[i].x += Math.cos(angle) * 5; vehicles[i].y += Math.sin(angle) * 5; if (vehicles[i].isOccupied) { LK.getSound('collision').play(); } } } } } function checkCurrentDistrict() { // Find what district the player is in if (player) { var foundDistrict = null; for (var i = 0; i < districts.length; i++) { if (districts[i].contains(player.x, player.y)) { foundDistrict = districts[i]; break; } } if (foundDistrict !== currentDistrict) { currentDistrict = foundDistrict; if (currentDistrict) { // Update district display districtText.setText('DISTRICT: ' + currentDistrict.name); // Save last district storage.lastDistrict = currentDistrict.name; // Show district notification var notification = new Text2('Entering ' + currentDistrict.name, { size: 60, fill: 0xFFFFFF }); notification.anchor.set(0.5, 0.5); notification.x = 2048 / 2; notification.y = 2732 / 2; LK.gui.addChild(notification); // Fade out notification tween(notification, { alpha: 0 }, { duration: 2000, onFinish: function onFinish() { notification.destroy(); } }); } } } } function handleMove(x, y, obj) { // Convert screen coordinates to world coordinates var worldX = x - gameWorld.x; var worldY = y - gameWorld.y; if (dragMode && player) { if (player.inVehicle) { // If in vehicle, set direction based on touch position var dx = worldX - player.inVehicle.x; var dy = worldY - player.inVehicle.y; var angle = Math.atan2(dy, dx); // Only move if there's fuel if (player.inVehicle.fuel > 0) { player.inVehicle.setVelocity(player.inVehicle.maxSpeed, angle); } } else { // If on foot, move player towards touch position var dx = worldX - player.x; var dy = worldY - player.y; var angle = Math.atan2(dy, dx); player.setVelocity(player.maxSpeed, angle); } } } game.down = function (x, y, obj) { dragMode = true; handleMove(x, y, obj); }; game.up = function (x, y, obj) { dragMode = false; // Stop player movement when touch is released if (player) { if (player.inVehicle) { player.inVehicle.velocity.x = 0; player.inVehicle.velocity.y = 0; } else { player.velocity.x = 0; player.velocity.y = 0; } } // Check if tap was to exit vehicle if (player && player.inVehicle) { // Double check if drag distance was small enough to be considered a tap var dx = x - (player.inVehicle.x + gameWorld.x); var dy = y - (player.inVehicle.y + gameWorld.y); var dragDistance = Math.sqrt(dx * dx + dy * dy); if (dragDistance < 50) { // Exit vehicle player.exitVehicle(); fuelGauge.visible = false; } } // Check if tap was to shoot if (player && !player.inVehicle) { // Convert screen coordinates to world coordinates var worldX = x - gameWorld.x; var worldY = y - gameWorld.y; // Calculate direction to shoot var dx = worldX - player.x; var dy = worldY - player.y; player.direction = Math.atan2(dy, dx); // Shoot bullet player.shootBullet(); } }; game.move = handleMove; game.update = function () { // Skip if game not initialized yet if (!player || !gameWorld) { return; } // Update all game objects player.update(); for (var i = 0; i < vehicles.length; i++) { vehicles[i].update(); } for (var i = 0; i < pedestrians.length; i++) { pedestrians[i].update(); } for (var i = 0; i < bullets.length; i++) { // Save intersection state before updating for (var j = 0; j < pedestrians.length; j++) { if (bullets[i].intersects(pedestrians[j])) { bullets[i].lastWasIntersecting = true; break; } else { bullets[i].lastWasIntersecting = false; } } bullets[i].update(); } // Update camera camera.update(); // Update minimap minimap.update(); // Update fuel gauge if in vehicle if (player.inVehicle) { fuelGauge.update(player.inVehicle.fuel); } // Check collisions checkCollisions(); // Check current district checkCurrentDistrict(); }; // Initialize game world initGameWorld();
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
defaults: {
highScore: 0,
lastDistrict: "downtown"
}
});
/****
* Classes
****/
var Building = Container.expand(function (width, height) {
var self = Container.call(this);
width = width || 200;
height = height || 200;
var buildingGraphics = self.attachAsset('building', {
anchorX: 0.5,
anchorY: 0.5,
width: width,
height: height
});
return self;
});
var District = Container.expand(function (name, color, x, y, width, height) {
var self = Container.call(this);
self.name = name;
self.color = color;
self.bounds = {
x: x,
y: y,
width: width,
height: height
};
// Create district text label
self.label = new Text2(name, {
size: 40,
fill: 0xFFFFFF
});
self.label.anchor.set(0.5, 0.5);
self.label.x = x + width / 2;
self.label.y = y + height / 2;
self.addChild(self.label);
// Check if a point is inside this district
self.contains = function (px, py) {
return px >= self.bounds.x && px <= self.bounds.x + self.bounds.width && py >= self.bounds.y && py <= self.bounds.y + self.bounds.height;
};
return self;
});
var FuelGauge = Container.expand(function () {
var self = Container.call(this);
// Create fuel gauge background
var gaugeBackground = self.attachAsset('fuel_bar_background', {
anchorX: 0,
anchorY: 0
});
// Create fuel bar
self.fuelBar = LK.getAsset('fuel_bar', {
anchorX: 0,
anchorY: 0
});
self.addChild(self.fuelBar);
// Create fuel text
self.fuelText = new Text2('FUEL', {
size: 20,
fill: 0xFFFFFF
});
self.fuelText.anchor.set(0.5, 0.5);
self.fuelText.x = 100;
self.fuelText.y = 15;
self.addChild(self.fuelText);
self.update = function (fuelLevel) {
// Update fuel bar width based on fuel level (0-100)
var fuelPercentage = Math.max(0, Math.min(100, fuelLevel)) / 100;
self.fuelBar.width = 200 * fuelPercentage;
// Update color based on fuel level
if (fuelPercentage < 0.3) {
self.fuelBar.tint = 0xff0000; // Red when low
} else if (fuelPercentage < 0.6) {
self.fuelBar.tint = 0xffff00; // Yellow when medium
} else {
self.fuelBar.tint = 0x00ff00; // Green when high
}
};
return self;
});
var GameObject = Container.expand(function () {
var self = Container.call(this);
self.velocity = {
x: 0,
y: 0
};
self.speed = 0;
self.maxSpeed = 5;
self.direction = 0;
self.active = true;
self.move = function () {
if (!self.active) {
return;
}
self.x += self.velocity.x;
self.y += self.velocity.y;
};
self.setVelocity = function (speed, direction) {
self.speed = Math.min(speed, self.maxSpeed);
self.direction = direction;
self.velocity.x = Math.cos(direction) * self.speed;
self.velocity.y = Math.sin(direction) * self.speed;
};
self.checkBoundaries = function () {
// Basic boundary checking to keep objects in the game world
var buffer = 50;
if (self.x < buffer) {
self.x = buffer;
self.velocity.x = 0;
} else if (self.x > worldWidth - buffer) {
self.x = worldWidth - buffer;
self.velocity.x = 0;
}
if (self.y < buffer) {
self.y = buffer;
self.velocity.y = 0;
} else if (self.y > worldHeight - buffer) {
self.y = worldHeight - buffer;
self.velocity.y = 0;
}
};
return self;
});
var Vehicle = GameObject.expand(function (type) {
var self = GameObject.call(this);
self.type = type || 'car';
self.isOccupied = false;
self.fuel = 100;
self.maxFuel = 100;
// Configure vehicle based on type
switch (self.type) {
case 'car':
self.maxSpeed = 8;
self.fuelConsumption = 0.1;
var vehicleGraphics = self.attachAsset('car', {
anchorX: 0.5,
anchorY: 0.5
});
break;
case 'truck':
self.maxSpeed = 6;
self.fuelConsumption = 0.15;
var vehicleGraphics = self.attachAsset('truck', {
anchorX: 0.5,
anchorY: 0.5
});
break;
case 'motorcycle':
self.maxSpeed = 10;
self.fuelConsumption = 0.08;
var vehicleGraphics = self.attachAsset('motorcycle', {
anchorX: 0.5,
anchorY: 0.5
});
break;
}
self.update = function () {
if (self.isOccupied) {
// When occupied, update fuel
if (self.fuel > 0 && (self.velocity.x !== 0 || self.velocity.y !== 0)) {
self.fuel -= self.fuelConsumption;
if (self.fuel <= 0) {
self.fuel = 0;
self.velocity.x = 0;
self.velocity.y = 0;
}
}
} else {
// AI behavior when not occupied
if (Math.random() < 0.01) {
var angle = Math.random() * Math.PI * 2;
self.setVelocity(self.maxSpeed * 0.5, angle);
}
}
self.move();
self.checkBoundaries();
// Update rotation based on movement direction
if (self.velocity.x !== 0 || self.velocity.y !== 0) {
self.rotation = Math.atan2(self.velocity.y, self.velocity.x);
}
};
return self;
});
var Player = GameObject.expand(function () {
var self = GameObject.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 100;
self.maxSpeed = 6;
self.inVehicle = null;
self.hasWeapon = true;
self.score = 0;
self.update = function () {
if (self.inVehicle) {
return;
}
self.move();
self.checkBoundaries();
};
self.takeDamage = function (amount) {
self.health -= amount;
LK.effects.flashObject(self, 0xff0000, 300);
if (self.health <= 0) {
self.health = 0;
LK.showGameOver();
}
};
self.exitVehicle = function () {
if (!self.inVehicle) {
return;
}
// Position player next to vehicle
self.x = self.inVehicle.x + 80;
self.y = self.inVehicle.y;
self.inVehicle.isOccupied = false;
self.inVehicle = null;
self.visible = true;
};
self.shootBullet = function () {
if (!self.hasWeapon || self.inVehicle) {
return;
}
var bullet = new Bullet();
bullet.x = self.x;
bullet.y = self.y;
bullet.lastWasIntersecting = false;
bullet.setVelocity(10, self.direction);
bullets.push(bullet);
gameWorld.addChild(bullet);
LK.getSound('gun_shot').play();
};
return self;
});
var Pedestrian = GameObject.expand(function () {
var self = GameObject.call(this);
var pedestrianGraphics = self.attachAsset('pedestrian', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 50;
self.maxSpeed = 2;
self.isAggressive = false;
self.targetX = self.x;
self.targetY = self.y;
self.decisionCooldown = 0;
self.update = function () {
self.decisionCooldown--;
if (self.decisionCooldown <= 0) {
// Make new decision about movement
if (Math.random() < 0.7) {
// Random movement
self.targetX = self.x + (Math.random() * 400 - 200);
self.targetY = self.y + (Math.random() * 400 - 200);
// Ensure target is within bounds
self.targetX = Math.max(100, Math.min(worldWidth - 100, self.targetX));
self.targetY = Math.max(100, Math.min(worldHeight - 100, self.targetY));
// Calculate direction to target
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var angle = Math.atan2(dy, dx);
self.setVelocity(self.maxSpeed * 0.5 + Math.random() * self.maxSpeed * 0.5, angle);
} else {
// Stop and idle
self.velocity.x = 0;
self.velocity.y = 0;
}
// Set cooldown before next decision
self.decisionCooldown = 60 + Math.floor(Math.random() * 120);
}
// If aggressive, chase player
if (self.isAggressive && player && !player.inVehicle) {
var dx = player.x - self.x;
var dy = player.y - self.y;
var distanceToPlayer = Math.sqrt(dx * dx + dy * dy);
if (distanceToPlayer < 500) {
var angle = Math.atan2(dy, dx);
self.setVelocity(self.maxSpeed, angle);
// Attack player if close enough
if (distanceToPlayer < 60 && Math.random() < 0.02) {
player.takeDamage(5);
}
}
}
self.move();
self.checkBoundaries();
// Update rotation based on movement direction
if (self.velocity.x !== 0 || self.velocity.y !== 0) {
self.rotation = Math.atan2(self.velocity.y, self.velocity.x);
}
};
self.takeDamage = function (amount) {
self.health -= amount;
LK.effects.flashObject(self, 0xff0000, 300);
LK.getSound('pedestrian_hurt').play();
// Turn aggressive when damaged
if (!self.isAggressive && self.health > 0) {
self.isAggressive = true;
}
if (self.health <= 0) {
self.health = 0;
self.active = false;
self.visible = false;
// Add score for defeating pedestrian
if (player) {
player.score += 10;
updateScore();
}
// Remove from game
var index = pedestrians.indexOf(self);
if (index > -1) {
pedestrians.splice(index, 1);
}
self.destroy();
}
};
return self;
});
var Bullet = GameObject.expand(function () {
var self = GameObject.call(this);
var bulletGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.damage = 20;
self.lifespan = 60; // frames alive before auto-destruction
self.update = function () {
self.move();
self.lifespan--;
// Check if bullet has expired
if (self.lifespan <= 0) {
self.active = false;
return;
}
// Ensure lastIntersecting is initialized
if (self.lastIntersecting === undefined) {
self.lastIntersecting = false;
}
};
return self;
});
var MiniMap = Container.expand(function () {
var self = Container.call(this);
// Create minimap background
var mapBackground = self.attachAsset('minimap_background', {
anchorX: 0,
anchorY: 0,
alpha: 0.7
});
// Player indicator on minimap
self.playerIndicator = LK.getAsset('minimap_player', {
anchorX: 0.5,
anchorY: 0.5
});
self.addChild(self.playerIndicator);
// Elements collection for buildings and roads
self.elements = [];
self.addElement = function (type, x, y, width, height, rotation) {
var element;
if (type === 'building') {
element = LK.getAsset('minimap_building', {
anchorX: 0.5,
anchorY: 0.5,
width: width / 10,
// Scale down for minimap
height: height / 10
});
} else if (type === 'road') {
element = LK.getAsset('minimap_road', {
anchorX: 0.5,
anchorY: 0.5,
width: width / 10,
height: height / 10
});
}
if (element) {
element.x = x / 10; // Scale to minimap coordinates
element.y = y / 10;
if (rotation !== undefined) {
element.rotation = rotation;
}
self.addChild(element);
self.elements.push(element);
}
};
self.update = function () {
if (player) {
// Update player indicator position on minimap
self.playerIndicator.x = player.x / 10;
self.playerIndicator.y = player.y / 10;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x222222
});
/****
* Game Code
****/
// World dimensions
var worldWidth = 4000;
var worldHeight = 4000;
// Game objects
var player = null;
var gameWorld = null;
var camera = null;
var minimap = null;
var fuelGauge = null;
var scoreText = null;
var districtText = null;
// Collections
var vehicles = [];
var pedestrians = [];
var buildings = [];
var roads = [];
var bullets = [];
var districts = [];
// Game state
var currentDistrict = null;
var dragMode = false;
// Initialize the game world
function initGameWorld() {
// Create world container
gameWorld = new Container();
game.addChild(gameWorld);
// Create districts
createDistricts();
// Create city layout
createCityLayout();
// Create player
player = new Player();
player.x = worldWidth / 2;
player.y = worldHeight / 2;
gameWorld.addChild(player);
// Create vehicles
createVehicles();
// Create pedestrians
createPedestrians();
// Setup camera
camera = {
x: 0,
y: 0,
update: function update() {
// Center camera on player
if (player) {
var targetX = -player.x + 2048 / 2;
var targetY = -player.y + 2732 / 2;
// Smooth camera movement
camera.x += (targetX - camera.x) * 0.1;
camera.y += (targetY - camera.y) * 0.1;
// Apply camera position to game world
gameWorld.x = camera.x;
gameWorld.y = camera.y;
}
}
};
// Create minimap
minimap = new MiniMap();
minimap.x = 2048 - 420;
minimap.y = 20;
LK.gui.addChild(minimap);
// Add buildings and roads to minimap
for (var i = 0; i < buildings.length; i++) {
minimap.addElement('building', buildings[i].x, buildings[i].y, buildings[i].width, buildings[i].height);
}
for (var i = 0; i < roads.length; i++) {
minimap.addElement('road', roads[i].x, roads[i].y, roads[i].width, roads[i].height, roads[i].rotation);
}
// Create fuel gauge
fuelGauge = new FuelGauge();
fuelGauge.x = 20;
fuelGauge.y = 20;
fuelGauge.visible = false; // Only visible when in vehicle
LK.gui.addChild(fuelGauge);
// Create score display
scoreText = new Text2('SCORE: 0', {
size: 40,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
// Create district display
districtText = new Text2('', {
size: 30,
fill: 0xFFFFFF
});
districtText.anchor.set(0, 0);
districtText.x = 20;
districtText.y = 70;
LK.gui.addChild(districtText);
// Play background music
LK.playMusic('city_ambience');
}
function createDistricts() {
// Create different city districts
districts.push(new District('Downtown', 0xff3333, 0, 0, worldWidth / 3, worldHeight / 3));
districts.push(new District('Suburbs', 0x33cc33, worldWidth / 3, 0, worldWidth / 3, worldHeight / 3));
districts.push(new District('Industrial', 0x3366ff, 2 * worldWidth / 3, 0, worldWidth / 3, worldHeight / 3));
districts.push(new District('Harbor', 0xffcc00, 0, worldHeight / 3, worldWidth / 3, worldHeight / 3));
districts.push(new District('Business', 0x9933ff, worldWidth / 3, worldHeight / 3, worldWidth / 3, worldHeight / 3));
districts.push(new District('Park', 0x33cccc, 2 * worldWidth / 3, worldHeight / 3, worldWidth / 3, worldHeight / 3));
districts.push(new District('Shopping', 0xff9933, 0, 2 * worldHeight / 3, worldWidth / 3, worldHeight / 3));
districts.push(new District('Residential', 0xcc33cc, worldWidth / 3, 2 * worldHeight / 3, worldWidth / 3, worldHeight / 3));
districts.push(new District('Entertainment', 0xffff33, 2 * worldWidth / 3, 2 * worldHeight / 3, worldWidth / 3, worldHeight / 3));
// Add district boundaries
for (var i = 0; i < districts.length; i++) {
gameWorld.addChild(districts[i]);
// Create visual boundaries between districts
if (i % 3 !== 2) {
// Vertical boundaries (except last column)
var boundary = LK.getAsset('district_boundary', {
anchorX: 0.5,
anchorY: 0.5
});
boundary.x = districts[i].bounds.x + districts[i].bounds.width;
boundary.y = districts[i].bounds.y + districts[i].bounds.height / 2;
boundary.height = districts[i].bounds.height;
gameWorld.addChild(boundary);
}
if (i < 6) {
// Horizontal boundaries (except last row)
var boundary = LK.getAsset('district_boundary', {
anchorX: 0.5,
anchorY: 0.5
});
boundary.x = districts[i].bounds.x + districts[i].bounds.width / 2;
boundary.y = districts[i].bounds.y + districts[i].bounds.height;
boundary.rotation = Math.PI / 2;
boundary.height = districts[i].bounds.width;
gameWorld.addChild(boundary);
}
}
}
function createCityLayout() {
// Create buildings
for (var i = 0; i < 200; i++) {
var building = new Building(100 + Math.random() * 300,
// Random width
100 + Math.random() * 300 // Random height
);
// Position building randomly within the world
building.x = Math.random() * worldWidth;
building.y = Math.random() * worldHeight;
// Prevent overlapping with existing buildings (simplified)
var overlapping = false;
for (var j = 0; j < buildings.length; j++) {
var other = buildings[j];
var distance = Math.sqrt(Math.pow(building.x - other.x, 2) + Math.pow(building.y - other.y, 2));
if (distance < 350) {
overlapping = true;
break;
}
}
if (!overlapping) {
buildings.push(building);
gameWorld.addChild(building);
}
}
// Create roads
for (var i = 0; i < 40; i++) {
// Horizontal roads
var roadH = LK.getAsset('road', {
anchorX: 0.5,
anchorY: 0.5,
width: worldWidth - 200,
height: 120
});
roadH.x = worldWidth / 2;
roadH.y = (i + 1) * (worldHeight / 41);
roads.push(roadH);
gameWorld.addChild(roadH);
// Add sidewalks alongside roads
var sidewalkH1 = LK.getAsset('sidewalk', {
anchorX: 0.5,
anchorY: 0.5,
width: worldWidth - 200,
height: 50
});
sidewalkH1.x = worldWidth / 2;
sidewalkH1.y = roadH.y - 85;
gameWorld.addChild(sidewalkH1);
var sidewalkH2 = LK.getAsset('sidewalk', {
anchorX: 0.5,
anchorY: 0.5,
width: worldWidth - 200,
height: 50
});
sidewalkH2.x = worldWidth / 2;
sidewalkH2.y = roadH.y + 85;
gameWorld.addChild(sidewalkH2);
}
for (var i = 0; i < 30; i++) {
// Vertical roads
var roadV = LK.getAsset('road', {
anchorX: 0.5,
anchorY: 0.5,
width: 120,
height: worldHeight - 200
});
roadV.rotation = Math.PI / 2;
roadV.x = (i + 1) * (worldWidth / 31);
roadV.y = worldHeight / 2;
roads.push(roadV);
gameWorld.addChild(roadV);
// Add sidewalks alongside roads
var sidewalkV1 = LK.getAsset('sidewalk', {
anchorX: 0.5,
anchorY: 0.5,
width: 50,
height: worldHeight - 200
});
sidewalkV1.x = roadV.x - 85;
sidewalkV1.y = worldHeight / 2;
sidewalkV1.rotation = Math.PI / 2;
gameWorld.addChild(sidewalkV1);
var sidewalkV2 = LK.getAsset('sidewalk', {
anchorX: 0.5,
anchorY: 0.5,
width: 50,
height: worldHeight - 200
});
sidewalkV2.x = roadV.x + 85;
sidewalkV2.y = worldHeight / 2;
sidewalkV2.rotation = Math.PI / 2;
gameWorld.addChild(sidewalkV2);
}
}
function createVehicles() {
// Vehicle types
var types = ['car', 'truck', 'motorcycle'];
// Create a variety of vehicles
for (var i = 0; i < 30; i++) {
var type = types[Math.floor(Math.random() * types.length)];
var vehicle = new Vehicle(type);
// Position vehicle on roads
var onVerticalRoad = Math.random() < 0.5;
if (onVerticalRoad) {
vehicle.x = (Math.floor(Math.random() * 30) + 1) * (worldWidth / 31);
vehicle.y = Math.random() * worldHeight;
} else {
vehicle.x = Math.random() * worldWidth;
vehicle.y = (Math.floor(Math.random() * 40) + 1) * (worldHeight / 41);
}
vehicles.push(vehicle);
gameWorld.addChild(vehicle);
}
}
function createPedestrians() {
// Create pedestrians
for (var i = 0; i < 50; i++) {
var pedestrian = new Pedestrian();
// Position pedestrian randomly on sidewalks
pedestrian.x = Math.random() * worldWidth;
pedestrian.y = Math.random() * worldHeight;
pedestrians.push(pedestrian);
gameWorld.addChild(pedestrian);
}
}
function updateScore() {
if (player) {
scoreText.setText('SCORE: ' + player.score);
// Update high score if needed
if (player.score > storage.highScore) {
storage.highScore = player.score;
}
}
}
function checkCollisions() {
// Player with vehicles (for entering)
if (player && !player.inVehicle) {
for (var i = 0; i < vehicles.length; i++) {
var vehicle = vehicles[i];
if (!vehicle.isOccupied && player.intersects(vehicle)) {
// Player can enter vehicle
if (dragMode) {
// Enter vehicle
player.inVehicle = vehicle;
vehicle.isOccupied = true;
player.visible = false;
// Play sound
LK.getSound('car_start').play();
// Show fuel gauge
fuelGauge.visible = true;
fuelGauge.update(vehicle.fuel);
break;
}
}
}
}
// Bullets with pedestrians and vehicles
for (var i = bullets.length - 1; i >= 0; i--) {
var bullet = bullets[i];
// Initialize lastWasIntersecting if not present
if (bullet.lastWasIntersecting === undefined) {
bullet.lastWasIntersecting = false;
}
// Check collision with pedestrians
for (var j = 0; j < pedestrians.length; j++) {
if (bullet.active && !bullet.lastWasIntersecting && bullet.intersects(pedestrians[j])) {
pedestrians[j].takeDamage(bullet.damage);
bullet.active = false;
break;
}
}
// Check collision with vehicles
for (var j = 0; j < vehicles.length; j++) {
if (bullet.active && bullet.intersects(vehicles[j])) {
// Damage vehicle or make it explode
LK.effects.flashObject(vehicles[j], 0xff0000, 300);
LK.getSound('collision').play();
// Bullets stop when hitting vehicles
bullet.active = false;
break;
}
}
// Check collision with buildings
for (var j = 0; j < buildings.length; j++) {
if (bullet.active && bullet.intersects(buildings[j])) {
bullet.active = false;
break;
}
}
// Remove inactive bullets
if (!bullet.active) {
bullet.destroy();
bullets.splice(i, 1);
}
}
// Vehicle with vehicle collisions
for (var i = 0; i < vehicles.length; i++) {
for (var j = i + 1; j < vehicles.length; j++) {
if (vehicles[i].intersects(vehicles[j])) {
// Simplified collision response - just reverse direction
vehicles[i].velocity.x *= -0.5;
vehicles[i].velocity.y *= -0.5;
vehicles[j].velocity.x *= -0.5;
vehicles[j].velocity.y *= -0.5;
LK.getSound('collision').play();
}
}
}
// Vehicle with building collisions
for (var i = 0; i < vehicles.length; i++) {
for (var j = 0; j < buildings.length; j++) {
if (vehicles[i].intersects(buildings[j])) {
// Simplified collision response - just stop
vehicles[i].velocity.x = 0;
vehicles[i].velocity.y = 0;
// Move away from building
var dx = vehicles[i].x - buildings[j].x;
var dy = vehicles[i].y - buildings[j].y;
var angle = Math.atan2(dy, dx);
vehicles[i].x += Math.cos(angle) * 5;
vehicles[i].y += Math.sin(angle) * 5;
if (vehicles[i].isOccupied) {
LK.getSound('collision').play();
}
}
}
}
}
function checkCurrentDistrict() {
// Find what district the player is in
if (player) {
var foundDistrict = null;
for (var i = 0; i < districts.length; i++) {
if (districts[i].contains(player.x, player.y)) {
foundDistrict = districts[i];
break;
}
}
if (foundDistrict !== currentDistrict) {
currentDistrict = foundDistrict;
if (currentDistrict) {
// Update district display
districtText.setText('DISTRICT: ' + currentDistrict.name);
// Save last district
storage.lastDistrict = currentDistrict.name;
// Show district notification
var notification = new Text2('Entering ' + currentDistrict.name, {
size: 60,
fill: 0xFFFFFF
});
notification.anchor.set(0.5, 0.5);
notification.x = 2048 / 2;
notification.y = 2732 / 2;
LK.gui.addChild(notification);
// Fade out notification
tween(notification, {
alpha: 0
}, {
duration: 2000,
onFinish: function onFinish() {
notification.destroy();
}
});
}
}
}
}
function handleMove(x, y, obj) {
// Convert screen coordinates to world coordinates
var worldX = x - gameWorld.x;
var worldY = y - gameWorld.y;
if (dragMode && player) {
if (player.inVehicle) {
// If in vehicle, set direction based on touch position
var dx = worldX - player.inVehicle.x;
var dy = worldY - player.inVehicle.y;
var angle = Math.atan2(dy, dx);
// Only move if there's fuel
if (player.inVehicle.fuel > 0) {
player.inVehicle.setVelocity(player.inVehicle.maxSpeed, angle);
}
} else {
// If on foot, move player towards touch position
var dx = worldX - player.x;
var dy = worldY - player.y;
var angle = Math.atan2(dy, dx);
player.setVelocity(player.maxSpeed, angle);
}
}
}
game.down = function (x, y, obj) {
dragMode = true;
handleMove(x, y, obj);
};
game.up = function (x, y, obj) {
dragMode = false;
// Stop player movement when touch is released
if (player) {
if (player.inVehicle) {
player.inVehicle.velocity.x = 0;
player.inVehicle.velocity.y = 0;
} else {
player.velocity.x = 0;
player.velocity.y = 0;
}
}
// Check if tap was to exit vehicle
if (player && player.inVehicle) {
// Double check if drag distance was small enough to be considered a tap
var dx = x - (player.inVehicle.x + gameWorld.x);
var dy = y - (player.inVehicle.y + gameWorld.y);
var dragDistance = Math.sqrt(dx * dx + dy * dy);
if (dragDistance < 50) {
// Exit vehicle
player.exitVehicle();
fuelGauge.visible = false;
}
}
// Check if tap was to shoot
if (player && !player.inVehicle) {
// Convert screen coordinates to world coordinates
var worldX = x - gameWorld.x;
var worldY = y - gameWorld.y;
// Calculate direction to shoot
var dx = worldX - player.x;
var dy = worldY - player.y;
player.direction = Math.atan2(dy, dx);
// Shoot bullet
player.shootBullet();
}
};
game.move = handleMove;
game.update = function () {
// Skip if game not initialized yet
if (!player || !gameWorld) {
return;
}
// Update all game objects
player.update();
for (var i = 0; i < vehicles.length; i++) {
vehicles[i].update();
}
for (var i = 0; i < pedestrians.length; i++) {
pedestrians[i].update();
}
for (var i = 0; i < bullets.length; i++) {
// Save intersection state before updating
for (var j = 0; j < pedestrians.length; j++) {
if (bullets[i].intersects(pedestrians[j])) {
bullets[i].lastWasIntersecting = true;
break;
} else {
bullets[i].lastWasIntersecting = false;
}
}
bullets[i].update();
}
// Update camera
camera.update();
// Update minimap
minimap.update();
// Update fuel gauge if in vehicle
if (player.inVehicle) {
fuelGauge.update(player.inVehicle.fuel);
}
// Check collisions
checkCollisions();
// Check current district
checkCurrentDistrict();
};
// Initialize game world
initGameWorld();