HTML5 游戏开发实战 | 俄罗斯方块_俄罗斯方块h5,大数据开发自定义View详解-程序员宅基地

技术标签: 2024年程序员学习  html5  前端  html  

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新大数据全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip204888 (备注大数据)
img

正文

■ 图6 L形方块下落前和下落后

定位和旋转形状

1. 定位

上面说到每个形状都是在自己的坐标系里面描述的,另外还有一个屏幕上的全局坐标系,用来给形状定位,这样就需要一个方法将形状的4个点从自身坐标系转换到屏幕上的全局坐标系,从而给形状定位。

假如S形在自身坐标系中4个点的坐标为:[[0,-1],[0,0],[-1,0],[-1,1]]。它当前在屏幕上全局坐标系位置为:[12,8],则4个点转换为全局坐标系的坐标为:[[0+12,-1+8],[0+12,0+8],[-1+12,0+8],[-1+12,1+8]]。这样,就完成了S形的全局坐标转换。

这里需要注意一个问题,形状自身坐标系是用(x,y)描述的,而全局坐标系为了逻辑上更直观,是用(row,col)描述的,所以在实际编程中并不是像上面那样转换的,而是:[[-1+12,0+8],[0+12,0+8],[0+12,-1+8],[1+12,-1+8]]即先将x变为col,y变为row,再转换为全局坐标系。

2. 旋转

旋转是在形状的自身坐标系中围绕形状的原点完成的,其公式很简单,每个点旋转后的坐标与旋转前的坐标的关系如下(向右旋转)。

x’=y

y’=-x

注意,正方形形状不发生旋转。

根据上面的分析,可以使用两个全局方法,用来对形状进行全局定位和旋转。

translate(data.row.col)函数将形状自身的坐标系转换为屏幕的全局坐标系,(row,col)为当前形状原点在屏幕中的位置。

function translate(data,row,col)(
var copy=[];
for(var i= 0;i< 4;i++){
   var temp ={
   ;temp.row = data[i][1] + row;temp.col = data[i][0]+ col;copy.push(temp);
return copy;

每种形状向右旋转就会形成一个新的形状,rotate(data)函数可以得到当前形状的方块旋转后的坐标数组。

//向右旋转形状:x'= y,y'= -xfunction rotate(data)!
var copy=[[],[],[][]];for(var i= 0;i<4;i++)
copy[i][0]= data[i][1];copyl[i][1]= -data[i][0];
return copy;

3. 游戏流程

俄罗斯方块游戏就是用一个定时器控制方块下落并重绘的过程,用户可以利用键盘输入改变方块状态。每隔一定的时间就重画当前下落方块和lines存储的固定方块,从而看到动态游戏效果。

俄罗斯方块下落过程中可能遇到种种情况。例如,是否需要消行,是否需要终止下落并且产生新的形状的方块等。具体的判断流程如下:首先判断是否可以继续下落,可以下落则row++即可;如果方块不能够继续下落,则将当前形状的方块添加到面板二维数组lines中,界面产生新的形状的方块。然后,判断是否需要消行。最后,请求重新绘制屏幕。

02、俄罗斯方块游戏设计的步骤

游戏页面index.html

<html>
< head >
< title></title><meta http - equiv= "Content - Type" content = "text/html; charset = UTF - 8">< script type = "text/javascript" language = "javascript" src = "jsgame. js"> </script></head >
< body >
<audio src ="Kalimba.mp3” id = "snd">你的浏览器不支持 audio 标记
</audio >
<canvas id= "html5 09 1"width= "260"heght = "400"style= "background- color: Black">你的浏览器不支持 Canvas 标记,请使用 Chrome 览器或者 Eirefox 浏览器/canvas>
<canvas id= "html5 09 2"width= "100"height = "100" style = "background- color: red">你的浏览器不支持 Canvas 标记,请使用 Chrome 浏览器或者 Erefox 浏览器/canvas><p /
<div id="textmsg">分数</div>
<input type ="button"value ="开始”onclick ="start()”/><input type ="button”id="btnPause"value="暂停"onclick = "pause()"/>< script type ="text/javascript">

设计脚本

1. 设计方块类Block

方块类Block中定义方块的类型ID,存储方块的形状二维数组data以及颜色。设计了将形状自身的坐标系转换为屏幕的坐标系的translate(row,col)函数,参数(row,col)为当前形状方块的原点在屏幕Map中的位置。rotate()函数可以获取当前形状方块旋转后的坐标数组。

x
*方块类
*说明:各种形状的方块
function Block(
//this.data=[[],[],[],[]];
Block.prototype.Block = function ()this.born();
//产生一个新的形状方块Block.prototype.born = function () //随机选择一个形状this.shape id = Math.floor(Math.random() * 7)+1;this.data = Shapes[ this.shape id];this.color = Colors[ this.shape id];console.log(this.data);
//产生1~7的数
//存储方块部件的形状
//存储方块部件的颜色
//将形状自身的坐标系转换为屏幕 Map 的坐标系//(row,col)为当前形状的方块的原点在 Map 中的位置Block.prototype.translate = function (row,col)var copy=[l;
for(var i=0;i<4;i++) (
var temp =;
temp.row = this.datali][1] + row;
temp.col = this.datalill0]+ col;
copy.push(temp)
return copy;
//向右旋转一个形状:x'= y,y'= -x,得到旋转后的 dataBlock.prototype.rotate = function (){var copy=[[],[],[],[]];for(var i=0;i<4; i++) !copy[i][0]= this.datal i][1];copy[ i][1]=- this.datailol;
return copy;

另外,程序中将各方块形状编号:Z形编号1,S形编号2,竖条形编号3,T形编号4,正方形编号5,L形编号6,反L形编号7。所有方块的形状采用数组Shapes存储。通过编号从数组Shapes中获取方块的形状信息。

//每一格的间距,即一个小方块的尺寸Spacing=20;
//各种形状的编号,0 代表没有形状
NoShape = 0;
ZShape = 1;
SShape = 2;
LineShape = 3;
IShape = 4;
SquareShape = 5;
LShape = 6;
MirroredLShape = 7
//各种形状的数据描述
Shapes =
[[O,0],[0,0],[0,0],[0,0]],[[O,-1],[0,0],[-1,0],[-1,1]],
[[o,-1],[0,0],[1,0],[1,1]],[[O,-1],[0,0],[0,1],[0,2]][[-1,0],[0,0],[1,0],[0,1]],[[O,0],[1,0],[0,1],[1,1]],[[-1,-1],[0,-1],[0,0],[0,1]],[[1,-1],[0,-1],[0,0],[0,1]]
//各种形状的颜色
Colors =["black""fuchsia","#cff","red","orange","aqua","green","yellow"l;

2. 设计游戏容器Map类

游戏容器Map类是游戏实例,应先定义游戏面板大小,在游戏面板中存储所有方块的“容器”——二维数组lines,初始时每个元素存储为NoShape(0),表示此格子处无方块。

*
* Map类说明:由m行 Line 组成的格子阵*
function Map(w,h) [
//游戏区域的长度和宽度
this.width = w;
this.height = h;
//生成 height 个 line 对象,每个 line 宽度为 widththis.lines =];for(var row= 0; row < h; row++this.lines[row]= this.newLine():
//说明:由 n个格子组成的一行Map.prototype.newLine = function ()var shapes =;for(var col= 0; col < this.width; col++)shapes[ col]= NoShape;return shapes;

isFullLine (row)函数判断一行是否全部被占用(满行),如果有一个格子为 NoShape 则返回 False。

Map.prototype.isFullLine = function (row) !var line = this.lines row];for(var col= 0; col < this.width; col++ )if(line[col]== NoShape)return false
return true;

预先移动或者旋转形状,调用isCollide(data)函数分析形状中的4个点是否有以下碰撞情况。

(1) col<0 || col>this.width,说明超出左右边界。

(2) row==this.height,说明形状已经到最底部。

(3) 任意一点的shape_id不为NoShape,则发生碰撞。

如果发生碰撞,则放弃移动或者旋转。

Map.prototype.isCollide = function (data)for(var i=0;i<4;i++)fvar row = data il.row;var col = data[i].col;//console.log(row,col);if(col < 0col== this.width) return true;if(row == this.height) return true;
if(row <0) continue;
else
if(this.lines[row][col  != 0)//NoShapereturn true;
return false;

形状在向下移动的过程中发生碰撞,appendShape=function (shape_id,data)则将形状加入lines容器中固定下来。

Map.prototype.appendShape = function( shape id,data)
//对于形状的 4个点
for(var i=0;i<4;i++)/
var row = datai].row;
var col = datalil.col;
//找到所在的格子,将格子的颜色改为形状的颜色
this.lines[row][col]= shape id;
//形状被加入 lines 容器中后,要进行逐行检测,发现满行则消除for(var row = 0; row < this.height; row++)
if(this.isFullLine(row)) 
//绘制消除效果
onClearRow(row);
/将满行删除
this.lines.splice(row,1);
//第一行添加新的一行
this.lines.unshift(this.newLine());

3. 设计游戏逻辑类GameModel

游戏逻辑类GameModel实现游戏控制,首先定义游戏面板map、当前的俄罗斯方块currentBlock、下一个的俄罗斯方块nextBlock以及当前的俄罗斯方块所在位置等。

function GameModel(w,h)
this.map = new Map(w,h);
this.currentBlock = new Block();
this.currentBlock.Block();
this.row = 1;
this.col= Math.floor(this.map.width / 2);this.nextBlock = new Block();
//当前的俄罗斯方块
//当前的俄罗斯方块所在位置(顶端中央)
//下一个俄罗斯方块
this.nextBlock.Block();

其次调用CreateNewBlock()函数产生新的俄罗斯方块。它先复制下一个形状this.nextBlock,再产生下一个俄罗斯方块。

GameModel.prototype.CreateNewBlock = function()
this.currentBlock = this.nextBlock;
this.row = 1;
this.col = Math.floor(this.map.width / 2);
//复制预览区形状
//重置形状的位置为出生地点(顶端中央)
this.nextBlock = new Block();
this.nextBlock.Block();

以下是控制形状方块左右移动、旋转和下移,并且保证左右移动时和lines中存储的固定方块、边界不碰撞。如果碰撞则恢复数据放弃移动。

//向左移动
GameModel.prototype.left = function()
this.col-- ;var temp = this.currentBlock.translate(this.row,this.col);if(this.map.isCollide(temp))
//发生碰撞则放弃移动
this.col++;
//通知数据发生了更新
else
onUpdate();
//向右移动
GameModel.prototype.right = function()this.col++;
var temp= this.currentBlock.translate(this.row,this.col);if(this.map.isCollide(temp))this.col-- ;
else
onUpdate();

同样保证旋转时和lines中存储的固定方块、边界不碰撞。如果碰撞则恢复数据放弃旋转。

//旋转
GameModel.prototype.rotate = function()
//正方形不旋转
if(this.currentBlock.shape id== SquareShape) return;//获得旋转后的数据
var copy = this.currentBlock.rotate();
//转换坐标系
var temp = this.currentBlock.translate(this.row, this.col);//发生碰撞则放弃旋转
if(this.map.isCollide(temp))
return;
//将旋转后的数据设为当前数据this.currentBlock.data = copy;//通知数据发生了更新

方块下落需判断是否“触底”或接触到其他已落方块。如果“触底”则固定到游戏面板上,此时要处理满行和游戏结束的判断,同时产生新的俄罗斯方块。

//下落
GameModel.prototype.down = function()
var old= this.currentBlock.translate(this.row,this.col);this.row++ ;
var temp= this.currentBlock.translate(this.row,this.col);if(this.map.isCollide(temp)) //发生碰撞则放弃下落this.row-- ;//如果在 1 也无法下落,则说明游戏结束if(this.row== 1)(
//通知游戏结束
onGameOver();
return;
//无法下落则将当前形状加入 Map 中this.map.appendShape(this.currentBlock.shape id,old);this.CreateNewBlock();
//产生新的俄罗斯方块
//通知数据发生了更新
onUpdate();

4. 游戏主程序

在定时事件中,完成下落功能。

var display = document.getElementById("htm15 09 1");var display2 = document.getElementById("htm15_09 2");
var model = null;
//游戏面板//预览区域
var loop interval= null;
var tick interval = null:
var waiting = false;
var speed = 500;
v珠跋糊傲安把奥樊喽唉哎啊爱碍暗跋拔敖稗傲八core = 0;
var textmsg = document.getElementById("textmsg”);function start)!
model = new GameModel(display.width / Spacing,display.height / Spacing);loop(;
function pause()waiting =!waiting;if(waiting)document.getElementById("btnPause").value ="继续”;else
document.getElementById("btnPause").value ="暂停”;
//消息循环function loop(){tick interval= setInterval(function()if(waiting) return;onTick() ;
//时钟事件即下落

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注大数据)
img

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

lue ="暂停”;
//消息循环function loop(){tick interval= setInterval(function()if(waiting) return;onTick() ;
//时钟事件即下落




**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注大数据)**
[外链图片转存中...(img-lNoZp5OO-1713298322991)]

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/2401_84185106/article/details/137849940

智能推荐

使用IPSET屏蔽美国IP_ipset封禁国外ip-程序员宅基地

文章浏览阅读387次,点赞6次,收藏8次。最近被美国IP盯上了,瞄的不间断攻击ADD-TO-CART页面。记录下用IPSET屏蔽过程。执行如下脚本,将IP地址段中的记录转换为Ipset指令,保存在。_ipset封禁国外ip

nodejs的字符串操作模块_nodejs 字符串操作模块-程序员宅基地

文章浏览阅读3.2w次。nodejs字符串操作简介需要引入querystring对象,querystring对象的方法有stringifyquerystring.stringify(“对象”,“分隔符”,“分配符”),将一个json对象,转为字符串,通过指定的分隔符,以及分配符 具体代码:var querystring = require('querystring');var result = querystring.s_nodejs 字符串操作模块

李宏毅机器学习笔记第1周-机器学习基本概念_anomaly compression-程序员宅基地

文章浏览阅读855次。机器学习基本概念_anomaly compression

MD5碰撞-程序员宅基地

文章浏览阅读9.4k次,点赞29次,收藏109次。在CTF中可以说是经常碰到md5加密了,一般都是进行强比较抑或是弱比较,考法非常多,但是万变不离其中。只要我们掌握了原理,一切问题便迎刃而解了。文章首发于我的博客,格式可能比较清晰,有兴趣了解CTF中MD5碰撞的伙伴可以移步查看。_md5碰撞

普里姆算法c语言(详细解读)_c语言普里姆算法-程序员宅基地

文章浏览阅读854次,点赞5次,收藏12次。找到与这个系统邻接的边(0,1),(5,4),比较两者的权值,容易发现权值最小的为25,因此加入边(5,4),同时加入结点4和边(5,4)。4.将0,5,4,3以及相关的边看成一个整体,与其邻接的边有(0,1)28,(4,6)24,(3,6)18,(3,2)12,四个边中权值最小的边是(3,2),所以加入结点2以及边(3,2)。5.与4中所构成的整体邻接的边有(0,1)28,(4,6)24,(3,6)18,(2,1)16,四者中权值最小的边为(2,1),所以加入结点1以及边(2,1)。_c语言普里姆算法

nohub 和 & 在linux上不间断后台运行程序-程序员宅基地

文章浏览阅读3.1k次,点赞2次,收藏15次。长时间在服务器上运行深度学习代码,使用nohub 命令行 & 可以让代码不间断在后台运行_nohub

随便推点

docker配置国内镜像源_docker国内镜像源-程序员宅基地

文章浏览阅读3.3w次,点赞9次,收藏25次。刚开始学习docker,发现下载镜像非常的慢。如果不经过,docker的镜像下载都来源于国外,因此需要配置国内的镜像源。Docker中国区官方镜像。_docker国内镜像源

Unity中怎么播放视频_unity 播放视频-程序员宅基地

文章浏览阅读1.9w次,点赞40次,收藏209次。一.首先在场景中新建UI中的Raw Image可以按住Alt再点击下图红色箭头所示将Raw Image铺满游戏全屏(也可以自己调整大小)二.给Raw Image添加Video Player组件三.在Assets或者自己想要的文件夹中创建Render Texture四.将准备好的视频(这里用到的视频格式是mp4)拖入项目中并做如下修改这里我把新建的Render Texture命名为2,拖入的视频也命名为2(随便命的,不要在意)这里我们看到这个Render Te..._unity 播放视频

使用BOOTICE 恢复系统启动项_bootice保存后没用-程序员宅基地

文章浏览阅读9.7k次,点赞2次,收藏9次。使用BOOTICE 恢复系统启动项我在安装deepin 系统的时候,经常遇到重启进不去系统,每次重启都会进入windows 系统,这让我感到特别头疼,试了好多次都不成功,有些情况是,成功后再次重启又回到了windows系统。后来终于在PE中利用一款叫做BOOT ICE的工具成功解决。BOOTICE— 引导扇区维护工具简介BOOTICE 是一个启动相关的维护的小工具,主要用于安装、修复、备份和恢复磁盘_bootice保存后没用

文本分类与SVM_svm分类-程序员宅基地

文章浏览阅读9.5w次,点赞54次,收藏202次。之前做过一些文本挖掘的项目,比如网页分类、微博情感分析、用户评论挖掘,也曾经将libsvm进行包装,写了一个文本分类的开软软件Tmsvm。所以这里将之前做过一些关于文本分类的东西整理总结一下。1 基础知识1. 1 样本整理文本分类属于有监督的学习,所以需要整理样本。根据业务需求,确定样本标签与数目,其中样本标签多为整数。在svm中其中如果为二分类,样本标签一般会设定为-1和_svm分类

力扣——206.反转链表_力扣链表反转-程序员宅基地

文章浏览阅读141次。题目python代码方法一:利用新列表,创建新的链表# Definition for singly-linked list.# class ListNode(object):# def __init__(self, val=0, next=None):# self.val = val# self.next = nextclass Solution(object): def reverseList(self, head): ""_力扣链表反转

如何解决深度冲突(Z-fighting),画面闪烁的问题-程序员宅基地

文章浏览阅读3.6k次,点赞3次,收藏6次。参考:OpenGL教程:深度测试深度冲突一个很常见的视觉错误会在两个平面或者三角形非常紧密地平行排列在一起时会发生,深度缓冲没有足够的精度来决定两个形状哪个在前面。结果就是这两个形状不断地在切换前后顺序,这会导致很奇怪的花纹。这个现象叫做深度冲突(Z-fighting),因为它看起来像是这两个形状在争夺(Fight)谁该处于顶端。防止深度冲突第一个也是最重要的技巧是永远不要把多个物体摆得太靠近,以至于它们的一些三角形会重叠。通过在两个物体之间设置一个用户无法注意到的偏移值,你可以完全避免这两个物体之_深度冲突

推荐文章

热门文章

相关标签