🎮ArcadeLab

摸金行动 完整版-多地图+撤离点

by BraveCoder31
423 lines12.5 KB
▶ Play
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>摸金行动 完整版-多地图+撤离点</title>
<style>
* { margin:0; padding:0; box-sizing:border-box; user-select:none; }
body { background:#1a1a1a; color:#fff; font-family:微软雅黑; overflow:hidden; }
#crosshair {
    position:fixed; top:50%; left:50%;
    transform:translate(-50%,-50%);
    width:24px; height:24px;
    border:2px solid #fff; border-radius:50%;
    pointer-events:none; z-index:20;
}
#game { width:100vw; height:100vh; position:relative; background:#2b241c; }
#player {
    width:40px; height:40px;
    background:#5490ff; border-radius:50%;
    position:absolute; transform:translate(-50%,-50%);
}
.wall {
    background:#44382b; border:3px solid #6b5947;
    position:absolute;
}
.safe {
    width:65px; height:55px;
    background:#806020; border:3px solid #ffd700;
    position:absolute; border-radius:4px;
}
.birdNest {
    width:45px; height:40px;
    background:#614a32; border-radius:50% 50% 40% 40%;
    position:absolute;
}
.trashPile {
    width:50px; height:35px;
    background:#524333; border-radius:6px;
    position:absolute;
}
.leavePoint {
    width:70px; height:60px;
    background:#27ae60; border:3px solid #fff;
    position:absolute; border-radius:8px;
    text-align:center; line-height:60px; font-weight:bold;
}
.loot {
    width:28px; height:28px;
    position:absolute; border-radius:3px;
    display:none;
}
.gold { background:#ffd700; }
.coin { background:#e6c200; }
.junk { background:#888; }
.poison { background:#9b2222; }
.medicine { background:#27ae60; }
.enemy {
    width:36px; height:36px;
    background:#c72c2c; border-radius:50%;
    position:absolute;
}
.bullet {
    width:6px; height:14px;
    background:#ffffff; border-radius:3px;
    position:absolute;
}
#ui {
    position:fixed; top:15px; left:15px;
    z-index:10; font-size:18px; line-height:1.6;
    background:rgba(0,0,0,0.5); padding:8px 12px; border-radius:6px;
}
#tip {
    position:fixed; bottom:25px; left:50%;
    transform:translateX(-50%); font-size:17px;
    color:#ffdd77; text-align:center;
    background:rgba(0,0,0,0.4); padding:6px 15px; border-radius:20px;
    z-index:10;
}
#mapTip{
    position:fixed; top:15px; right:15px;
    background:rgba(0,0,0,0.5); padding:8px 12px;
    border-radius:6px; font-size:18px; z-index:10;
}
.overBox{
    position:fixed; top:0;left:0;width:100vw;height:100vh;
    background:rgba(0,0,0,0.85);z-index:30;
    display:none;text-align:center;padding-top:200px;
    font-size:36px;
}
</style>
</head>
<body>
<div id="crosshair"></div>
<div id="game">
    <div id="player"></div>
</div>

<div id="ui">
    💰 总收益:<span id="totalScore">0</span><br>
    🔫 子弹:∞ 无限<br>
    ⚠️ 小心负面物品!
</div>
<div id="mapTip">当前地图:<span id="mapName">一号区域</span></div>
<div id="tip">WASD移动 | 鼠标左键开枪 | E键搜刮/撤离 | M键切换地图</div>
<div class="overBox" id="overBox">
    <div>✅ 成功撤离!本局得分:<span id="finalScore">0</span></div>
    <div style="font-size:20px;margin-top:20px">刷新页面重新开始</div>
</div>

<script>
const game = document.getElementById('game');
const player = document.getElementById('player');
const scoreDom = document.getElementById('totalScore');
const tipDom = document.getElementById('tip');
const mapNameDom = document.getElementById('mapName');
const overBox = document.getElementById('overBox');
const finalScoreDom = document.getElementById('finalScore');

let playerX = window.innerWidth / 2;
let playerY = window.innerHeight / 2;
const moveSpeed = 5;
let keys = {};
let mouseHold = false;
let totalScore = 0;
let nowMap = 1;

let safes = [];
let birdNests = [];
let trashes = [];
let leavePoints = [];
let enemies = [];
let bullets = [];

const lootTypeList = [
    { name: "金条", score: 10, className: "gold" },
    { name: "钱币", score: 5, className: "coin" },
    { name: "药品", score: 8, className: "medicine" },
    { name: "废旧杂物", score: 1, className: "junk" },
    { name: "破损毒物", score: -15, className: "poison" }
];

function clearAllObj(){
    safes.forEach(item=>item.remove());
    birdNests.forEach(item=>item.remove());
    trashes.forEach(item=>item.remove());
    leavePoints.forEach(item=>item.remove());
    enemies.forEach(item=>item.remove());
    document.querySelectorAll('.wall').forEach(w=>w.remove());
    safes=[];birdNests=[];trashes=[];leavePoints=[];enemies=[];bullets=[];
}

function buildWall(x, y, w, h) {
    let wall = document.createElement('div');
    wall.className = "wall";
    wall.style.left = x + "px";
    wall.style.top = y + "px";
    wall.style.width = w + "px";
    wall.style.height = h + "px";
    game.appendChild(wall);
}

function createSafe(x, y) {
    let obj = document.createElement('div');
    obj.className = "safe";
    obj.style.left = x + "px";
    obj.style.top = y + "px";
    obj.dataset.open = "false";
    game.appendChild(obj);
    let loot = createRandomLoot(obj);
    obj.loot = loot;
    safes.push(obj);
}

function createBirdNest(x, y) {
    let obj = document.createElement('div');
    obj.className = "birdNest";
    obj.style.left = x + "px";
    obj.style.top = y + "px";
    obj.dataset.open = "false";
    game.appendChild(obj);
    let loot = createRandomLoot(obj);
    obj.loot = loot;
    birdNests.push(obj);
}

function createTrash(x, y) {
    let obj = document.createElement('div');
    obj.className = "trashPile";
    obj.style.left = x + "px";
    obj.style.top = y + "px";
    obj.dataset.open = "false";
    game.appendChild(obj);
    let loot = createRandomLoot(obj);
    obj.loot = loot;
    trashes.push(obj);
}

function createLeavePoint(x,y){
    let obj = document.createElement('div');
    obj.className = "leavePoint";
    obj.style.left = x + "px";
    obj.style.top = y + "px";
    obj.innerText = "撤离点";
    game.appendChild(obj);
    leavePoints.push(obj);
}

function createRandomLoot(parent) {
    let loot = document.createElement('div');
    loot.className = "loot";
    let randomIdx = Math.floor(Math.random() * lootTypeList.length);
    let targetLoot = lootTypeList[randomIdx];
    loot.classList.add(targetLoot.className);
    loot.dataset.name = targetLoot.name;
    loot.dataset.score = targetLoot.score;
    loot.style.left = (parseFloat(parent.style.left) + 15) + "px";
    loot.style.top = (parseFloat(parent.style.top) + 10) + "px";
    loot.style.display = "none";
    game.appendChild(loot);
    return loot;
}

function createEnemy() {
    let enemy = document.createElement('div');
    enemy.className = "enemy";
    let x = Math.random() * window.innerWidth;
    let y = Math.random() * window.innerHeight;
    enemy.style.left = x + "px";
    enemy.style.top = y + "px";
    game.appendChild(enemy);
    enemies.push(enemy);
}

function loadMap1(){
    mapNameDom.innerText = "一号区域";
    buildWall(200, 0, 20, 350);
    buildWall(500, 250, 20, 400);
    buildWall(0, 450, window.innerWidth, 20);
    createSafe(100, 120);
    createSafe(620, 150);
    createSafe(320, 520);
    createBirdNest(260, 220);
    createBirdNest(700, 380);
    createTrash(150, 380);
    createTrash(480, 550);
    createTrash(600, 280);
    createLeavePoint(window.innerWidth-120,window.innerHeight-100);
    for(let i=0;i<3;i++) createEnemy();
}

function loadMap2(){
    mapNameDom.innerText = "二号仓库";
    buildWall(350,0,20,400);
    buildWall(100,200,600,20);
    buildWall(0,500,window.innerWidth,20);
    createSafe(80,80);
    createSafe(720,420);
    createSafe(400,580);
    createBirdNest(180,300);
    createBirdNest(550,120);
    createTrash(280,450);
    createTrash(650,220);
    createLeavePoint(50,window.innerHeight-100);
    for(let i=0;i<4;i++) createEnemy();
}

function loadMap3(){
    mapNameDom.innerText = "三号据点";
    buildWall(150,100,500,20);
    buildWall(150,300,500,20);
    buildWall(300,0,20,window.innerHeight);
    createSafe(80,180);
    createSafe(750,200);
    createSafe(750,400);
    createBirdNest(200,450);
    createBirdNest(600,120);
    createTrash(100,520);
    createTrash(680,500);
    createLeavePoint(window.innerWidth/2-35,window.innerHeight-90);
    for(let i=0;i<5;i++) createEnemy();
}

function switchMap(){
    clearAllObj();
    playerX = window.innerWidth/2;
    playerY = window.innerHeight/2;
    nowMap++;
    if(nowMap>3) nowMap=1;
    if(nowMap===1) loadMap1();
    if(nowMap===2) loadMap2();
    if(nowMap===3) loadMap3();
    tipDom.innerText = "已切换地图!继续搜刮物资";
    setTimeout(()=>{
        tipDom.innerText = "WASD移动 | 鼠标左键开枪 | E键搜刮/撤离 | M键切换地图";
    },1500);
}

function searchItem() {
    let allItems = [...safes, ...birdNests, ...trashes];
    let playerCenterX = playerX;
    let playerCenterY = playerY;

    allItems.forEach(item => {
        if (item.dataset.open === "true") return;
        let itemX = parseFloat(item.style.left) + 25;
        let itemY = parseFloat(item.style.top) + 20;
        let dist = Math.hypot(playerCenterX - itemX, playerCenterY - itemY);

        if (dist < 60) {
            item.dataset.open = "true";
            item.loot.style.display = "block";
            let lootName = item.loot.dataset.name;
            let lootScore = Number(item.loot.dataset.score);
            totalScore += lootScore;
            scoreDom.innerText = totalScore;

            if (lootScore > 0) {
                tipDom.innerText = `✅ 搜到【${lootName}】,+${lootScore}分`;
            } else if (lootScore < 0) {
                tipDom.innerText = `❌ 捡到【${lootName}】,${lootScore}分`;
            } else {
                tipDom.innerText = `📦 搜到【${lootName}】,收益一般`;
            }

            setTimeout(() => {
                item.loot.remove();
                tipDom.innerText = "WASD移动 | 鼠标左键开枪 | E键搜刮/撤离 | M键切换地图";
            }, 1200);
        }
    });

    leavePoints.forEach(lp=>{
        let lpX = parseFloat(lp.style.left)+35;
        let lpY = parseFloat(lp.style.top)+30;
        let dist = Math.hypot(playerX-lpX,playerY-lpY);
        if(dist<70){
            finalScoreDom.innerText = totalScore;
            overBox.style.display = "block";
        }
    });
}

function fireBullet(e) {
    let bullet = document.createElement('div');
    bullet.className = "bullet";
    bullet.style.left = playerX + "px";
    bullet.style.top = playerY + "px";
    game.appendChild(bullet);
    bullets.push(bullet);
    let angle = Math.atan2(e.clientY - playerY, e.clientX - playerX);
    bullet.vx = Math.cos(angle) * 14;
    bullet.vy = Math.sin(angle) * 14;
}

function checkCollide(a, b) {
    let aRect = a.getBoundingClientRect();
    let bRect = b.getBoundingClientRect();
    return !(aRect.bottom < bRect.top || aRect.top > bRect.bottom ||
             aRect.right < bRect.left || aRect.left > bRect.right);
}

document.addEventListener('keydown', e => {
    keys[e.code] = true;
    if (e.code === "KeyE") searchItem();
    if (e.code === "KeyM") switchMap();
});
document.addEventListener('keyup', e => keys[e.code] = false);
document.addEventListener('mousedown', e => {
    mouseHold = true;
    fireBullet(e);
});
document.addEventListener('mouseup', () => mouseHold = false);

function gameLoop() {
    if (keys["KeyW"] || keys["ArrowUp"]) playerY -= moveSpeed;
    if (keys["KeyS"] || keys["ArrowDown"]) playerY += moveSpeed;
    if (keys["KeyA"] || keys["ArrowLeft"]) playerX -= moveSpeed;
    if (keys["KeyD"] || keys["ArrowRight"]) playerX += moveSpeed;

    playerX = Math.max(25, Math.min(window.innerWidth - 25, playerX));
    playerY = Math.max(25, Math.min(window.innerHeight - 25, playerY));
    player.style.left = playerX + "px";
    player.style.top = playerY + "px";

    if (mouseHold) {
        fireBullet(event);
    }

    for (let i = bullets.length - 1; i >= 0; i--) {
        let b = bullets[i];
        let x = parseFloat(b.style.left) + b.vx;
        let y = parseFloat(b.style.top) + b.vy;
        b.style.left = x + "px";
        b.style.top = y + "px";

        if (x < 0 || x > window.innerWidth || y < 0 || y > window.innerHeight) {
            b.remove();
            bullets.splice(i, 1);
            continue;
        }

        for (let j = enemies.length - 1; j >= 0; j--) {
            let en = enemies[j];
            if (checkCollide(b, en)) {
                en.remove();
                enemies.splice(j, 1);
                b.remove();
                bullets.splice(i, 1);
                setTimeout(createEnemy, 2500);
                break;
            }
        }
    }
    requestAnimationFrame(gameLoop);
}

loadMap1();
gameLoop();
</script>
</body>
</html>

Game Source: 摸金行动 完整版-多地图+撤离点

Creator: BraveCoder31

Libraries: none

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