当前位置:网站首页>大道至简 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
边栏推荐
- Free patent download tutorial (HowNet, Espacenet)
- 这个项目可以让你在几分钟快速了解某个编程语言
- Custom function form of pychar shortcut key
- Mongodb (from 0 to 1), 11 days mongodb primary to intermediate advanced secret
- The choice of enterprise database is usually decided by the system architect - the newstack
- In order to save money, I learned PHP in one day!
- Skywalking series blog 5-apm-customize-enhance-plugin
- Face to face Manual Chapter 16: explanation and implementation of fair lock of code peasant association lock and reentrantlock
- Natural language processing - BM25 commonly used in search
- Python filtering sensitive word records
猜你喜欢
比特币一度突破14000美元,即将面临美国大选考验
Construction of encoder decoder model with keras LSTM
Brief introduction of TF flags
NLP model Bert: from introduction to mastery (2)
华为云“四个可靠”的方法论
Wow, elasticsearch multi field weight sorting can play like this
The road of C + + Learning: from introduction to mastery
I think it is necessary to write a general idempotent component
[JMeter] two ways to realize interface Association: regular representation extractor and JSON extractor
Jetcache buried some of the operation, you can't accept it
随机推荐
Common algorithm interview has been out! Machine learning algorithm interview - KDnuggets
Analysis of etcd core mechanism
vue-codemirror基本用法:实现搜索功能、代码折叠功能、获取编辑器值及时验证
Python filtering sensitive word records
Face to face Manual Chapter 16: explanation and implementation of fair lock of code peasant association lock and reentrantlock
IPFS/Filecoin合法性:保护个人隐私不被泄露
5.4 static resource mapping
Skywalking series blog 5-apm-customize-enhance-plugin
如何玩转sortablejs-vuedraggable实现表单嵌套拖拽功能
What is the difference between data scientists and machine learning engineers? - kdnuggets
Save the file directly to Google drive and download it back ten times faster
6.5 request to view name translator (in-depth analysis of SSM and project practice)
Wechat applet: prevent multiple click jump (function throttling)
一篇文章带你了解CSS3 背景知识
Cglib 如何实现多重代理?
快速排序为什么这么快?
Jetcache buried some of the operation, you can't accept it
Individual annual work summary and 2019 work plan (Internet)
Lane change detection
Natural language processing - BM25 commonly used in search