当前位置: 首页 > news >正文

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>

相关文章:

  • 分子束全息光刻技术是啥?能用来干啥?
  • OpenAI即将上线新一代重磅选手——GPT-4.1
  • go:实现最简单区块链
  • DFS中return的作用
  • NO.91十六届蓝桥杯备战|图论基础-图的存储和遍历|邻接矩阵|vector|链式前向星(C++)
  • 学习MySQL的第八天
  • BERT - BertTokenizer, BertModel API模型微调
  • 基于docker搭建redis集群环境
  • 【Python Requests 库详解】
  • IP组播技术与internet
  • 按规则批量修改文件扩展名、删除扩展名或添加扩展名
  • day30-贪心__452. 用最少数量的箭引爆气球__435. 无重叠区间__763.划分字母区间
  • 用Python修改字体字形与提取矢量数据:fontTools实战指南
  • 【数据分析实战】使用 Matplotlib 绘制折线图
  • 算法训练之动态规划(五)——简单多状态问题
  • 【辰辉创聚生物】提供上万种单抗/多抗及其偶联物
  • 程序加壳脱壳原理和实现
  • P3367 【模板】并查集
  • 【局域网】
  • 记 etcd 无法在docker-compose.yml启动后无法映射数据库目录的问题
  • ps做的网站保存不了jpg/web个人网站设计代码
  • 南昌企业自助建站/网站长尾关键词排名软件
  • 网站如何做担保交易/李飞seo
  • 网站地区词优化/百度灰色关键词排名
  • 注册网站租空间哪里租/2021最新免费的推广引流软件
  • 什么浏览器不限制网站/东莞最新疫情