当前位置:网站首页>Road to simple HTML + JS to achieve the most simple game Tetris
Road to simple HTML + JS to achieve the most simple game Tetris
2020-11-06 21:04:00 【kingapple】
Preface
To be honest, this is actually the second Tetris I wrote .
This rewrite , Besides reviewing the code I wrote before , There are also some new ideas .
One of the most important purposes is to separate the rendering layer from the logic layer at the code level ( Redesign the code ).
—— The final effect is as follows .
On the subject
Take a look at some of the concepts and logic of Tetris
One 、 square
The most traditional Tetris , Only 7 Square block .
Usually by T、I、Z、S、L、J、O this 7 One letter instead of .
Convert to code as follows .
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]],
],
};
The code above has two sets of squares .( Matrix , No lift )
There is no direct connection between the two , They are two ideas derived from rotating squares .
The biggest difference between the two is , The rotation of the first group of matrix blocks needs to be converted by relevant algorithms , Relatively complex .
And the second group , We have enumerated the rotation results of U.S. and Chinese squares , Better to understand .
The first box option
let shapData = shaps['T']
// Rotate the matrix by algorithm
shapData = matirx2dRotation(shapData)
const shapRender = (vector) => {
// It's a little different from enumeration
}
The second kind of square rotation
// For example, the following code can be directly removed T One of the rotation data of the square
// Each vector in this data plus the square offset in the scene of the block is the rendering data of the block
const shapData = enumShaps['T'][1]
// vector Offset ( It's the location of the square in the scene )
const shapRender = (vector) => {
return shapData.map(([x, y]) => [x + X, y + Y]);
}
The above complete code is in the bottom warehouse address
Two 、 Collision and logic
The standard situation , Only one square in the scene receives player action .
The player's box is generated and handed over to the player after the game begins .
Player controlled squares , Every time the player operates feedback, the collision logic is detected .
The operation feedback here is mainly on the left side of the block 、 Right 、 Move down and rotate .
- Whether the square overflows the scene ( The left and right sides of the scene collide with the bottom boundary )
- Whether the square collides with the static square in the scene
Every game heartbeat interval , You also need to drop the block controlled by the current player by one space .
Whether it is the player's active block drop or the game heartbeat interval will automatically drop the box . We need to detect whether it collides with the bottom of the scene or other static squares .
If the collision holds up , Add the current block to the static block sequence .
At this point, you can execute the logic of the small block .
You need to fill the vacant position after playing the square .
Finally, a new box is generated and added to the scene .
As the new box enters the scene , You need to detect collisions with still squares immediately . If true, then the game is game over.
// Block static logic
const isShapDead = vector => {
// ... If true, it is added to the sequence of static squares
}
// Whether it overflows the scene
// No need to detect the top
const isOverFlow = vectors => {
const [width, height] = screenSize;
return vectors.some(([x, y]) => {
return x < 0 || x >= width || y >= height;
});
}
// Is there a collision
const isShapHit = vectors => {
// ...
}
// Whether the game fails
const isGameOver = data => {
// Square initial position vector
const [, y] = vector;
if (y <= 0 && isShapHit(data)) {
return true;
}
return false;
}
The above complete code is in the bottom warehouse address
3、 ... and 、 The rendering layer is separated from the logic layer
Every time the game beats , With every user action feedback will trigger rendering
Maybe it's been separating the front and back for some time , A little bit virtual dom A little bit of an impact on .
Redesigned code , Virtualize the whole process of the game .
Only in every heartbeat ( Similar to the concept of frames in the game ) Or the user will push the game virtual data to the rendering layer after each active operation , The rendering logic is implemented by the render layer .
// TetrisJS The logic code of the whole game
const TJS = new TetrisJS({
screenSize,
intervals: 1000,
});
// update To accept the push of the rendering request in the callback letter of
TJS.update(() => {
// TJS.map It's the virtual data of the game
renderGame(TJS.map)
});
const renderGame = data => {
// render Rendering logic
}
Finally, code the warehouse ( The above code is based on this )https://github.com/applelee/tetris-js.git
Old code ( Be careful )https://github.com/applelee/tetris-js-old.git
版权声明
本文为[kingapple]所创,转载请带上原文链接,感谢
边栏推荐
- An article takes you to understand CSS pagination examples
- How about small and medium-sized enterprises choose shared office?
- Introduction to Google software testing
- Junit测试出现 empty test suite
- 游戏开发中的新手引导与事件管理系统
- Git rebase is in trouble. What to do? Waiting line
- ES6 learning notes (3): teach you to use js object-oriented thinking to realize the function of adding, deleting, modifying and checking tab column
- Some operations kept in mind by the front end foundation GitHub warehouse management
- es创建新的索引库并拷贝旧的索引库 实践亲测有效!
- electron 實現檔案下載管理器
猜你喜欢
事务的本质和死锁的原理
Flink's datasource Trilogy 2: built in connector
游戏开发中的新手引导与事件管理系统
ES6 learning notes (4): easy to understand the new grammar of ES6
window系统 本机查找端口号占用方法
2020年第四届中国 BIM (数字建造)经理高峰论坛即将在杭举办
Use modelarts quickly, zero base white can also play AI!
StickEngine-架构12-通信协议
Bitcoin once exceeded 14000 US dollars and is about to face the test of the US election
游戏主题音乐对游戏的作用
随机推荐
【字节跳动 秋招岗位开放啦】Ohayoo!放学别走,我想约你做游戏!!!
Can you do it with only six characters?
Analysis of serilog source code -- how to use it
Zero basis to build a web search engine of its own
嘉宾专访|2020 PostgreSQL亚洲大会阿里云数据库专场:王涛
【:: 是什么语法?】
游戏主题音乐对游戏的作用
行为型模式之解释器模式
Markdown tricks
华为云微认证考试简介
Contract trading system development | construction of smart contract trading platform
Network programming NiO: Bio and NiO
如何对数据库账号权限进行精细化管理?
Behind the record breaking Q2 revenue of Alibaba cloud, the cloud opening mode is reshaping
How to turn data into assets? Attracting data scientists
【自学unity2d传奇游戏开发】如何让角色动起来
Elasticsearch database | elasticsearch-7.5.0 application construction
How to understand Python iterators and generators?
How to hide part of barcode text in barcode generation software
hdu3974 Assign the task線段樹 dfs序