推箱子游戏JS实现

2023-05-16

参考以下教学视频编写

教学视频:Canvas画布实现推箱子游戏-HTML5前端设计JavaScript原生开发_哔哩哔哩_bilibili

箱子地图

Boxdata.js

//1:围墙 2:目标点 3:箱子 4:角色 5:在目标点的箱子
var levels = [];
levels[0]=[
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0],
    [0,0,0,0,0,1,2,0,0,0,1,0,0,0,0,0],
    [0,0,0,0,0,1,0,3,0,4,1,0,0,0,0,0],
    [0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0],
    [0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0],
    [0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
]

1.地图绘制

pushBox.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="Boxdata.js"></script>
</head>
<body>
    <canvas id="mycanvas" height="800" width="800">     
    </canvas>
    <script>
        /** @type {HTMLCanvasElement} */
        var canv = document.getElementById("mycanvas");
        var ctx = canv.getContext("2d");

        var level = levels[0];

        var g={
            wall:{color:'#333',data:[]},
            target:{color:'#9f3',data:[]},
            box:{color:'rgba(255,50,0,0.8)',data:[]},
            player:{color:'rgba(255,220,0,0.8)',data:[]}
        }

        var objects = ['wall','target','box','player'];

        for(let i=0;i<16;i++){
            for(let j=0;j<16;j++){
                let d=level[i][j];
                let id = i*16+j;
                if(d>0){
                    if(d==5){
                        g['target'].data.push(id);
                        g['box'].data.push(id);
                    }else{
                        g[objects[d-1]].data.push(id);
                    }
                }
            }
        }

      g['wall'].data.forEach(n=>drawRRect('wall',n))
      g['target'].data.forEach(n=>drawRRect('target',n))
      g['box'].data.forEach(n=>drawRRect('box',n))
      g['player'].data.forEach(n=>drawRRect('player',n))
      
     
// 绘制圆角矩形
       function drawRRect(object,id){
           let w = 800/16,r=5,m=2;
           let [x,y] = [id%16*w,~~(id/16)*w]; //~~取整
           ctx.save();
           if(object=='target'){
               r=24              
           }
           ctx.beginPath();
           ctx.moveTo(x,y+r);
           ctx.arcTo(x,y+w-m,x+w-m,y+w-m,r);
           ctx.arcTo(x+w-m,y+w-m,x+w-m,y+w-m-r,r);
           ctx.arcTo(x+w-m,y,x,y,r);
           ctx.arcTo(x,y,x,y+w-m,r);
           ctx.fillStyle=g[object].color;
           ctx.fill();
           ctx.restore();
       }
    </script>
</body>
</html>

2.移动玩家角色

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="Boxdata.js"></script>
</head>
<body>
    <canvas id="mycanvas" height="800" width="800">     
    </canvas>
    <script>
        /** @type {HTMLCanvasElement} */
        var canv = document.getElementById("mycanvas");
        var ctx = canv.getContext("2d");
 
        var level = levels[0];
 
        var g={
            wall:{color:'#333',data:[]},
            target:{color:'#9f3',data:[]},
            box:{color:'rgba(255,50,0,0.8)',data:[]},
            player:{color:'rgba(255,220,0,0.8)',data:[]}
        }
 
        var objects = ['wall','target','box','player'];
 
        for(let i=0;i<16;i++){
            for(let j=0;j<16;j++){
                let d=level[i][j];
                let id = i*16+j;
                if(d>0){
                    if(d==5){
                        g['target'].data.push(id);
                        g['box'].data.push(id);
                    }else{
                        g[objects[d-1]].data.push(id);
                    }
                }
            }
        }
 
      g['wall'].data.forEach(n=>drawRRect('wall',n))
      g['target'].data.forEach(n=>drawRRect('target',n))
      g['box'].data.forEach(n=>drawRRect('box',n))
      g['player'].data.forEach(n=>drawRRect('player',n))
      
     
        // 绘制圆角矩形
       function drawRRect(object,id){
           let w = 800/16,r=5,m=2;
           let [x,y] = [id%16*w,~~(id/16)*w]; //~~取整
           ctx.save();
           if(object=='target'){
               r=24              
           }
           ctx.beginPath();
           ctx.moveTo(x,y+r);
           ctx.arcTo(x,y+w-m,x+w-m,y+w-m,r);
           ctx.arcTo(x+w-m,y+w-m,x+w-m,y+w-m-r,r);
           ctx.arcTo(x+w-m,y,x,y,r);
           ctx.arcTo(x,y,x,y+w-m,r);
           ctx.fillStyle=g[object].color;
           ctx.fill();
           ctx.restore();
       }

       //添加键盘监听
       document.addEventListener('keydown',ev=>{
           //方向键,根据方向键,dir移动的id
           let dir = [-1,-16,1,16][ev.keyCode-37]
           console.log(ev.code,ev.keyCode,dir)
           let player = g.player.data[0]
           let index = g['player'].data.indexOf(player)
           console.log(player,index)
           move('player',player,dir)
       })

       //移动玩家角色和箱子
       function move(who,id,dir){
            let next = id+dir
            let index = g[who].data.indexOf(id)
            g[who].data[index]=next
            //重绘地图
            ctx.clearRect(0,0,800,800)
            objects.forEach(obj=>g[obj].data.forEach(n=>drawRRect(obj,n)))
       }
    </script>
</body>
</html>

3. 添加撞墙判断,移动箱子和过关判断

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="Boxdata.js"></script>
</head>
<body>
    <canvas id="mycanvas" height="800" width="800">     
    </canvas>
    <script>
        /** @type {HTMLCanvasElement} */
        var canv = document.getElementById("mycanvas");
        var ctx = canv.getContext("2d");
 
        var level = levels[0];
 
        var g={
            wall:{color:'#333',data:[]},
            target:{color:'#9f3',data:[]},
            box:{color:'rgba(255,50,0,0.8)',data:[]},
            player:{color:'rgba(255,220,0,0.8)',data:[]}
        }
 
        var objects = ['wall','target','box','player'];
 
        for(let i=0;i<16;i++){
            for(let j=0;j<16;j++){
                let d=level[i][j];
                let id = i*16+j;
                if(d>0){
                    if(d==5){
                        g['target'].data.push(id);
                        g['box'].data.push(id);
                    }else{
                        g[objects[d-1]].data.push(id);
                    }
                }
            }
        }
 
      g['wall'].data.forEach(n=>drawRRect('wall',n))
      g['target'].data.forEach(n=>drawRRect('target',n))
      g['box'].data.forEach(n=>drawRRect('box',n))
      g['player'].data.forEach(n=>drawRRect('player',n))
      
     
        // 绘制圆角矩形
       function drawRRect(object,id){
           let w = 800/16,r=5,m=2;
           let [x,y] = [id%16*w,~~(id/16)*w]; //~~取整
           ctx.save();
           if(object=='target'){
               r=24              
           }
           ctx.beginPath();
           ctx.moveTo(x,y+r);
           ctx.arcTo(x,y+w-m,x+w-m,y+w-m,r);
           ctx.arcTo(x+w-m,y+w-m,x+w-m,y+w-m-r,r);
           ctx.arcTo(x+w-m,y,x,y,r);
           ctx.arcTo(x,y,x,y+w-m,r);
           ctx.fillStyle=g[object].color;
           ctx.fill();
           ctx.restore();
       }
 
       //添加键盘监听
       document.addEventListener('keydown',ev=>{
           //方向键,根据方向键,dir移动的id
           let dir = [-1,-16,1,16][ev.keyCode-37]
           
           let playerid = g.player.data[0]

	   let next = playerid+dir
           
	   //判断是否撞墙	
	   if(g.wall.data.includes(next)) return

	   //判断是否移动箱子	 
	   if(g.box.data.includes(next)){

		let boxid=next
		
		let boxnext = boxid+dir
		
                //判断箱子是否撞墙或撞箱子
		if(g.wall.data.includes(boxnext)||g.box.data.includes(boxnext)) return
		
		move('box',boxid,dir)
			
           }

           //移动玩家角色
           move('player',playerid,dir)

	   //判断游戏结束
	   checkOver()
       })
 
       //移动玩家角色和箱子
       function move(who,id,dir){
            let next = id+dir
            let index = g[who].data.indexOf(id)
	    
            g[who].data[index]=next
	    
            //重绘地图
            ctx.clearRect(0,0,800,800)
            objects.forEach(obj=>g[obj].data.forEach(n=>drawRRect(obj,n)))
       }

	//判断游戏结束
	function checkOver(){
        let win = g.box.data.every(b=>g.target.data.includes(b))
	if(win){
        	setTimeout(()=>{
			alert("恭喜过关!")	
		},100)
	  }
        }
    </script>
</body>
</html>

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

推箱子游戏JS实现 的相关文章

  • 解决第一次使用zookeeper闪退问题

    1 复制zookeeper 3 4 13 conf zoo sample cfg文件 xff0c 改名为zoo cfg 2 windows点击zookeeper 3 4 13 bin zkServer cmd命令启动zookeeper注册中
  • Android 11 update-api 遇到的问题

    1 缺少 非空判断 error log Missing nullability on method 96 getSecurityRestrictPwd 96 return MissingNullability import android
  • linux 文件 目录 默认权限

    结论 在linux系统中任何文件 目录都有一定的权限 xff0c 对于新创建的文件或目录 xff0c 也会有默认的访问权限 可能是出于安全的考虑 xff0c linux系统新建文件默认没有执行权限 xff0c 其最大权限为rw rw rw
  • centos 7 安装xfce 4桌面环境

    默认情况下 xff0c 完整安装的CentOS 7将安装GNOME图形用户界面 xff08 GUI xff09 xff0c 并且将在系统启动后加载 但是 xff0c 如果我们安装的CentOS没有安装GUI xff0c 那么我们总是可以稍后
  • Android 屏幕处于横屏状态 旋转180度界面切换显示

    span span public SreenOrientationListener mSreenOrientationListener span span mSreenOrientationListener 61 new SreenOrie
  • linux 桌面管理器 xfce 用户自动登录

    vi etc lightdm lightdm conf SeatDefaults autologin user 61 username 需要登录的用户名 autologin user timeout 61 delay
  • python 并行计算 pathos模块 简介

    目录 pathos模块 1 pathos自身的多进程方法 xff08 pathos multiprocessing ProcessPool pathos multiprocessing ProcessingPool pathos pools
  • 自然对数的底“e”的由来

    目录 一 神奇的 加减术 二 约翰 纳皮尔 xff08 John Napier xff09 的伟大贡献 发明对数 三 e在哪里 xff1f 是如何出现并逐步确认的呢 xff1f xff08 一 xff09 在制作对数表的过程中更加深入认识e
  • postgresql 报错 FATAL: no pg_hba.conf entry for host 未配置允许远程连接 解决方法

    目录 错误现象 问题原因 解决方案 1 进入到data目录下 xff0c 找到pg hba conf文件 2 修改文件 3 进入到postgres用户下 xff0c 执行命名 4 连接成功 错误现象 问题原因 这是在远程连接时pg hba
  • js javascript 解决 强制关注才能阅读

    问题现象 xff1a 强制关注 才能展开看文章 解决方法 xff1a chrome浏览器 打开文章网页 快捷键F12 然后切换到Console界面 复制一下代码回车 就可以阅读全部文章了 var article content 61 doc
  • linux 查看系统已安装内核

    目录 1 RHEL CentOS Fedora 2 Debian Ubuntu Linux Mint 3 SUSE openSUSE 4 Arch Linux 1 RHEL CentOS Fedora 在终端中执行如下命令查看已安装的 Li
  • win11 报错 你的IT管理员已经限制对此应用一些区域的访问 解决方法

    你的IT管理员已经限制对此应用一些区域的访问 你尝试访问的项目不可用 有关详细 请与你的IT支持人员联系 1 按下win 43 s xff0c 在框中输入cmd xff0c 右键管理员身份运行 2 在命令提示符中输入 reg add HKE
  • HTTPS和HTTP的区别

    什么是 HTTPS HTTPS 基于安全套接字层的超文本传输协议 或者是 HTTP over SSL 是一个 Netscape 开发的 Web 协议 你也可以说 xff1a HTTPS 61 HTTP 43 SSL HTTPS 在 HTTP
  • 正则表达式在线自动生成器

    正则表达式的强大众所周知 xff0c 它令程序员的头痛程度也数一数二的 最近我发现了一个网站 xff0c txt2re xff0c 能够自动为你生成正则表达式 xff0c 而且很灵活 xff0c 在这里推荐一下 网址 https www t
  • transfer-encoding:chunked的含义

    Transfer Encoding chunked 表示输出的内容长度不能确定 xff0c 普通的静态页面 图片之类的基本上都用不到这个 但动态页面就有可能会用到 xff0c 但我也注意到大部分asp php asp net动态页面输出的时
  • 回首2013,展望2014

    此刻值此2013年末 xff0c 明天便是元旦 近日浏览CSDN论坛时 xff0c 发现有许多的坛友都在写2013年度总结 xff0c 博客作为个人的名片 xff0c 也决定开始尝试写博客 xff0c 我的第一篇博客就是关于2013年度总结
  • i tell you 微软各种 操作系统 应用程序 开发工具 下载

    I tell you 提供微软系各种操作系统 xff08 win7 xp win10 xff09 应用程序 xff08 office project visio等 xff09 开发人员工具 xff08 visual C 43 43 visu
  • docker 设置国内镜像源

    目录 国内加速地址 修改方法 国内加速地址 1 Docker中国区官方镜像 https registry docker cn com 2 网易 http hub mirror c 163 com 3 ustc https docker mi
  • Docker网络代理设置

    背景 在一些实验室环境 xff0c 服务器没有直接连接外网的权限 xff0c 需要通过网络代理 我们通常会将网络代理直接配置在 etc environment etc profile之类的配置文件中 xff0c 这对于大部分操作都是可行的

随机推荐

  • android布局优化(ViewStub)

    页面中有些布局在初始化时没必要显示 xff0c 但是又不得不事先在布局文件中写好 xff0c 虽然设置成了invisible或gone xff0c 但是在初始化时还是会加载 xff0c 这无疑会影响页面加载速度 针对这一情况 xff0c A
  • iOS类似Android的ViewPager

    WhdeViewPager 类似安卓的 ViewPager Android ViewPager GitHub https github com whde WhdeViewPager 效果如下 使用 viewPager 61 WhdeView
  • ubuntu怎么切换到root用户,切换到root账号方法

    ubuntu怎么切换到root用户 xff0c 使用su root命令 xff0c 去切换到root权限 xff0c 会提示输入密码 xff0c 可是如何也输不对 xff0c 提示 Authentication failure 或者是提示认
  • left join 基本用法

    废话不多说 xff0c 来看例子 一 建表 xff0c 导入测试数据 create table temp1 aid VARCHAR2 5 not null car VARCHAR2 10 not null create table temp
  • Ubuntu系统与Linux常用命令

    目录 一 Ubuntu系统 xff1a 1 Ubuntu目录的简介2 Ubuntu与人交互3 人与Linux系统进行交互1 如何打开一个终端 xff1a 2 终端命令提示 4 Ubuntu命令的组成1 命令目的 xff1a 2 命令的格式
  • STM32串口打印输出乱码的解决办法

    前言 最近在试用uFUN开发板 xff0c 下载配套的Demo程序 xff0c 串口数据输出正常 xff0c 当使用另一个模板工程 xff0c 调用串口printf调试功能时 xff0c 输出的却是乱码 xff0c 最后发现是外部晶振频率不
  • 扬州大学信息工程学院2022届考研情况分析(主要针对专业课为858程序设计与数据结构的专业)

    作者 xff1a 64 江上 酒 23扬大信工考研交流群 xff1a 714584589 今年初试专业课为858程序设计与数据结构的人数达475人 xff0c 进入复试的共计118人 xff08 含计科 软工及电子信息各个方向 xff09
  • Android(12)浅析 偏好设置 Preference(一)

    Android 12 浅析 偏好设置 Preference xff08 一 xff09 官方基本用法 xff1a https developer android google cn guide topics ui settings 效果演示
  • 扬州大学信息工程学院2023届考研情况分析(针对858计算机专业基础的所有考生)

    扬州大学信息工程学院2023届考研情况分析 xff08 针对858计算机专业基础的所有考生 xff09 作者 xff1a 64 江上 酒 24扬大信工考研交流群 xff1a 714584589 进入复试的基本要求及各方向招生的详细计划如下图
  • Spring启动类源码学习小记

    现在面试Java 的 xff0c 都必备SpringBoot了 xff0c 一说SpringBoot xff0c 面试官又喜欢问底层 xff0c 我也是这种形式主义的受害者之一 xff0c 但是还别说 xff0c 自从看了底层源码 xff0
  • 电脑桌面美化(Win10)

    这是你的电脑桌面 而有人的桌面是这样的 这样的 有的人会把桌面图标放到dock栏里 xff0c 再把任务栏变成透明的 xff0c 再换个动态壁纸 xff0c 在加个频谱听听音乐 各种花里胡哨的 xff0c 是不是很羡慕 而电脑桌面完全取决于
  • 总结2014——迷茫以及迷茫过后的坚持

    首先 xff0c 借用一句话和大家共勉 xff1a 少一些功利主义的追求 xff0c 多一些不为什么的坚持 xff01 xff01 不知不觉15年也快过了1个月了 xff0c 还是想着要为14年做一下总结 xff1a 记录一下自己的历程 今
  • 无人机运动学控制中的坐标系,及惯性坐标系与机体坐标系之间的矩阵转换 欧拉角

    一 无人机控制中的坐标系 无人机运动学中 xff0c 有三种需要了解的坐标系 1 1 地球中心坐标系 xff08 ECEF xff09 地球中心坐标系 xff0c 即坐标系原点位于地心 X轴通过格林尼治线和赤道线的交点 xff0c 正方向为
  • 无人机飞控算法-姿态估计-欧拉角-旋转矩阵-四元数

    无人机飞控算法 姿态估计 此系列记录了我理解的卡尔曼滤波从0到1的过程 xff0c 从姿态估计到位置估计 xff0c 我们从核心点一个个出发 xff0c 并结合实际模块的应用来一一揭开卡尔曼滤波的神秘面纱 提示 xff1a 在系列文章中 x
  • bash下变量PS1的完整理解

    本文并不会讲解如何设置PS1以获得你喜欢的提示符 xff1b 本文会围绕PS1这个变量 xff0c 就其涉及到的一些概念展开讨论 导言 ubuntu 的默认 shell 是 bash xff0c bash 下有个变量 PS1 xff0c 我
  • 我的世界Mod整合包中的Mod下载

    MC中Mod整合包有时通过启动器无法正常安装 xff0c 此时可以其中通过提供的manifest json文件获取其在curseforge网站中的信息 文件中的projectID是Mod的ID fileID是对应版本文件的ID 通过这两个值
  • 使用OpenCV给图片添加Logo

    import cv2 import numpy as np imgcat 61 cv2 imread 34 d img cat jpg 34 imglogo 61 cv2 imread 34 d img logo jpg 34 imglog
  • Minecraft中Python编程

    安装Raspberry Jam Mod Raspberry Jam Mod是arpruss为Minecraft开发的插件 xff0c 在PC版Minecraft中的实现了树莓派版的Python接口 可以从这里下载最新版本 作者提供了自动安装
  • 打开AS提示错误弹框缺少com.android.tools.design.org.jetbrains.android插件

    打开AS提示错误弹框缺少com android tools design org jetbrains android插件 今个准备升级一下AS来着 xff0c 然后出现了这个问题 xff0c 原因是我屏蔽了Kotlin插件 解决方法 xff
  • 推箱子游戏JS实现

    参考以下教学视频编写 教学视频 xff1a Canvas画布实现推箱子游戏 HTML5前端设计JavaScript原生开发 哔哩哔哩 bilibili 箱子地图 Boxdata js 1 xff1a 围墙 2 xff1a 目标点 3 xff