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

news2025/7/8 18:17:13

实现效果

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

实现过程

<!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>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2334667.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

字符串与栈和队列-算法小结

字符串 双指针 反转字符串(双指针) 力扣题目链接 void reverseString(vector<char>& s) {for (int i 0, j s.size() - 1; i < s.size()/2; i, j--) {swap(s[i],s[j]);} }反转字符串II 力扣题目链接 遍历字符串的过程中&#xff0c;只要让 i (2 * k)&#…

类似东郊到家的上门按摩预约服务系统小程序APP源码全开源

&#x1f525; 为什么上门按摩正在席卷全国&#xff1f; 万亿蓝海市场爆发 2024年中国按摩市场规模突破8000亿&#xff0c;上门服务增速达65% 90后成消费主力&#xff0c;**72%**白领每月至少使用1次上门按摩&#xff08;数据来源&#xff1a;艾媒咨询&#xff09; 传统痛点…

Python | 在Pandas中按照中值对箱形图排序

箱形图是可视化数据分布的强大工具&#xff0c;因为它们提供了对数据集内的散布、四分位数和离群值的洞察。然而&#xff0c;当处理多个组或类别时&#xff0c;通过特定的测量&#xff08;如中位数&#xff09;对箱形图进行排序可以提高清晰度并有助于揭示模式。在本文中&#…

游戏引擎学习第215天

总结并为今天做铺垫 今天的工作内容是解决调试系统中的一个小问题。昨天我们已经完成了大部分的调试系统工作&#xff0c;但还有一个小部分没有完全处理&#xff0c;那就是关于如何层次化组织数据的问题。我们遇到的一个问题是&#xff0c;演示代码中仍有一个尚未解决的部分&a…

【Redis】redis事物与管道

Redis 事务&#xff08;Transaction&#xff09; 事务概念 事务&#xff1a;是一组操作的集合&#xff0c;是不可分割的工作单元。Redis 事务特点&#xff1a; 一个事务可以一次执行多个命令。所有命令都被顺序化&#xff0c;形成一个队列。所有命令在执行 EXEC 时一次性、顺…

Django信号使用完全指南示例

推荐超级课程: 本地离线DeepSeek AI方案部署实战教程【完全版】Docker快速入门到精通Kubernetes入门到大师通关课AWS云服务快速入门实战目录 **引言:****先决条件:****目录:****1. 什么是Django信号?****2:设置你的Django项目****2.1. 安装Django**2.2. 创建一个Django项…

vulkanscenegraph显示倾斜模型(5.9)-vsg中vulkan资源的编译

前言 上一章深入剖析了GPU资源内存及其管理&#xff0c;vsg中为了提高设备内存的利用率&#xff0c;同时减少内存(GPU)碎片&#xff0c;采用GPU资源内存池机制(vsg::MemoryBufferPools)管理逻辑缓存(VkBuffer)与物理内存(VkDeviceMemory)。本章将深入vsg中vulkan资源的编译(包含…

今日行情明日机会——20250409

今日行情还需要考虑关税对抗~ 2025年4月8日涨停的主要行业方向分析 1. 军工&#xff08;19家涨停&#xff09; 细分领域&#xff1a;国防装备、航空航天、军民融合。催化因素&#xff1a;国家安全战略升级、国防预算增加、重大军工项目落地预期。 2. 免税&#xff08;15家涨…

系统分析师(六)-- 计算机网络

概述 TCP/IP 协议族 DNS DHCP 网络规划与设计 逻辑网络设计 物理网络设计 题目 层次化网络设计 网络冗余设计 综合布线系统 IP地址 网络接入技术 其他网络技术应用 物联网

Qwen2.5-VL Technical Report 论文翻译和理解

一、TL&#xff1b;DR Qwen2.5-VL是QwenVL的最新模型&#xff0c;在视觉识别、精准目标定位、稳健文档解析以及长视频理解等方面实现了重大突破引入了动态分辨率处理和绝对时间编码&#xff0c;使其能够处理不同尺寸的图像以及长达数小时的视频&#xff0c;并实现秒级事件定位…

Foxmail邮件客户端跨站脚本攻击漏洞(CNVD-2025-06036)技术分析

Foxmail邮件客户端跨站脚本攻击漏洞&#xff08;CNVD-2025-06036&#xff09;技术分析 漏洞背景 ‌漏洞编号‌&#xff1a;CNVD-2025-06036 ‌CVE编号‌&#xff1a;待分配 ‌厂商‌&#xff1a;腾讯Foxmail ‌影响版本‌&#xff1a;Foxmail < 7.2.25 ‌漏洞类型‌&#x…

高并发内存池(三):PageCache(页缓存)的实现

前言&#xff1a; 在前两期内容中&#xff0c;我们深入探讨了内存管理机制中在 ThreadCache 和 CentralCache两个层级进行内存申请的具体实现。这两层缓存作为高效的内存分配策略&#xff0c;能够快速响应线程的内存需求&#xff0c;减少锁竞争&#xff0c;提升程序性能。 本期…

Linux驱动开发-网络设备驱动

Linux驱动开发-网络设备驱动 一&#xff0c;网络设备总体结构1.1 总体架构1.2 NAPI数据处理机制 二&#xff0c;RMII和MDIO2.1 RMII接口2.2 MDIO接口 三&#xff0c;MAC和PHY模块3.1 MAC模块3.2 PHY模块 四&#xff0c;网络模型4.1 网络的OSI和TCP/IP分层模型4.1.1 传输层&…

DataEase同比环比

DataEase同比环比 前言术语实现表结构设计DataEase设计创建数据集创建仪表盘最后前言 某大数据项目,需要比较展示今年跟去年的数据,如下图: 说明:比较24,25的产品销量,相同月份做一组,并排放一块 还有更进一步: 说明:比较24,25相同月份,相同产品的销量 直接用DataE…

RAG 工程基础

RAG 概念 RAG&#xff08;Retrieval - Augmented Generation&#xff09;技术是一种将检索与生成相结合的人工智能技术&#xff0c;旨在利用外部知识源来增强语言模型的生成能力&#xff0c;提高生成内容的质量、准确性和相关性。 具体来说&#xff0c;RAG 技术在处理用户输入的…

基础算法:滑动窗口_python版本

能使用滑动窗口的题&#xff0c;基本都需要数字为正整数&#xff0c;这样才能保证滑入一个数字总和是增加的(单调性) 一、209. 长度最小的子数组 思路&#xff1a; 已每个位置为右端点&#xff0c;依次加大左端点&#xff0c;最短不满足 sum(num[left,right]) < target的。…

Qt 之opengl shader language

着色器示例代码 实际运行效果

PyRoboPlan 库,给 panda 机械臂微分 IK 上大分,关节限位、碰撞全不怕

视频讲解&#xff1a; PyRoboPlan 库&#xff0c;给 panda 机械臂微分 IK 上大分&#xff0c;关节限位、碰撞全不怕 代码仓库&#xff1a;https://github.com/LitchiCheng/mujoco-learning 今天分享PyRoboPlan库&#xff0c;比之前的方式优点在于&#xff0c;这个库考虑了机械…

GPT - TransformerDecoderBlock

本节代码定义了一个 TransformerDecoderBlock 类&#xff0c;它是 Transformer 架构中解码器的一个基本模块。这个模块包含了多头自注意力&#xff08;Multi-Head Attention&#xff09;、前馈网络&#xff08;Feed-Forward Network, FFN&#xff09;和层归一化&#xff08;Lay…

LabVIEW 控制电机需注意的关键问题

在自动化控制系统中&#xff0c;LabVIEW 作为图形化编程平台&#xff0c;因其高度可视化、易于集成硬件等优势&#xff0c;被广泛应用于电机控制场景。然而&#xff0c;要实现稳定、精确、高效的电机控制&#xff0c;仅有软件并不足够&#xff0c;还需结合硬件选型、控制逻辑设…