🎮ArcadeLab

绿茵对决 手机版

by GoldenFlame69
227 lines6.8 KB
▶ Play
✅ 手机版|绿茵对决(触屏版)

手机浏览器直接打开玩!横屏玩,左边虚拟摇杆移动,右边两个按钮:传球、射门,有AI对手,不用安装。
使用方法:

1. 复制下面全部代码

2. 手机备忘录新建笔记粘贴,保存,改后缀为 .html

3. 用浏览器打开(推荐Chrome、Edge),横屏!
<!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;-webkit-tap-highlight-color:transparent}
html,body{height:100%;overflow:hidden;background:#111;color:#fff;font-family:system-ui}
#wrap{width:100vw;height:100vh;display:flex;flex-direction:column;align-items:center;justify-content:center}
#score{font-size:22px;margin:6px}
#gameBox{position:relative}
#field{background:#2e7d32;border:2px solid #fff}
/* 虚拟摇杆 */
#joystick{position:absolute;left:20px;bottom:20px;width:120px;height:120px;border-radius:50%;background:rgba(255,255,255,0.2);touch-action:none}
#stick{width:44px;height:44px;border-radius:50%;background:rgba(255,255,255,0.5);position:absolute;left:50%;top:50%;transform:translate(-50%,-50%)}
/* 按钮 */
#btns{position:absolute;right:20px;bottom:20px;display:flex;gap:12px}
.btn{width:70px;height:70px;border-radius:50%;border:none;font-size:16px;font-weight:bold;color:white}
#passBtn{background:#3498db}
#shootBtn{background:#e74c3c}
</style>
</head>
<body>
<div id="wrap">
<div id="score">🔴你:0 | 🤖AI:0</div>
<div id="gameBox">
<canvas id="field" width="720" height="400"></canvas>
<div id="joystick">
    <div id="stick"></div>
</div>
<div id="btns">
    <button class="btn" id="passBtn">传球</button>
    <button class="btn" id="shootBtn">射门</button>
</div>
</div>
</div>

<script>
const canvas = document.getElementById('field');
const ctx = canvas.getContext('2d');
const W = canvas.width;
const H = canvas.height;

// 玩家(红色,你控制)
const player = {x:120,y:H/2,r:16,c:'#ff4444',speed:3.8};
// AI球员(蓝色)
const ai = {x:W-120,y:H/2,r:16,c:'#4488ff',speed:2.6};
// 足球
const ball = {x:W/2,y:H/2,r:11,vx:0,vy:0,friction:0.97};
// 球门
const goalH = 110;
const goalLeft = {x:0,y:H/2-goalH/2,w:10,h:goalH};
const goalRight = {x:W-10,y:H/2-goalH/2,w:10,h:goalH};

let scoreP = 0, scoreAI = 0;
let moveX = 0, moveY = 0; //摇杆输出方向

// 摇杆
const joy = document.getElementById('joystick');
const stick = document.getElementById('stick');
const joyR = joy.clientWidth / 2;
let joyDown = false;

joy.addEventListener('touchstart', e=>{joyDown=true;updateJoy(e.touches[0])})
joy.addEventListener('touchmove', e=>{if(joyDown) updateJoy(e.touches[0])})
joy.addEventListener('touchend', ()=>{joyDown=false;moveX=0;moveY=0;stick.style.transform='translate(-50%,-50%)'})

function updateJoy(touch){
    const rect = joy.getBoundingClientRect();
    let tx = touch.clientX - rect.left - joyR;
    let ty = touch.clientY - rect.top - joyR;
    const dist = Math.hypot(tx,ty);
    if(dist>joyR-22){
        const s = (joyR-22)/dist;
        tx *= s; ty *= s;
    }
    stick.style.transform = `translate(calc(-50% + ${tx}px),calc(-50% + ${ty}px))`;
    moveX = tx/(joyR-22);
    moveY = ty/(joyR-22);
}

// 传球、射门按钮
document.getElementById('passBtn').addEventListener('touchstart',()=>kick(player,5.5))
document.getElementById('shootBtn').addEventListener('touchstart',()=>kick(player,10))

function kick(who,power){
    const dx = ball.x - who.x;
    const dy = ball.y - who.y;
    const d = Math.hypot(dx,dy);
    if(d < who.r + ball.r + 18){
        ball.vx = dx/d * power;
        ball.vy = dy/d * power;
    }
}
function circleHit(a,b){
    return Math.hypot(a.x-b.x,a.y-b.y) < a.r + b.r;
}
function resetBall(){
    ball.x=W/2;ball.y=H/2;ball.vx=0;ball.vy=0;
}
function updateScore(){
    document.getElementById('score').innerText = `🔴你:${scoreP} | 🤖AI:${scoreAI}`
}

// AI逻辑
function aiUpdate(){
    // AI追球
    const dx = ball.x - ai.x;
    const dy = ball.y - ai.y;
    const d = Math.hypot(dx,dy);
    if(d>ai.r+ball.r+12){
        ai.x += dx/d * ai.speed;
        ai.y += dy/d * ai.y/d * ai.speed;
    }else{
        // AI拿到球会往你的球门踢
        ball.vx = -7;
        ball.vy = (Math.random()-0.5)*4;
    }
    ai.x = Math.max(ai.r, Math.min(W-ai.r, ai.x));
    ai.y = Math.max(ai.r, Math.min(H-ai.r, ai.y));
}

function loop(){
    // 玩家移动
    player.x += moveX * player.speed;
    player.y += moveY * player.speed;
    player.x = Math.max(player.r, Math.min(W-player.r, player.x));
    player.y = Math.max(player.r, Math.min(H-player.r, player.y));

    // 球物理
    ball.x += ball.vx;
    ball.y += ball.vy;
    ball.vx *= ball.friction;
    ball.vy *= ball.friction;

    // 球场边界反弹(上下)
    if(ball.y < ball.r || ball.y > H-ball.r){
        ball.vy *= -0.85;
    }
    // 进球判定
    if(ball.x < ball.r && ball.y>goalLeft.y && ball.y<goalLeft.y+goalLeft.h){
        scoreAI++; updateScore(); resetBall();
    }
    if(ball.x > W-ball.r && ball.y>goalRight.y && ball.y<goalRight.y+goalRight.h){
        scoreP++; updateScore(); resetBall();
    }
    // 左右挡板(不是球门区域)
    if(ball.x<ball.r || ball.x>W-ball.r){
        ball.vx *= -0.85;
    }

    // 球员碰球
    if(circleHit(player,ball)){
        const dx = ball.x-player.x;
        const dy = ball.y-player.y;
        ball.vx += dx*0.12;
        ball.vy += dy*0.12;
    }
    if(circleHit(ai,ball)){
        const dx = ball.x-ai.x;
        const dy = ball.y-ai.y;
        ball.vx += dx*0.12;
        ball.vy += dy*0.12;
    }

    aiUpdate();

    // 绘制
    ctx.fillStyle='#2e7d32';ctx.fillRect(0,0,W,H);
    ctx.strokeStyle='#fff';ctx.lineWidth=2;
    ctx.beginPath();ctx.arc(W/2,H/2,70,0,Math.PI*2);ctx.stroke();
    ctx.beginPath();ctx.moveTo(W/2,0);ctx.lineTo(W/2,H);ctx.stroke();
    // 球门
    ctx.fillStyle='#ffffff';
    ctx.fillRect(goalLeft.x,goalLeft.y,goalLeft.w,goalLeft.h);
    ctx.fillRect(goalRight.x,goalRight.y,goalRight.w,goalRight.h);

    // 球员
    drawCircle(player);
    drawCircle(ai);
    // 足球
    drawCircle({...ball,c:'#000'});

    requestAnimationFrame(loop);
}
function drawCircle(o){
    ctx.fillStyle=o.c;
    ctx.beginPath();ctx.arc(o.x,o.y,o.r,0,Math.PI*2);ctx.fill();
}
loop();
</script>
</body>
</html>
🎮 手机操作说明

• ✋ 左下角摇杆滑动:控制红色球员跑动

• 🔵 蓝色传球按钮:近距离轻轻推球

• 🔴 红色射门按钮:大力射门

• 🤖 对手是AI,会追球、进攻你球门

• ⚽ 球有摩擦力,会慢慢停下

想要升级版本吗?我可以再加:

1. 双人同屏触屏对战(左右各一个摇杆)

2. 时间倒计时、胜利提示

3. 蓄力射门(按住越久力量越大)

4. 加音效(进球、哨声)

你想要哪个?

Game Source: 绿茵对决 手机版

Creator: GoldenFlame69

Libraries: none

Complexity: complex (227 lines, 6.8 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-goldenflame69" to link back to the original. Then publish at arcadelab.ai/publish.