🎮ArcadeLab

Untitled Game

by SparkShark50
354 lines11.9 KB
▶ Play
<!DOCTYPE html>
<html lang="zh-HK">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
超级复杂枪战大作
<style>
*{margin:0;padding:0;box-sizing:border-box;font-family:system-ui,sans-serif}
html,body{width:100%;height:100%;overflow:hidden}
canvas{display:block;touch-action:none}
#ui{position:fixed;inset:0;color:#fff;user-select:none}

/* 主菜单 */
.mainMenu{position:absolute;inset:0;background:rgba(0,0,0,0.35);display:flex;flex-direction:column;align-items:flex-end;justify-content:flex-end;padding:30px;gap:14px}
.btn{width:170px;height:64px;font-size:20px;border:none;border-radius:12px;background:#2578ed;color:#fff}

/* 全屏幕弹窗面板 */
.panel{position:absolute;inset:0;background:rgba(0,0,0,0.88);display:none;flex-wrap:wrap;align-items:center;justify-content:center;gap:20px;padding:20px}
.box{width:160px;height:200px;background:#222;border-radius:12px;display:flex;align-items:center;justify-content:center;font-size:22px;border:solid 2px #444}

/* 游戏控件默认隐藏,开局先出 */
.joy{position:absolute;bottom:25px;left:25px;width:160px;height:160px;border-radius:50%;background:rgba(255,255,255,0.12);display:none}
.joyInner{width:70px;height:70px;border-radius:50%;background:rgba(255,255,255,0.35);position:absolute;left:45px;top:45px}
.shootBtn{position:absolute;bottom:35px;right:35px;width:110px;height:110px;border-radius:50%;background:rgba(220,40,40,0.6);border:none;color:#fff;font-size:22px;display:none}
.runBtn{position:absolute;bottom:160px;right:35px;width:70px;height:70px;border-radius:50%;background:rgba(40,180,220,0.5);border:none;color:#fff;display:none}

/* 主页中间角色预览 */
.previewChar{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width:130px;height:130px;border-radius:14px;border:solid 2px #ffffff55}
</style>
</head>
<body>
<canvas id="c"></canvas>
<div id="ui">
    <!-- 主页菜单 -->
    <div class="mainMenu" id="mainMenu">
        <button class="btn" onclick="openMode()">选择模式</button>
        <button class="btn" onclick="startGame()">开始游戏</button>
        <button class="btn" onclick="openSkin()">皮肤中心</button>
    </div>

    <!-- 主页中间角色 -->
    <div class="previewChar" id="previewChar"></div>

    <!-- 模式选择 -->
    <div class="panel" id="modePanel">
        <div class="box" onclick="setMode('train')">超级训练场</div>
        <div class="box" onclick="setMode('stage1')">关卡一</div>
        <div class="box" onclick="setMode('stage2')">关卡二</div>
        <div class="box" onclick="setMode('survive')">无限生存</div>
        <button class="btn" style="position:absolute;top:20px;right:20px" onclick="closeAllPanel()">返回</button>
    </div>

    <!-- 皮肤面板 -->
    <div class="panel" id="skinPanel">
        <div class="box" style="background:#fff" onclick="setSkin('#ffffff')">白色</div>
        <div class="box" style="background:#000" onclick="setSkin('#000000')">黑色</div>
        <div class="box" style="background:#348ede" onclick="setSkin('#348ede')">蓝色</div>
        <div class="box" style="background:#ff7700" onclick="setSkin('#ff7700')">橙色</div>
        <button class="btn" style="position:absolute;top:20px;right:20px" onclick="closeAllPanel()">返回</button>
    </div>

    <!-- 操控按键 -->
    <div class="joy" id="joy"><div class="joyInner" id="joyIn"></div></div>
    <button class="shootBtn" id="shootBtn">射击</button>
    <button class="runBtn" id="runBtn">奔跑</button>
</div>

<script>
const c = document.getElementById("c");
const ctx = c.getContext("2d");
let W,H;
function resize(){W=innerWidth;H=innerHeight;c.width=W;c.height=H}
resize();onresize=resize;

// ========== 全新超级复杂游戏数据(100%新版) ==========
let gameState = "menu";
let gameMode = "train";

// 玩家全维度属性
let ply = {
    x:0,y:0,speed:3.5,rushSpeed:6,
    hp:100,maxHp:100,armor:0,helmet:0,
    color:"#ffffff",angle:0,
    weapon:"rifle",shootCd:0,reloadCd:0,
    mag:30,maxMag:30,ammo:999,
    kill:0,totalDmg:0,running:false
};

// 全新5款专业枪械数据
const WEAPON = {
    pistol:{dmg:8,cd:0.28,mag:12,spread:0.08,name:"手枪"},
    smg:{dmg:5,cd:0.09,mag:40,spread:0.15,name:"冲锋枪"},
    shotgun:{dmg:12,cd:0.6,mag:8,spread:0.3,bulletNum:8,name:"散弹枪"},
    rifle:{dmg:9,cd:0.13,mag:30,spread:0.06,name:"突击步枪"},
    sniper:{dmg:48,cd:1.4,mag:5,spread:0.01,name:"狙击枪"}
};

// 游戏数组
let enemies = [];
let bullets = [];
let items = [];
let effects = [];
let poison = {r:1400,spd:0.08};
let walls = [];

// 摇杆
let joy = {active:false,dx:0,dy:0}
const joyDom = document.getElementById("joy");
const joyInDom = document.getElementById("joyIn");

// ========== UI函数 ==========
function openMode(){closeAllPanel();document.getElementById("modePanel").style.display="flex"}
function openSkin(){closeAllPanel();document.getElementById("skinPanel").style.display="flex"}
function closeAllPanel(){
    document.querySelectorAll(".panel").forEach(p=>p.style.display="none");
}
function setMode(m){gameMode=m;closeAllPanel()}
function setSkin(col){ply.color=col}

// ========== 开局初始化全新复杂地图 ==========
function startGame(){
    gameState="play";
    closeAllPanel();
    // 强制游戏横屏
    screen.orientation.lock("landscape").catch(e=>{});

    // 重置玩家
    ply.x=W/2;ply.y=H/2;ply.hp=ply.maxHp;ply.kill=0;ply.totalDmg=0;
    ply.mag=WEAPON[ply.weapon].mag;ply.shootCd=0;ply.reloadCd=0;

    // 显示操控
    joyDom.style.display="block";
    shootBtn.style.display="block";
    runBtn.style.display="block";

    // 生成随机掩体障碍物
    walls=[];
    for(let i=0;i<12;i++){
        walls.push({
            x:Math.random()*1200-600+W/2,
            y:Math.random()*1200-600+H/2,
            w:40+Math.random()*60,
            h:40+Math.random()*60
        })
    }

    // 生成敌人
    spawnEnemy();

    // 重置毒圈
    poison.r=1400;
}

// 生成智能AI敌人
function spawnEnemy(){
    enemies=[];
    let num = gameMode=="train"?3 : gameMode=="stage1"?6 : gameMode=="stage2"?10 : 18;
    for(let i=0;i<num;i++){
        enemies.push({
            x:W/2 + (Math.random()-0.5)*900,
            y:H/2 + (Math.random()-0.5)*900,
            hp:70+Math.random()*40,
            speed:1.2+Math.random()*1.2,
            shootCd:Math.random()*2,
            state:"patrol", // patrol/chase/attack/hide
            dir:Math.random()*Math.PI*2
        })
    }
}

// ========== 射击系统(后坐力+散布) ==========
function shoot(){
    if(ply.shootCd>0||ply.reloadCd>0||ply.mag<=0)return;
    let w = WEAPON[ply.weapon];
    ply.shootCd = w.cd;
    ply.mag--;

    // 后坐力偏移
    let spread = (Math.random()-0.5)*w.spread;
    let bulletNum = w.bulletNum||1;
    for(let i=0;i<bulletNum;i++){
        bullets.push({
            x:ply.x,y:ply.y,
            vx:Math.cos(ply.angle+spread)*14,
            vy:Math.sin(ply.angle+spread)*14,
            dmg:w.dmg
        })
    }
    // 枪口火焰特效
    effects.push({x:ply.x,y:ply.y,type:"fire",life:0.15})
}

// ========== 触摸摇杆操控 ==========
joyDom.addEventListener("touchstart",e=>{
    joy.active=true;
})
document.addEventListener("touchmove",e=>{
    if(!joy.active)return;
    let t = e.touches[0];
    let rect = joyDom.getBoundingClientRect();
    let cx = rect.left+rect.width/2;
    let cy = rect.top+rect.height/2;
    joy.dx = t.clientX - cx;
    joy.dy = t.clientY - cy;
    let d = Math.hypot(joy.dx,joy.dy);
    if(d>70){joy.dx=joy.dx/d*70;joy.dy=joy.dy/d*70}
    joyInDom.style.left = 45+joy.dx+"px";
    joyInDom.style.top = 45+joy.dy+"px";
})
document.addEventListener("touchend",()=>{
    joy.active=false;joy.dx=0;joy.dy=0;
    joyInDom.style.left="45px";joyInDom.style.top="45px";
})
shootBtn.ontouchstart=shoot;
runBtn.ontouchstart=()=>ply.running=true;
runBtn.ontouchend=()=>ply.running=false;

// ========== 主循环(超级复杂更新逻辑) ==========
function loop(){
    // 草地地图底色
    ctx.fillStyle="#598c56";
    ctx.fillRect(0,0,W,H);

    if(gameState=="menu"){
        // 主页中间角色预览
        ctx.fillStyle=ply.color;
        ctx.fillRect(W/2-25,H/2-25,50,50);
        ctx.fillStyle="#000";
        ctx.beginPath();
        ctx.arc(W/2-12,H/2-10,5,0,Math.PI*2);
        ctx.arc(W/2+12,H/2-10,5,0,Math.PI*2);
        ctx.fill();
    }

    if(gameState=="play"){
        // 毒圈收缩
        poison.r -= poison.spd;
        // 毒圈伤害
        let disP = Math.hypot(ply.x-W/2,ply.y-H/2);
        if(disP>poison.r) ply.hp -= 0.4;

        // 玩家移动
        let spd = ply.running?ply.rushSpeed:ply.speed;
        ply.x += joy.dx/12*spd;
        ply.y += joy.dy/12*spd;

        // 冷却计时
        if(ply.shootCd>0)ply.shootCd-=1/60;

        // 绘制掩体
        ctx.fillStyle="#666";
        walls.forEach(w=>ctx.fillRect(w.x,w.y,w.w,w.h));

        // 更新子弹
        for(let i=bullets.length-1;i>=0;i--){
            let b=bullets[i];
            b.x+=b.vx;b.y+=b.vy;

            // 打墙消失
            let hitWall = false;
            walls.forEach(w=>{
                if(b.x>w.x&&b.x<w.x+w.w&&b.y>w.y&&b.y<w.y+w.h)hitWall=true;
            })
            if(hitWall){bullets.splice(i,1);continue}

            // 打敌人
            enemies.forEach(e=>{
                let d=Math.hypot(b.x-e.x,b.y-e.y);
                if(d<28){
                    e.hp -= b.dmg;
                    ply.totalDmg += b.dmg;
                    effects.push({x:e.x,y:e.y,type:"hit",life:0.3})
                    bullets.splice(i,1);
                }
            })

            // 出界删除
            if(Math.abs(b.x-W/2)>1500||Math.abs(b.y-H/2)>1500)bullets.splice(i,1);
        }

        // 超级智能AI敌人逻辑
        enemies.forEach(e=>{
            let d = Math.hypot(e.x-ply.x,e.y-ply.y);
            // 近距离追击+开枪
            if(d<350){
                e.state="attack";
                e.x += (ply.x-e.x)/d*e.speed;
                e.y += (ply.y-e.y)/d*e.speed;
                e.shootCd -= 1/60;
                if(e.shootCd<=0&&d<280){
                    e.shootCd=1.2;
                    let ed = Math.hypot(e.x-ply.x,e.y-ply.y);
                    ply.hp -= 6;
                    effects.push({x:ply.x,y:ply.y,type:"hit",life:0.2})
                }
            }else{
                // 远处巡逻
                e.state="patrol";
                e.dir += (Math.random()-0.5)*0.05;
                e.x += Math.cos(e.dir)*e.speed*0.6;
                e.y += Math.sin(e.dir)*e.speed*0.6;
            }

            // 敌人死亡判定
            if(e.hp<=0){
                ply.kill++;
                enemies.splice(enemies.indexOf(e),1);
            }
        })

        // 绘制玩家
        ctx.fillStyle=ply.color;
        ctx.fillRect(ply.x-22,ply.y-22,44,44);
        ctx.fillStyle="#000";
        ctx.beginPath();
        ctx.arc(ply.x-10,ply.y-10,5,0,Math.PI*2);
        ctx.arc(ply.x+10,ply.y-10,5,0,Math.PI*2);
        ctx.fill();

        // 绘制敌人
        enemies.forEach(e=>{
            ctx.fillStyle="#d63031";
            ctx.fillRect(e.x-22,e.y-22,44,44);
        })

        // 特效渲染
        effects.forEach((ef,i)=>{
            ef.life-=1/60;
            if(ef.type=="hit"){ctx.fillStyle="#fff";ctx.fillText("击中",ef.x,ef.y-10)}
            if(ef.type=="fire"){ctx.fillStyle="#ffaa00";ctx.fillRect(ef.x,ef.y,12,12)}
            if(ef.life<=0)effects.splice(i,1);
        })

        // 绘制毒圈
        ctx.strokeStyle="#ff2222";
        ctx.lineWidth=4;
        ctx.beginPath();
        ctx.arc(W/2,H/2,poison.r,0,Math.PI*2);
        ctx.stroke();

        // UI血量、击杀
        ctx.fillStyle="#fff";
        ctx.font="bold 20px sans-serif";
        ctx.fillText(`血量:${Math.floor(ply.hp)}`,20,35);
        ctx.fillText(`击杀:${ply.kill}`,20,65);
        ctx.fillText(`弹药:${ply.mag}`,20,95);
    }

    requestAnimationFrame(loop);
}
loop();
</script>
</body>
</html>

Game Source: Untitled Game

Creator: SparkShark50

Libraries: none

Complexity: complex (354 lines, 11.9 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: untitled-game-sparkshark50" to link back to the original. Then publish at arcadelab.ai/publish.