文件名:game1.html

黄金矿工网页游戏,运行的效果还不错,直接po图和代码。

<!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; }
        body {
            background: #1a1a2e;
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
            font-family: "Microsoft YaHei", sans-serif;
        }
        #game-container {
            position: relative;
            width: 800px;
            height: 600px;
            border-radius: 12px;
            overflow: hidden;
            box-shadow: 0 20px 60px rgba(0,0,0,0.5);
        }
        canvas { display: block; }
        #ui-overlay {
            position: absolute;
            top: 0; left: 0; right: 0;
            display: flex;
            justify-content: space-between;
            padding: 15px 25px;
            pointer-events: none;
            z-index: 10;
        }
        .ui-box {
            background: rgba(0,0,0,0.55);
            color: #ffd700;
            padding: 8px 18px;
            border-radius: 8px;
            font-size: 18px;
            font-weight: bold;
            border: 1px solid rgba(255,215,0,0.3);
        }
        .ui-box span { color: #fff; margin-left: 6px; }
        #message {
            position: absolute;
            top: 50%; left: 50%;
            transform: translate(-50%,-50%);
            text-align: center;
            z-index: 20;
            display: none;
        }
        #message h2 {
            font-size: 42px;
            color: #ffd700;
            text-shadow: 2px 2px 8px rgba(0,0,0,0.8);
            margin-bottom: 15px;
        }
        #message p {
            font-size: 22px;
            color: #fff;
            margin-bottom: 25px;
        }
        #message button {
            padding: 12px 40px;
            font-size: 20px;
            font-weight: bold;
            color: #4a3010;
            background: linear-gradient(135deg, #ffd700, #ffb300);
            border: none;
            border-radius: 30px;
            cursor: pointer;
            box-shadow: 0 4px 15px rgba(255,215,0,0.4);
            transition: transform 0.2s;
        }
        #message button:hover { transform: scale(1.08); }
        #hint {
            position: absolute;
            bottom: 15px; left: 50%;
            transform: translateX(-50%);
            color: rgba(255,255,255,0.5);
            font-size: 14px;
            z-index: 10;
            pointer-events: none;
        }
    </style>
</head>
<body>
    <div id="game-container">
        <canvas id="game" width="800" height="600"></canvas>
        <div id="ui-overlay">
            <div class="ui-box">分数<span id="score">0</span></div>
            <div class="ui-box">目标<span id="target">500</span></div>
            <div class="ui-box">第<span id="level">1</span>关</div>
            <div class="ui-box">时间<span id="time">60</span>s</div>
        </div>
        <div id="message">
            <h2 id="msg-title"></h2>
            <p id="msg-text"></p>
            <button id="msg-btn" onclick="handleButton()">开始游戏</button>
        </div>
        <div id="hint">按 空格键 或 点击屏幕 发射钩子</div>
    </div>

<script>
var canvas = document.getElementById('game');
var ctx = canvas.getContext('2d');
var W = canvas.width, H = canvas.height;

// 游戏状态
var state = 'menu'; // menu, playing, levelComplete, gameOver, win
var score = 0;
var level = 1;
var targetScore = 500;
var timeLeft = 60;
var timer = null;

// 矿工位置
var minerX = W / 2;
var minerY = 80;

// 钩子状态
var hook = {
    angle: 0,           // 当前摆动角度(弧度)
    swingSpeed: 0.025,  // 摆动速度
    swingDir: 1,        // 摆动方向
    maxAngle: Math.PI * 0.42, // 最大摆角
    length: 50,         // 当前绳长
    baseLength: 50,     // 基础绳长
    speed: 0,           // 发射速度
    state: 'swinging',  // swinging, extending, retracting
    grabbed: null       // 抓到的物体
};

// 物体类型定义
var itemTypes = {
    gold_s:   { r: 12, weight: 1, score: 50,  color: '#ffd700', name: '小金块' },
    gold_m:   { r: 18, weight: 2, score: 100, color: '#ffd700', name: '中金块' },
    gold_l:   { r: 28, weight: 4, score: 250, color: '#ffd700', name: '大金块' },
    diamond:  { r: 10, weight: 1, score: 600, color: '#00ffff', name: '钻石' },
    rock_s:   { r: 20, weight: 3, score: 20,  color: '#888',    name: '小石头' },
    rock_l:   { r: 32, weight: 5, score: 50,  color: '#666',    name: '大石头' },
    bag:      { r: 14, weight: 2, score: 0,   color: '#8b4513', name: '神秘袋' } // 随机分数
};

var items = [];

// 粒子效果
var particles = [];

function initLevel(lv) {
    items = [];
    particles = [];
    hook.angle = 0;
    hook.swingDir = 1;
    hook.length = hook.baseLength;
    hook.speed = 0;
    hook.state = 'swinging';
    hook.grabbed = null;

    // 摆动速度随关卡增加
    hook.swingSpeed = 0.025 + lv * 0.003;

    // 生成物体
    var counts = {
        gold_s:  4 + Math.floor(lv * 0.5),
        gold_m:  3,
        gold_l:  1 + Math.floor(lv * 0.3),
        diamond: lv >= 2 ? 1 : 0,
        rock_s:  3 + lv,
        rock_l:  2 + Math.floor(lv * 0.5),
        bag:     lv >= 3 ? 1 : 0
    };

    for (var key in counts) {
        for (var i = 0; i < counts[key]; i++) {
            placeItem(key);
        }
    }

    timeLeft = Math.max(40, 70 - lv * 5);
    targetScore = 500 + (lv - 1) * 300;
    updateUI();
}

function placeItem(typeKey) {
    var t = itemTypes[typeKey];
    var attempts = 0;
    while (attempts < 50) {
        var x = 60 + Math.random() * (W - 120);
        var y = 180 + Math.random() * (H - 220);
        // 检查不与其他物体重叠
        var ok = true;
        for (var i = 0; i < items.length; i++) {
            var dx = x - items[i].x;
            var dy = y - items[i].y;
            if (Math.sqrt(dx*dx + dy*dy) < items[i].r + t.r + 8) { ok = false; break; }
        }
        if (ok) {
            items.push({ x: x, y: y, r: t.r, weight: t.weight, score: t.score, color: t.color, name: t.name, type: typeKey });
            return;
        }
        attempts++;
    }
}

// 钩子末端坐标
function hookEnd() {
    return {
        x: minerX + Math.sin(hook.angle) * hook.length,
        y: minerY + Math.cos(hook.angle) * hook.length
    };
}

function fireHook() {
    if (hook.state !== 'swinging') return;
    hook.state = 'extending';
    hook.speed = 7;
}

function update() {
    if (state !== 'playing') return;

    // 钩子摆动
    if (hook.state === 'swinging') {
        hook.angle += hook.swingSpeed * hook.swingDir;
        if (hook.angle > hook.maxAngle) { hook.angle = hook.maxAngle; hook.swingDir = -1; }
        if (hook.angle < -hook.maxAngle) { hook.angle = -hook.maxAngle; hook.swingDir = 1; }
    }

    // 钩子伸出
    if (hook.state === 'extending') {
        hook.length += hook.speed;
        var end = hookEnd();
        // 碰撞检测:抓到物体
        for (var i = 0; i < items.length; i++) {
            var item = items[i];
            var dx = end.x - item.x;
            var dy = end.y - item.y;
            if (Math.sqrt(dx*dx + dy*dy) < item.r + 6) {
                hook.grabbed = item;
                hook.state = 'retracting';
                items.splice(i, 1);
                // 拉回速度取决于重量
                hook.speed = Math.max(1.5, 7 - item.weight * 1.2);
                spawnParticles(end.x, end.y, item.color);
                break;
            }
        }
        // 到达边界
        if (end.x < 0 || end.x > W || end.y > H - 10) {
            hook.state = 'retracting';
            hook.speed = 5;
        }
    }

    // 钩子收回
    if (hook.state === 'retracting') {
        hook.length -= hook.speed;
        if (hook.length <= hook.baseLength) {
            hook.length = hook.baseLength;
            hook.state = 'swinging';
            // 结算抓到的物体
            if (hook.grabbed) {
                var earned = hook.grabbed.score;
                if (hook.grabbed.type === 'bag') {
                    earned = 50 + Math.floor(Math.random() * 400);
                }
                score += earned;
                showFloatText('+' + earned, minerX, minerY + 30, hook.grabbed.color);
                hook.grabbed = null;
                updateUI();
            }
        }
    }

    // 更新粒子
    for (var p = particles.length - 1; p >= 0; p--) {
        particles[p].x += particles[p].vx;
        particles[p].y += particles[p].vy;
        particles[p].vy += 0.15;
        particles[p].life--;
        if (particles[p].life <= 0) particles.splice(p, 1);
    }

    // 更新飘字
    for (var f = floatTexts.length - 1; f >= 0; f--) {
        floatTexts[f].y -= 1.2;
        floatTexts[f].life--;
        if (floatTexts[f].life <= 0) floatTexts.splice(f, 1);
    }

    // 检查关卡完成
    if (score >= targetScore) {
        levelComplete();
    }

    // 检查物品抓完但未达标
    if (items.length === 0 && hook.state === 'swinging' && score < targetScore) {
        gameOver();
    }
}

var floatTexts = [];

function showFloatText(text, x, y, color) {
    floatTexts.push({ text: text, x: x, y: y, color: color, life: 50 });
}

function spawnParticles(x, y, color) {
    for (var i = 0; i < 12; i++) {
        var a = Math.random() * Math.PI * 2;
        var s = 2 + Math.random() * 4;
        particles.push({
            x: x, y: y,
            vx: Math.cos(a) * s,
            vy: Math.sin(a) * s - 2,
            color: color,
            life: 30,
            size: 2 + Math.random() * 3
        });
    }
}

// ============ 渲染 ============

function draw() {
    // 背景
    drawBackground();

    // 物体
    for (var i = 0; i < items.length; i++) {
        drawItem(items[i]);
    }

    // 钩子和绳子
    drawHook();

    // 矿工
    drawMiner();

    // 粒子
    for (var p = 0; p < particles.length; p++) {
        ctx.globalAlpha = particles[p].life / 30;
        ctx.fillStyle = particles[p].color;
        ctx.beginPath();
        ctx.arc(particles[p].x, particles[p].y, particles[p].size, 0, Math.PI * 2);
        ctx.fill();
    }
    ctx.globalAlpha = 1;

    // 飘字
    for (var f = 0; f < floatTexts.length; f++) {
        ctx.globalAlpha = floatTexts[f].life / 50;
        ctx.font = 'bold 24px "Microsoft YaHei"';
        ctx.fillStyle = floatTexts[f].color;
        ctx.textAlign = 'center';
        ctx.fillText(floatTexts[f].text, floatTexts[f].x, floatTexts[f].y);
    }
    ctx.globalAlpha = 1;
}

function drawBackground() {
    // 天空
    var skyGrad = ctx.createLinearGradient(0, 0, 0, 160);
    skyGrad.addColorStop(0, '#87ceeb');
    skyGrad.addColorStop(1, '#b0e0e6');
    ctx.fillStyle = skyGrad;
    ctx.fillRect(0, 0, W, 160);

    // 草地
    ctx.fillStyle = '#4a7c3a';
    ctx.fillRect(0, 150, W, 20);
    ctx.fillStyle = '#3a6c2a';
    for (var i = 0; i < W; i += 15) {
        ctx.fillRect(i, 148, 3, 8);
    }

    // 地下
    var earthGrad = ctx.createLinearGradient(0, 170, 0, H);
    earthGrad.addColorStop(0, '#8b5e3c');
    earthGrad.addColorStop(0.5, '#6b4226');
    earthGrad.addColorStop(1, '#4a2c16');
    ctx.fillStyle = earthGrad;
    ctx.fillRect(0, 170, W, H - 170);

    // 地下纹理
    ctx.strokeStyle = 'rgba(0,0,0,0.1)';
    ctx.lineWidth = 1;
    for (var j = 180; j < H; j += 30) {
        ctx.beginPath();
        for (var k = 0; k < W; k += 40) {
            ctx.moveTo(k, j);
            ctx.lineTo(k + 20, j + 5);
        }
        ctx.stroke();
    }

    // 小石头装饰
    ctx.fillStyle = 'rgba(0,0,0,0.15)';
    for (var s = 0; s < 20; s++) {
        ctx.beginPath();
        ctx.arc(50 + Math.random() * 700, 200 + Math.random() * 380, 3 + Math.random() * 4, 0, Math.PI * 2);
        ctx.fill();
    }
}

function drawMiner() {
    // 身体
    ctx.fillStyle = '#2196f3';
    ctx.fillRect(minerX - 16, minerY - 5, 32, 25);
    // 头
    ctx.fillStyle = '#ffdbac';
    ctx.beginPath();
    ctx.arc(minerX, minerY - 18, 14, 0, Math.PI * 2);
    ctx.fill();
    // 矿工帽
    ctx.fillStyle = '#ffeb3b';
    ctx.beginPath();
    ctx.arc(minerX, minerY - 22, 14, Math.PI, 0);
    ctx.fill();
    ctx.fillRect(minerX - 16, minerY - 22, 32, 4);
    // 帽灯
    ctx.fillStyle = '#fff';
    ctx.beginPath();
    ctx.arc(minerX, minerY - 30, 4, 0, Math.PI * 2);
    ctx.fill();
    ctx.fillStyle = 'rgba(255,255,0,0.3)';
    ctx.beginPath();
    ctx.moveTo(minerX, minerY - 30);
    ctx.lineTo(minerX - 20, minerY - 50);
    ctx.lineTo(minerX + 20, minerY - 50);
    ctx.closePath();
    ctx.fill();
}

function drawHook() {
    var end = hookEnd();

    // 绳子
    ctx.strokeStyle = '#333';
    ctx.lineWidth = 2;
    ctx.beginPath();
    ctx.moveTo(minerX, minerY + 15);
    ctx.lineTo(end.x, end.y);
    ctx.stroke();

    // 钩子
    ctx.save();
    ctx.translate(end.x, end.y);
    ctx.rotate(hook.angle);

    // 钩子爪
    ctx.strokeStyle = '#555';
    ctx.lineWidth = 4;
    ctx.lineCap = 'round';
    ctx.beginPath();
    ctx.moveTo(0, 0);
    ctx.lineTo(-10, 12);
    ctx.moveTo(0, 0);
    ctx.lineTo(10, 12);
    ctx.stroke();
    // 钩子尖
    ctx.fillStyle = '#888';
    ctx.beginPath();
    ctx.arc(-10, 12, 3, 0, Math.PI * 2);
    ctx.arc(10, 12, 3, 0, Math.PI * 2);
    ctx.fill();

    ctx.restore();

    // 抓到的物体跟随钩子
    if (hook.grabbed) {
        hook.grabbed.x = end.x;
        hook.grabbed.y = end.y + 10;
        drawItem(hook.grabbed);
    }
}

function drawItem(item) {
    ctx.save();

    if (item.type === 'diamond') {
        // 钻石
        ctx.fillStyle = item.color;
        ctx.beginPath();
        ctx.moveTo(item.x, item.y - item.r);
        ctx.lineTo(item.x + item.r * 0.8, item.y);
        ctx.lineTo(item.x, item.y + item.r);
        ctx.lineTo(item.x - item.r * 0.8, item.y);
        ctx.closePath();
        ctx.fill();
        ctx.strokeStyle = '#00bfff';
        ctx.lineWidth = 1.5;
        ctx.stroke();
        // 闪光
        ctx.fillStyle = 'rgba(255,255,255,0.6)';
        ctx.beginPath();
        ctx.moveTo(item.x - 3, item.y - item.r + 3);
        ctx.lineTo(item.x + 3, item.y - item.r + 3);
        ctx.lineTo(item.x, item.y);
        ctx.closePath();
        ctx.fill();
    } else if (item.type === 'bag') {
        // 神秘袋
        ctx.fillStyle = item.color;
        ctx.beginPath();
        ctx.ellipse(item.x, item.y + 2, item.r, item.r * 1.1, 0, 0, Math.PI * 2);
        ctx.fill();
        ctx.fillStyle = '#a0522d';
        ctx.fillRect(item.x - 6, item.y - item.r - 4, 12, 6);
        ctx.fillStyle = '#ffd700';
        ctx.font = 'bold 10px Arial';
        ctx.textAlign = 'center';
        ctx.fillText('?', item.x, item.y + 5);
    } else if (item.type && item.type.indexOf('gold') >= 0) {
        // 金块
        var grad = ctx.createRadialGradient(item.x - item.r * 0.3, item.y - item.r * 0.3, 0, item.x, item.y, item.r);
        grad.addColorStop(0, '#fff8dc');
        grad.addColorStop(0.4, item.color);
        grad.addColorStop(1, '#daa520');
        ctx.fillStyle = grad;
        ctx.beginPath();
        ctx.arc(item.x, item.y, item.r, 0, Math.PI * 2);
        ctx.fill();
        // 高光
        ctx.fillStyle = 'rgba(255,255,255,0.4)';
        ctx.beginPath();
        ctx.ellipse(item.x - item.r * 0.35, item.y - item.r * 0.35, item.r * 0.3, item.r * 0.2, -0.5, 0, Math.PI * 2);
        ctx.fill();
    } else {
        // 石头
        var rgrad = ctx.createRadialGradient(item.x - item.r * 0.3, item.y - item.r * 0.3, 0, item.x, item.y, item.r);
        rgrad.addColorStop(0, '#aaa');
        rgrad.addColorStop(1, item.color);
        ctx.fillStyle = rgrad;
        ctx.beginPath();
        ctx.arc(item.x, item.y, item.r, 0, Math.PI * 2);
        ctx.fill();
        // 纹理
        ctx.strokeStyle = 'rgba(0,0,0,0.2)';
        ctx.lineWidth = 1;
        ctx.beginPath();
        ctx.arc(item.x + item.r * 0.3, item.y - item.r * 0.1, item.r * 0.4, 0, Math.PI * 2);
        ctx.stroke();
    }

    ctx.restore();
}

// ============ 游戏流程 ============

function startGame() {
    score = 0;
    level = 1;
    state = 'playing';
    initLevel(level);
    showMessage(null);
    startTimer();
}

function levelComplete() {
    state = 'levelComplete';
    clearInterval(timer);
    showMessage('第' + level + '关完成!', '分数: ' + score + ' / 目标: ' + targetScore, '下一关');
}

function nextLevel() {
    level++;
    state = 'playing';
    initLevel(level);
    showMessage(null);
    startTimer();
}

function gameOver() {
    state = 'gameOver';
    clearInterval(timer);
    showMessage('游戏结束', '最终分数: ' + score + ' / 目标: ' + targetScore, '重新开始');
}

function startTimer() {
    clearInterval(timer);
    timer = setInterval(function() {
        if (state !== 'playing') return;
        timeLeft--;
        updateUI();
        if (timeLeft <= 0) {
            if (score >= targetScore) {
                levelComplete();
            } else {
                gameOver();
            }
        }
    }, 1000);
}

function handleButton() {
    var btn = document.getElementById('msg-btn');
    if (state === 'menu' || state === 'gameOver') {
        startGame();
    } else if (state === 'levelComplete') {
        nextLevel();
    }
}

function showMessage(title, text, btnText) {
    var msg = document.getElementById('message');
    if (title === null) {
        msg.style.display = 'none';
        return;
    }
    msg.style.display = 'block';
    document.getElementById('msg-title').textContent = title;
    document.getElementById('msg-text').textContent = text || '';
    document.getElementById('msg-btn').textContent = btnText || '确定';
}

function updateUI() {
    document.getElementById('score').textContent = score;
    document.getElementById('target').textContent = targetScore;
    document.getElementById('level').textContent = level;
    document.getElementById('time').textContent = timeLeft;
}

// ============ 输入 ============

document.addEventListener('keydown', function(e) {
    if (e.code === 'Space') {
        e.preventDefault();
        if (state === 'playing') fireHook();
    }
});

canvas.addEventListener('click', function() {
    if (state === 'playing') fireHook();
});

// ============ 主循环 ============

function gameLoop() {
    update();
    draw();
    requestAnimationFrame(gameLoop);
}

// 初始画面
showMessage('黄金矿工', '抓取金块和钻石,达到目标分数过关!', '开始游戏');
draw();
gameLoop();
</script>
</body>
</html>

Logo

AtomGit AI 社区提供模型库、数据集、Agent、Token等资源

更多推荐