🎮ArcadeLab

太空战机

by ShadowRider50
461 lines11.0 KB
▶ Play
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<title>太空战机</title>
<style>
*{margin:0;padding:0;box-sizing:border-box;font-family:Arial}
body{background:#111;overflow:hidden;}

/* 开始界面 */
#startPage{
    width:100vw;height:100vh;
    background:#0a0a20;
    display:flex;
    flex-direction:column;
    align-items:center;
    justify-content:center;
    gap:25px;
}
#startBtn,#skinBtn{
    padding:16px 40px;
    font-size:22px;
    border:none;
    border-radius:10px;
    background:#00aaff;
    color:#fff;
    font-weight:bold;
    width:220px;
}
#skinBtn{
    background:#6644ff;
}

/* 皮肤选择界面 */
#skinPage{
    width:100vw;height:100vh;
    background:#0a0a20;
    display:none;
    flex-direction:column;
    align-items:center;
    justify-content:center;
    gap:30px;
}
.skin-item{
    width:240px;
    padding:15px;
    border:2px solid #444;
    border-radius:10px;
    color:#fff;
    text-align:center;
}
.skin-locked{
    border-color:#ff5555;
    color:#aaa;
}
#backBtn{
    padding:12px 30px;
    border:none;
    border-radius:8px;
    background:#555;
    color:#fff;
    font-size:18px;
}

/* 游戏主界面 */
#gamePage{
    width:100vw;height:100vh;
    display:none;
    flex-direction:column;
    align-items:center;
    justify-content:space-around;
    padding:15px 0;
    position:relative;
}
#topInfo{
    display:flex;
    gap:40px;
}
#scoreBox,#hpBox{
    color:#00aaff;
    font-size:26px;
    font-weight:bold;
}
#gameCanvas{
    border:2px solid #333;
    background:#000518;
}

/* 控制按钮区域 */
#controlArea{
    display:flex;
    align-items:center;
    gap:40px;
}
#directionPad{
    display:grid;
    grid-template-columns: 60px 60px;
    gap:6px;
}
#fireBtn{
    width:80px;height:80px;
    border:none;
    border-radius:50%;
    background:#ff3333;
    color:#fff;
    font-size:18px;
    font-weight:bold;
}
#fireBtn:active{background:#ff6666;}
.dir-btn{
    width:60px;height:60px;
    font-size:24px;
    border:none;
    border-radius:8px;
    background:#444;
    color:#fff;
}
.dir-btn:active{background:#00aaff;}
#btnLeft{grid-column:1;}
#btnRight{grid-column:2;}

/* 失败弹窗 */
#failModal{
    position:absolute;
    top:0;left:0;
    width:100%;height:100%;
    background:rgba(0,0,0,0.85);
    display:none;
    flex-direction:column;
    align-items:center;
    justify-content:center;
    gap:20px;
}
#failText{
    color:#ff4444;
    font-size:48px;font-weight:bold;
}
#finalScore{
    color:#00aaff;
    font-size:28px;
}
#restartBtn,#menuBtn{
    padding:14px 36px;
    font-size:20px;
    border:none;
    border-radius:8px;
    color:#fff;
}
#restartBtn{
    background:#00aaff;
}
#menuBtn{
    background:#666666;
}
</style>
</head>
<body>
<!-- 主菜单 -->
<div id="startPage">
    <h1 style="color:#00aaff;font-size:42px">太空战机</h1>
    <button id="startBtn">开始游戏</button>
    <button id="skinBtn">更换战机皮肤</button>
</div>

<!-- 皮肤选择页 -->
<div id="skinPage">
    <h2 style="color:#fff">战机皮肤商店</h2>
    <div class="skin-item" id="skin1">
        <h3>纯白战机</h3>
        <p>已解锁,直接使用</p>
    </div>
    <div class="skin-item skin-locked" id="skin2">
        <h3>深蓝战机</h3>
        <p>累计得分 ≥ 150 解锁</p>
    </div>
    <button id="backBtn">返回</button>
</div>

<!-- 游戏界面 -->
<div id="gamePage">
    <div id="topInfo">
        <div id="scoreBox">当前得分:0</div>
        <div id="hpBox">生命值:❤❤❤</div>
    </div>
    <canvas id="gameCanvas" width="400" height="450"></canvas>

    <div id="controlArea">
        <div id="directionPad">
            <button class="dir-btn" id="btnLeft">←</button>
            <button class="dir-btn" id="btnRight">→</button>
        </div>
        <button id="fireBtn">发射</button>
    </div>

    <div id="failModal">
        <div id="failText">战机被击毁</div>
        <div id="finalScore"></div>
        <button id="restartBtn">重新再来</button>
        <button id="menuBtn">返回主菜单</button>
    </div>
</div>

<script>
// 页面元素
const startPage = document.getElementById('startPage');
const skinPage = document.getElementById('skinPage');
const gamePage = document.getElementById('gamePage');
const startBtn = document.getElementById('startBtn');
const skinBtn = document.getElementById('skinBtn');
const backBtn = document.getElementById('backBtn');
const skin1 = document.getElementById('skin1');
const skin2 = document.getElementById('skin2');
const failModal = document.getElementById('failModal');
const restartBtn = document.getElementById('restartBtn');
const menuBtn = document.getElementById('menuBtn');
const scoreBox = document.getElementById('scoreBox');
const hpBox = document.getElementById('hpBox');
const finalScore = document.getElementById('finalScore');
const btnLeft = document.getElementById('btnLeft');
const btnRight = document.getElementById('btnRight');
const fireBtn = document.getElementById('fireBtn');

const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');

// 全局存档数据(浏览器本地保存)
let saveData = JSON.parse(localStorage.getItem('spaceFighterSave')) || {
    totalScore: 0,
    useSkin: 1,
    unlockSkin2: false
};

// 保存存档
function saveGame(){
    localStorage.setItem('spaceFighterSave', JSON.stringify(saveData));
}

// 游戏变量
let score = 0;
let hp = 3;
let gameLoop;
let moveDir = 0;
let bullets = [];
let enemies = [];
let enemySpawnTimer;

// 玩家战机设置
const player = {
    x: 175,
    y: 380,
    w: 50,
    h: 40,
    speed: 11
};

// 更新皮肤解锁状态
function updateSkinUI(){
    if(saveData.unlockSkin2){
        skin2.classList.remove('skin-locked');
        skin2.innerHTML = `<h3>深蓝战机</h3><p>已解锁,点击使用</p>`;
    }
}

// 选择皮肤
skin1.onclick = ()=>{
    saveData.useSkin = 1;
    saveGame();
    alert("已切换为纯白战机");
};
skin2.onclick = ()=>{
    if(saveData.unlockSkin2){
        saveData.useSkin = 2;
        saveGame();
        alert("已切换为深蓝战机");
    }else{
        alert("累计得分达到150分才能解锁!");
    }
};

// 页面切换
skinBtn.onclick = ()=>{
    updateSkinUI();
    startPage.style.display = 'none';
    skinPage.style.display = 'flex';
};
backBtn.onclick = ()=>{
    skinPage.style.display = 'none';
    startPage.style.display = 'flex';
};

// 初始化游戏
function initGame(){
    score = 0;
    hp = 3;
    moveDir = 0;
    bullets = [];
    enemies = [];
    scoreBox.innerText = `当前得分:${score}`;
    hpBox.innerText = `生命值:❤❤❤`;
    player.x = 175;

    if(gameLoop) clearInterval(gameLoop);
    if(enemySpawnTimer) clearInterval(enemySpawnTimer);

    gameLoop = setInterval(gameUpdate, 16);
    enemySpawnTimer = setInterval(spawnEnemy, 1200);
}

// 生成敌人:限制左右边界,不会贴边
function spawnEnemy(){
    const margin = 40;
    const xPos = margin + Math.random() * (canvas.width - margin*2 - 20);
    enemies.push({
        x: xPos,
        y: -20,
        r: 12,
        speed: 3.5
    });
}

// 发射子弹
function fireBullet(){
    bullets.push({
        x: player.x + player.w / 2 - 3,
        y: player.y,
        w:6,
        h:14,
        speed:7
    });
}

// 长按移动控制
btnLeft.addEventListener('mousedown', ()=>moveDir = -1);
btnLeft.addEventListener('mouseup', ()=>moveDir = 0);
btnLeft.addEventListener('mouseleave', ()=>moveDir = 0);
btnRight.addEventListener('mousedown', ()=>moveDir = 1);
btnRight.addEventListener('mouseup', ()=>moveDir = 0);
btnRight.addEventListener('mouseleave', ()=>moveDir = 0);

btnLeft.addEventListener('touchstart', (e)=>{e.preventDefault();moveDir = -1});
btnLeft.addEventListener('touchend', ()=>moveDir = 0);
btnRight.addEventListener('touchstart', (e)=>{e.preventDefault();moveDir = 1});
btnRight.addEventListener('touchend', ()=>moveDir = 0);

fireBtn.addEventListener('click', fireBullet);
fireBtn.addEventListener('touchstart', (e)=>{e.preventDefault();fireBullet()});

// 开始游戏
startBtn.onclick = ()=>{
    startPage.style.display = 'none';
    gamePage.style.display = 'flex';
    initGame();
};
// 重新再来
restartBtn.onclick = ()=>{
    failModal.style.display = 'none';
    initGame();
};
// 返回主菜单
menuBtn.onclick = ()=>{
    failModal.style.display = 'none';
    gamePage.style.display = 'none';
    startPage.style.display = 'flex';
    clearInterval(gameLoop);
    clearInterval(enemySpawnTimer);
};

// 扣血逻辑
function loseHp(){
    hp--;
    let heartStr = "";
    for(let i=0;i<hp;i++) heartStr += "❤";
    hpBox.innerText = `生命值:${heartStr}`;
    if(hp <= 0){
        clearInterval(gameLoop);
        clearInterval(enemySpawnTimer);
        // 累计总分更新,判断解锁皮肤
        saveData.totalScore += score;
        if(saveData.totalScore >= 150) saveData.unlockSkin2 = true;
        saveGame();
        finalScore.innerText = `最终得分:${score}`;
        failModal.style.display = 'flex';
    }
}

// 游戏主循环
function gameUpdate(){
    ctx.fillStyle = '#000518';
    ctx.fillRect(0,0,canvas.width,canvas.height);

    player.x += moveDir * player.speed;
    player.x = Math.max(0, Math.min(canvas.width - player.w, player.x));

    // 更新子弹
    for(let i = bullets.length - 1; i >= 0; i--){
        bullets[i].y -= bullets[i].speed;
        if(bullets[i].y < -20) bullets.splice(i,1);
    }

    // 敌人更新与碰撞
    for(let ei = enemies.length - 1; ei >= 0; ei--){
        const enemy = enemies[ei];
        enemy.y += enemy.speed;

        // 撞到战机扣血
        const dx = (player.x+player.w/2) - enemy.x;
        const dy = (player.y+player.h/2) - enemy.y;
        const dist = Math.sqrt(dx*dx+dy*dy);
        if(dist < enemy.r + 20){
            enemies.splice(ei,1);
            loseHp();
            if(hp <= 0) return;
        }

        // 子弹击中敌人
        for(let bi = bullets.length -1; bi >=0; bi--){
            const bullet = bullets[bi];
            if(bullet.x < enemy.x+enemy.r && bullet.x+bullet.w > enemy.x-enemy.r
                && bullet.y < enemy.y+enemy.r && bullet.y+bullet.h > enemy.y-enemy.r){
                enemies.splice(ei,1);
                bullets.splice(bi,1);
                score += 15;
                scoreBox.innerText = `当前得分:${score}`;
                break;
            }
        }

        if(enemy.y > canvas.height + 20) enemies.splice(ei,1);
    }

    // 绘制战机皮肤
    if(saveData.useSkin === 1) ctx.fillStyle = '#ffffff';
    else ctx.fillStyle = '#2244aa';
    ctx.beginPath();
    ctx.moveTo(player.x+player.w/2, player.y);
    ctx.lineTo(player.x, player.y+player.h);
    ctx.lineTo(player.x+player.w, player.y+player.h);
    ctx.closePath();
    ctx.fill();

    // 子弹
    ctx.fillStyle = '#00aaff';
    bullets.forEach(b=>{
        ctx.fillRect(b.x,b.y,b.w,b.h);
    });

    // 红色敌人球
    ctx.fillStyle = '#ff2222';
    enemies.forEach(e=>{
        ctx.beginPath();
        ctx.arc(e.x,e.y,e.r,0,Math.PI*2);
        ctx.fill();
    });
}

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

Game Source: 太空战机

Creator: ShadowRider50

Libraries: none

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