• 23-11-2025, 17:55:50
    #1
    <!DOCTYPE html>
    <html lang="tr">
    <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <title>GTA: San HTML - Final Fix</title>
    <style>
        body { margin: 0; overflow: hidden; background: #111; font-family: 'Verdana', sans-serif; touch-action: none; user-select: none; cursor: crosshair; }
        canvas { display: block; }
        
        #ui-layer { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; }
        
        #minimap-container {
            position: absolute; top: 10px; right: 10px;
            width: 140px; height: 140px;
            border: 4px solid #fff; border-radius: 50%; overflow: hidden;
            background: #000; box-shadow: 0 0 10px rgba(0,0,0,0.5);
        }
        
        #hud-stats {
            position: absolute; top: 160px; right: 10px;
            text-align: right; color: white; font-weight: bold; text-shadow: 2px 2px 0 #000;
        }
        #money { color: #2ecc71; font-size: 26px; margin-bottom: 5px; }
        #wanted-level { color: #3498db; font-size: 22px; letter-spacing: 3px; }
        #health-bar-bg { width: 130px; height: 12px; background: #444; border: 2px solid #fff; margin-left: auto; margin-top: 5px; }
        #health-bar { width: 100%; height: 100%; background: #e74c3c; transition: width 0.2s; }
        #ammo-display { font-size: 20px; color: #f1c40f; margin-top: 5px; display: none; }
    
        #interact-msg {
            position: absolute; top: 60%; left: 50%; transform: translate(-50%, -50%);
            color: #fff; background: rgba(0,0,0,0.7); padding: 10px 20px; border-radius: 20px;
            font-size: 20px; font-weight: bold; border: 2px solid #f1c40f;
            display: none; z-index: 150;
        }
    
        #shop-menu {
            position: absolute; top: 0; left: 0; width: 100%; height: 100%;
            background: rgba(0,0,0,0.9); z-index: 200;
            display: none; flex-direction: column; align-items: center; justify-content: center;
            pointer-events: auto; cursor: default;
        }
        .shop-item {
            background: #222; color: white; border: 2px solid #f1c40f;
            padding: 15px; width: 280px; margin: 10px; text-align: center;
            cursor: pointer; font-size: 18px; font-weight: bold; transition: 0.2s;
        }
        .shop-item:hover { background: #f1c40f; color: black; transform: scale(1.05); }
    
        #wasted-screen {
            position: absolute; top: 0; left: 0; width: 100%; height: 100%;
            background: rgba(150, 0, 0, 0.6); z-index: 100;
            display: none; flex-direction: column; align-items: center; justify-content: center;
        }
        #wasted-text { color: #fff; font-size: 70px; font-weight: 900; text-shadow: 4px 4px 0 #000; letter-spacing: 5px; transform: rotate(-5deg); }
        #mission-msg { position: absolute; bottom: 120px; width: 100%; text-align: center; color: #f1c40f; font-size: 24px; font-weight: bold; text-shadow: 2px 2px 0 #000; display: none; }
    
        /* Mobil Kontroller */
        .btn { position: absolute; width: 65px; height: 65px; background: rgba(255,255,255,0.2); border: 2px solid rgba(255,255,255,0.4); border-radius: 50%; pointer-events: auto; display: none; color: white; align-items: center; justify-content: center; font-size: 24px; }
        #joy-bg { position: absolute; bottom: 30px; left: 30px; width: 130px; height: 130px; background: rgba(255,255,255,0.1); border-radius: 50%; pointer-events: auto; display: none; }
        #joy-stick { position: absolute; top: 50%; left: 50%; width: 50px; height: 50px; background: rgba(255,255,255,0.4); border-radius: 50%; transform: translate(-50%, -50%); pointer-events: none; }
        #btn-enter { bottom: 110px; right: 25px; border-color: #f1c40f; background: rgba(241, 196, 15, 0.3); } 
        #btn-shoot { bottom: 30px; right: 25px; border-color: #e74c3c; background: rgba(231, 76, 60, 0.3); } 
    </style>
    </head>
    <body>
    
    <canvas id="gameCanvas"></canvas>
    
    <div id="ui-layer">
        <div id="minimap-container"><canvas id="minimap" width="150" height="150"></canvas></div>
        <div id="hud-stats">
            <div id="money">$100</div>
            <div id="wanted-level">☆☆☆☆☆</div>
            <div id="health-bar-bg"><div id="health-bar"></div></div>
            <div id="ammo-display">🔫 0</div>
        </div>
        
        <div id="interact-msg">[E] ETKİLEŞİM</div>
        <div id="mission-msg">GÖREV GÜNCELLENDİ</div>
    
        <div id="wasted-screen">
            <div id="wasted-text">YAKALANDIN</div>
        </div>
        
        <div id="shop-menu">
            <h2 style="color:#f1c40f; text-shadow: 2px 2px 0 #000;">KARABORSA SİLAHÇI</h2>
            <div class="shop-item" onclick="buyItem('health', 200)">❤️ CAN YENİLE ($200)</div>
            <div class="shop-item" onclick="buyItem('ammo', 500)">🔫 MERMİ AL ($500)</div>
            <div class="shop-item" onclick="buyItem('bribe', 1000)">⭐ POLİSTEN KURTUL ($1000)</div>
            <div class="shop-item" style="border-color:#e74c3c; color:#e74c3c" onclick="closeShop()">KAPAT</div>
        </div>
    
        <div id="joy-bg"><div id="joy-stick"></div></div>
        <div id="btn-enter" class="btn">👋</div>
        <div id="btn-shoot" class="btn">🔥</div>
    </div>
    
    <script>
    window.onload = init;
    
    const canvas = document.getElementById('gameCanvas');
    const ctx = canvas.getContext('2d');
    const miniCanvas = document.getElementById('minimap');
    const miniCtx = miniCanvas.getContext('2d');
    const isMobile = 'ontouchstart' in window || navigator.maxTouchPoints > 0;
    
    let width, height;
    let camera = { x: 0, y: 0 };
    const BLOCK = 80;
    const MAP_SIZE = 20;
    
    let keys = { w:0, a:0, s:0, d:0, e:0, shoot:0 };
    let mouse = { x: 0, y: 0, down: false };
    let inputVector = { x:0, y:0 };
    let map = []; 
    let roadTiles = [], sidewalkTiles = [];
    // FIX: Kaldırım karelerini hızlıca kontrol etmek için bir Set oluşturuldu
    let sidewalkSet = new Set();
    
    let cars = [], peds = [], items = [], bullets = [], particles = [], shops = [];
    let mission = { active: false, x: 0, y: 0 };
    let isGamePaused = false;
    let canInteract = null;
    
    let player = {
        x: 0, y: 0, angle: 0, targetAngle: 0, state: 'on_foot', car: null,
        health: 100, money: 100, wanted: 0, weapon: 'fist', ammo: 0, lastAttack: 0, 
        radius: 6
    };
    
    function init() {
        resize();
        window.addEventListener('resize', resize);
        setupControls();
    
        generateMap(); 
        respawnPlayer();
        
        for(let i=0; i<12; i++) spawnCar();
        for(let i=0; i<20; i++) spawnPed();
        for(let i=0; i<3; i++) spawnShop();
        
        nextMission();
        requestAnimationFrame(loop);
    }
    
    function resize() {
        width = canvas.width = window.innerWidth;
        height = canvas.height = window.innerHeight;
        if(isMobile) {
            document.querySelectorAll('.btn').forEach(b => b.style.display = 'flex');
            document.getElementById('joy-bg').style.display = 'block';
            document.body.style.cursor = 'default';
        }
    }
    
    // --- HARİTA & SPAWN ---
    function generateMap() {
        map = []; roadTiles = []; sidewalkTiles = []; sidewalkSet.clear();
        for(let y=0; y<MAP_SIZE; y++) { let r=[]; for(let x=0; x<MAP_SIZE; x++) r.push(0); map.push(r); }
        for(let x=2; x<MAP_SIZE-1; x+=4) for(let y=0; y<MAP_SIZE; y++) map[y][x] = 1; 
        for(let y=2; y<MAP_SIZE-1; y+=4) for(let x=0; x<MAP_SIZE; x++) map[y][x] = (map[y][x] === 1) ? 3 : 2; 
        
        for(let y=0; y<MAP_SIZE; y++) for(let x=0; x<MAP_SIZE; x++) {
            if(map[y][x] > 0) roadTiles.push({x: x, y: y});
            else {
                let isSide = false;
                if(x>0 && map[y][x-1]>0) isSide=true; if(x<MAP_SIZE-1 && map[y][x+1]>0) isSide=true;
                if(y>0 && map[y-1][x]>0) isSide=true; if(y<MAP_SIZE-1 && map[y+1][x]>0) isSide=true;
                if(isSide) {
                    sidewalkTiles.push({x: x, y: y});
                    sidewalkSet.add(`${x},${y}`);
                }
            }
        }
    }
    
    function respawnPlayer() {
        if(sidewalkTiles.length > 0) { 
            let t = sidewalkTiles[Math.floor(Math.random()*sidewalkTiles.length)]; 
            player.x = t.x*BLOCK+BLOCK/2; player.y = t.y*BLOCK+BLOCK/2; 
        } else { player.x = 200; player.y = 200; }
        
        player.health = 100; player.wanted = 0; player.weapon = 'fist'; 
        player.state = 'on_foot'; player.car = null;
        document.getElementById('wasted-screen').style.display = 'none';
        updateUI();
    }
    
    function spawnCar() {
        if(roadTiles.length === 0) return;
        let t = roadTiles[Math.floor(Math.random()*roadTiles.length)];
        let angle = map[t.y][t.x] === 1 ? Math.PI/2 : 0;
        cars.push({x: t.x*BLOCK+BLOCK/2, y: t.y*BLOCK+BLOCK/2, angle: angle, speed: 2, radius: 15, color: ['#e74c3c','#8e44ad','#3498db','#fff'][Math.floor(Math.random()*4)]});
    }
    function spawnPed(type='civilian') {
        if(sidewalkTiles.length === 0) return;
        let t = sidewalkTiles[Math.floor(Math.random()*sidewalkTiles.length)];
        peds.push({x: t.x*BLOCK+BLOCK/2, y: t.y*BLOCK+BLOCK/2, angle: Math.random()*6.28, type: type, health: 100, radius: 8, color: type==='police'?'#3498db':['#2ecc71','#d35400','#16a085'][Math.floor(Math.random()*3)]});
    }
    function spawnShop() {
        if(sidewalkTiles.length === 0) return;
        let t = sidewalkTiles[Math.floor(Math.random()*sidewalkTiles.length)];
        shops.push({x: t.x*BLOCK+BLOCK/2, y: t.y*BLOCK+BLOCK/2});
    }
    function nextMission() {
        if(sidewalkTiles.length === 0) return;
        let t = sidewalkTiles[Math.floor(Math.random()*sidewalkTiles.length)];
        mission.x = t.x*BLOCK+BLOCK/2; mission.y = t.y*BLOCK+BLOCK/2;
        mission.active = true; showMsg("GÖREV: SARI ALANA GİT", "#f1c40f");
    }
    
    // --- ETKİLEŞİM & DÜKKAN ---
    function checkInteractions() {
        canInteract = null;
        document.getElementById('interact-msg').style.display = 'none';
        if(player.state !== 'on_foot') return;
    
        let nearShop = shops.find(s => dist(player.x, player.y, s.x, s.y) < 65);
        if(nearShop) { canInteract = 'shop'; document.getElementById('interact-msg').innerText = "[E] DÜKKANA GİR"; }
    
        if(mission.active && dist(player.x, player.y, mission.x, mission.y) < 65) { 
            canInteract = 'mission'; document.getElementById('interact-msg').innerText = "[E] GÖREVİ YAP";
        }
    
        if(canInteract) document.getElementById('interact-msg').style.display = 'block';
    }
    function openShop() { document.getElementById('shop-menu').style.display='flex'; isGamePaused=true; }
    function closeShop() { document.getElementById('shop-menu').style.display='none'; isGamePaused=false; }
    function completeMission() {
        player.money += 500; showMsg("BAŞARILI! +$500", "#2ecc71");
        mission.active = false; setTimeout(nextMission, 3000);
    }
    function buyItem(item, cost) {
        if(player.money>=cost) { player.money-=cost; if(item==='health')player.health=100; if(item==='ammo'){player.weapon='pistol';player.ammo+=30;} if(item==='bribe')player.wanted=0; updateUI(); showMsg("SATIN ALINDI!","#2ecc71"); }
        else showMsg("YETERSİZ PARA!","#c0392b");
    }
    
    // --- FİZİK & HAREKET (TAKILMA ÖNLEYİCİ) ---
    function checkCollision(x, y, r) { 
        let m = r; 
        if(isWall(x-m, y-m) || isWall(x+m, y-m) || isWall(x-m, y+m) || isWall(x+m, y+m)) return true; 
        return false; 
    }
    function isWall(x, y) { 
        let gx = Math.floor(x/BLOCK), gy = Math.floor(y/BLOCK); 
        if(gx<0 || gx>=MAP_SIZE || gy<0 || gy>=MAP_SIZE) return true; 
        // FIX: Bir kare çim ise (0) VE aynı zamanda bir kaldırım değilse, o zaman duvardır.
        return map[gy][gx] === 0 && !sidewalkSet.has(`${gx},${gy}`); 
    }
    
    function update() {
        if(isGamePaused || player.health<=0) return;
    
        if(player.state === 'on_foot') {
            let mx = isMobile ? inputVector.x : (keys.d-keys.a), my = isMobile ? inputVector.y : (keys.s-keys.w);
            
            if(mx||my) {
                let spd = 4;
                if(isMobile) player.targetAngle = Math.atan2(my,mx);
                
                let nextX = player.x + mx * spd * (isMobile?1:0.7);
                if(!checkCollision(nextX, player.y, player.radius)) player.x = nextX;
                
                let nextY = player.y + my * spd * (isMobile?1:0.7);
                if(!checkCollision(player.x, nextY, player.radius)) player.y = nextY;
            }
            
            if(!isMobile) player.targetAngle = Math.atan2(mouse.y - (player.y-camera.y), mouse.x - (player.x-camera.x));
            
            let diff = player.targetAngle - player.angle;
            while (diff < -Math.PI) diff += Math.PI * 2; while (diff > Math.PI) diff -= Math.PI * 2;
            player.angle += diff * 0.2;
    
            if((!isMobile && mouse.down) || (isMobile && keys.shoot)) {
                if(Date.now()-player.lastAttack>300) { attack(); player.lastAttack=Date.now(); }
            }
            
            checkInteractions(); 
            
            items.forEach((it,i)=>{if(dist(player.x,player.y,it.x,it.y)<30){if(it.type==='gun'){player.weapon='pistol';player.ammo+=20;showMsg("SİLAH BULUNDU!","#2ecc71");}items.splice(i,1);}});
            
            let pgx = Math.floor(player.x/BLOCK), pgy = Math.floor(player.y/BLOCK);
            if(map[pgy] && map[pgy][pgx] === 0) {
                if(map[pgy][pgx+1] !== 0) player.x += 2;
                else if(map[pgy][pgx-1] !== 0) player.x -= 2;
                else if(map[pgy+1][pgx] !== 0) player.y += 2;
                else if(map[pgy-1][pgx] !== 0) player.y -= 2;
            }
        }
        
        if(player.state === 'driving') {
            let c=player.car, gas=keys.w||(inputVector.y<-0.3), rev=keys.s||(inputVector.y>0.3), left=keys.a||(inputVector.x<-0.3), right=keys.d||(inputVector.x>0.3);
            if(gas)c.speed+=0.2; if(rev)c.speed-=0.2; c.speed*=0.96;
            if(Math.abs(c.speed)>0.5) c.angle+=(right?0.06:(left?-0.06:0))*(c.speed>0?1:-1);
            let nx=c.x+Math.cos(c.angle)*c.speed, ny=c.y+Math.sin(c.angle)*c.speed;
            if(checkCollision(nx,ny,15)){c.speed*=-0.5;c.x-=Math.cos(c.angle)*10;c.y-=Math.sin(c.angle)*10;}else{c.x=nx;c.y=ny;}
            peds.forEach((p,i)=>{if(dist(c.x,c.y,p.x,p.y)<25&&Math.abs(c.speed)>2)hitPed(p,i,true);});
            player.x=c.x; player.y=c.y;
        }
    
        updateTraffic(); updatePeds(); updateBullets();
        
        if(player.wanted > 0) {
            let pols = peds.filter(p => p.type === 'police').length;
            if(pols < player.wanted && Math.random() < 0.01) spawnPed('police');
        }
    
        camera.x += (player.x - width/2 - camera.x) * 0.1;
        camera.y += (player.y - height/2 - camera.y) * 0.1;
        updateUI(); drawMinimap();
    }
    
    function updateTraffic() {
        cars.forEach(c => { if(c===player.car)return;
            let gx=Math.floor(c.x/BLOCK), gy=Math.floor(c.y/BLOCK), type=map[gy]?map[gy][gx]:0, cx=gx*BLOCK+BLOCK/2, cy=gy*BLOCK+BLOCK/2;
            if(type===1 && Math.abs(c.x-cx)>2)c.x+=(cx-c.x)*0.05; if(type===2 && Math.abs(c.y-cy)>2)c.y+=(cy-c.y)*0.05;
            if(Math.abs(c.x-cx)<10 && Math.abs(c.y-cy)<10) {
                if(type===3) c.angle=[0,Math.PI/2,Math.PI,-Math.PI/2][Math.floor(Math.random()*4)];
                else if(type===1) c.angle=Math.sin(c.angle)>0?Math.PI/2:-Math.PI/2; else if(type===2) c.angle=Math.cos(c.angle)>0?0:Math.PI;
            }
            let stop=false; if(dist(c.x,c.y,player.x,player.y)<70)stop=true;
            cars.forEach(o=>{if(c!==o && dist(c.x,c.y,o.x,o.y)<70 && Math.abs(Math.atan2(o.y-c.y,o.x-c.x)-c.angle)<1.0)stop=true;});
            if(stop)c.speed*=0.8; else if(c.speed<3)c.speed+=0.1;
            c.x+=Math.cos(c.angle)*c.speed; c.y+=Math.sin(c.angle)*c.speed;
            if(c.x<0)c.x=MAP_SIZE*BLOCK;if(c.x>MAP_SIZE*BLOCK)c.x=0;if(c.y<0)c.y=MAP_SIZE*BLOCK;if(c.y>MAP_SIZE*BLOCK)c.y=0;
        });
    }
    function updatePeds() {
        peds.forEach((p, i) => { let speed=1;
            if(p.type==='police'&&player.wanted>0){p.angle=Math.atan2(player.y-p.y,player.x-p.x);speed=3.2;if(dist(p.x,p.y,player.x,player.y)<200&&Math.random()<0.03)bullets.push({x:p.x,y:p.y,angle:p.angle+(Math.random()-0.5)*0.2,speed:10,owner:'police',life:60});}
            else if(p.panic)speed=3;
            let nx=p.x+Math.cos(p.angle)*speed, ny=p.y+Math.sin(p.angle)*speed;
            if(!checkCollision(nx,ny,5)){p.x=nx;p.y=ny;}else p.angle=Math.random()*6.28;
            if(Math.random()<0.01)p.angle+=(Math.random()-0.5);
        });
    }
    function attack() {
        if(player.weapon==='fist') peds.forEach((p,i)=>{if(dist(player.x,player.y,p.x,p.y)<40)hitPed(p,i,false);});
        else if(player.weapon==='pistol'&&player.ammo>0){player.ammo--;bullets.push({x:player.x,y:player.y,angle:player.angle,speed:15,owner:'player',life:50});}
    }
    function hitPed(p,idx,isCar) {
        p.health-=isCar?100:35; blood(p.x,p.y);
        if(p.type!=='enemy'){player.wanted=Math.min(5,player.wanted+1);showMsg("ARANIYORSUN!","#e74c3c");}
        if(p.health<=0){peds.splice(idx,1);if(p.type==='police')items.push({x:p.x,y:p.y,type:'gun'});}else p.panic=true;
    }
    function updateBullets() {
        for(let i=bullets.length-1;i>=0;i--){let b=bullets[i];b.x+=Math.cos(b.angle)*b.speed;b.y+=Math.sin(b.angle)*b.speed;b.life--;if(isWall(b.x,b.y)||b.life<=0){bullets.splice(i,1);continue;}if(b.owner!=='player'&&dist(b.x,b.y,player.x,player.y)<20){player.health-=10;blood(player.x,player.y);bullets.splice(i,1);if(player.health<=0)document.getElementById('wasted-screen').style.display='flex',setTimeout(respawnPlayer,3000);}if(b.owner==='player')peds.forEach((p,idx)=>{if(dist(b.x,b.y,p.x,p.y)<20){hitPed(p,idx,false);bullets.splice(i,1);}});}
    }
    
    // --- ÇİZİM ---
    function draw() {
        ctx.setTransform(1,0,0,1,0,0); ctx.fillStyle='#2c3e50'; ctx.fillRect(0,0,width,height);
        ctx.save(); ctx.translate(-camera.x,-camera.y);
        let startX=Math.floor(camera.x/BLOCK), startY=Math.floor(camera.y/BLOCK), endX=startX+Math.ceil(width/BLOCK)+1, endY=startY+Math.ceil(height/BLOCK)+1;
        for(let y=startY;y<endY;y++)for(let x=startX;x<endX;x++){if(x<0||y<0||x>=MAP_SIZE||y>=MAP_SIZE)continue;let px=x*BLOCK,py=y*BLOCK;if(map[y][x]===0){ctx.fillStyle='#27ae60';ctx.fillRect(px,py,BLOCK,BLOCK);ctx.fillStyle='#1e824c';ctx.fillRect(px+5,py+5,BLOCK-10,BLOCK-10);}else{ctx.fillStyle='#7f8c8d';ctx.fillRect(px,py,BLOCK,BLOCK);ctx.fillStyle='#f1c40f';if(map[y][x]===1)ctx.fillRect(px+38,py,4,BLOCK);if(map[y][x]===2)ctx.fillRect(px,py+38,BLOCK,4);}}
        
        shops.forEach(s=>{ctx.fillStyle='rgba(155,89,182,0.5)';ctx.beginPath();ctx.arc(s.x,s.y,35,0,6.28);ctx.fill();ctx.fillStyle='#fff';ctx.font="12px Verdana";ctx.fillText("SHOP",s.x-15,s.y);});
        if(mission.active){ctx.fillStyle='rgba(241,196,15,0.5)';ctx.beginPath();ctx.arc(mission.x,mission.y,45,0,6.28);ctx.fill();ctx.strokeStyle='#f1c40f';ctx.lineWidth=3;ctx.stroke();}
        items.forEach(i=>{ctx.fillStyle='#e67e22';ctx.fillRect(i.x-10,i.y-10,20,20);ctx.strokeStyle='#fff';ctx.strokeRect(i.x-10,i.y-10,20,20);});
        particles.forEach((p,i)=>{ctx.fillStyle=p.color;ctx.fillRect(p.x,p.y,p.size,p.size);p.life--;if(p.life<=0)particles.splice(i,1);});
        cars.forEach(c=>{ctx.save();ctx.translate(c.x,c.y);ctx.rotate(c.angle);ctx.fillStyle=c.color;ctx.fillRect(-18,-10,36,20);ctx.fillStyle='#f1c40f';ctx.fillRect(18,-8,5,4);ctx.fillRect(18,4,5,4);ctx.restore();});
        peds.forEach(p=>{ctx.save();ctx.translate(p.x,p.y);ctx.rotate(p.angle);ctx.fillStyle=p.type==='police'?'#2980b9':p.color;ctx.beginPath();ctx.arc(0,0,10,0,6.28);ctx.fill();ctx.restore();});
        if(player.state==='on_foot'){ctx.save();ctx.translate(player.x,player.y);ctx.rotate(player.angle);ctx.fillStyle='#f39c12';ctx.beginPath();ctx.arc(0,0,9,0,6.28);ctx.fill();ctx.fillStyle='#000';if(player.weapon==='fist'){ctx.beginPath();ctx.arc(8,-8,3,0,6.28);ctx.fill();ctx.beginPath();ctx.arc(8,8,3,0,6.28);ctx.fill();}else ctx.fillRect(0,2,20,4);ctx.restore();}
        ctx.fillStyle='#fff'; bullets.forEach(b=>{ctx.beginPath();ctx.arc(b.x,b.y,3,0,6.28);ctx.fill();});
        ctx.restore();
    }
    
    function drawMinimap() {
        miniCtx.fillStyle = '#222'; miniCtx.fillRect(0, 0, 150, 150);
        miniCtx.save(); miniCtx.translate(75, 75); miniCtx.rotate(-player.angle); miniCtx.translate(-player.x/5, -player.y/5);
        for(let y=0; y<MAP_SIZE; y++) for(let x=0; x<MAP_SIZE; x++) { if(map[y][x] > 0) { miniCtx.fillStyle = '#7f8c8d'; miniCtx.fillRect(x*BLOCK/5, y*BLOCK/5, BLOCK/5, BLOCK/5); } }
        shops.forEach(s => { miniCtx.fillStyle = '#9b59b6'; miniCtx.beginPath(); miniCtx.arc(s.x/5, s.y/5, 4, 0, 6.28); miniCtx.fill(); });
        if(mission.active) { miniCtx.fillStyle = '#f1c40f'; miniCtx.beginPath(); miniCtx.arc(mission.x/5, mission.y/5, 5, 0, 6.28); miniCtx.fill(); }
        miniCtx.restore();
        miniCtx.fillStyle = '#f39c12'; miniCtx.beginPath(); miniCtx.arc(75, 75, 3, 0, 6.28); miniCtx.fill();
    }
    
    function dist(x1,y1,x2,y2){return Math.sqrt((x1-x2)**2+(y1-y2)**2);}
    function blood(x,y){for(let i=0;i<8;i++)particles.push({x,y,size:4,color:'#c0392b',life:30});}
    function showMsg(t,c){let m=document.getElementById('mission-msg'); m.innerText=t; m.style.color=c; m.style.display='block'; setTimeout(()=>m.style.display='none',2000);}
    
    function interact() {
        if(isGamePaused) return;
        if(player.state === 'driving') { player.state='on_foot'; player.x-=30; player.car=null; }
        else { let near=cars.find(c=>dist(player.x,player.y,c.x,c.y)<60); if(near){player.state='driving'; player.car=near;} }
    }
    function updateUI() {
        document.getElementById('money').innerText="$"+player.money; document.getElementById('health-bar').style.width=Math.max(0,player.health)+'%';
        let s="";for(let i=0;i<5;i++)s+=i<player.wanted?"★":"☆";document.getElementById('wanted-level').innerText=s;
        let btnShoot=document.getElementById('btn-shoot'), ammoDiv=document.getElementById('ammo-display');
        if(player.weapon==='pistol'){if(isMobile)btnShoot.style.display='flex';ammoDiv.style.display='block';ammoDiv.innerText=`🔫 ${player.ammo}`;}
        else{if(isMobile)btnShoot.style.display='none';ammoDiv.style.display='none';}
    }
    
    function setupControls() {
        window.addEventListener('keydown', e => {
            if(e.key.toLowerCase() === 'w') keys.w = 1;
            if(e.key.toLowerCase() === 's') keys.s = 1;
            if(e.key.toLowerCase() === 'a') keys.a = 1;
            if(e.key.toLowerCase() === 'd') keys.d = 1;
            if(e.key.toLowerCase() === 'e') { 
                if(canInteract==='shop') openShop();
                else if(canInteract==='mission') completeMission();
                else interact();
            }
        });
        
        window.addEventListener('keyup', e => {
            if(e.key.toLowerCase() === 'w') keys.w = 0;
            if(e.key.toLowerCase() === 's') keys.s = 0;
            if(e.key.toLowerCase() === 'a') keys.a = 0;
            if(e.key.toLowerCase() === 'd') keys.d = 0;
        });
        
        window.addEventListener('mousemove', e => {
            mouse.x = e.clientX; 
            mouse.y = e.clientY;
        });
        
        window.addEventListener('mousedown', e => {
            if(e.button === 0) mouse.down = true;
        });
        
        window.addEventListener('mouseup', e => {
            if(e.button === 0) mouse.down = false;
        });
    
        if(isMobile) {
            let joy=document.getElementById('joy-bg'), stick=document.getElementById('joy-stick');
            
            joy.addEventListener('touchstart', e => {
                e.preventDefault();
                let t = e.touches[0];
                let r = joy.getBoundingClientRect();
                let dx = t.clientX - (r.left + 70);
                let dy = t.clientY - (r.top + 70);
                let d = Math.min(Math.hypot(dx, dy), 50);
                let a = Math.atan2(dy, dx);
                inputVector.x = Math.cos(a) * (d/50);
                inputVector.y = Math.sin(a) * (d/50);
                stick.style.transform = `translate(calc(-50% + ${inputVector.x*50}px), calc(-50% + ${inputVector.y*50}px))`;
            });
            
            joy.addEventListener('touchmove', e => {
                e.preventDefault();
                let t = e.touches[0];
                let r = joy.getBoundingClientRect();
                let dx = t.clientX - (r.left + 70);
                let dy = t.clientY - (r.top + 70);
                let d = Math.min(Math.hypot(dx, dy), 50);
                let a = Math.atan2(dy, dx);
                inputVector.x = Math.cos(a) * (d/50);
                inputVector.y = Math.sin(a) * (d/50);
                stick.style.transform = `translate(calc(-50% + ${inputVector.x*50}px), calc(-50% + ${inputVector.y*50}px))`;
            });
            
            joy.addEventListener('touchend', () => {
                inputVector = {x: 0, y: 0};
                stick.style.transform = `translate(-50%, -50%)`;
            });
            
            document.getElementById('btn-enter').onclick = () => {
                if(canInteract==='shop') openShop();
                else if(canInteract==='mission') completeMission();
                else interact();
            };
            
            document.getElementById('btn-shoot').addEventListener('touchstart', () => {
                keys.shoot = 1;
            });
            
            document.getElementById('btn-shoot').addEventListener('touchend', () => {
                keys.shoot = 0;
            });
        }
    }
    
    function loop() { 
        update(); 
        draw(); 
        requestAnimationFrame(loop); 
    }
    </script>
    </body>
    </html>


    yumru atarsan mouse clikc ile polis aramaya başlar her vuruşta aranma yıldızı artar ve polisler sana saldırır takip eder



    yakalanırsan yakalandın yazar oyun tekrar başlar


    dükkanlara e ile basıp bir takım ürünler alabilirsin


    can ,yenileme , silah , polisten kurtul



    arabaya yanaşıp e ile basıp arabaya biner insanları ezebilirsin - polisi öldürünce silahını alabilirsin



    sarı alana giderseniz e ye basarsanız para verir görev yapmış olursunuz



    Selamlar yapay zeka ile basit birşey yaptım gta 2 benzeri geliştirmesi size kalmış kodları attım (buglar vs olabilir stabil çalışmayabilir iyi forumlar
  • 23-11-2025, 18:00:04
    #2
    Üyeliği durduruldu
    Süper olmuş hocam, elinize sağlık
  • 23-11-2025, 18:01:52
    #3
    Setindir adlı üyeden alıntı: mesajı görüntüle
    Süper olmuş hocam, elinize sağlık
    teşekkürler iyi forumlar
  • 23-11-2025, 18:03:57
    #4
    💰+50.000₺ PASİF GELİR
    Hocam hilesi var mı 😆
  • 23-11-2025, 18:07:52
    #5
    gl4d14tor adlı üyeden alıntı: mesajı görüntüle
    hocam hilesi var mı 😆
    hesoyam
  • 23-11-2025, 18:39:29
    #6
    Elinize sağlık claude mi
  • 23-11-2025, 18:40:49
    #7
    byaxios adlı üyeden alıntı: mesajı görüntüle
    Elinize sağlık claude mi
    Teşekkürler gemini + chat.z.ai