html简易实现推箱子小游戏原理(易上手)

实现效果

使用方向键移动,将橙色箱子推到绿色目标区域(黑色块为墙,白色块为可通过区域,蓝球为小人)

实现过程

html 复制代码
<!DOCTYPE html>
<html>
<head>
    <title>推箱子小游戏</title>
    <style>
        .game-container {
            display: grid;
            grid-template-columns: repeat(8, 50px);
            gap: 2px;
            background: #333;
            padding: 10px;
        }

        .cell {
            width: 50px;
            height: 50px;
            background: #eee;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 24px;
        }

        .wall {
            background: #444;
        }

        .box {
            background: #ff9900;
            border-radius: 5px;
        }

        .player {
            background: #2196F3;
            border-radius: 50%;
            width: 35px;
            height: 35px;
        }

        .target {
            background: #4CAF50;
        }

        .box-on-target {
            background: #8BC34A;
        }
    </style>
</head>
<body>
    <div class="game-container" id="game"></div>
    <p>使用方向键移动,将橙色箱子推到绿色目标区域(黑色块为墙,白色块为可通过区域,蓝球为小人)</p>

    <script>
        // 关卡配置
        const level = [
            [1, 1, 1, 1, 1, 1, 1, 1],
            [1, 0, 0, 0, 0, 0, 0, 1],
            [1, 0, 2, 3, 0, 2, 0, 1],
            [1, 0, 1, 3, 4, 1, 0, 1],
            [1, 0, 2, 0, 3, 0, 0, 1],
            [1, 0, 0, 0, 0, 0, 0, 1],
            [1, 1, 1, 1, 1, 1, 1, 1]
        ];

        let playerPosition = { x: 4, y: 3 };
        let boxes = [];
        const gameContainer = document.getElementById('game');

        // 初始化游戏
        function initGame() {
            gameContainer.innerHTML = '';
            boxes = [];

            level.forEach((row, y) => {
                row.forEach((cell, x) => {
                    const cellElement = document.createElement('div');
                    cellElement.className = 'cell';
                    
                    switch(cell) {
                        case 1: 
                            cellElement.classList.add('wall');
                            break;
                        case 2:
                            cellElement.classList.add('target');
                            break;
                        case 3:
                            boxes.push({ x, y });
                            cellElement.classList.add('box');
                            break;
                        case 4:
                            playerPosition = { x, y };
                            break;
                    }
                    
                    gameContainer.appendChild(cellElement);
                });
            });

            updatePlayerPosition();
        }

        // 更新玩家位置
        function updatePlayerPosition() {
            document.querySelectorAll('.cell').forEach(cell => {
                cell.classList.remove('player');
            });
            
            const index = playerPosition.y * 8 + playerPosition.x;
            gameContainer.children[index].classList.add('player');
        }

        // 移动检测
        function canMove(dx, dy) {
            const newX = playerPosition.x + dx;
            const newY = playerPosition.y + dy;
            
            // 边界检测
            if (newX < 0 || newX >= 8 || newY < 0 || newY >= 7) return false;
            
            // 获取目标位置的单元格
            const targetCell = level[newY][newX];
            const targetIndex = newY * 8 + newX;
            const targetElement = gameContainer.children[targetIndex];
            
            // 如果是墙
            if (targetCell === 1) return false;
            
            // 检查是否有箱子
            const boxIndex = boxes.findIndex(b => b.x === newX && b.y === newY);
            if (boxIndex > -1) {
                // 检查箱子后面的位置
                const boxNewX = newX + dx;
                const boxNewY = newY + dy;
                
                if (boxNewX < 0 || boxNewX >= 8 || boxNewY < 0 || boxNewY >= 7) return false;
                
                const nextCell = level[boxNewY][boxNewX];
                const nextIndex = boxNewY * 8 + boxNewX;
                const nextElement = gameContainer.children[nextIndex];
                
                // 检查箱子后面的位置是否可移动
                if (nextCell === 1 || boxes.some(b => b.x === boxNewX && b.y === boxNewY)) {
                    return false;
                }
                
                // 移动箱子
                boxes[boxIndex].x = boxNewX;
                boxes[boxIndex].y = boxNewY;
                
                // 更新箱子显示
                targetElement.classList.remove('box');
                nextElement.classList.toggle('box', true);
                nextElement.classList.toggle('box-on-target', nextElement.classList.contains('target'));
            }
            
            return true;
        }

        // 处理键盘事件
        document.addEventListener('keydown', (e) => {
            let dx = 0, dy = 0;
            
            switch(e.key) {
                case 'ArrowUp': dy = -1; break;
                case 'ArrowDown': dy = 1; break;
                case 'ArrowLeft': dx = -1; break;
                case 'ArrowRight': dx = 1; break;
                default: return;
            }
            
            if (canMove(dx, dy)) {
                playerPosition.x += dx;
                playerPosition.y += dy;
                updatePlayerPosition();
                checkWin();
            }
        });

        // 胜利检测
        function checkWin() {
            const allBoxesOnTarget = boxes.every(box => {
                const index = box.y * 8 + box.x;
                return gameContainer.children[index].classList.contains('target');
            });
            
            if (allBoxesOnTarget) {
                setTimeout(() => alert('恭喜过关!'), 100);
            }
        }

        // 启动游戏
        initGame();
    </script>
</body>
</html>
相关推荐
用户69371750013842 小时前
Google 正在“收紧侧加载”:陌生 APK 安装或需等待 24 小时
android·前端
蓝帆傲亦2 小时前
Web 前端搜索文字高亮实现方法汇总
前端
用户69371750013842 小时前
Room 3.0:这次不是升级,是重来
android·前端·google
漫随流水3 小时前
旅游推荐系统(view.py)
前端·数据库·python·旅游
踩着两条虫5 小时前
VTJ.PRO 核心架构全公开!从设计稿到代码,揭秘AI智能体如何“听懂人话”
前端·vue.js·ai编程
jzlhll1236 小时前
kotlin Flow first() last()总结
开发语言·前端·kotlin
用头发抵命6 小时前
Vue 3 中优雅地集成 Video.js 播放器:从组件封装到功能定制
开发语言·javascript·ecmascript
蓝冰凌6 小时前
Vue 3 中 defineExpose 的行为【defineExpose暴露ref变量】详解:自动解包、响应性与实际使用
前端·javascript·vue.js
奔跑的呱呱牛7 小时前
generate-route-vue基于文件系统的 Vue Router 动态路由生成工具
前端·javascript·vue.js