Meta Description" name="description" />
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<title>Mini GTA Mobile</title>
<style>
body { margin:0; overflow:hidden; background:#333; }
canvas { display:block; margin:auto; background:#87ceeb; touch-action: none; }
#info {
position:absolute; top:5px; left:5px; color:white; font-family:Arial;
background:rgba(0,0,0,0.5); padding:5px; border-radius:5px; font-size:14px;
}
.button {
position:absolute; width:60px; height:60px; background:rgba(0,0,0,0.6); color:white;
font-size:20px; border-radius:50%; text-align:center; line-height:60px; user-select:none;
}
#btnUp{ bottom:120px; left:60px; }
#btnDown{ bottom:20px; left:60px; }
#btnLeft{ bottom:70px; left:0px; }
#btnRight{ bottom:70px; left:120px; }
#btnPrev{ top:50px; right:100px; width:50px; height:50px; line-height:50px; }
#btnNext{ top:50px; right:30px; width:50px; height:50px; line-height:50px; }
#btnGarage{ top:120px; right:65px; width:50px; height:50px; line-height:50px; }
</style>
</head>
<body>
<div id="info">Coins: <span id="coins">0</span></div>
<canvas id="gameCanvas" width="700" height="400"></canvas>
<!-- Touch Controls -->
<div class="button" id="btnUp">↑</div>
<div class="button" id="btnDown">↓</div>
<div class="button" id="btnLeft">←</div>
<div class="button" id="btnRight">→</div>
<div class="button" id="btnPrev">◀</div>
<div class="button" id="btnNext">▶</div>
<div class="button" id="btnGarage">E</div>
<script>
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
// Map size
const mapWidth = 6000, mapHeight = 1200;
// 40 cars
const cars = [
{name:'Lamborghini Aventador', color:'#ff0000', width:50, height:25},
{name:'Lamborghini Huracan', color:'#ff3300', width:50, height:25},
{name:'Lamborghini Sian', color:'#ff6600', width:50, height:25},
{name:'Lamborghini Urus', color:'#ff9933', width:50, height:25},
{name:'Lamborghini Countach', color:'#ffcc33', width:50, height:25},
{name:'Ferrari LaFerrari', color:'#cc0000', width:50, height:25},
{name:'Ferrari SF90', color:'#ff1a1a', width:50, height:25},
{name:'Ferrari F8', color:'#ff4d4d', width:50, height:25},
{name:'Ferrari 812 Superfast', color:'#ff6666', width:50, height:25},
{name:'Ferrari Roma', color:'#ff9999', width:50, height:25},
{name:'Bugatti Chiron', color:'#0000ff', width:55, height:28},
{name:'Bugatti Divo', color:'#0033ff', width:55, height:28},
{name:'Bugatti Veyron', color:'#3366ff', width:55, height:28},
{name:'Bugatti Centodieci', color:'#3399ff', width:55, height:28},
{name:'Koenigsegg Jesko', color:'#00ff00', width:60, height:30},
{name:'Koenigsegg Regera', color:'#00cc00', width:60, height:30},
{name:'Koenigsegg Gemera', color:'#33ff33', width:60, height:30},
{name:'Koenigsegg CCXR', color:'#66ff66', width:60, height:30},
{name:'Pagani Huayra', color:'#ff00ff', width:55, height:28},
{name:'Pagani Zonda', color:'#cc00cc', width:55, height:28},
{name:'Pagani Imola', color:'#ff33ff', width:55, height:28},
{name:'McLaren P1', color:'#ff6600', width:50, height:25},
{name:'McLaren 720S', color:'#ff9933', width:50, height:25},
{name:'McLaren GT', color:'#ffcc66', width:50, height:25},
{name:'Porsche 911', color:'#ffff00', width:50, height:25},
{name:'Porsche Taycan', color:'#ffcc00', width:50, height:25},
{name:'Porsche 918', color:'#ffdd33', width:50, height:25},
{name:'Audi R8', color:'#00ffff', width:50, height:25},
{name:'BMW M8', color:'#33ffff', width:50, height:25},
{name:'Nissan GT-R', color:'#66ffff', width:50, height:25},
{name:'Toyota Prado', color:'#996633', width:55, height:28},
{name:'Toyota LC200', color:'#663300', width:55, height:28},
{name:'Toyota LC300', color:'#996600', width:55, height:28},
{name:'Mercedes G-Wagon', color:'#666666', width:55, height:28},
{name:'Range Rover', color:'#339966', width:55, height:28},
{name:'Mercedes Maybach', color:'#cc9966', width:55, height:28},
{name:'Nissan Skyline R34', color:'#003366', width:55, height:28},
{name:'Ford Mustang GT', color:'#ff3300', width:50, height:25},
{name:'BMW M5 CS', color:'#3333ff', width:50, height:25},
{name:'Toyota Supra Mk4', color:'#ff6600', width:50, height:25}
];
// Player
let currentCarIndex = 0;
let playerCar = {...cars[currentCarIndex], x:1000, y:600, angle:0, speed:0, inGarage:false};
// Touch control states
const controls = {up:false, down:false, left:false, right:false, prev:false, next:false, garage:false};
// Touch events
['Up','Down','Left','Right','Prev','Next','Garage'].forEach(id=>{
const btn=document.getElementById('btn'+id);
btn.addEventListener('touchstart',()=>controls[id.toLowerCase()]=true);
btn.addEventListener('touchend',()=>controls[id.toLowerCase()]=false);
});
// Switch car function
function switchCar(idx){
const oldX=playerCar.x, oldY=playerCar.y, oldAngle=playerCar.angle, oldGarage=playerCar.inGarage;
playerCar = {...cars[idx], x:oldX, y:oldY, angle:oldAngle, speed:0, inGarage:oldGarage};
currentCarIndex = idx;
}
// Zones
const zones = [
{name:'Los Santos', x:0, y:0, w:2000, h:1200},
{name:'San Fierro', x:2000, y:0, w:2000, h:1200},
{name:'Las Venturas', x:4000, y:0, w:2000, h:1200}
];
// Map elements
const roads=[], buildings=[], trees=[], coins=[], trafficCars=[];
// Generate elements
zones.forEach((zone,i)=>{
for(let j=0;j<4;j++){
roads.push({x:zone.x+100,y:zone.y+200+j*250,w:zone.w-200,h:80});
roads.push({x:zone.x+100+j*500,y:zone.y+100,w:80,h:zone.h-200});
}
for(let b=0;b<5;b++){
buildings.push({
x:zone.x+200+b*300,
y:zone.y+50,
w:120,
h:100,
isMansion:i===0 && b<3,
garageX:zone.x+200+b*300+90,
garageY:zone.y+70,
garageW:30,
garageH:50
});
}
for(let t=0;t<15;t++){
trees.push({x:zone.x+Math.random()*zone.w, y:zone.y+Math.random()*zone.h, r:10+Math.random()*10});
}
for(let c=0;c<20;c++){
coins.push({x:zone.x+Math.random()*zone.w, y:zone.y+Math.random()*zone.h, r:8, collected:false});
}
for(let tc=0;tc<10;tc++){
const car={...cars[Math.floor(Math.random()*cars.length)]};
car.x=zone.x+Math.random()*zone.w;
car.y=zone.y+Math.random()*zone.h;
car.angle=Math.random()*Math.PI*2;
car.speed=2+Math.random()*2;
trafficCars.push(car);
}
});
let coinsCollected=0;
// Garage enter/exit
function toggleGarage(){
buildings.forEach(b=>{
if(b.isMansion){
const dx=playerCar.x-(b.garageX+b.garageW/2);
const dy=playerCar.y-(b.garageY+b.garageH/2);
if(Math.sqrt(dx*dx+dy*dy)<40){
playerCar.inGarage=!playerCar.inGarage;
if(playerCar.inGarage){
playerCar.x=b.garageX+b.garageW/2;
playerCar.y=b.garageY+b.garageH/2;
}
}
}
});
}
// Game loop
function gameLoop(){ update(); draw(); requestAnimationFrame(gameLoop); }
// Update
function update(){
if(controls.left) playerCar.angle -= 0.05;
if(controls.right) playerCar.angle += 0.05;
if(controls.up) playerCar.speed += 0.3;
if(controls.down) playerCar.speed -= 0.2;
if(controls.prev){ let idx=currentCarIndex-1; if(idx>=0) switchCar(idx); controls.prev=false; }
if(controls.next){ let idx=currentCarIndex+1; if(idx<cars.length) switchCar(idx); controls.next=false; }
if(controls.garage){ toggleGarage(); controls.garage=false; }
playerCar.speed*=0.94;
playerCar.x+=Math.cos(playerCar.angle)*playerCar.speed;
playerCar.y+=Math.sin(playerCar.angle)*playerCar.speed;
if(playerCar.x<0) playerCar.x=0;
if(playerCar.x>mapWidth) playerCar.x=mapWidth;
if(playerCar.y<0) playerCar.y=0;
if(playerCar.y>mapHeight) playerCar.y=mapHeight;
coins.forEach(c=>{
if(!c.collected){
const dx=playerCar.x-c.x, dy=playerCar.y-c.y;
if(Math.sqrt(dx*dx+dy*dy)<30){c.collected=true; coinsCollected++; document.getElementById('coins').innerText=coinsCollected;}
}
});
trafficCars.forEach(c=>{
c.x+=Math.cos(c.angle)*c.speed;
c.y+=Math.sin(c.angle)*c.speed;
if(c.x<0||c.x>mapWidth) c.angle=Math.PI-c.angle;
if(c.y<0||c.y>mapHeight) c.angle=-c.angle;
const dx=c.x-playerCar.x, dy=c.y-playerCar.y;
if(Math.sqrt(dx*dx+dy*dy)<30){playerCar.speed*=0.7;c.speed*=0.8;}
});
}
// Draw
function draw(){
const camX=playerCar.x-canvas.width/2;
const camY=playerCar.y-canvas.height/2;
ctx.fillStyle='#87ceeb'; ctx.fillRect(0,0,canvas.width,canvas.height);
ctx.fillStyle='#555'; roads.forEach(r=>ctx.fillRect(r.x-camX,r.y-camY,r.w,r.h));
buildings.forEach(b=>{
ctx.fillStyle=b.isMansion?'#8b0000':'#a0522d';
ctx.fillRect(b.x-camX,b.y-camY,b.w,b.h);
if(b.isMansion){
ctx.fillStyle='#333';
ctx.fillRect(b.garageX-camX,b.garageY-camY,b.garageW,b.garageH);
}
});
ctx.fillStyle='#0a0'; trees.forEach(t=>{ctx.beginPath();ctx.arc(t.x-camX,t.y-camY,t.r,0,Math.PI*2);ctx.fill();});
ctx.fillStyle='yellow'; coins.forEach(c=>{if(!c.collected){ctx.beginPath();ctx.arc(c.x-camX,c.y-camY,c.r,0,Math.PI*2);ctx.fill();}});
trafficCars.forEach(c=>{ctx.save(); ctx.translate(c.x-camX,c.y-camY); ctx.rotate(c.angle); ctx.fillStyle=c.color; ctx.fillRect(-c.width/2,-c.height/2,c.width,c.height); ctx.restore();});
ctx.save(); ctx.translate(playerCar.x-camX,playerCar.y-camY); ctx.rotate(playerCar.angle); ctx.fillStyle=playerCar.color; ctx.fillRect(-playerCar.width/2,-playerCar.height/2,playerCar.width,playerCar.height); ctx.restore();
}
gameLoop();
</script>
</body>
</html>1
1
10KB
10KB
417.0ms
428.0ms
417.0ms