🎮ArcadeLab

巨猿进化旷野 | 猿族时代风格

by RocketDragon88
340 lines10.1 KB
▶ Play
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>巨猿进化旷野 | 猿族时代风格</title>
    <style>
        *{margin:0;padding:0;box-sizing:border-box;font-family:system-ui}
        body{overflow:hidden;background:#000}
        #game{display:block}
        #info{
            position:absolute;top:10px;left:10px;color:white;
            background:rgba(0,0,0,0.65);padding:12px;border-radius:8px;
            min-width:280px;line-height:1.5;
            z-index:10;
        }
        #warning{
            position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);
            color:#ffd24d;font-size:32px;font-weight:bold;
            text-shadow:0 0 10px #000,0 0 20px #000;
            pointer-events:none;opacity:0;
            z-index:15;
        }
    </style>
</head>
<body>
<canvas id="game"></canvas>
<div id="info">
    <div>形态:<span id="evo">幼年巨猿</span></div>
    <div>等级:<span id="lv">1</span> / 200000</div>
    <div id="kingTip"></div>
    <div>操作:WASD移动,触碰野怪战斗,触碰蛋吞食</div>
</div>
<div id="warning"></div>

<script>
const canvas = document.getElementById("game");
const ctx = canvas.getContext("2d");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

// 玩家数据
let player = {
    x: canvas.width/2,
    y: canvas.height/2,
    lv: 1,
    size: 28,
    speed: 3.2,
    evolveStage: 0,
    evolveFlash: 0
};

// 进化序列【最终形态:190000级】
const evolveConfig = [
    {need:0,     name:"幼年巨猿",     color:"#a88968", glow:"#ffd700"},
    {need:30,    name:"蓝焰巨猿",     color:"#5a88d8", glow:"#88aaff"},
    {need:80,    name:"熔岩巨猿",     color:"#d84a4a", glow:"#ff6600"},
    {need:200,   name:"雷霆巨猿",     color:"#6b44d8", glow:"#aa66ff"},
    {need:500,   name:"山岳巨猿",     color:"#8b6b4a", glow:"#d4a76a"},
    {need:1000,  name:"白银巨猿",     color:"#d8d8d8", glow:"#ffffff"},
    {need:3000,  name:"黄金巨猿",     color:"#ffd700", glow:"#ffec8b"},
    {need:8000,  name:"暗影巨猿",     color:"#2e1a47", glow:"#8822ff"},
    {need:20000, name:"虚空巨猿",     color:"#111122", glow:"#cc44ff"},
    {need:50000, name:"混沌巨猿",     color:"#8b2244", glow:"#ff2266"},
    {need:100000,name:"太古巨猿",     color:"#102840", glow:"#22ddff"},
    {need:150000,name:"洪荒巨猿",     color:"#501010", glow:"#ff3333"},
    {need:190000,name:"终焉创世巨猿", color:"#050010", glow:"#ffdd22"}
];

// 按键监听
const key = {};
window.addEventListener("keydown",e=>key[e.key.toLowerCase()]=true);
window.addEventListener("keyup",e=>key[e.key.toLowerCase()]=false);

let enemies = [];
let eggs = [];
let hills = [];

// 地形山坡
function spawnHill(){
    return {
        x: Math.random()*canvas.width,
        y: Math.random()*canvas.height,
        radius: 35 + Math.random()*80
    }
}

// 生成野生巨猿
function spawnEnemy(){
    return {
        x: Math.random()*canvas.width,
        y: Math.random()*canvas.height,
        lv: Math.floor(Math.random()*80)+5,
        size: 20,
        speed:1.2 + Math.random()*1.1,
        targetX:0,
        targetY:0,
        huntKing: false
    }
}

// 生成元素蛋
function spawnEgg(){
    const type = Math.floor(Math.random()*4);
    let addMin,addMax,color,glow;
    if(type===0){addMin=3;addMax=8;color="#cccccc";glow="#eeeeee"}
    else if(type===1){addMin=10;addMax=22;color="#4298e8";glow="#82c8ff"}
    else if(type===2){addMin=25;addMax=45;color="#ffbb22";glow="#ffdd77"}
    else {addMin=-35;addMax=55;color="#662277";glow="#aa44dd"}
    return {
        x: Math.random()*canvas.width,
        y: Math.random()*canvas.height,
        min:addMin,max:addMax,
        color,glow
    }
}

// 世界初始化/重置函数
function initWorld(){
    player.lv = 1;
    player.x = canvas.width/2;
    player.y = canvas.height/2;
    enemies = [];
    eggs = [];
    hills = [];
    for(let i=0;i<14;i++) enemies.push(spawnEnemy());
    for(let i=0;i<22;i++) eggs.push(spawnEgg());
    for(let i=0;i<18;i++) hills.push(spawnHill());
    updateEvolve();
}

// 更新进化形态
function updateEvolve(){
    let newStage = 0;
    for(let i=evolveConfig.length-1;i>=0;i--){
        if(player.lv >= evolveConfig[i].need){
            newStage = i; break;
        }
    }
    if(player.evolveStage !== newStage){
        player.evolveFlash = 90; //进化闪光动画
    }
    player.evolveStage = newStage;
    const cfg = evolveConfig[newStage];
    document.getElementById("evo").innerText = cfg.name;
    document.getElementById("lv").innerText = player.lv;
    player.size = 28 + newStage*14;
}

// 获取全场最高等级
function getKingLevel(){
    let maxLv = player.lv;
    enemies.forEach(e=>{
        if(e.lv>maxLv) maxLv = e.lv;
    })
    return maxLv;
}
function isPlayerKing(){
    const maxLv = getKingLevel();
    return player.lv === maxLv;
}

// 距离计算
function dist(a,b){
    return Math.hypot(a.x-b.x,a.y-b.y);
}

initWorld();

// 游戏主循环
function loop(){
    // 20万级重置判定
    if(player.lv >= 200000){
        alert("🎉抵达200000级!世界重置,新一轮进化开始!");
        initWorld();
    }

    // 玩家移动控制
    if(key["w"]) player.y -= player.speed;
    if(key["s"]) player.y += player.speed;
    if(key["a"]) player.x -= player.speed;
    if(key["d"]) player.x += player.speed;
    player.x = Math.max(player.size, Math.min(canvas.width-player.size, player.x));
    player.y = Math.max(player.size, Math.min(canvas.height-player.size, player.y));

    // 吞食蛋
    for(let i=eggs.length-1;i>=0;i--){
        const e = eggs[i];
        if(dist(player,e) < player.size+14){
            const gain = Math.floor(Math.random()*(e.max-e.min)+e.min);
            player.lv += gain;
            if(player.lv < 1) player.lv = 1;
            eggs.splice(i,1);
            eggs.push(spawnEgg());
            updateEvolve();
        }
    }

    // 野怪碰撞吞噬等级
    for(let i=enemies.length-1;i>=0;i--){
        const en = enemies[i];
        if(dist(player,en) < player.size/2 + en.size/2){
            player.lv += en.lv;
            enemies.splice(i,1);
            enemies.push(spawnEnemy());
            updateEvolve();
        }
    }

    // 野怪AI逻辑
    const kingExists = isPlayerKing();
    enemies.forEach(en=>{
        if(kingExists){
            en.huntKing = Math.random() < 0.35; //35%追杀王者,其余游荡
        }else{
            en.huntKing = false;
        }

        if(en.huntKing){
            const dx = player.x - en.x;
            const dy = player.y - en.y;
            en.x += dx*0.016 * en.speed;
            en.y += dy*0.016 * en.speed;
        }else{
            if(Math.random()<0.01){
                en.targetX = Math.random()*canvas.width;
                en.targetY = Math.random()*canvas.height;
            }
            const dx = en.targetX - en.x;
            const dy = en.targetY - en.y;
            en.x += dx*0.009 * en.speed;
            en.y += dy*0.009 * en.speed;
        }
        en.x = Math.max(12,Math.min(canvas.width-12,en.x));
        en.y = Math.max(12,Math.min(canvas.height-12,en.y));
    })

    // ============ 渲染 卡通鲜亮画风(匹配截图画质) ============
    // 天空渐变背景
    const skyGrad = ctx.createLinearGradient(0,0,0,canvas.height);
    skyGrad.addColorStop(0,"#62b8ff");
    skyGrad.addColorStop(0.4,"#a4d2ff");
    skyGrad.addColorStop(1,"#88c970");
    ctx.fillStyle=skyGrad;
    ctx.fillRect(0,0,canvas.width,canvas.height);

    // 绘制远景山坡
    hills.forEach(h=>{
        ctx.beginPath();
        ctx.arc(h.x,h.y,h.radius,0,Math.PI*2);
        const hillGrad = ctx.createRadialGradient(h.x,h.y,0,h.x,h.y,h.radius);
        hillGrad.addColorStop(0,"#b2c99c");
        hillGrad.addColorStop(1,"#799c62");
        ctx.fillStyle = hillGrad;
        ctx.fill();
    })

    // 绘制元素蛋 + 光晕特效
    eggs.forEach(e=>{
        //外层光晕
        ctx.beginPath();
        ctx.arc(e.x,e.y,18,0,Math.PI*2);
        ctx.fillStyle = e.glow + "50";
        ctx.fill();
        //蛋本体
        ctx.beginPath();
        ctx.arc(e.x,e.y,13,0,Math.PI*2);
        ctx.fillStyle = e.color;
        ctx.fill();
        ctx.strokeStyle="#000";
        ctx.lineWidth=1.5;
        ctx.stroke();
    })

    // 野生巨猿 + 头顶等级文字
    enemies.forEach(en=>{
        ctx.beginPath();
        ctx.arc(en.x,en.y,en.size+5,0,Math.PI*2);
        ctx.fillStyle="#11111155";
        ctx.fill();
        ctx.beginPath();
        ctx.arc(en.x,en.y,en.size,0,Math.PI*2);
        ctx.fillStyle="#333333";
        ctx.fill();
        ctx.strokeStyle="#000";
        ctx.lineWidth=2;
        ctx.stroke();

        //野怪头顶等级(和截图一样彩色字体)
        ctx.font = "bold 18px sans-serif";
        ctx.fillStyle="#ff3333";
        ctx.textAlign="center";
        ctx.fillText(`Lv.${en.lv}`,en.x,en.y-en.size-8);
    })

    // 玩家巨猿渲染
    const pCfg = evolveConfig[player.evolveStage];
    //进化闪光叠加
    if(player.evolveFlash>0){
        player.evolveFlash--;
        ctx.fillStyle=`rgba(255,255,255,${player.evolveFlash/120})`;
        ctx.fillRect(0,0,canvas.width,canvas.height);
    }
    //外层光环
    ctx.beginPath();
    ctx.arc(player.x,player.y,player.size+8,0,Math.PI*2);
    ctx.fillStyle = pCfg.glow + "55";
    ctx.fill();
    //主体巨猿
    ctx.beginPath();
    ctx.arc(player.x,player.y,player.size,0,Math.PI*2);
    ctx.fillStyle = pCfg.color;
    ctx.fill();
    ctx.strokeStyle="#000";
    ctx.lineWidth=3;
    ctx.stroke();

    //玩家头顶等级
    ctx.font = "bold 22px sans-serif";
    ctx.fillStyle="#ffdd22";
    ctx.textAlign="center";
    ctx.fillText(`Lv.${player.lv}`,player.x,player.y-player.size-12);

    // 王者皇冠判定
    const kingTipDom = document.getElementById("kingTip");
    if(isPlayerKing()){
        kingTipDom.innerText = "👑 旷野王者!所有巨猿感知你的位置";
        ctx.font = `${player.size*0.85}px serif`;
        ctx.fillText("👑",player.x-player.size/2.2, player.y-player.size-player.size*0.2);
    }else{
        kingTipDom.innerText = "";
    }

    requestAnimationFrame(loop);
}

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

Game Source: 巨猿进化旷野 | 猿族时代风格

Creator: RocketDragon88

Libraries: none

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