User prompt
polis daha iyi oynasın
User prompt
Remove the gun tissue from the police's hand but still keep shooting
User prompt
When the character comes to a car, he controls the car and when he gets in the car, his speed increases.
User prompt
When the character hovers over a car, he becomes invisible and controls the car. When he gets into the car, his speed increases.
User prompt
move the health bar to the bottom left
User prompt
Add a health indicator as assets to the bottom right
User prompt
Move it a little further to the left and add the arrow keys as assets
User prompt
Make the arrow keys a little larger and move the keys to the bottom right
User prompt
Add touch-sensitive arrow keys to the game so we can move the player.
User prompt
Add a texture to the game at the bottom left, when you press that texture, the language selection screen will appear and there will be "English" and "Turkish" options. When you press the "Turkish" option, the game will be in "Turkish". When you press the "English" option, the game will be in "English" language.
User prompt
Translate the game's texts into "Turkish" language
User prompt
Enlarge the health text at the bottom right a bit
User prompt
Let there be a maximum of 7 men
User prompt
Add a text like this at the bottom: "Health: (health number)" instead of (health number), you write our health. The game starts with 900 and every time we buy a bullet, it decreases by 300.
User prompt
Cars, you shouldn't be born surrounded by cars
User prompt
Let the maximum number of houses be 10
User prompt
Have small random spaces between houses, but don't overdo it
User prompt
If you haven't added a health bar at the bottom right, add it now.
User prompt
Add a life bar at the bottom right, the game will start with 100 full, when you get 3 bullets, the life bar will run out and the game will end.
User prompt
add a health bar to the top right of the game
User prompt
People shouldn't move nonsense, just move left and right in order.
User prompt
Let only one police officer be born
User prompt
The cars should not move, they should stay where they are
User prompt
buildings should not be up or down
User prompt
Buildings should not be everywhere, only in rows on the edges
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Building class
var Building = Container.expand(function () {
var self = Container.call(this);
var bldg = self.attachAsset('building', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
// Car class
var Car = Container.expand(function () {
var self = Container.call(this);
var carSprite = self.attachAsset('car', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 18;
self.direction = 0; // in radians, 0 = right
self.driver = null; // Player or null
self.ai = false;
self.aiTarget = null;
self.update = function () {
// Store previous position for collision revert
var prevX = self.x;
var prevY = self.y;
// Cars do not move; skip player and AI movement logic
// Prevent passing through buildings
for (var i = 0; typeof buildings !== "undefined" && i < buildings.length; i++) {
if (self.intersects(buildings[i])) {
self.x = prevX;
self.y = prevY;
break;
}
}
// Clamp to city bounds
if (self.x < 90) self.x = 90;
if (self.x > 2048 - 90) self.x = 2048 - 90;
if (self.y < 100) self.y = 100;
if (self.y > 2732 - 90) self.y = 2732 - 90;
};
return self;
});
// Mission marker class
var MissionMarker = Container.expand(function () {
var self = Container.call(this);
var marker = self.attachAsset('mission', {
anchorX: 0.5,
anchorY: 0.5
});
self.active = true;
return self;
});
// Pedestrian class
var Pedestrian = Container.expand(function () {
var self = Container.call(this);
var pedSprite = self.attachAsset('pedestrian', {
anchorX: 0.5,
anchorY: 0.5
});
// Pedestrians only move left and right in order
self.speed = 4 + Math.random() * 4;
self.direction = Math.random() < 0.5 ? 0 : Math.PI; // 0 = right, PI = left
self.update = function () {
var prevX = self.x;
var prevY = self.y;
// Move only in X direction (left/right)
self.x += Math.cos(self.direction) * self.speed;
// No Y movement
// Prevent passing through buildings
for (var i = 0; typeof buildings !== "undefined" && i < buildings.length; i++) {
if (self.intersects(buildings[i])) {
self.x = prevX;
self.y = prevY;
// Reverse direction on building collision
self.direction = self.direction === 0 ? Math.PI : 0;
break;
}
}
// Bounce off city bounds (left/right only)
if (self.x < 60) {
self.x = 60;
self.direction = 0; // move right
}
if (self.x > 2048 - 60) {
self.x = 2048 - 60;
self.direction = Math.PI; // move left
}
};
return self;
});
// Player class
var Player = Container.expand(function () {
var self = Container.call(this);
var playerSprite = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 12;
self.inCar = false;
self.car = null;
self.direction = {
x: 0,
y: 0
}; // For movement
self.update = function () {
if (!self.inCar) {
// Store previous position
var prevX = self.x;
var prevY = self.y;
self.x += self.direction.x * self.speed;
self.y += self.direction.y * self.speed;
// Prevent passing through buildings
for (var i = 0; typeof buildings !== "undefined" && i < buildings.length; i++) {
if (self.intersects(buildings[i])) {
self.x = prevX;
self.y = prevY;
break;
}
}
// Clamp to city bounds
if (self.x < 50) self.x = 50;
if (self.x > 2048 - 50) self.x = 2048 - 50;
if (self.y < 100) self.y = 100;
if (self.y > 2732 - 50) self.y = 2732 - 50;
} else if (self.car) {
// Follow car position
self.x = self.car.x;
self.y = self.car.y;
}
};
return self;
});
// Police bullet class
var PoliceBullet = Container.expand(function () {
var self = Container.call(this);
var bulletSprite = self.attachAsset('mission', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.5
});
self.speed = 16;
self.direction = 0;
self.lifetime = 60; // frames
self.update = function () {
if (typeof self.lastX === "undefined") self.lastX = self.x;
if (typeof self.lastY === "undefined") self.lastY = self.y;
self.x += Math.cos(self.direction) * self.speed;
self.y += Math.sin(self.direction) * self.speed;
self.lifetime--;
// Remove if out of bounds or expired
if (self.x < 0 || self.x > 2048 || self.y < 0 || self.y > 2732 || self.lifetime <= 0) {
if (typeof policeBullets !== "undefined") {
for (var i = 0; i < policeBullets.length; i++) {
if (policeBullets[i] === self) {
policeBullets.splice(i, 1);
break;
}
}
}
self.destroy();
return;
}
self.lastX = self.x;
self.lastY = self.y;
};
return self;
});
// Police car class
var PoliceCar = Container.expand(function () {
var self = Container.call(this);
var policeSprite = self.attachAsset('police', {
anchorX: 0.5,
anchorY: 0.5
});
// (Gun asset removed from police hand)
self.speed = 4;
self.direction = 0;
self.target = null; // Player or car
self.sirenOn = false;
self.bulletCooldown = 0;
self.update = function () {
if (self.target) {
var prevX = self.x;
var prevY = self.y;
var tx = self.target.x - self.x;
var ty = self.target.y - self.y;
var dist = Math.sqrt(tx * tx + ty * ty);
// Enhanced AI behavior based on distance and wanted level
var aggressionLevel = Math.min(wantedLevel, 5);
var enhancedSpeed = self.speed + aggressionLevel * 1.5; // Faster at higher wanted levels
if (dist > 10) {
// Smart pathfinding around buildings
var directPath = true;
var targetDirection = Math.atan2(ty, tx);
// Check if direct path is blocked by buildings
for (var i = 0; typeof buildings !== "undefined" && i < buildings.length; i++) {
var building = buildings[i];
var bx = building.x - self.x;
var by = building.y - self.y;
var buildingDist = Math.sqrt(bx * bx + by * by);
// If building is between police and target, find alternate path
if (buildingDist < 300) {
var angleToBldg = Math.atan2(by, bx);
var angleDiff = Math.abs(targetDirection - angleToBldg);
if (angleDiff < Math.PI / 3) {
// Building blocks direct path
directPath = false;
// Choose left or right path around building
var leftAngle = angleToBldg - Math.PI / 2;
var rightAngle = angleToBldg + Math.PI / 2;
// Pick the angle that gets closer to target
var leftDx = Math.cos(leftAngle);
var leftDy = Math.sin(leftAngle);
var rightDx = Math.cos(rightAngle);
var rightDy = Math.sin(rightAngle);
if (leftDx * tx + leftDy * ty > rightDx * tx + rightDy * ty) {
self.direction = leftAngle;
} else {
self.direction = rightAngle;
}
break;
}
}
}
if (directPath) {
self.direction = targetDirection;
}
// Predictive targeting - aim where player will be
if (self.target === player && !player.inCar) {
var predictionTime = dist / enhancedSpeed;
var predictedX = player.x + player.direction.x * player.speed * predictionTime;
var predictedY = player.y + player.direction.y * player.speed * predictionTime;
var ptx = predictedX - self.x;
var pty = predictedY - self.y;
if (Math.sqrt(ptx * ptx + pty * pty) < dist) {
self.direction = Math.atan2(pty, ptx);
}
}
// Move with enhanced speed
self.x += Math.cos(self.direction) * enhancedSpeed;
self.y += Math.sin(self.direction) * enhancedSpeed;
// Prevent passing through buildings
for (var i = 0; typeof buildings !== "undefined" && i < buildings.length; i++) {
if (self.intersects(buildings[i])) {
self.x = prevX;
self.y = prevY;
// Try alternative movement when stuck
self.direction += (Math.random() - 0.5) * Math.PI / 2;
break;
}
}
}
// Enhanced shooting behavior
var shootingRange = 500 + aggressionLevel * 100; // Longer range at higher wanted
var baseCooldown = Math.max(30, 90 - aggressionLevel * 15); // Faster shooting at higher wanted
// Lead target for better accuracy
var aimDirection = self.direction;
if (dist < shootingRange && self.bulletCooldown <= 0 && typeof policeBullets !== "undefined") {
// Predictive aiming for moving targets
if (self.target === player && (player.direction.x !== 0 || player.direction.y !== 0)) {
var bulletSpeed = 16;
var timeToHit = dist / bulletSpeed;
var futureX = player.x + player.direction.x * player.speed * timeToHit;
var futureY = player.y + player.direction.y * player.speed * timeToHit;
aimDirection = Math.atan2(futureY - self.y, futureX - self.x);
}
// Burst fire at high wanted levels
var burstCount = aggressionLevel >= 3 ? 2 : 1;
for (var b = 0; b < burstCount; b++) {
var bullet = new PoliceBullet();
bullet.x = self.x + Math.cos(aimDirection) * 70;
bullet.y = self.y + Math.sin(aimDirection) * 70;
bullet.direction = aimDirection + (b > 0 ? (Math.random() - 0.5) * 0.3 : 0); // Slight spread for burst
policeBullets.push(bullet);
if (typeof game !== "undefined") game.addChild(bullet);
}
self.bulletCooldown = baseCooldown + Math.floor(Math.random() * 30);
}
if (self.bulletCooldown > 0) self.bulletCooldown--;
}
// Clamp to city bounds
if (self.x < 90) self.x = 90;
if (self.x > 2048 - 90) self.x = 2048 - 90;
if (self.y < 100) self.y = 100;
if (self.y > 2732 - 90) self.y = 2732 - 90;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x222222
});
/****
* Game Code
****/
// Enhanced police coordination
function updatePoliceCoordination() {
if (policeCars.length > 1 && wantedLevel >= 3) {
// Coordinate police to surround player
for (var i = 0; i < policeCars.length; i++) {
var police = policeCars[i];
var angleOffset = i / policeCars.length * Math.PI * 2;
var surroundDistance = 300;
// Calculate flanking position
var targetX = player.x + Math.cos(angleOffset) * surroundDistance;
var targetY = player.y + Math.sin(angleOffset) * surroundDistance;
// Adjust police target to flanking position instead of direct pursuit
if (Math.random() < 0.3) {
// 30% chance to use flanking behavior
var flankTx = targetX - police.x;
var flankTy = targetY - police.y;
var flankDist = Math.sqrt(flankTx * flankTx + flankTy * flankTy);
if (flankDist > 50) {
police.direction = Math.atan2(flankTy, flankTx);
}
}
}
}
}
// Police spawn logic
// Mission marker: yellow ellipse
// Building: dark gray box
// Road: gray box
// Pedestrian: green ellipse
// Police car: white box with blue
// Car: blue box
// Player character: red box
// City layout
// Arrow key assets
var buildings = [];
var cars = [];
var policeCars = [];
var pedestrians = [];
var missionMarkers = [];
var score = 0;
var wantedLevel = 0;
var missionActive = false;
var missionTarget = null;
var missionText = null;
var dragNode = null;
var policeBullets = [];
var lastTouch = {
x: 0,
y: 0
};
var policeSirenTimer = 0;
// Life bar variables
var life = 900;
var maxLife = 900;
var bulletsHit = 0;
// Helper to update health text
function updateHealthText() {
if (typeof healthText !== "undefined") {
healthText.setText('Sağlık: ' + life);
}
if (typeof updateHearts === "function") updateHearts();
}
// Life bar UI (bottom left)
var lifeBarBg = LK.getAsset('mission', {
anchorX: 0,
anchorY: 1,
scaleX: 4.5,
scaleY: 0.7,
x: 60,
y: 2732 - 60,
tint: 0x222222
});
var lifeBar = LK.getAsset('mission', {
anchorX: 0,
anchorY: 1,
scaleX: 4.4,
scaleY: 0.6,
x: 70,
y: 2732 - 70,
tint: 0x4caf50
});
game.addChild(lifeBarBg);
game.addChild(lifeBar);
// Health text at the bottom left
var healthText = new Text2('Sağlık: 900', {
size: 110,
fill: "#fff"
});
healthText.anchor.set(0, 1);
healthText.x = 80;
healthText.y = 2732 - 10;
game.addChild(healthText);
// --- Health indicator as heart assets (bottom left) ---
var heartIcons = [];
function updateHearts() {
// Remove old hearts
for (var i = 0; i < heartIcons.length; i++) {
if (heartIcons[i].parent) heartIcons[i].parent.removeChild(heartIcons[i]);
}
heartIcons = [];
// Show 3 hearts, full or empty based on health
var heartsToShow = 3;
var fullHearts = Math.max(0, Math.min(3, Math.ceil(life / (maxLife / 3))));
for (var i = 0; i < heartsToShow; i++) {
var assetId = i < fullHearts ? 'heart_full' : 'heart_empty';
var heart = LK.getAsset(assetId, {
anchorX: 0,
anchorY: 1,
x: 40 + i * 100,
y: 2732 - 320,
scaleX: 1.1,
scaleY: 1.1
});
game.addChild(heart);
heartIcons.push(heart);
}
}
updateHearts();
// Add road background
var road = LK.getAsset('road', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
});
game.addChild(road);
// Add buildings only in columns along the left and right edges (no top/bottom rows)
// Left column
for (var j = 0; j < 10; j++) {
var b = new Building();
b.x = 150;
// Add a small random space between houses, but don't overdo it
var yOffset = 200 + j * 210 + Math.floor(Math.random() * 30); // up to 30px random gap
b.y = yOffset;
buildings.push(b);
game.addChild(b);
}
// Right column
for (var j = 0; j < 10; j++) {
var b = new Building();
b.x = 2048 - 150;
// Add a small random space between houses, but don't overdo it
var yOffset = 200 + j * 210 + Math.floor(Math.random() * 30); // up to 30px random gap
b.y = yOffset;
buildings.push(b);
game.addChild(b);
}
// Helper: get a random position not inside any building
function getValidSpawnPosition(minX, maxX, minY, maxY, margin, entityWidth, entityHeight) {
var tries = 0;
var x, y, tempObj;
margin = margin || 0;
entityWidth = entityWidth || 60;
entityHeight = entityHeight || 60;
do {
x = minX + Math.random() * (maxX - minX);
y = minY + Math.random() * (maxY - minY);
// Create a temp object to check intersection
tempObj = {
x: x,
y: y,
width: entityWidth,
height: entityHeight,
intersects: function intersects(b) {
// Simple AABB check
var ax1 = this.x - this.width / 2,
ay1 = this.y - this.height / 2,
ax2 = this.x + this.width / 2,
ay2 = this.y + this.height / 2;
var bx1 = b.x - 135,
by1 = b.y - 135,
bx2 = b.x + 135,
by2 = b.y + 135;
return !(ax2 < bx1 || ax1 > bx2 || ay2 < by1 || ay1 > by2);
}
};
var inside = false;
for (var i = 0; i < buildings.length; i++) {
if (tempObj.intersects(buildings[i])) {
inside = true;
break;
}
}
tries++;
if (tries > 100) break; // fallback, shouldn't happen
} while (inside);
return {
x: x,
y: y
};
}
// Add mission marker
function spawnMission() {
if (missionTarget) {
missionTarget.destroy();
}
var marker = new MissionMarker();
var pos = getValidSpawnPosition(400, 1600, 400, 2200, 0, 80, 80);
marker.x = pos.x;
marker.y = pos.y;
missionMarkers = [marker];
missionTarget = marker;
game.addChild(marker);
missionActive = true;
if (missionText) {
missionText.setText("Go to the yellow marker!");
}
}
spawnMission();
// Add player
var player = new Player();
var playerPos = getValidSpawnPosition(300, 1748, 2732 - 600, 2732 - 100, 0, 120, 120);
player.x = playerPos.x;
player.y = playerPos.y;
game.addChild(player);
// Add cars (AI)
for (var i = 0; i < 5; i++) {
var tryCount = 0;
var valid = false;
var carPos;
while (!valid && tryCount < 30) {
carPos = getValidSpawnPosition(400, 1600, 400, 2200, 0, 180, 90);
valid = true;
// Check not surrounded by other cars (no car within 220px in both x and y)
for (var j = 0; j < cars.length; j++) {
var other = cars[j];
if (Math.abs(carPos.x - other.x) < 220 && Math.abs(carPos.y - other.y) < 220) {
valid = false;
break;
}
}
tryCount++;
}
var c = new Car();
c.x = carPos.x;
c.y = carPos.y;
c.ai = true;
var tgt = getValidSpawnPosition(400, 1600, 400, 2200, 0, 180, 90);
c.aiTarget = {
x: tgt.x,
y: tgt.y
};
cars.push(c);
game.addChild(c);
}
// Add police car (starts inactive)
function spawnPolice() {
var pc = new PoliceCar();
var policePos = getValidSpawnPosition(200, 1800, 200, 2200, 0, 130, 130);
pc.x = policePos.x;
pc.y = policePos.y;
pc.target = player;
policeCars.push(pc);
game.addChild(pc);
}
function removeAllPolice() {
for (var i = 0; i < policeCars.length; i++) {
policeCars[i].destroy();
}
policeCars = [];
}
// Add pedestrians
for (var i = 0; i < 7; i++) {
var p = new Pedestrian();
var pedPos = getValidSpawnPosition(200, 1800, 200, 2400, 0, 120, 120);
p.x = pedPos.x;
p.y = pedPos.y;
pedestrians.push(p);
game.addChild(p);
}
// Score display
var scoreTxt = new Text2('Puan: 0', {
size: 90,
fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Wanted level display
var wantedTxt = new Text2('Aranma: 0', {
size: 70,
fill: 0xFF4444
});
wantedTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(wantedTxt);
wantedTxt.y = 100;
// Mission text
missionText = new Text2('Sarı işarete git!', {
size: 70,
fill: 0xFFE100
});
missionText.anchor.set(0.5, 0);
LK.gui.top.addChild(missionText);
missionText.y = 200;
// Touch controls
var moveTouchId = null;
var moveStart = null;
var moveDir = {
x: 0,
y: 0
};
// Helper: get direction from drag
function getDir(from, to) {
var dx = to.x - from.x;
var dy = to.y - from.y;
var len = Math.sqrt(dx * dx + dy * dy);
if (len < 30) return {
x: 0,
y: 0
};
return {
x: dx / len,
y: dy / len
};
}
// --- Arrow Key Touch Controls ---
// Arrow button size and spacing
var arrowBtnSize = 230; // larger
var arrowBtnSpacing = 60; // more spacing for bigger buttons
var arrowBtnAlpha = 0.7;
var arrowBtnTint = 0xeeeeee;
var arrowBtnTintActive = 0x4caf50;
// Arrow button containers
var arrowBtns = {
up: null,
down: null,
left: null,
right: null
};
var arrowBtnStates = {
up: false,
down: false,
left: false,
right: false
};
// Helper: create an arrow button using asset
function createArrowBtn(direction, x, y, rotation) {
var assetId = '';
if (direction === "up") assetId = 'arrow_up';
if (direction === "down") assetId = 'arrow_down';
if (direction === "left") assetId = 'arrow_left';
if (direction === "right") assetId = 'arrow_right';
var btn = LK.getAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.45,
scaleY: 1.45,
x: x,
y: y,
tint: arrowBtnTint
});
btn.alpha = arrowBtnAlpha;
// Touch handlers
btn.down = function (x, y, obj) {
arrowBtnStates[direction] = true;
btn.tint = arrowBtnTintActive;
btn.alpha = 1;
updateArrowDirection();
};
btn.up = function (x, y, obj) {
arrowBtnStates[direction] = false;
btn.tint = arrowBtnTint;
btn.alpha = arrowBtnAlpha;
updateArrowDirection();
};
// For touch move off the button
btn.out = btn.up;
return btn;
}
// Place arrow buttons further to the left, spaced out
var arrowY = 2732 - 220;
var arrowXRight = 2048 - 420; // move further left from right margin
arrowBtns.left = createArrowBtn("left", arrowXRight - arrowBtnSize - arrowBtnSpacing, arrowY, 0);
arrowBtns.down = createArrowBtn("down", arrowXRight, arrowY, 0);
arrowBtns.right = createArrowBtn("right", arrowXRight + arrowBtnSize + arrowBtnSpacing, arrowY, 0);
arrowBtns.up = createArrowBtn("up", arrowXRight, arrowY - arrowBtnSize - arrowBtnSpacing, 0);
// Add to game
game.addChild(arrowBtns.left);
game.addChild(arrowBtns.down);
game.addChild(arrowBtns.right);
game.addChild(arrowBtns.up);
// Update player direction based on arrow keys
function updateArrowDirection() {
if (player.inCar) {
player.direction = {
x: 0,
y: 0
};
return;
}
var dx = 0,
dy = 0;
if (arrowBtnStates.left) dx -= 1;
if (arrowBtnStates.right) dx += 1;
if (arrowBtnStates.up) dy -= 1;
if (arrowBtnStates.down) dy += 1;
// Normalize
if (dx !== 0 || dy !== 0) {
var len = Math.sqrt(dx * dx + dy * dy);
player.direction = {
x: dx / len,
y: dy / len
};
} else {
player.direction = {
x: 0,
y: 0
};
}
}
// When any arrow is pressed, prevent normal touch movement
for (var dir in arrowBtns) {
(function (direction) {
var btn = arrowBtns[direction];
btn.down = function (x, y, obj) {
arrowBtnStates[direction] = true;
btn.tint = arrowBtnTintActive;
btn.alpha = 1;
updateArrowDirection();
};
btn.up = function (x, y, obj) {
arrowBtnStates[direction] = false;
btn.tint = arrowBtnTint;
btn.alpha = arrowBtnAlpha;
updateArrowDirection();
};
btn.out = btn.up;
})(dir);
}
// Touch down: start movement or enter/exit car
game.down = function (x, y, obj) {
lastTouch.x = x;
lastTouch.y = y;
// If player is near a car and not in car, enter car
if (!player.inCar) {
for (var i = 0; i < cars.length; i++) {
var c = cars[i];
if (!c.driver && Math.abs(player.x - c.x) < 120 && Math.abs(player.y - c.y) < 90) {
// Enter car
player.inCar = true;
player.car = c;
c.driver = player;
LK.getSound('car_enter').play();
return;
}
}
} else if (player.inCar) {
// Exit car
var c = player.car;
player.inCar = false;
player.car = null;
if (c) c.driver = null;
LK.getSound('car_exit').play();
return;
}
// Set player direction toward touch/cursor
// If any arrow key is pressed, ignore normal touch movement
if (!arrowBtnStates.left && !arrowBtnStates.right && !arrowBtnStates.up && !arrowBtnStates.down) {
if (!player.inCar) {
var dx = x - player.x;
var dy = y - player.y;
var len = Math.sqrt(dx * dx + dy * dy);
if (len > 10) {
player.direction = {
x: dx / len,
y: dy / len
};
} else {
player.direction = {
x: 0,
y: 0
};
}
}
moveTouchId = true;
}
};
// Touch move: update direction
game.move = function (x, y, obj) {
lastTouch.x = x;
lastTouch.y = y;
if (moveTouchId && !player.inCar && !arrowBtnStates.left && !arrowBtnStates.right && !arrowBtnStates.up && !arrowBtnStates.down) {
var dx = x - player.x;
var dy = y - player.y;
var len = Math.sqrt(dx * dx + dy * dy);
if (len > 10) {
player.direction = {
x: dx / len,
y: dy / len
};
} else {
player.direction = {
x: 0,
y: 0
};
}
}
};
// Touch up: stop movement
game.up = function (x, y, obj) {
moveTouchId = null;
if (!arrowBtnStates.left && !arrowBtnStates.right && !arrowBtnStates.up && !arrowBtnStates.down) {
player.direction = {
x: 0,
y: 0
};
}
};
// Main update loop
game.update = function () {
// Update player
player.update();
// Update cars
for (var i = 0; i < cars.length; i++) {
cars[i].update();
// AI: cars do not move, so do not pick new targets
}
// Update police coordination
updatePoliceCoordination();
// Update police
for (var i = 0; i < policeCars.length; i++) {
policeCars[i].update();
// Siren sound (more frequent at higher wanted levels)
var sirenFreq = Math.max(30, 90 - wantedLevel * 15);
if (wantedLevel > 0 && LK.ticks % sirenFreq === 0) {
LK.getSound('police_siren').play();
}
// Police catch player
// (No game over when police touch player or player's car)
if (policeCars[i].intersects(player)) {
// Optionally, you could add a visual effect or wanted level increase here
}
// Police catch player's car
if (player.inCar && policeCars[i].intersects(player.car)) {
// Optionally, you could add a visual effect or wanted level increase here
}
}
// Update police bullets and check collision with player
for (var i = policeBullets.length - 1; i >= 0; i--) {
var bullet = policeBullets[i];
bullet.update();
// Only check collision if bullet is still in game
if (bullet && player && bullet.intersects(player)) {
bulletsHit++;
// Remove bullet on hit
policeBullets.splice(i, 1);
bullet.destroy();
// Flash effect
LK.effects.flashScreen(0xff0000, 400);
// Decrease health by 300 for each bullet bought (hit)
life = Math.max(0, life - 300);
updateHealthText();
// Update life bar width and color
var lifeFrac = life / maxLife;
lifeBar.scaleX = 4.4 * lifeFrac;
if (lifeFrac > 0.6) {
lifeBar.tint = 0x4caf50;
} else if (lifeFrac > 0.3) {
lifeBar.tint = 0xffe100;
} else {
lifeBar.tint = 0xff4444;
}
// Game over if 3 bullets hit or health is 0
if (bulletsHit >= 3 || life <= 0) {
LK.showGameOver();
return;
}
}
}
// Update pedestrians
for (var i = 0; i < pedestrians.length; i++) {
pedestrians[i].update();
// If player or car hits pedestrian, increase wanted level
if (!player.inCar && player.intersects(pedestrians[i])) {
wantedLevel = Math.min(5, wantedLevel + 1);
LK.effects.flashObject(pedestrians[i], 0xff0000, 500);
}
if (player.inCar && player.car && player.car.intersects(pedestrians[i])) {
wantedLevel = Math.min(5, wantedLevel + 1);
LK.effects.flashObject(pedestrians[i], 0xff0000, 500);
}
}
// Update mission marker
if (missionActive && missionTarget && player.intersects(missionTarget)) {
// Complete mission
LK.getSound('mission_complete').play();
score += 100;
scoreTxt.setText('Puan: ' + score);
missionActive = false;
missionTarget.destroy();
missionTarget = null;
missionText.setText("Görev Tamamlandı!");
// Next mission after short delay
LK.setTimeout(function () {
missionText.setText("Sarı işarete git!");
spawnMission();
}, 1200);
}
// Update wanted level
wantedTxt.setText('Aranma: ' + wantedLevel);
// Enhanced police spawn logic with scaling
var maxPolice = Math.min(wantedLevel, 4); // Up to 4 police cars at max wanted level
if (wantedLevel > 0 && policeCars.length < maxPolice) {
// Spawn additional police more frequently at higher wanted levels
if (LK.ticks % (180 - wantedLevel * 20) === 0) {
spawnPolice();
}
}
if (wantedLevel === 0 && policeCars.length > 0) {
removeAllPolice();
}
// Wanted level decay
if (wantedLevel > 0 && LK.ticks % 180 === 0) {
wantedLevel--;
}
// Win condition: score
if (score >= 1000) {
LK.showYouWin();
return;
}
// Reset life bar if game restarted (life > maxLife means new game)
if (life > maxLife) {
life = maxLife;
bulletsHit = 0;
lifeBar.scaleX = 4.4;
lifeBar.tint = 0x4caf50;
updateHealthText();
if (typeof updateHearts === "function") updateHearts();
}
};
// Prevent elements in top left 100x100
// (All GUI elements are centered or offset downward)
// --- Language selection UI ---
// Add a language icon texture at bottom left
// Use pedestrian icon as placeholder
var langIcon = LK.getAsset('lang_icon', {
anchorX: 0,
anchorY: 1,
x: 20,
y: 2732 - 20,
scaleX: 1,
scaleY: 1
});
game.addChild(langIcon);
// Language popup container (hidden by default)
var langPopup = new Container();
langPopup.visible = false;
langPopup.x = 2048 / 2;
langPopup.y = 2732 / 2;
// Popup background
var popupBg = LK.getAsset('mission', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 7,
scaleY: 4,
tint: 0x222222
});
langPopup.addChild(popupBg);
// "Select Language" text
var langTitle = new Text2("Select Language", {
size: 90,
fill: "#fff"
});
langTitle.anchor.set(0.5, 0);
langTitle.y = -180;
langPopup.addChild(langTitle);
// English button
var enBtnBg = LK.getAsset('mission', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 3.5,
scaleY: 1.2,
tint: 0xeeeeee,
y: -30
});
langPopup.addChild(enBtnBg);
var enBtnText = new Text2("English", {
size: 80,
fill: "#222"
});
enBtnText.anchor.set(0.5, 0.5);
enBtnText.y = -30;
langPopup.addChild(enBtnText);
// Turkish button
var trBtnBg = LK.getAsset('mission', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 3.5,
scaleY: 1.2,
tint: 0xeeeeee,
y: 100
});
langPopup.addChild(trBtnBg);
var trBtnText = new Text2("Türkçe", {
size: 80,
fill: "#222"
});
trBtnText.anchor.set(0.5, 0.5);
trBtnText.y = 100;
langPopup.addChild(trBtnText);
game.addChild(langPopup);
// Language state
var language = "tr"; // default Turkish
function setLanguage(lang) {
language = lang;
if (lang === "tr") {
scoreTxt.setText('Puan: ' + score);
wantedTxt.setText('Aranma: ' + wantedLevel);
missionText.setText(missionActive ? "Sarı işarete git!" : "Görev Tamamlandı!");
healthText.setText('Sağlık: ' + life);
langTitle.setText("Dil Seçimi");
enBtnText.setText("İngilizce");
trBtnText.setText("Türkçe");
} else {
scoreTxt.setText('Score: ' + score);
wantedTxt.setText('Wanted: ' + wantedLevel);
missionText.setText(missionActive ? "Go to the yellow marker!" : "Mission Complete!");
healthText.setText('Health: ' + life);
langTitle.setText("Select Language");
enBtnText.setText("English");
trBtnText.setText("Turkish");
}
}
// Show popup on lang icon press
langIcon.down = function (x, y, obj) {
langPopup.visible = true;
};
// Hide popup when clicking outside (optional, not required by prompt)
// Add down handler to popup background to prevent propagation
popupBg.down = function (x, y, obj) {};
// English button press
enBtnBg.down = function (x, y, obj) {
setLanguage("en");
langPopup.visible = false;
};
enBtnText.down = enBtnBg.down;
// Turkish button press
trBtnBg.down = function (x, y, obj) {
setLanguage("tr");
langPopup.visible = false;
};
trBtnText.down = trBtnBg.down;
// On game start, set initial language
setLanguage(language);
// End of MVP code for GTA7: Micro City Mayhem; ===================================================================
--- original.js
+++ change.js
@@ -193,30 +193,98 @@
var prevY = self.y;
var tx = self.target.x - self.x;
var ty = self.target.y - self.y;
var dist = Math.sqrt(tx * tx + ty * ty);
+ // Enhanced AI behavior based on distance and wanted level
+ var aggressionLevel = Math.min(wantedLevel, 5);
+ var enhancedSpeed = self.speed + aggressionLevel * 1.5; // Faster at higher wanted levels
if (dist > 10) {
- self.direction = Math.atan2(ty, tx);
- self.x += Math.cos(self.direction) * self.speed;
- self.y += Math.sin(self.direction) * self.speed;
+ // Smart pathfinding around buildings
+ var directPath = true;
+ var targetDirection = Math.atan2(ty, tx);
+ // Check if direct path is blocked by buildings
+ for (var i = 0; typeof buildings !== "undefined" && i < buildings.length; i++) {
+ var building = buildings[i];
+ var bx = building.x - self.x;
+ var by = building.y - self.y;
+ var buildingDist = Math.sqrt(bx * bx + by * by);
+ // If building is between police and target, find alternate path
+ if (buildingDist < 300) {
+ var angleToBldg = Math.atan2(by, bx);
+ var angleDiff = Math.abs(targetDirection - angleToBldg);
+ if (angleDiff < Math.PI / 3) {
+ // Building blocks direct path
+ directPath = false;
+ // Choose left or right path around building
+ var leftAngle = angleToBldg - Math.PI / 2;
+ var rightAngle = angleToBldg + Math.PI / 2;
+ // Pick the angle that gets closer to target
+ var leftDx = Math.cos(leftAngle);
+ var leftDy = Math.sin(leftAngle);
+ var rightDx = Math.cos(rightAngle);
+ var rightDy = Math.sin(rightAngle);
+ if (leftDx * tx + leftDy * ty > rightDx * tx + rightDy * ty) {
+ self.direction = leftAngle;
+ } else {
+ self.direction = rightAngle;
+ }
+ break;
+ }
+ }
+ }
+ if (directPath) {
+ self.direction = targetDirection;
+ }
+ // Predictive targeting - aim where player will be
+ if (self.target === player && !player.inCar) {
+ var predictionTime = dist / enhancedSpeed;
+ var predictedX = player.x + player.direction.x * player.speed * predictionTime;
+ var predictedY = player.y + player.direction.y * player.speed * predictionTime;
+ var ptx = predictedX - self.x;
+ var pty = predictedY - self.y;
+ if (Math.sqrt(ptx * ptx + pty * pty) < dist) {
+ self.direction = Math.atan2(pty, ptx);
+ }
+ }
+ // Move with enhanced speed
+ self.x += Math.cos(self.direction) * enhancedSpeed;
+ self.y += Math.sin(self.direction) * enhancedSpeed;
// Prevent passing through buildings
for (var i = 0; typeof buildings !== "undefined" && i < buildings.length; i++) {
if (self.intersects(buildings[i])) {
self.x = prevX;
self.y = prevY;
+ // Try alternative movement when stuck
+ self.direction += (Math.random() - 0.5) * Math.PI / 2;
break;
}
}
}
- // Fire bullet if close enough and cooldown is 0
- if (dist < 600 && self.bulletCooldown <= 0 && typeof policeBullets !== "undefined") {
- var bullet = new PoliceBullet();
- bullet.x = self.x + Math.cos(self.direction) * 70;
- bullet.y = self.y + Math.sin(self.direction) * 70;
- bullet.direction = self.direction;
- policeBullets.push(bullet);
- if (typeof game !== "undefined") game.addChild(bullet);
- self.bulletCooldown = 90 + Math.floor(Math.random() * 60); // 1.5s-2.5s
+ // Enhanced shooting behavior
+ var shootingRange = 500 + aggressionLevel * 100; // Longer range at higher wanted
+ var baseCooldown = Math.max(30, 90 - aggressionLevel * 15); // Faster shooting at higher wanted
+ // Lead target for better accuracy
+ var aimDirection = self.direction;
+ if (dist < shootingRange && self.bulletCooldown <= 0 && typeof policeBullets !== "undefined") {
+ // Predictive aiming for moving targets
+ if (self.target === player && (player.direction.x !== 0 || player.direction.y !== 0)) {
+ var bulletSpeed = 16;
+ var timeToHit = dist / bulletSpeed;
+ var futureX = player.x + player.direction.x * player.speed * timeToHit;
+ var futureY = player.y + player.direction.y * player.speed * timeToHit;
+ aimDirection = Math.atan2(futureY - self.y, futureX - self.x);
+ }
+ // Burst fire at high wanted levels
+ var burstCount = aggressionLevel >= 3 ? 2 : 1;
+ for (var b = 0; b < burstCount; b++) {
+ var bullet = new PoliceBullet();
+ bullet.x = self.x + Math.cos(aimDirection) * 70;
+ bullet.y = self.y + Math.sin(aimDirection) * 70;
+ bullet.direction = aimDirection + (b > 0 ? (Math.random() - 0.5) * 0.3 : 0); // Slight spread for burst
+ policeBullets.push(bullet);
+ if (typeof game !== "undefined") game.addChild(bullet);
+ }
+ self.bulletCooldown = baseCooldown + Math.floor(Math.random() * 30);
}
if (self.bulletCooldown > 0) self.bulletCooldown--;
}
// Clamp to city bounds
@@ -237,18 +305,42 @@
/****
* Game Code
****/
-// Arrow key assets
-// City layout
-// Player character: red box
-// Car: blue box
-// Police car: white box with blue
-// Pedestrian: green ellipse
-// Road: gray box
-// Building: dark gray box
+// Enhanced police coordination
+function updatePoliceCoordination() {
+ if (policeCars.length > 1 && wantedLevel >= 3) {
+ // Coordinate police to surround player
+ for (var i = 0; i < policeCars.length; i++) {
+ var police = policeCars[i];
+ var angleOffset = i / policeCars.length * Math.PI * 2;
+ var surroundDistance = 300;
+ // Calculate flanking position
+ var targetX = player.x + Math.cos(angleOffset) * surroundDistance;
+ var targetY = player.y + Math.sin(angleOffset) * surroundDistance;
+ // Adjust police target to flanking position instead of direct pursuit
+ if (Math.random() < 0.3) {
+ // 30% chance to use flanking behavior
+ var flankTx = targetX - police.x;
+ var flankTy = targetY - police.y;
+ var flankDist = Math.sqrt(flankTx * flankTx + flankTy * flankTy);
+ if (flankDist > 50) {
+ police.direction = Math.atan2(flankTy, flankTx);
+ }
+ }
+ }
+ }
+}
+// Police spawn logic
// Mission marker: yellow ellipse
-// Sound effects
+// Building: dark gray box
+// Road: gray box
+// Pedestrian: green ellipse
+// Police car: white box with blue
+// Car: blue box
+// Player character: red box
+// City layout
+// Arrow key assets
var buildings = [];
var cars = [];
var policeCars = [];
var pedestrians = [];
@@ -729,13 +821,16 @@
for (var i = 0; i < cars.length; i++) {
cars[i].update();
// AI: cars do not move, so do not pick new targets
}
+ // Update police coordination
+ updatePoliceCoordination();
// Update police
for (var i = 0; i < policeCars.length; i++) {
policeCars[i].update();
- // Siren sound
- if (wantedLevel > 0 && LK.ticks % 60 === 0) {
+ // Siren sound (more frequent at higher wanted levels)
+ var sirenFreq = Math.max(30, 90 - wantedLevel * 15);
+ if (wantedLevel > 0 && LK.ticks % sirenFreq === 0) {
LK.getSound('police_siren').play();
}
// Police catch player
// (No game over when police touch player or player's car)
@@ -809,11 +904,15 @@
}, 1200);
}
// Update wanted level
wantedTxt.setText('Aranma: ' + wantedLevel);
- // Police spawn logic
- if (wantedLevel > 0 && policeCars.length < 1) {
- spawnPolice();
+ // Enhanced police spawn logic with scaling
+ var maxPolice = Math.min(wantedLevel, 4); // Up to 4 police cars at max wanted level
+ if (wantedLevel > 0 && policeCars.length < maxPolice) {
+ // Spawn additional police more frequently at higher wanted levels
+ if (LK.ticks % (180 - wantedLevel * 20) === 0) {
+ spawnPolice();
+ }
}
if (wantedLevel === 0 && policeCars.length > 0) {
removeAllPolice();
}
the modern gun. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
delete background
delete background
delete background
Draw a modern road viewed from above. In-Game asset. 2d. High contrast. No shadows
delete background
arrow pointing up. In-Game asset. 2d. High contrast. No shadows
arrow pointing down. In-Game asset. 2d. High contrast. No shadows
arrow pointing right. In-Game asset. 2d. High contrast. No shadows
arrow pointing left. In-Game asset. 2d. High contrast. No shadows
delete background
delete background