碰碰赛车竞速|网页版
by SparkHero40179 lines5.2 KB
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>碰碰赛车竞速|网页版</title>
<style>
*{margin:0;padding:0;box-sizing:border-box}
body{background:#222;color:#fff;font-family:system-ui,Arial;overflow:hidden;touch-action:none}
#game{display:block;margin:0 auto;background:#444}
.info{text-align:center;padding:8px;font-size:15px}
.ctrl{display:flex;width:100%;position:fixed;bottom:12px;gap:10px;padding:0 12px;display:none}
.btn{flex:1;height:70px;background:#36f;border:none;border-radius:12px;color:#fff;font-size:22px;font-weight:bold;user-select:none;-webkit-user-select:none}
.btn:active{background:#24d}
@media (max-width:768px){
.ctrl{display:flex;}
}
</style>
</head>
<body>
<div class="info">电脑:WASD / 方向键|手机:底部触屏按钮,撞开对手拿分</div>
<canvas id="game"></canvas>
<div class="ctrl">
<button class="btn" id="btnLeft">←</button>
<button class="btn" id="btnGas">加速</button>
<button class="btn" id="btnBrake">减速</button>
<button class="btn" id="btnRight">→</button>
</div>
<script>
const canvas = document.getElementById('game');
const ctx = canvas.getContext('2d');
function resize(){
if(window.innerWidth > 768){
canvas.width = 600;
canvas.height = 800;
}else{
canvas.width = Math.min(window.innerWidth, 420);
canvas.height = window.innerHeight - 110;
}
}
resize();
window.addEventListener('resize',resize);
const roadW = 240;
const roadX = ()=>(canvas.width - roadW)/2;
const player = {
x: roadX() + roadW/2 - 20,
y: canvas.height - 120,
w: 40,
h: 70,
speed: 0,
maxSpeed:7,
turn:0
};
const keys = {left:false,right:false,gas:false,brake:false};
const cars = [];
for(let i=0;i<5;i++){
cars.push({
x: roadX()+30 + (i*45)%(roadW-60),
y: -120*i - 80,
w:40,h:70,
speed:2.5+Math.random()*2,
color:['#ff4444','#4488ff','#44dd44','#dddd44','#dd44dd'][i]
})
}
let roadOffset = 0;
let score = 0;
//触屏按钮
const btnLeft = document.getElementById('btnLeft');
const btnRight = document.getElementById('btnRight');
const btnGas = document.getElementById('btnGas');
const btnBrake = document.getElementById('btnBrake');
function bindTouch(btn,key){
btn.addEventListener('touchstart',e=>{e.preventDefault();keys[key]=true})
btn.addEventListener('touchend',e=>{e.preventDefault();keys[key]=false})
}
bindTouch(btnLeft,'left');
bindTouch(btnRight,'right');
bindTouch(btnGas,'gas');
bindTouch(btnBrake,'brake');
//键盘
document.addEventListener('keydown',e=>{
if(e.code==='KeyA'||e.code==='ArrowLeft') keys.left=true;
if(e.code==='KeyD'||e.code==='ArrowRight') keys.right=true;
if(e.code==='KeyW'||e.code==='ArrowUp') keys.gas=true;
if(e.code==='KeyS'||e.code==='ArrowDown') keys.brake=true;
})
document.addEventListener('keyup',e=>{
if(e.code==='KeyA'||e.code==='ArrowLeft') keys.left=false;
if(e.code==='KeyD'||e.code==='ArrowRight') keys.right=false;
if(e.code==='KeyW'||e.code==='ArrowUp') keys.gas=false;
if(e.code==='KeyS'||e.code==='ArrowDown') keys.brake=false;
})
function rectCollision(a,b){
return a.x < b.x+b.w && a.x+a.w > b.x && a.y < b.y+b.h && a.y+a.h > b.y;
}
function loop(){
const rx = roadX();
if(keys.gas) player.speed = Math.min(player.speed+0.15, player.maxSpeed);
else if(keys.brake) player.speed = Math.max(player.speed-0.15, -2);
else player.speed *= 0.96;
if(keys.left) player.turn = -0.04;
else if(keys.right) player.turn = 0.04;
else player.turn *= 0.85;
player.x += player.turn * 32;
player.x = Math.max(rx, Math.min(rx+roadW-player.w, player.x));
roadOffset += player.speed * 4;
if(roadOffset>100) roadOffset=0;
score += player.speed * 0.08;
for(let c of cars){
c.y += c.speed*4 - player.speed*4;
if(Math.random()<0.007){
c.x += (Math.random()>0.5?1:-1)*40;
c.x = Math.max(rx, Math.min(rx+roadW - c.w, c.x));
}
if(c.y>canvas.height){
c.y = -100;
c.x = rx + 20 + Math.random()*(roadW-60);
c.speed = 2.5 + Math.random()*2.2;
}
if(rectCollision(player,c)){
player.speed *= 0.7;
c.speed *= 0.6;
const dx = player.x - c.x;
if(dx>0){
player.x +=5;c.x -=5;
}else{
player.x -=5;c.x +=5;
}
}
}
ctx.fillStyle='#222';
ctx.fillRect(0,0,canvas.width,canvas.height);
ctx.fillStyle='#444';
ctx.fillRect(rx,0,roadW,canvas.height);
ctx.strokeStyle='#fff';
ctx.lineWidth=4;
ctx.setLineDash([40,30]);
ctx.beginPath();
ctx.moveTo(rx+roadW/2, roadOffset);
ctx.lineTo(rx+roadW/2, canvas.height);
ctx.stroke();
ctx.setLineDash([]);
for(let c of cars){
ctx.fillStyle=c.color;
ctx.fillRect(c.x,c.y,c.w,c.h);
ctx.fillStyle='#222';
ctx.fillRect(c.x+8,c.y+10,c.w-16,18);
}
ctx.fillStyle='#2288ff';
ctx.fillRect(player.x,player.y,player.w,player.h);
ctx.fillStyle='#88ddff';
ctx.fillRect(player.x+7,player.y+12,player.w-14,20);
ctx.fillStyle='white';
ctx.font='20px Arial';
ctx.fillText('分数:'+Math.floor(score),12,30);
requestAnimationFrame(loop);
}
loop();
</script>
</body>
</html>
Game Source: 碰碰赛车竞速|网页版
Creator: SparkHero40
Libraries: none
Complexity: moderate (179 lines, 5.2 KB)
The full source code is displayed above on this page.
Remix Instructions
To remix this game, copy the source code above and modify it. Add a ARCADELAB header at the top with "remix_of: game-sparkhero40" to link back to the original. Then publish at arcadelab.ai/publish.