当前位置:网站首页>大道至简 html + js 实现最朴实的小游戏俄罗斯方块
大道至简 html + js 实现最朴实的小游戏俄罗斯方块
2020-11-06 21:04:00 【kingapple】
前言
老实说这其实这是自己写的第二个俄罗斯方块。
本次的重写,除了复习一下以前自己写的代码的同时,也加有了一些新的思考。
其中最重要的一个目的就是渲染层与逻辑层在代码层面的分离(重新设计代码)。
——最终效果图如下。
正题
来看下一下俄罗斯方块的一些概念与逻辑
一、方块
最传统的俄罗斯方块,只有7个方块。
通常由T、I、Z、S、L、J、O这7个字母代替。
转换成代码如下。
shaps = {
'I': [
[1, 1, 1, 1],
],
'L': [
[1, 1, 1],
[1, 0, 0],
],
'J': [
[1, 1, 1],
[0, 0, 1],
],
'Z': [
[1, 1, 0],
[0, 1, 1],
],
'S': [
[0, 1, 1],
[1, 1, 0],
],
'T': [
[1, 1, 1],
[0, 1, 0],
],
'O': [
[1, 1],
[1, 1],
],
};
enumShaps = {
'I': [
[[0,0],[1,0],[2,0],[3,0]],
[[1,-1],[1,0],[1,1],[1,2]],
],
'L':[
[[0,0],[1,0],[2,0],[0,1]],
[[0,0],[1,0],[1,1],[1,2]],
[[2,0],[0,1],[1,1],[2,1]],
[[0,0],[0,1],[0,2],[1,2]],
],
'J':[
[[0,0],[1,0],[2,0],[2,1]],
[[1,0],[1,1],[1,2],[0,2]],
[[0,0],[0,1],[1,1],[2,1]],
[[0,0],[1,0],[0,1],[0,2]],
],
'Z':[
[[0,0],[1,0],[1,1],[2,1]],
[[1,0],[1,1],[0,1],[0,2]],
],
'S':[
[[1,0],[2,0],[0,1],[1,1]],
[[0,0],[0,1],[1,1],[1,2]],
],
'T':[
[[0,0],[1,0],[2,0],[1,1]],
[[1,-1],[1,0],[1,1],[0,0]],
[[0,0],[1,0],[2,0],[1,-1]],
[[1,-1],[1,0],[1,1],[2,0]],
],
'O':[
[[1,0],[2,0],[1,1],[2,1]],
],
};
上面代码有两组方块。(矩阵型,没举型)
两者没有直接联系,是旋转方块衍生的两种思路。
两者最大的区别在于,第一组矩阵型方块的旋转需要相关算法进行换算,相对复杂。
而第二组,已经将美中方块的旋转结果枚举出来,更佳便于理解。
第一种方块选装
let shapData = shaps['T']
// 用算法旋转矩阵
shapData = matirx2dRotation(shapData)
const shapRender = (vector) => {
// 与枚举型略有不同
}
第二种方块旋转
// 比如下面代码接可以直接去除T方块的其中一个旋转数据
// 这个数据中的各个矢量再加上方块的场景中的方块偏移量就是方块的渲染数据了
const shapData = enumShaps['T'][1]
// vector 偏移量(就是方块在场景中的位置信息)
const shapRender = (vector) => {
return shapData.map(([x, y]) => [x + X, y + Y]);
}
以上完整代码在底部仓库地址中
二、碰撞与逻辑
标准的情况,场景中只有唯一一个方块收到玩家操作。
玩家操作的方块在游戏开始后便生成并交与玩家控制权。
玩家控制的方块,每当玩家操作反馈后进行碰撞逻辑的检测。
这里的操作反馈主要是方块左、右、下移动与旋转。
- 方块是否溢出场景(场景左右与底部边界碰撞)
- 方块是否碰撞场景中静止的方块
每次游戏心跳间隔,还需要将当前玩家控制的方块下降一格。
其中不论是玩家主动方块下降或是游戏心跳间隔中自动将方块下降。都需要检测是否与场景底部或其它静止方块发生碰撞与否。
如果碰撞成立,则将当前方块加入静止方块序列。
这时候就可以执行小方块的逻辑。
消玩方块后需要将空缺出来的位置补上。
最后生成一个新的方块加入到场景中。
新的方块进入场景的同时,需要立即检测与静止方块的碰撞。如果为真则游戏是否game over。
// 方块静止逻辑
const isShapDead = vector => {
// ...如果为真便加入到静止方块的序列
}
// 是否溢出场景
// 不需要检测顶部
const isOverFlow = vectors => {
const [width, height] = screenSize;
return vectors.some(([x, y]) => {
return x < 0 || x >= width || y >= height;
});
}
// 是否发生碰撞
const isShapHit = vectors => {
// ...
}
// 游戏是否失败
const isGameOver = data => {
// 方块初始位置矢量
const [, y] = vector;
if (y <= 0 && isShapHit(data)) {
return true;
}
return false;
}
以上完整代码在底部仓库地址中
三、渲染层与逻辑层分离
每一次游戏心跳,与每一次用户操作反馈会触发渲染
或许是做前后端分离有些时日了,多少受了虚拟dom的一点影响。
重新设计的代码,将游戏的整个过程虚拟化。
只在每一个心跳(类似游戏中帧的概念)或者用户每次主动操作后才会推送游戏虚拟数据到渲染层,由渲染层实现渲染逻辑。
// TetrisJS 整个游戏的逻辑代码
const TJS = new TetrisJS({
screenSize,
intervals: 1000,
});
// update 的回调函中接受渲染请求的推送
TJS.update(() => {
// TJS.map就是游戏的虚拟数据
renderGame(TJS.map)
});
const renderGame = data => {
// render 渲染逻辑
}
最后上仓库代码(以上代码基于此)https://github.com/applelee/tetris-js.git
老代码(慎点)https://github.com/applelee/tetris-js-old.git
版权声明
本文为[kingapple]所创,转载请带上原文链接,感谢
https://my.oschina.net/u/1243524/blog/4540920
边栏推荐
- ES6学习笔记(五):轻松了解ES6的内置扩展对象
- Vuejs development specification
- 一篇文章带你了解CSS 渐变知识
- Solve the problem of database insert data garbled in PL / SQL developer
- Synchronous configuration from git to consult with git 2consul
- 仅用六种字符来完成Hello World,你能做到吗?
- ES6学习笔记(二):教你玩转类的继承和类的对象
- Python download module to accelerate the implementation of recording
- Vue.js Mobile end left slide delete component
- The choice of enterprise database is usually decided by the system architect - the newstack
猜你喜欢
Three Python tips for reading, creating and running multiple files
PN8162 20W PD快充芯片,PD快充充电器方案
DRF JWT authentication module and self customization
How to customize sorting for pandas dataframe
一篇文章教会你使用Python网络爬虫下载酷狗音乐
快速排序为什么这么快?
Network security engineer Demo: the original * * is to get your computer administrator rights! 【***】
Word segmentation, naming subject recognition, part of speech and grammatical analysis in natural language processing
Tool class under JUC package, its name is locksupport! Did you make it?
Construction of encoder decoder model with keras LSTM
随机推荐
一篇文章带你了解HTML表格及其主要属性介绍
ES6学习笔记(五):轻松了解ES6的内置扩展对象
Wechat applet: prevent multiple click jump (function throttling)
Python基础数据类型——tuple浅析
Python基础变量类型——List浅析
If PPT is drawn like this, can the defense of work report be passed?
零基础打造一款属于自己的网页搜索引擎
每个前端工程师都应该懂的前端性能优化总结:
After reading this article, I understand a lot of webpack scaffolding
Pattern matching: The gestalt approach一种序列的文本相似度方法
Python download module to accelerate the implementation of recording
6.2 handleradapter adapter processor (in-depth analysis of SSM and project practice)
有了这个神器,快速告别垃圾短信邮件
小程序入门到精通(二):了解小程序开发4个重要文件
仅用六种字符来完成Hello World,你能做到吗?
From zero learning artificial intelligence, open the road of career planning!
Python filtering sensitive word records
Arrangement of basic knowledge points
Did you blog today?
Analysis of ThreadLocal principle