🎮ArcadeLab

像素草原生存

by SwiftCoder84
308 lines9.2 KB
▶ Play
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>像素草原生存</title>
<style>
*{margin:0;padding:0;box-sizing:border-box}
body{background:#222;display:flex;justify-content:center;padding-top:20px}
#game{
    width:800px;height:600px;background:#7ccd7c;
    position:relative;overflow:hidden;border:3px solid #fff;
}
/*玩家样式*/
.player{
    width:32px;height:32px;font-size:32px;
    position:absolute;left:400px;top:300px;
    transition:0.08s;user-select:none;
}
/*怪物通用*/
.monster{position:absolute;font-size:32px;user-select:none;}
.boss-small{font-size:36px;}
.boss-final{font-size:128px;}
/*方向按键 左下*/
.dir-box{
    position:absolute;left:20px;bottom:20px;
    display:grid;grid-template-columns:50px 50px 50px;gap:6px;
}
.dir-btn{
    width:50px;height:50px;border-radius:50%;
    background:#ffffff88;border:2px solid white;
    display:grid;place-items:center;color:#000;font-weight:bold;
}
/*技能按钮 右下*/
.skill-box{position:absolute;right:20px;bottom:20px;display:flex;gap:10px}
.skill-btn{
    width:60px;height:60px;border-radius:50%;
    background:#fff8;border:2px solid white;
    color:#000;font-size:14px;
}
/*血量、击杀数UI*/
.ui{
    position:absolute;top:10px;left:10px;color:white;
    font-size:18px;text-shadow:1px 1px black;
}
.night{background:#2c3e50;transition:2s}
.tree{position:absolute;font-size:28px}
</style>
</head>
<body>
<div id="game">
    <div class="ui">
        生命:<span id="hp">15</span>/15<br>
        击杀:<span id="kill">0</span><br>
        武器:<span id="weapon">木剑(2伤)</span><br>
        盾牌:<span id="shield">未解锁</span>
    </div>
    <div class="player" id="player">😀</div>

    <!--方向键布局-->
    <div class="dir-box">
        <div></div>
        <div class="dir-btn" data-dir="up">↑</div>
        <div></div>
        <div class="dir-btn" data-dir="left">←</div>
        <div></div>
        <div class="dir-btn" data-dir="right">→</div>
        <div></div>
        <div class="dir-btn" data-dir="down">↓</div>
        <div></div>
    </div>

    <!--技能按钮-->
    <div class="skill-box">
        <button class="skill-btn" id="dig">挖掘</button>
        <button class="skill-btn" id="attack">攻击</button>
    </div>
</div>

<script>
const game = document.getElementById('game');
const player = document.getElementById('player');
const hpText = document.getElementById('hp');
const killText = document.getElementById('kill');
const weaponText = document.getElementById('weapon');
const shieldText = document.getElementById('shield');

//玩家数据
let playerData = {
    x:400,y:300,speed:4,hp:15,maxHp:15,
    damage:2,kill:0,shield:false,
    weapon:'木剑(2伤)',night:false,gameOver:false
};
let monsters = [];
let smallBossSpawned = false;
let finalBossSpawned = false;
let finalBoss = null;

//移动控制
let moveDir = {up:false,down:false,left:false,right:false};
document.querySelectorAll('.dir-btn').forEach(btn=>{
    const d = btn.dataset.dir;
    btn.onmousedown = ()=>moveDir[d]=true;
    btn.onmouseup = ()=>moveDir[d]=false;
    btn.ontouchstart = ()=>moveDir[d]=true;
    btn.ontouchend = ()=>moveDir[d]=false;
});

//更新玩家位置
function movePlayer(){
    if(playerData.gameOver) return;
    if(moveDir.up && playerData.y>0) playerData.y -= playerData.speed;
    if(moveDir.down && playerData.y<568) playerData.y += playerData.speed;
    if(moveDir.left && playerData.x>0) playerData.x -= playerData.speed;
    if(moveDir.right && playerData.x<768) playerData.x += playerData.speed;
    player.style.left = playerData.x+'px';
    player.style.top = playerData.y+'px';
    requestAnimationFrame(movePlayer);
}
movePlayer();

//解锁装备判定
function checkUnlock(){
    const k = playerData.kill;
    if(k>=30 && !playerData.shield){
        playerData.shield = true;
        shieldText.textContent = '已拥有(减伤1/3)';
    }
    if(k>=100 && playerData.damage===2){
        playerData.damage = 6;
        weaponText.textContent = '钻石剑(6伤)';
    }
    if(k>=200 && playerData.damage===6){
        playerData.damage = 8;
        weaponText.textContent = '合金剑(8伤)';
    }
    //小蟑螂boss
    if(k>=50 && !smallBossSpawned){
        spawnSmallBoss();
        smallBossSpawned = true;
    }
    //最终恶灵骑士boss
    if(k>=300 && !finalBossSpawned){
        spawnFinalBoss();
        finalBossSpawned = true;
    }
}

//生成普通怪物 夜晚才刷
function spawnMonster(){
    if(playerData.gameOver || !playerData.night) return;
    const types = [
        {emoji:'👽',hp:6,dmg:2,name:'外星人'},
        {emoji:'👻',hp:6,dmg:3,name:'幽灵'},
    ];
    const t = types[Math.floor(Math.random()*2)];
    const m = document.createElement('div');
    m.className = 'monster';
    m.textContent = t.emoji;
    m.style.left = Math.random()*750+'px';
    m.style.top = Math.random()*550+'px';
    game.appendChild(m);
    monsters.push({
        el:m,x:parseFloat(m.style.left),y:parseFloat(m.style.top),
        hp:t.hp,maxHp:t.hp,dmg:t.dmg,type:t.name
    });
}

//生成蟑螂小boss
function spawnSmallBoss(){
    const boss = document.createElement('div');
    boss.className = 'monster boss-small';
    boss.textContent = '🪳';
    boss.style.left = '200px';
    boss.style.top = '200px';
    game.appendChild(boss);
    monsters.push({
        el:boss,x:200,y:200,hp:40,maxHp:40,dmg:6,type:'蟑螂Boss'
    });
}

//生成最终恶灵骑士BOSS
function spawnFinalBoss(){
    const boss = document.createElement('div');
    boss.className = 'monster boss-final';
    boss.textContent = '🏇⚔️';
    boss.style.left = '350px';
    boss.style.top = '200px';
    game.appendChild(boss);
    finalBoss = {el:boss,x:350,y:200,hp:50,maxHp:50,dmg:10};
}

//攻击按钮
document.getElementById('attack').onclick = attackMonster;
document.getElementById('attack').ontouchstart = attackMonster;
function attackMonster(){
    if(playerData.gameOver) return;
    const px = playerData.x, py = playerData.y;
    //攻击普通怪物
    for(let i=monsters.length-1;i>=0;i--){
        const m = monsters[i];
        const dis = Math.hypot(m.x-px,m.y-py);
        if(dis<60){
            m.hp -= playerData.damage;
            if(m.hp<=0){
                m.el.remove();
                monsters.splice(i,1);
                playerData.kill++;
                killText.textContent = playerData.kill;
                checkUnlock();
            }
        }
    }
    //攻击最终BOSS
    if(finalBoss){
        const dis = Math.hypot(finalBoss.x-px,finalBoss.y-py);
        if(dis<130){
            finalBoss.hp -= playerData.damage;
            if(finalBoss.hp<=0){
                alert('恭喜!击败恶灵骑士,游戏通关!');
                playerData.gameOver = true;
            }
        }
    }
}

//怪物自动追击玩家+攻击玩家
function monsterAI(){
    if(playerData.gameOver) return;
    const px = playerData.x, py = playerData.y;
    //小怪AI
    monsters.forEach(m=>{
        const dx = px - m.x, dy = py - m.y;
        m.x += dx>0?1.2:-1.2;
        m.y += dy>0?1.2:-1.2;
        m.el.style.left = m.x+'px';
        m.el.style.top = m.y+'px';
        //碰到玩家造成伤害
        const dist = Math.hypot(m.x-px,m.y-py);
        if(dist<35){
            let hurt = m.dmg;
            if(playerData.shield) hurt = Math.floor(hurt*2/3);
            playerData.hp -= hurt;
            hpText.textContent = playerData.hp;
            if(playerData.hp<=0){
                alert('你被怪物击败,游戏结束');
                playerData.gameOver = true;
            }
        }
    });
    //最终BOSS攻击
    if(finalBoss){
        const dx = px-finalBoss.x, dy = py-finalBoss.y;
        finalBoss.x += dx>0?0.8:-0.8;
        finalBoss.y += dy>0?0.8:-0.8;
        finalBoss.el.style.left = finalBoss.x+'px';
        finalBoss.el.style.top = finalBoss.y+'px';
        const dist = Math.hypot(finalBoss.x-px,finalBoss.y-py);
        if(dist<120){
            let hurt = finalBoss.dmg;
            if(playerData.shield) hurt = Math.floor(hurt*2/3);
            playerData.hp -= hurt;
            hpText.textContent = playerData.hp;
            if(playerData.hp<=0){
                alert('被恶灵骑士击杀,游戏失败');
                playerData.gameOver = true;
            }
        }
    }
    requestAnimationFrame(monsterAI);
}
monsterAI();

//昼夜循环:白天无怪,夜晚刷怪
setInterval(()=>{
    playerData.night = !playerData.night;
    if(playerData.night){
        game.classList.add('night');
        spawnMonster();
    }else{
        game.classList.remove('night');
    }
},12000);

//挖掘木头(白天刷新树木)
document.getElementById('dig').onclick = ()=>{
    if(playerData.gameOver) return;
    if(!playerData.night){
        const tree = document.createElement('div');
        tree.className = 'tree';
        tree.textContent = '🪵';
        tree.style.left = Math.random()*750+'px';
        tree.style.top = Math.random()*550+'px';
        game.appendChild(tree);
    }
}

//初始刷新几根木头
for(let a=0;a<8;a++){
    const tree = document.createElement('div');
    tree.className = 'tree';
    tree.textContent = '🪵';
    tree.style.left = Math.random()*750+'px';
    tree.style.top = Math.random()*550+'px';
    game.appendChild(tree);
}
</script>
</body>
</html>

Game Source: 像素草原生存

Creator: SwiftCoder84

Libraries: none

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