第一次写俄罗斯方块的时候已经是1年多前了,也是我刚刚学js不久。
为了加强对js的理解又加上对游戏的爱好,于是在没有参考他人的思路和代码下,自己用最基本的js代码写出了基于canvas的俄罗斯方块。
在大三的暑假,我又用了es6的语法进行了改进,包含了class的语法糖、箭头函数等,进一步增加自己对es6的理解,代码有400+行
想要做这个小游戏,必须先熟悉h5的canvas,js对数组的处理,键盘事件监听和处理,定时器的使用等,其他的就是基本的逻辑处理了。
游戏的规则就是核心,也是我们代码的重中之重
这里的逻辑核心是需要判断方块是否碰撞(当前运动的方块和已经定位好的方块有碰撞以致于当前的运动的方块不能在向下走,因为我们的方块默认是向下走的,如果不能向下走,是视为已经定位好的方块,然后在生成一个新的方块从初始位置继续往下走)。
而且这个碰撞还需要应用在方块变形的时候,同样地,如果方块在变形的过程中和其他定位好的方块进行碰撞,则我们应该阻止这个方块进行变形成功,
附上代码,欢迎讨论和指正
<!doctype html><html lang="en"><head><meta chart="utf-8"><title>es6-重构俄罗斯方块(基于canvas)</title><style type="text/css">#tetris{ margin: 10px 250px;}</style></head><body><canvas width="700" height="525" id="tetri餐厅英语情景对话s"></canvas><div id="text" style='color: red;font-size: 30px;'>当前分数:0</div><script type="text/javascript">/*** [一个完整的俄罗斯方块类 design by magic_xiang]* @param {number} side [每个方块边长(px),默认35]* @param {number} width [一行包含的方块数(个),默认20]* @param {number} height [一列包含的方块数(个),默认15]* @param {number} speed [方块下落移动速度(ms),默认400]*/class tetris{c爱国演讲稿400字onstructor(side=35, width=20, height=15, speed=400){this.side = side // 每个方块边长this.width = width // 一行包含的方块数this.height = height // 一列包含的方块数this.speed = speed // 方块下落移动速度this.num_blcok // 当前方块类型的数字变量this.type_color // 当前颜色类型的字符串变量this.ident // tinterval的标识this.direction = 1 // 方块方向,初始化为1,默认状态 this.grade = 0 // 用来计算分数this.over = fal // 游戏是否结束this.arr_bx = [] // 存放当前方块的x坐标this.arr_by = [] // 存放当前方块的y坐标this.arr_store_x = [] // 存放到达底部所有方块的x坐标this.arr_store_y = [] // 存放到达底部所有方块的y坐标this.arr_store_color = [] // 存放到达底部所有方块的颜色this.paints = document.getelementbyid('tetris').getcontext('2d')//获取画笔lf = this}// 封装paints方法,让代码更简洁paintfr(x, y, scale=1){this.paints.fillrect(x*this.side, y*this.side, scale*this.side, scale*this.side)}// 游戏开始gamestart(){this.init()this.run()}// 初始化工作init(){this.initbackground()this.initblock()}// 方块自动下落run(){this.ident = tinterval("lf.down_speed_up()", this.speed)}// 初始化地图initbackground(){this.paints.beginpath()this.paints.fillstyle='#000000' //地图填充颜色为黑色for(let i = 0; i < this.height; i++){for(let j = 0; j < this.width; j++){this.paintfr(j, i)}}this.paints.clopath()}// 初始化方块的位置和颜色initblock(){this.paints.beginpath()this.createrandom('rcolor') //生成颜色字符串,this.paints.fillstyle = this.type_colorthis.createrandom('rblock') //生成方块类型数字this.arr_bx.foreach((item, index) => {this.paintfr(item, this.arr_by[index], 0.9)})this.paints.clopath()}// 利用数组画方块drawblock(color){this.paints.beginpath()this.paints.fillstyle = colorthis.arr_bx.foreach((item, index) => {this.paintfr(item, this.arr_by[index], 0.9)})this.paints.clopath()}// 画已经在定位好的方块drawstaticblock(){this.arr_store_x.foreach((item, index) => {this.paints.beginpath()this.paints.fillstyle = this.arr_store_color[index]this.paintfr(item, this.arr_store_y[index], 0.9)this.paints.clopath()})}// 生成随机数返回方块类型或颜色类型createrandom(type){let temp = this.width/2-1if (type == 'rblock'){ //如果是方块类型this.num_blcok = math.round(math.random()*4+1)switch(this.num_blcok){ca 1:this.arr_bx.push(t秃废网名emp,temp-1,temp,temp+1)this.arr_by.push(0,1,1,1)breakca 2:this.arr_bx.push(temp,temp-1,temp-1,temp+1)this.arr_by.push(1,0,1,1)breakca 3:this.arr_bx.push(temp,temp-1,temp+1,temp+2)this.arr_by.push(0,0,0,0)breakca 4:this.arr_bx.push(temp,temp-1,temp,temp+1)this.arr_by.push(0,0,1,1)breakca 5:this.arr_bx.push(temp,temp+1,temp,temp+1)this.arr_by.push(0,0,1,1)break}}if (type == 'rcolor'){ //如果是颜色类型let num_color = math.round(math.random()*8+1) switch(num_color){ca 1:this.type_color='#3ef72a'breakca 2:this.type_color='yellow'breakca 3:this.type_color='#2fe0bf'breakca 4:this.type_color='red'breakca 5:this.type_color='gray'breakca 6:this.type_color='#c932c6'breakca 7:this.type_color= '#fc751b'breakca 8:this.type_color= '#6e6edd'breakca 9:this.type_color= '#f4e9e1'break}}}// 判断方块之间是否碰撞(下),以及变形时是否越过下边界judgecollision_down(){for(let i = 0; i < this.arr_bx.length; i++){if (this.arr_by[i] + 1 == this.height){ //变形时是否越过下边界return fal} if (this.arr_store_x.length != 0) { //判断方块之间是否碰撞(下)for(let j = 0; j < this.arr_store_x.length; j++){if (this.arr_bx[i] == this.arr_store_x[j]) {if (this.arr_by[i] + 1 == this.arr_store_y[j]) {return fal}}}} }return true}//判断方块之间是否碰撞(左右),以及变形时是否越过左右边界judgecollision_other(num){for(let i = 0; i < this.arr_bx.length; i++){if (num == 1) { //变形时是否越过右边界if (this.arr_bx[i] == this.width - 1) return fal}if (num == -1) { //变形时是否越过左边界if (this.arr_bx[i] == 0)return fal}if (this.arr_store_x.length != 0) { //判断方块之间是否碰撞(左右)for(let j = 0; j < this.arr_store_x.length; j++){if (this.arr_by[i] == this.arr_store_y[j]) {if (this.arr_bx[i] + num == this.arr_store_x[j]) {return fal}}}}}return true;}//方向键为下的加速函数down_speed_up(){let flag_all_down = trueflag_all_down = this.judgecollision_down()if (flag_all_down) {this.initbackground()for(let i = 0; i < this.arr_by.length; i++){this.arr_by[i] = this.arr_by[i] + 1}}el{for(let i=0; i < this.arr_bx.length; i++){this.arr_store_x.push(this.arr_bx[i])this.arr_store_y.push(this.arr_by[i])this.arr_store_color.push(this.type_color)}this.arr_bx.splice(0,this.arr_bx.length)this.arr_by.splice(0,this.arr_by.length)this.initblock()}this.clearunderblock()this.drawblock(this.type_color)this.drawstaticblock()this.gameover()}//方向键为左右的左移动函数move(dir_temp){this.initbackground()if (dir_temp == 1) { //右let flag_all_right = trueflag_all_right = this.judgecollision_other(1)if (flag_all_right) {for(let i = 0; i < this.arr_by.length; i++){this.arr_bx[i] = this.arr_bx[i]+1}}}el{let flag_all_left = trueflag_all_left = this.judgecollision_other(-1)if (flag_all_left) {for(let i=0; i < this.arr_by.length; i++){this.arr_bx[i] = this.arr_bx[i]-1}}}this.drawblock(this.type_color)this.drawstaticblock()}//方向键为空格的变换方向函数up_change_direction会当凌绝顶一览众山小(num_blcok){ if (num_blcok == 5) {return}let arr_tempx = []let arr_tempy = []//因为不知道是否能够变形成功,所以先存储起来for(let i = 0;i < this.arr_bx.length; i++){ arr_tempx.push(this.arr_bx[i])arr_tempy.push(this.arr_by[i])}this.direction++//将中心坐标提取出来,变形都以当前中心为准let ax_temp = this.arr_bx[0] let ay_temp = this.arr_by[0]this.arr_bx.splice(0, this.arr_bx.length) //将数组清空 this.arr_by.splice(0, this.arr_by.length)if (num_blcok == 1) {switch(this.direction%4){ca 1:this.arr_bx.push(ax_temp,ax_temp-1,ax_temp,ax_temp+1)this.arr_by.push(ay_temp,ay_temp+1,ay_temp+1,ay_temp+1)breakca 2:this.arr_bx.push(ax_temp,ax_temp-1,ax_temp,ax_temp)this.arr_by.push(ay_temp,ay_temp,ay_temp-1,ay_temp+1)breakca 3:this.arr_bx.push(ax_temp,ax_temp-1,ax_temp,ax_temp+1)this.arr_by.push(ay_temp,ay_temp,ay_temp+1,ay_temp)breakca 0:this.arr_bx.push(ax_temp,ax_temp,ax_temp,ax_temp+1)this.arr_by.push(ay_temp,ay_temp-1,ay_temp+1,ay_temp)break}}if (num_blcok == 2) {switch(this.direction%4){ca 1:this.arr_bx.push(ax_temp,ax_temp-1,ax_temp-1,ax_temp+1)this.arr_by.push(ay_temp,ay_temp,ay_temp-1,ay_temp)breakca 2:this.arr_bx.push(ax_temp,ax_temp,ax_temp,ax_temp-1)this.arr_by.push(ay_temp,ay_temp-1,ay_temp+1,ay_temp+1)breakca 3:this.arr_bx.push(ax_temp,ax_temp-1,ax_temp+1,ax_temp+1)this.arr_by.push(ay_temp,ay_temp,ay_temp,ay_temp+1)breakca 0:this.arr_bx.push(ax_temp,ax_temp,ax_temp,ax_temp+1)this.arr_by.push(ay_temp,ay_temp-1,ay_temp+1,ay_temp-1)break}}if (num_blcok == 3) {switch(this.direction%4){ca 1:this.arr_bx.push(ax_temp,ax_temp-1,ax_temp+1,ax_temp+2)this.arr_by.push(ay_temp,ay_temp,ay_temp,ay_temp)breakca 2:this.arr_bx.push(ax_temp,ax_temp,ax_temp,ax_temp)this.arr_by.push(ay_temp,ay_temp-1,ay_temp+1,ay_temp+2)breakca 3:this.arr_bx.push(ax_temp,ax_temp-1,ax_temp+1,ax_temp+2)this.arr_by.push(ay_temp,ay_temp,ay_temp,ay_temp)breakca 0:this.arr_bx.push(ax_temp,ax_temp,ax_temp,ax_temp)this.arr_by.push(ay_temp,ay_temp-1,ay_temp+1,ay_temp+2)break}}if (num_blcok == 4) {switch(this.direction%4){ca 1:this.arr_bx.push(ax_temp,ax_temp-1,ax_temp,ax_temp+1)this.arr_by.push(ay_temp,ay_temp,ay_temp+1,ay_temp+1)breakca 2:this.arr_bx.push(ax_temp,ax_temp,ax_temp+1,ax_temp+1)this.arr_by.push(ay_temp,ay_temp+1,ay_temp,ay_temp-1)breakca 3:this.arr_bx.push(ax_temp,ax_temp,ax_temp-1,ax_temp+1)this.arr_by.push(ay_temp,ay_temp-1,ay_temp,ay_temp-1)breakca 0:this.arr_bx.push(ax_temp,ax_temp,ax_temp+1,ax_temp+1)this.arr_by.push(ay_temp,ay_temp-1,ay_temp,ay_temp+1)break}}if (! (this.judgecollision_other(-1) && this.judgecollision_down() && this.judgecollision_other(1) )) { //如果变形不成功则执行下面代码this.arr_bx.splice(0, this.arr_bx.length) this.arr_by.splice(0, this.arr_by.length)for(let i=0; i< arr_tempx.length; i++){this.arr_bx.push(arr_tempx[i])this.arr_by.push(arr_tempy[i])}}this.drawstaticblock()}//一行满了清空方块,上面方块y坐标+1clearunderblock(){//删除低层方块let arr_row=[]let line_numif (this.arr_store_x.length != 0) {for(let j = this.height-1; j >= 0; j--){for(let i 当你 歌词= 0; i < this.arr_store_color.length; i++){if (this.arr_store_y[i] == j) {arr_row.push(i)}}if (arr_row.length == this.width) {line_num = jbreak}el{arr_row.splice(0, arr_row.length)}}}if (arr_row.length == this.width) {//计算成绩gradethis.grade++document.getelementbyid('text').innerhtml = '当前成绩:'+this.gradefor(let i = 0; i < arr_row.length; i++){this.arr_store_x.splice(arr_row[i]-i, 1)this.arr_store_y.splice(arr_row[i]-i, 1)this.arr_store_color.splice(arr_row[i]-i, 1)}//让上面的方块往下掉一格for(let i = 0; i < this.arr_store_color.length; i++){if (this.arr_store_y[i] < line_num) {this.arr_store_y[i] = this.arr_store_y[i]+1}}}}//判断游戏结束gameover(){for(let i=0; i < this.arr_store_x.length; i++){if (this.arr_store_y[i] == 0) {clearinterval(this.ident)this.over = true}}}}let tetrisobj = new tetris()tetrisobj.gamestart()//方向键功能函数document.onkeydown = (e) => { if (tetrisobj.over)returnswitch(e.keycode){ca 40: // 方向为下tetrisobj.down_speed_up()breakca 32: // 空格换方向tetrisobj.initbackground() //重画地图tetrisobj.up_change_direction(tetrisobj.num_blcok)tetrisobj.drawblock(tetrisobj.type_color)breakca 37: // 方向为左tetrisobj.initbackground()tetrisobj.move(-1)tetrisobj.drawblock(tetrisobj.type_color)breakca 39: // 方向为右tetrisobj.initbackground()tetrisobj.move(1)tetrisobj.drawblock(tetrisobj.type_color)break} }</script></body></html>
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持www.887551.com。
本文发布于:2023-04-03 03:46:35,感谢您对本站的认可!
本文链接:https://www.wtabcd.cn/fanwen/zuowen/67652408107c65e9fe31f0d0256549fa.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文word下载地址:Html5原创俄罗斯方块(基于canvas).doc
本文 PDF 下载地址:Html5原创俄罗斯方块(基于canvas).pdf
留言与评论(共有 0 条评论) |