js canvas实现俄罗斯方块


Posted in Javascript onOctober 11, 2020

本文实例为大家分享了canvas实现俄罗斯方块的具体代码,供大家参考,具体内容如下

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <title>Document</title>
</head>
<body style="margin: 0;">
 <canvas id="tetris" style="border: 1px solid #000;"></canvas>
 <div id="text" style='color: red;font-size: 30px;'>当前分数:0</div>
</body>
<script>
 let cav = document.getElementById('tetris')
 let text = document.getElementById('text')
 let ctx = cav.getContext('2d')
 let k = 40 //倍数
 let speed = 1000
 let grade = 0
 let restartFlag = false
 let timer = null
 let curGraphPositionList = []
 let curtype = undefined
 let transformNum = 0
 let blockGraph = Array(10)
 let beforeUpdateGraph = []
 for(let i = 0;i<blockGraph.length;i++){
  blockGraph[i] = Array(20)
 }
 cav.width = 10*k 
 cav.height = 20*k
 ctx.fillStyle="yellow"
 ctx.strokeStyle="black"
 function ramdomRectType(){
  return Math.floor((Math.random()*7)+1)
 }
 function randomXposition(){
  return Math.floor(Math.random()*10)
 }
 function drawRect(position,width){
  ctx.beginPath()
  ctx.rect(position[0],position[1],width,width)
  ctx.fill();
  ctx.stroke()
 }
 function drawGraph(positionList){
  if(positionList.length===0){
   return
  }
  for(let item of positionList){
   let x= item[0]*k
   let y= item[1]*k
   let position = [x,y]
   drawRect(position,k)
  }
 }
 function isOut(position,xOry){//x:0,y:1
  if(xOry===0){
   if(position<0||position>9){
    return true
   }else{
    return false
   }
  }else{
   if(position<0||position>19){
    return true
   }else{
    return false
   }
  }
 }
 function randomRectShape(){
  let rposition = randomXposition()
  let type = ramdomRectType()
  curtype = type
  transformNum = 0
  let positionList = []
  let one = []
  let two = []
  let three = []
  let four = []
  switch(type){
   case 1:
    if(isOut(rposition+2,0)){
     return randomRectShape()
    }else{
     one = [rposition+2,0]
     two = [rposition,1]
     three = [rposition+1,1]
     four = [rposition+2,1]
    }
    break;
   case 2:
    if(isOut(rposition+2,0)){
     return randomRectShape()
    }else{
     one = [rposition,0]
     two = [rposition,1]
     three = [rposition+1,1]
     four = [rposition+2,1]
    }
    break;
   case 3:
    if(isOut(rposition+2,0)){
     return randomRectShape()
    }else{
     one = [rposition+1,0]
     two = [rposition+2,0]
     three = [rposition,1]
     four = [rposition+1,1]
    }
    break;
   case 4:
    if(isOut(rposition+2,0)){
     return randomRectShape()
    }else{
     one = [rposition,0]
     two = [rposition+1,0]
     three = [rposition+1,1]
     four = [rposition+2,1]
    }
    break;
   case 5:
    if(isOut(rposition+2,0)){
     return randomRectShape()
    }else{
     one = [rposition+1,0]
     two = [rposition,1]
     three = [rposition+1,1]
     four = [rposition+2,1]
    }
    break;
   case 6:
    if(isOut(rposition+1,0)){
     return randomRectShape()
    }else{
     one = [rposition,0]
     two = [rposition+1,0]
     three = [rposition,1]
     four = [rposition+1,1]
    }
    break;
   case 7:
    if(isOut(rposition+3,0)){
     return randomRectShape()
    }else{
     one = [rposition,0]
     two = [rposition+1,0]
     three = [rposition+2,0]
     four = [rposition+3,0]
    }
    break;
  }
  positionList.push(one,two,three,four)
  return positionList
 }
 function clearRect(position,width){
  ctx.clearRect(position[0]*k-1,position[1]*k-1,width+2,width+2)
 }
 function clearGraph(curGraphPositionList){
  if(curGraphPositionList.length===0){
   return 
  }
  for(let item of curGraphPositionList){
   clearRect(item,k)
  }
 }
 function clearGraphList(){
  let graphList = []
  for(let i = 0;i< blockGraph.length;i++){
   for(let j =0;j< blockGraph[i].length;j++){
    if(blockGraph[i][j]===1){
     graphList.push([i,j])
    }
   }
  }
  clearGraph(graphList)
 }
 function isTouchOtherBlock(position){
  return blockGraph[position[0]][position[1]] === 1
 }
 function updateBlockGraph(graphPositionList){
  for(let i =0;i<graphPositionList.length;i++){
   let x = parseInt(graphPositionList[i][0]) 
   let y = parseInt(graphPositionList[i][1])
   blockGraph[x][y] = 1
  }
  let transformArray = []
  for(let i=0;i<20;i++){
   let arr = blockGraph.map((item)=>{
    return item[i]
   })
   transformArray.push(arr)
  }
  let flagList = []
  for(let i in transformArray){
   let flag = 1
   for(let j in transformArray[i]){
    if(transformArray[i][j]!==1){
     flag = 0
     break
    }
   }
   flagList.push(flag)
  }
  let score = flagList.filter((item)=>{
   return item === 1
  })
  if(score.length>0){
   grade = grade + score.length
   text.innerHTML = '当前分数:'+grade
   for(let i in transformArray){
    if(flagList[i]===1){
     for(let j in transformArray[i]){
      transformArray[i][j]=undefined
     }
    }
   }
   let hasBlockList = []
   for(let i in transformArray){
    let flagOfHasBlock = 0
    for(let j in transformArray[i]){
     if(transformArray[i][j]!==undefined){
      flagOfHasBlock = 1
      break
     }
    }
    hasBlockList.push(flagOfHasBlock)
   }
   for(let i = transformArray.length -1 ;i>=0;i--){
    if(hasBlockList[i]===1){
     let count = 0
     for(let j = i ;j<19;j++){
      if(hasBlockList[j+1]===0){
       count++
      }else{
       break
      }
     }
     if(count===0){
      continue
     }
     for(let j in transformArray[i]){
      if(transformArray[i][j]===1){
       transformArray[i][j] = undefined
       transformArray[i+count][j] = 1
      }
     }
     hasBlockList[i]=0
     hasBlockList[i+count]=1
    }
   }
   let newBlockGraph = []
   for(let i=0;i<10;i++){
    let arr = transformArray.map((item)=>{
     return item[i]
    })
    newBlockGraph.push(arr)
   }
   clearGraphList()
   blockGraph = newBlockGraph
  }
 }
 function movePosition(curGraphPositionList,direct){
  switch(direct){
   case 'left':
    let minL = Math.min(...curGraphPositionList.map((item)=>{
     return item[0]
    }))
    if(minL-1<0){
     return curGraphPositionList
    }else{
     let changeFlag = true
     let next = curGraphPositionList.map((item)=>{
      return [item[0]-1,item[1]]
     })
     for(let item of next){
      if(isTouchOtherBlock(item)){
       changeFlag = false
      }
     }
     if(changeFlag){
      return next
     }else{
      return curGraphPositionList
     }
    }
    break;
   case 'right':
    let maxR = Math.max(...curGraphPositionList.map((item)=>{
     return item[0]
    }))
    if(maxR+1>9){
     return curGraphPositionList
    }else{
     let changeFlag = true
     let next = curGraphPositionList.map((item)=>{
      return [item[0]+1,item[1]]
     })
     for(let item of next){
      if(isTouchOtherBlock(item)){
       changeFlag = false
      }
     }
     if(changeFlag){
      return next
     }else{
      return curGraphPositionList
     }
    }
    break;
   case 'down':
    let maxD = Math.max(...curGraphPositionList.map((item)=>{
     return item[1]
    }))
    if(maxD>18){
     updateBlockGraph(curGraphPositionList)
     restartFlag = true
     return curGraphPositionList
    }else{
     let changeFlag = true
     let next = curGraphPositionList.map((item)=>{
      return [item[0],item[1]+1]
     })
     for(let item of next){
      if(isTouchOtherBlock(item)){
       changeFlag = false
      }
     }
     if(changeFlag){
      return next
     }else{
      updateBlockGraph(curGraphPositionList)
      restartFlag = true
      return curGraphPositionList
     }
    }
    break;
  }
 }
 function checkOver(positionList){
  for(let i in positionList){
   let x = positionList[i][0]
   let y = positionList[i][1]
   if(blockGraph[x][y]===1){
    over()
    alert('游戏结束')
    return true
   }
  }
  return false
 }
 function drawGraphList(){
  let graphList = []
  for(let i = 0;i< blockGraph.length;i++){
   for(let j =0;j< blockGraph[i].length;j++){
    if(blockGraph[i][j]===1){
     graphList.push([i,j])
    }
   }
  }
  drawGraph(graphList)
 }
 function isComplexData (data) {
  if(data===null||data===undefined){
   return false
  }
  let flag = data.constructor===Array||data.constructor===Object
  return flag
 }

 function deepCopy (data) {
  if(!isComplexData (data)){
   return data
  }
  let result = null
  if(data.constructor===Array){
   result = []
  }else{
   result = {}
  }
  for(let i in data){
   result[i] = deepCopy (data[i])
  }
  return result
 }

 function move(direct){
  clearGraph(curGraphPositionList)
  curGraphPositionList = movePosition(curGraphPositionList,direct)
  if(restartFlag){
   drawGraphList(blockGraph)
  }else{
   drawGraph(curGraphPositionList)
  }
 }
 function transform (curtype) {
  let checkArr = deepCopy(curGraphPositionList)
  if(transformNum>=3){
   transformNum = 0
  }else{
   transformNum++
  }
  switch(curtype){
   case 1:
    caseOne(checkArr)
    break;
   case 2:
    caseTwo(checkArr)
    break;
   case 3:
    caseThree(checkArr)
    break;
   case 4:
    caseFour(checkArr)
    break;
   case 5:
    caseFive(checkArr)
    break;
   case 6:
    caseSix(checkArr)
    break;
   case 7:
    caseSeven(checkArr)
    break;
  }
  //start check outside
  let outflag = false
  let xArr = checkArr.map((item)=>{
   return item[0]
  })
  let yArr = checkArr.map((item)=>{
   return item[1]
  })
  for(let item of xArr){
   if(isOut(item,0)){
    outflag = true
   }
  }
  for(let item of yArr){
   if(isOut(item,1)){
    outflag = true
   }
  }
  if(outflag){
   if(transformNum<=0){
    transformNum = 3
   }else{
    transformNum--
   }
   return
  }
  //end check
  if(!checkTranfromTouchBlock(checkArr)){
    if(transformNum<=0){
     transformNum = 3
    }else{
     transformNum--
    }
    return
  }else{
   clearGraph(curGraphPositionList)
   curGraphPositionList = checkArr
   drawGraph(curGraphPositionList)
  }
 }
 function checkTranfromTouchBlock(checkArr){
  let changeFlag = true
  for(let item of checkArr){
   if(isTouchOtherBlock(item)){
    changeFlag = false
   }
  }
  return changeFlag
 }
 function caseOne(checkarr){
  switch(transformNum){
   case 0:
    checkarr[0][0]=checkarr[0][0]+2
    checkarr[1][0]=checkarr[1][0]-1
    checkarr[1][1]=checkarr[1][1]-1
    checkarr[3][0]=checkarr[3][0]+1
    checkarr[3][1]=checkarr[3][1]+1
    break;
   case 1:
    checkarr[0][1]=checkarr[0][1]+2
    checkarr[1][0]=checkarr[1][0]+1
    checkarr[1][1]=checkarr[1][1]-1
    checkarr[3][0]=checkarr[3][0]-1
    checkarr[3][1]=checkarr[3][1]+1
    break;
   case 2:
    checkarr[0][0]=checkarr[0][0]-2
    checkarr[1][0]=checkarr[1][0]+1
    checkarr[1][1]=checkarr[1][1]+1
    checkarr[3][0]=checkarr[3][0]-1
    checkarr[3][1]=checkarr[3][1]-1
    break;
   case 3:
    checkarr[0][1]=checkarr[0][1]-2
    checkarr[1][0]=checkarr[1][0]-1
    checkarr[1][1]=checkarr[1][1]+1
    checkarr[3][0]=checkarr[3][0]+1
    checkarr[3][1]=checkarr[3][1]-1
    break;
  }
 }
 function caseTwo(checkarr){
  switch(transformNum){
   case 0:
    checkarr[0][1]=checkarr[0][1]-2
    checkarr[1][0]=checkarr[1][0]-1
    checkarr[1][1]=checkarr[1][1]-1
    checkarr[3][0]=checkarr[3][0]+1
    checkarr[3][1]=checkarr[3][1]+1
    break;
   case 1:
    checkarr[0][0]=checkarr[0][0]+2
    checkarr[1][0]=checkarr[1][0]+1
    checkarr[1][1]=checkarr[1][1]-1
    checkarr[3][0]=checkarr[3][0]-1
    checkarr[3][1]=checkarr[3][1]+1
    break;
   case 2:
    checkarr[0][1]=checkarr[0][1]+2
    checkarr[1][0]=checkarr[1][0]+1
    checkarr[1][1]=checkarr[1][1]+1
    checkarr[3][0]=checkarr[3][0]-1
    checkarr[3][1]=checkarr[3][1]-1
    break;
   case 3:
    checkarr[0][0]=checkarr[0][0]-2
    checkarr[1][0]=checkarr[1][0]-1
    checkarr[1][1]=checkarr[1][1]+1
    checkarr[3][0]=checkarr[3][0]+1
    checkarr[3][1]=checkarr[3][1]-1
    break;
  }
 }
 function caseThree(checkarr){
  if(transformNum%2!==0){
   checkarr[0][0]=checkarr[0][0]+1
   checkarr[0][1]=checkarr[0][1]+1
   checkarr[1][1]=checkarr[1][1]+2
   checkarr[2][0]=checkarr[2][0]+1
   checkarr[2][1]=checkarr[2][1]-1
  }else{
   checkarr[0][0]=checkarr[0][0]-1
   checkarr[0][1]=checkarr[0][1]-1
   checkarr[1][1]=checkarr[1][1]-2
   checkarr[2][0]=checkarr[2][0]-1
   checkarr[2][1]=checkarr[2][1]+1
  }
 }

 function caseFour(checkarr){
  if(transformNum%2!==0){
   checkarr[0][0]=checkarr[0][0]+2
   checkarr[1][0]=checkarr[1][0]+1
   checkarr[1][1]=checkarr[1][1]+1
   checkarr[3][0]=checkarr[3][0]-1
   checkarr[3][1]=checkarr[3][1]+1
  }else{
   checkarr[0][0]=checkarr[0][0]-2
   checkarr[1][0]=checkarr[1][0]-1
   checkarr[1][1]=checkarr[1][1]-1
   checkarr[3][0]=checkarr[3][0]+1
   checkarr[3][1]=checkarr[3][1]-1
  }
 }
 function caseFive(checkarr){
  switch(transformNum){
   case 0:
    checkarr[0][0]=checkarr[0][0]+1
    checkarr[0][1]=checkarr[0][1]-1
    checkarr[1][0]=checkarr[1][0]-1
    checkarr[1][1]=checkarr[1][1]-1
    checkarr[3][0]=checkarr[3][0]+1
    checkarr[3][1]=checkarr[3][1]+1
    break;
   case 1:
    checkarr[0][0]=checkarr[0][0]+1
    checkarr[0][1]=checkarr[0][1]+1
    checkarr[1][0]=checkarr[1][0]+1
    checkarr[1][1]=checkarr[1][1]-1
    checkarr[3][0]=checkarr[3][0]-1
    checkarr[3][1]=checkarr[3][1]+1
    break;
   case 2:
    checkarr[0][0]=checkarr[0][0]-1
    checkarr[0][1]=checkarr[0][1]+1
    checkarr[1][0]=checkarr[1][0]+1
    checkarr[1][1]=checkarr[1][1]+1
    checkarr[3][0]=checkarr[3][0]-1
    checkarr[3][1]=checkarr[3][1]-1
    break;
   case 3:
    checkarr[0][0]=checkarr[0][0]-1
    checkarr[0][1]=checkarr[0][1]-1
    checkarr[1][0]=checkarr[1][0]-1
    checkarr[1][1]=checkarr[1][1]+1
    checkarr[3][0]=checkarr[3][0]+1
    checkarr[3][1]=checkarr[3][1]-1
    break;
  }
 }
 function caseSix(checkarr){
  return
 }
 function caseSeven(checkarr){
  if(transformNum%2!==0){
   checkarr[0][0]=checkarr[0][0]+2
   checkarr[0][1]=checkarr[0][1]-2
   checkarr[1][0]=checkarr[1][0]+1
   checkarr[1][1]=checkarr[1][1]-1
   checkarr[3][0]=checkarr[3][0]-1
   checkarr[3][1]=checkarr[3][1]+1
  }else{
   checkarr[0][0]=checkarr[0][0]-2
   checkarr[0][1]=checkarr[0][1]+2
   checkarr[1][0]=checkarr[1][0]-1
   checkarr[1][1]=checkarr[1][1]+1
   checkarr[3][0]=checkarr[3][0]+1
   checkarr[3][1]=checkarr[3][1]-1
  }
 }
 function setTimer(speed) {
  clearInterval(timer)
  timer = setInterval(()=>{
   move('down')
   if(restartFlag){
    newBlock()
   }
  },speed)
 }
 function newBlock(){
  restartFlag = false
  curGraphPositionList = randomRectShape()
  drawGraph(curGraphPositionList)
  let overflag = checkOver(curGraphPositionList)
  if(overflag){
   return
  }
  setTimer(speed)
 }
 function start() {
  newBlock()
 }
 function over() {
  clearInterval(timer)
 }
 start()

 let pauseFlag = false
 document.addEventListener('keydown',(event)=>{
  if(event.keyCode===37){
   move('left')
  }else if(event.keyCode===39){
   move('right')
  }else if(event.keyCode===40){
   speed=30
   setTimer(speed)
  }else if(event.keyCode===32){
   pauseFlag = !pauseFlag
   if(pauseFlag){
    over()
   }else{
    setTimer(speed)
   }
  }else if(event.keyCode===38){
   // clearGraph(curGraphPositionList)
   transform (curtype)
  }
 })
 document.addEventListener('keyup',(event)=>{
  if(event.keyCode===40){
   speed=1000
   setTimer(speed)
  }
 })

</script>
</html>

更多有趣的经典小游戏实现专题,分享给大家:

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
url 特殊字符 传递参数解决方法
Jan 01 Javascript
javascript Firefox与IE 替换节点的方法
Feb 24 Javascript
前端开发必须知道的JS之原型和继承
Jul 06 Javascript
正则表达式搭配js轻松处理json文本方便而老古
Feb 17 Javascript
分享JS代码实现鼠标放在输入框上输入框和图片同时更换样式
Sep 01 Javascript
实例解析js中try、catch、finally的执行规则
Feb 24 Javascript
bootstrap是什么_动力节点Java学院整理
Jul 14 Javascript
JavaScript函数中的this四种绑定形式
Aug 15 Javascript
JavaScript数据结构与算法之二叉树插入节点、生成二叉树示例
Feb 21 Javascript
JS实现水平移动与垂直移动动画
Dec 19 Javascript
JavaScript回调函数callback用法解析
Jan 14 Javascript
JavaScript实现图片放大预览效果
Nov 02 Javascript
利用js canvas实现五子棋游戏
Oct 11 #Javascript
H5+css3+js搭建带验证码的登录页面
Oct 11 #Javascript
原生js生成图片验证码
Oct 11 #Javascript
js实现石头剪刀布游戏
Oct 11 #Javascript
js+h5 canvas实现图片验证码
Oct 11 #Javascript
vue2和vue3的v-if与v-for优先级对比学习
Oct 10 #Javascript
如何手写简易的 Vue Router
Oct 10 #Javascript
You might like
php统计文章排行示例
2014/03/04 PHP
PHP小教程之实现链表
2014/06/09 PHP
PHP新建类问题分析及解决思路
2015/11/19 PHP
phpinfo()中Loaded Configuration File(none)的解决方法
2017/01/16 PHP
浅谈PHP中类和对象的相关函数
2017/04/26 PHP
php实现文件预览功能
2017/05/23 PHP
PHP递归实现文件夹的复制、删除、查看大小操作示例
2017/08/11 PHP
javasciprt下jquery函数$.post执行无响应的解决方法
2014/03/13 Javascript
jquery的each方法使用示例分享
2014/03/25 Javascript
JavaScript实现检查页面上的广告是否被AdBlock屏蔽了的方法
2014/11/03 Javascript
JS中取二维数组中最大值的方法汇总
2016/04/17 Javascript
JS控制弹出悬浮窗口(一览画面)的实例代码
2016/05/30 Javascript
Three.js学习之文字形状及自定义形状
2016/08/01 Javascript
JS基于面向对象实现的选项卡效果示例
2016/12/20 Javascript
基于canvas的二维码邀请函生成插件
2017/02/14 Javascript
JS+HTML5实现上传图片预览效果完整实例【测试可用】
2017/04/20 Javascript
详解nodejs实现本地上传图片并预览功能(express4.0+)
2017/06/28 NodeJs
深入理解Vue生命周期、手动挂载及挂载子组件
2017/09/27 Javascript
jQuery实现的简单前端搜索功能示例
2017/10/28 jQuery
简化vuex的状态管理方案的方法
2018/06/02 Javascript
微信小程序仿知乎实现评论留言功能
2018/11/28 Javascript
jQuery模仿ToDoList实现简单的待办事项列表
2019/12/30 jQuery
vue学习笔记之slot插槽基本用法实例分析
2020/02/01 Javascript
详解Vue.js 响应接口
2020/07/04 Javascript
在react项目中使用antd的form组件,动态设置input框的值
2020/10/24 Javascript
python执行shell获取硬件参数写入mysql的方法
2014/12/29 Python
python实现报表自动化详解
2017/11/16 Python
Python 实现还原已撤回的微信消息
2019/06/18 Python
Python如何将图像音视频等资源文件隐藏在代码中(小技巧)
2020/02/16 Python
护理专科自荐书范文
2014/02/18 职场文书
奥巴马获胜演讲稿
2014/05/15 职场文书
学校运动会霸气口号
2014/06/07 职场文书
党员一帮一活动总结
2014/07/08 职场文书
工作失职检讨书(精华篇)
2014/10/15 职场文书
我的法兰西岁月观后感
2015/06/09 职场文书
课题研究阶段性总结
2015/08/13 职场文书