上一章讲述马里奥跳跃动作和刹车的动作,本章对Json文件改动较多,我会一一讲解,还涉及到了部分代码重构

本章的提交ID:7419c4a70c772a45795d20ceb6559c1e1e8d8e3a

github地址:ainuo5213的超级马里奥

本节目录

目录讲解:

1. loaders/level.js:原loadLevelAsync方法和loadTiles方法移动到了单独的文件,用于单独生成loadLevelAsync

实现效果

layers.js文件改动

layers.js将原本用于获取TileResolver从实例中改为了创建实例,并且使用外部传入的tiles,在redraw方法中用于清空当前临时创建的bufferContext的内容,避免重复渲染

Level.js改动

Level.js去掉了tiles、tileCollider的初始化操作,暴露一个方法用于设置马里奥碰撞检测实例和tiles

loader.js改动

loader.js删掉了loadTiles、loadLevelAsync方法,将loadJson暴露了出去

,供loader/level.js使用

TilCollider碰撞检测实例改动

因之前遗漏,这里改动一下name为type

1-1关卡数据json改动

1-1.json改动都标有注释,各位可以尝试理解一下

{"spriteSheet": "overworld",// 模式,用于16x16单位的多个元素拼凑而成的图片生成"patterns": {// 云,云被划分为了6个单位,上面3个,下面三个"cloud-single": {"tiles": [{"name": "cloud-1-1","ranges": [[0, 0]]},{"name": "cloud-1-2","ranges": [[1, 0]]},{"name": "cloud-1-3","ranges": [[2, 0]]},{"name": "cloud-2-1","ranges": [[0, 1]]},{"name": "cloud-2-2","ranges": [[1, 1]]},{"name": "cloud-2-3","ranges": [[2, 1]]}]},// 水管体,水管体被划分为了2个单位,左边一个,右边一个"pipe-section-vert": {"tiles": [{"name": "pipe-vert-left","type": "ground","ranges": [[0, 0]]},{"name": "pipe-vert-right","type": "ground","ranges": [[1, 0]]}]},// 水管帽子被划分为了2个单位,左边一个,右边一个"pipe-cap-vert": {"tiles": [{"name": "pipe-insert-vert-left","type": "ground","ranges": [[0, 0]]},{"name": "pipe-insert-vert-right","type": "ground","ranges": [[1, 0]]}]},// 高度为2的水管,被划分为了2个,上边1个单位是水管帽,下边1个单位是水管体"pipe-2h": {"tiles": [{"pattern": "pipe-cap-vert","ranges": [[0, 0]]},{"pattern": "pipe-section-vert","ranges": [[0, 1,1, 1]]}]},// 高度为3的水管,被划分为了2个,上边1个单位是水管帽,下边2个单位是水管体"pipe-3h": {"tiles": [{"pattern": "pipe-cap-vert","ranges": [[0, 0]]},{"pattern": "pipe-section-vert","ranges": [[0, 1,1, 2]]}]},// 高度为4的水管,被划分为了2个,上边1个单位是水管帽,下边3个单位是水管体"pipe-4h": {"tiles": [{"pattern": "pipe-cap-vert","ranges": [[0, 0]]},{"pattern": "pipe-section-vert","ranges": [[0, 1,1, 3]]}]}},// 背景渲染部分,整合了之前的backgrounds,并加入了水管(2h、3h、4h)和云"layers": [{"tiles": [{"name": "sky","ranges": [[0, 212,0, 13]]},{"name": "ground","type": "ground","ranges": [[0, 212,13, 2]]},{"name": "sky","ranges": [[75, 2,13, 2],[92, 2,13, 2],[157, 2,13, 2]]},{"name": "ground","type": "ground","ranges": [[5, 3,9, 1],[29, 5],[5, 7,9],[12, 6,11, 1],[2, 1,11, 1],[10, 2,10, 1],[10, 2,10],[9, 1,0, 7]]}]},{"tiles": [{"name": "bricks","type": "ground","ranges": [[27, 5,9],[83, 3,9],[86, 6,5],[96, 3,5],[99, 9],[105, 2,9],[123, 5],[126, 3,5],[132, 4,5],[133, 2,9],[171, 4,9]]},{"name": "chance","type": "ground","ranges": [[2, 2],[23, 9],[28, 9],[30, 9],[29, 5],[84, 9],[99, 5],[114, 5],[111, 9],[114, 9],[117, 9],[133, 2, 5],[173, 9]]},{"name": "chocolate","type": "ground","ranges": [[141, 1, 9],[140, 2, 10],[139, 3, 11],[138, 4, 12],[144, 1, 9],[144, 2, 10],[144, 3, 11],[144, 4, 12],[155, 2, 9],[154, 3, 10],[153, 4, 11],[152, 5, 12],[159, 1, 9],[159, 2, 10],[159, 3, 11],[159, 4, 12],[191, 2, 5],[190, 3, 6],[189, 4, 7],[188, 5, 8],[187, 6, 9],[186, 7, 10],[185, 8, 11],[184, 9, 12]]},{"pattern": "pipe-2h","ranges": [[35, 11],[167, 11],[182, 11]]},{"pattern": "pipe-3h","ranges": [[45, 10]]},{"pattern": "pipe-4h","ranges": [[53, 9],[64, 9]]},{"pattern": "cloud-single","ranges": [[2, 2],[25, 2],[35, 3],[44, 2],[64, 3],[74, 2],[80, 3],[90, 2],[108, 3],[118, 2],[128, 3],[138, 2]]}]}]
}

overworld.json地图切片数据改动

地图切片数据加入了6个单位的云和4个单位的水管,用于切不同的16x16的方格进行渲染,所以说云占6个单位,长3宽2等

loader/level.js

loader/level.js是之前loadTiles和loadAsync的整合,并进行部分优化,将每个循环拆分到了外部,降低主代码区的代码长度,利于维护和扩展

import { createBackgroundLayer, createrSpriteLayer } from "../layers.js";
import { Matrix } from "../Math.js";
import { Level } from "../Level.js";
import { loadJson, loadSpriteSheet } from "../loader.js";export function loadLevelAsync(name) {return loadJson(`/src/levels/${name}.json`).then(data => Promise.all([data, loadSpriteSheet(data.spriteSheet)])).then(([levelJson, backgroundSprite]) => {const level = new Level();// 加载level中的matrix每一个格子的数据到tilesconst mergedTiles = levelJson.layers.reduce((mergedTiles, layer) => {return mergedTiles.concat(layer.tiles);}, []);// 动态设置level的碰撞检测类const collisionGrid = createCollisionGrid(mergedTiles, levelJson.patterns);level.setCollisionGrid(collisionGrid);levelJson.layers.forEach(layer => {const backgroundGrid = createBackgroundGrid(layer.tiles, levelJson.patterns);const backgroundLayer = createBackgroundLayer(level, backgroundGrid, backgroundSprite);level.compositor.layers.push(backgroundLayer);})// 创建马里奥图像的回调const marioSpriteLayer = createrSpriteLayer(level.entities);level.compositor.layers.push(marioSpriteLayer);return level;})
}// 一个range范围内的x和y对象集合
function* expandSpan(xStart, xLen, yStart, yLen) {const xEnd = xStart + xLen;const yEnd = yStart + yLen;for (let x = xStart; x < xEnd; x++) {for (let y = yStart; y < yEnd; y++) {yield { x, y };}}
}// 展开一个range,原range.forEach...
function expandRange(range) {// 修改渲染逻辑: 当配置中的range为4位数,则其分别为x位置开始xStart、x方向渲染长度xLen、y位置开始yStart、y方向渲染长度yLen//             当配置中的range为2位数,则其分别为x位置开始xStart、y位置开始yStart,此时yLen、xLen均为1//             当配置中的range为3位数,则其分别为x位置开始xStart、x方向渲染长度xLen、y位置开始yStart,此时yLen为1if (range.length === 4) {const [xStart, xLen, yStart, yLen] = range;return expandSpan(xStart, xLen, yStart, yLen);} else if (range.length === 2) {const [xStart, yStart] = range;return expandSpan(xStart, 1, yStart, 1);} else if (range.length === 3) {const [xStart, xLen, yStart] = range;return expandSpan(xStart, xLen, yStart, 1);}
}// 展开多个ranges(原tile.ranges.forEach...)
function* expandRanges(ranges) {for (const range of ranges) {for (const item of expandRange(range)) {yield item}}
}// 展开tiles为制定格式的对象的数组(如果该元素是pattern,就继续展开pattern对应的那个对象知道展开到底)
function expandTiles(tiles, patterns) {const expandedTiles = [];function walkTiles(tiles, offsetX, offsetY) {for (const tile of tiles) {for (const { x, y } of expandRanges(tile.ranges)) {const derivedX = x + offsetX;const derivedY = y + offsetY;if (tile.pattern) {const tiles = patterns[tile.pattern].tiles;walkTiles(tiles, derivedX, derivedY);} else {expandedTiles.push({tile,x: derivedX,y: derivedY});}}}}walkTiles(tiles, 0, 0);return expandedTiles;
}// 循环遍历展开了的tiles,生成matrix
function createCollisionGrid(tiles, patterns) {const matrix = new Matrix();for (const { tile, x, y } of expandTiles(tiles, patterns)) {matrix.set(x, y, {type: tile.type,name: tile.name});}return matrix;
}// 循环遍历展开了的tiles,生成matrix
function createBackgroundGrid(tiles, patterns) {const matrix = new Matrix();for (const { tile, x, y } of expandTiles(tiles, patterns)) {matrix.set(x, y, {type: tile.type,name: tile.name,});}return matrix;
}

本节代码重构较多,大家多多理解重构部分

原生JS超级马里奥(第九天)相关推荐

  1. 原生JS超级马里奥(第五天)

    上一章讲的是键盘事件监听,实现马里奥的跳跃功能,本章讲述马里奥和大地(砖块)的碰撞检测,代码有点多,原视频长度差不多1个小时20分钟,大家可以看原视频进行理解,边看边敲,我在这里写的代码和注释仅我自己 ...

  2. 原生JS超级马里奥(第三天)

    上一章主要是绘制马里奥和绘制图像代码的部分重构 本章主要是用于时间控制,实现马里奥每次弹跳的定点和弹跳起点一致,对源代码拆分比较多,各位可以跟着原作者视频一起敲 本章的提交ID:90dc4d0a02c ...

  3. 原生JS超级马里奥(第一天)

    这段时间心血来潮,在网上找了一大堆前端关于游戏制作的博客,诸如飞机大战.魂斗罗等,但是个人思维限制,可能想的不是很多.很全面,最终放弃了个人独立开发的打算.皇天不负有心人,最终在youtube上找到了 ...

  4. 原生JS超级马里奥(第四天)

    上一章讲的是马里奥速度改变的事件控制,本章改动较多,例如将马里奥位置改变拆分为一个一个的特征类,还有键盘事件监听,实现马里奥的跳跃功能,各位可以跟着原作者视频一起敲 本章的提交ID:e5caf33c8 ...

  5. 原生JS超级马里奥(第八天)

    上一章讲述马里奥前进和后退动画以及其他一些动画,本章讲述马里奥跳跃动作和刹车的动作 本章的提交ID:493f38d8628e5beaa23c72ff6c38f76e46fa5b3a github地址: ...

  6. 前端原生js实现图片轮播效果,超级简单,备注详细

    原生js实现简单轮播图,效果如下 纯生js实现轮播图 链接: link. 图片: 我们可以通过左右两边的箭头来播放图片,在我们的鼠标放在图片上时,自动播放结束,转化为手动播放,可以通过小圆点来点击切换 ...

  7. 总结获取原生JS(javascript)的父节点、子节点、兄弟节点

    关于原生JS获取节点,一直是个头疼的问题,而且调用方法的名字又贼长了,所以我选择用JQ,好像跑题了-- 话不多说看代码 获取父节点 及 父节点下所有子节点(兄弟节点) <ul><li ...

  8. gdiplus判断一个点是否在圆弧线上_面试前必读!!!原生JS补给(上)

    前言 你盼世界,我盼望你无bug.Hello 大家好!我是霖呆呆! 几个月前看过一遍三元大佬的<(建议收藏)原生JS灵魂之问, 请问你能接得住几个?>[¹]系列,当时是利用上下班公交的时间 ...

  9. 星级评价的代码php,JavaScript_使用jQuery实现星级评分代码分享,前面有一篇原生js实现星级评 - phpStudy...

    使用jQuery实现星级评分代码分享 前面有一篇原生js实现星级评分 .可能覆盖面不是很广,现在给出一个jquery实现的星级评分. http://s.thsi.cn/js/jquery-1.7.2. ...

最新文章

  1. 网管员应掌握好的学习方法
  2. UIImageView图片视图的基本概念和使用方法
  3. 配置zabbix监控windows,cmd运行报错cannot connect to Service Manager: [0x00000005]
  4. [JavaWeb-XML]XML_解析_解析方式
  5. OpenShift v3:使用WildFly和MySQL的Java EE 7入门
  6. 《jQuery基础》总结
  7. 登录后 可编辑页面 php,如何查找和编辑登录的php页面以及更改详细信息 - WordPress - srcmini...
  8. Unity中的场景切换
  9. preg_replace的一些细节
  10. selenium学习过程中遇到的问题
  11. Android中加载ETC2压缩格式(PKM后缀)纹理
  12. Google开发者账号申请
  13. 手机的内核版本、基带版本等都是什么意思?
  14. Nginx神来之笔,提高并发原来如此简单
  15. 三菱je -c中映射表的作用_最新款中东版三菱帕杰罗V93 现车热卖
  16. 清北学堂2019.8.9
  17. modelsim仿真加速注意点
  18. 【转载】哪些域名后缀可在工信部进行备案操作
  19. 都说岁月不饶人,我们又何曾饶过岁月
  20. 分布式系统以及分布式系统架构的优缺点

热门文章

  1. 亚马逊推广六步,迅速打造爆款。
  2. 【已阅】man,cp,mv,alias,more,less,head,tail指令与文件片段读取和管道的初步介绍
  3. 鸿蒙心理测评中心,最近很火的心理测试:你第一眼看到的是什么?测出你的背后隐藏性格!...
  4. 哪款蓝牙耳机颜值比较高?高颜值蓝牙耳机盘点
  5. java Integer值比较
  6. 知了堂|给你一个网站你是如何来渗透测试的?(信安面试题)
  7. thinkpad怎么把计算机设置到桌面,教你thinkpad桌面设置为纯色以及macbook笔记本怎么...
  8. Android 实现倒计时动画效果
  9. HTML5新增内容元素和表单控件
  10. hexo+yilia添加版权声明