使用JS代码实现俄罗斯方块游戏


Posted in Javascript onAugust 03, 2018

简单的JS俄罗斯方块游戏源码,先给大家展示下效果图,如果大家感觉不错,请参考实现代码,

  效果图:

使用JS代码实现俄罗斯方块游戏

 代码如下,复制即可使用:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>使用JS实现俄罗斯方块游戏</title>
<style type="text/css">
  .MainFrame
  {
    border: 1px solid burlywood;
    margin: 10px auto;
    position: relative;
    background-color: silver;
  }
  .MainFramediv
  {
    float: left;
    margin: 1px;
    position: absolute;
    /*z-index: -1;*/
  }
  .smallDiv
  {
    margin: 1px;
    position: absolute;
  }
  .smallDivblack
  {
    /*float: left;*/
    margin: 1px;
    /*margin: 1px;*/
    position: absolute;
    /*z-index: 2;*/
  }
  #tetris{
    width: 50%;
    margin: 0 auto;
    padding: 0;
    /*border: 1px solid silver;*/
  }
  #tetris:after{
    content: "";
    Display: block;
    Clear: both;
  }
  #control{
    float: left;
    border: 1px solid silver;
    width: 150px;
    height: 578px;
    margin-top: 10px;
    margin-left: 20px;
    padding-top: 30px;
    font-size: 24px;
    font-weight: 400;
    color: blue;
    text-align: center;
  }
  #level,#regame{
    width: 100px;
    height: 30px;
    border: 1px solid blue;
    font-size: 16px;
    color: red;
    font-weight: 300;
  }
  #control p{
    margin-top: 200px;
  }
  #regame{
    margin-top: 100px;
    font-weight: 600;
    background-color: azure;
  }
  #TFrime{
    float: left;
  }
  #info{
    float: left;
    border: 1px solid silver;
    width: 150px;
    height: 578px;
    margin: 10px auto;
    padding-top: 30px;
    text-align: center;
    color: blue;
    font-size: 24px;
    font-weight: 400;
  }
  #nextfigure{
    width: 100px;
    height: 100px;
    background-color: silver;
    margin: 0 auto;
    margin-bottom: 100px;
    position: relative;
  }
  .drawdiv{
    background-color: red;
    margin: 1px;
    border: 1px solid silver;
    position: absolute;
  }
</style>
<!-- 此处需要自己修改JS路径 -->
<script src="js/GameFrame.js" type="text/javascript" charset="utf-8"></script>
<script src="js/graph.js" type="text/javascript" charset="utf-8"></script>
<script src="js/index.js" type="text/javascript" charset="utf-8"></script>
</head>
<body onload="initGame()">
<div id="tetris">
  <div id="control">
    难度:
    <div><select id="level" onchange="changespeed()">
      <option value="1000">简单
      <option value="500">一般
      <option value="200">困难
    </select></div>
    <input type="button" id="regame" value="重 新 开 始" onclick="regame()">
    <p>
      ↑:变换<br>
      ←:左移<br>
      →:右移<br>
      ↓:加速<br>
    </p>
  </div>
  <div id="TFrime"></div>
  <div id="info">
    下一个图形:
    <div id="nextfigure">
    </div>
    <div>分数:<span id="score">0</span></div>
  </div>
</div>
<div style="text-align:center;margin:10px 0; font:normal 14px/24px 'MicroSoft YaHei';">
<p>适用浏览器:360、FireFox、Chrome、Safari、Opera、傲游、搜狗、世界之窗. 不支持IE8及以下浏览器。</p>
</div>
</body>
</html>

 GameFrame.js

function GameFrame(unit,row,col)
{
  //单位的像素
  this.unit = unit;
  //横向单位个数(列),,(一行的个数)
  this.row = row;
  //纵向单位个数(行),,(一列的个数)
  this.col =col;
  //保存页面创建div容器的属性
  this.Content;
  //小图形
  this.samlldiv;
  //定时器id
  this.intervalid;
  //速度
  this.speed =document.getElementById("level").value;
  //速度是否改变
  this.ChangeSped=0;
  //记录每个位置是否有div
  this.datas=[];
  //记录消除行数相应的分数
  this.score=[0,100,300,600,1000]
  //记录当前的图形的下标
  this.now;
  //记录下一个图形的下标
  this.next;
  //记录当前的图形的颜色
  this.nowcolor;
  //记录下一个图形的颜色
  this.nextcolor;
  //保存7种图形相对坐标的数组
  this.arr = "0,1,0,2,1,2,2,2;0,1,1,1,1,2,2,2;0,1,0,2,1,1,2,1;0,2,1,1,1,2,2,1;1,0,1,1,1,2,1,3;1,1,1,2,2,1,2,2;1,1,2,0,2,1,2,2".split(";");
  //保存小方块的颜色
  this.color=["red","blue","green","yellow","#00FFFF","#930093","#F80000","#984B4B"];
  //初始化容器div
  this.init = function()
  {
    //创建div
    var div = document.createElement("div");
    //设置div的宽度
    div.style.width = (this.unit*this.row)+"px";
    //设置div的高度
    div.style.height=(this.unit*this.col)+"px";
    //设置div的样式
    div.className="MainFrame";
    div.id="MainFrame";
    //加入到body中
    document.getElementById("TFrime").appendChild(div);
    this.Content =div; //保存div的引用
    //初始化数组
    for(var i=0;i<this.col;i++)  //i为行
    {
      for(var j=0;j<this.row;j++){        //j为列
      var sdiv = document.createElement("div");
      sdiv.className="MainFramediv";
      sdiv.style.width = (this.unit - 2) + "px";
      sdiv.style.height = (this.unit - 2) + "px";
      sdiv.style.left=(j*this.unit)+"px";
      sdiv.style.top=(i*this.unit)+"px";
      this.Content.appendChild(sdiv);
      this.datas.push(0);
      }
    }
    this.next=Math.floor(Math.random() * this.arr.length);
    this.nextcolor=this.color[Math.floor(Math.random() * this.color.length)];
    Start();
  }
  this.MoveLeft = function()
  {
    this.samlldiv.moveleft();
  }
  this.MoveRight = function(){
    this.samlldiv.moveright();
  }
  this.Change = function(){
    this.samlldiv.change();
  }
  this.MoveDown = function(){
    if(this.samlldiv.movedown())
    {
//      for(var i=0;i<this.samlldiv.divs.length;i++)
//      {
//        this.Content.removeChild(this.samlldiv.divs[i]);
//      }
      this.samlldiv.rescore();
      Start();
    }
  }
  function Start()
  {
    //将next值传给now
    this.frame.now=this.frame.next;
    this.frame.nowcolor=this.frame.nextcolor;
    //创建小div
    this.frame.samlldiv=new Graph(this.frame);
    this.frame.samlldiv.init(this.frame.now,this.frame.nowcolor);
    //绘出下一个图形
    this.frame.next=Math.floor(Math.random() * this.frame.arr.length);
    this.frame.nextcolor=this.frame.color[Math.floor(Math.random() * this.frame.color.length)];
    draw();
    //调用定时器下落
    this.frame.intervalid = setInterval(autoMoveDown,this.frame.speed);
    //判断游戏是否结束
    if (this.frame.samlldiv.movedown()){
        clearInterval(this.frame.intervalid);
        alert("游戏结束!");
      }
  }
  function autoMoveDown()
  {
    if(this.frame.samlldiv.movedown())
    {
      this.frame.samlldiv.rescore();
      Start();
    }
    //改变速度
    if(this.frame.ChangeSped){
      clearInterval(this.frame.intervalid);
      this.frame.intervalid = setInterval(autoMoveDown,this.frame.speed);
      this.frame.ChangeSped=0;
    }
  }
  //速度改变,令ChangeSped值为1
  this.changespeed=function(){
    this.speed=document.getElementById("level").value;
    this.ChangeSped=1;
//    alert(this.ChangeSped);
  }
  //绘制下一个图形
  function draw(){
    //清楚原有的图形
    var cleardiv=document.getElementsByClassName("drawdiv");
    for(;;){
      if(cleardiv.length){
        document.getElementById("nextfigure").removeChild(cleardiv[0]);
      }else{
        break;
      }
    }
    //绘制图形
    var smallarr = this.frame.arr[this.frame.next].split(",");
    for (var i = 0; i < 8; i += 2) {
    var drawdiv = document.createElement("div");
    drawdiv.className = "drawdiv";
    drawdiv.style.backgroundColor=this.frame.nextcolor;
    drawdiv.style.width = (this.frame.unit - 2) + "px";
    drawdiv.style.height = (this.frame.unit - 2) + "px";
    drawdiv.style.top = (((smallarr[i] - 0) * this.frame.unit)+18) + "px";
    drawdiv.style.left = (((smallarr[i + 1] - 0) * this.frame.unit)+18) + "px";
    document.getElementById("nextfigure").appendChild(drawdiv);
    }
  }
}

 graph.js

function Graph(frame) {
  //保存7种图形相对坐标的数组
//  var arr = "0,1,0,2,1,2,2,2;0,1,1,1,1,2,2,2;0,1,0,2,1,1,2,1;0,2,1,1,1,2,2,1;1,0,1,1,1,2,1,3;1,1,1,2,2,1,2,2;1,1,2,0,2,1,2,2".split(";");
  //保存4个小图形的数组
  this.divs = [];
  //外部容器div的数组
  this.parentFrame = frame;
  //图形横纵偏移
  this.x = 0;
  this.y = 0;
  //记录图形的坐标数组
  this.zb = [];
  //记录消除的行数
  this.line=0;
  //初始化小图形的方法
  this.init = function(rand,color) {
      //计算图形其实坐标的单位
      var startleft = (this.parentFrame.row - 4) / 2;
      this.x = startleft;
      //随机生成图形数组下标
//      var rand = Math.floor(Math.random() * arr.length);
      //分解图形的坐标
      var smallarr = this.parentFrame.arr[rand].split(",");
      this.zb = smallarr;
      //循环设置小div的 left和top
      for (var i = 0; i < 8; i += 2) {
        //创建小div
        var smalldiv = document.createElement("div");
        //设置样式
        smalldiv.className = "smallDiv";
        //设置颜色
        smalldiv.style.backgroundColor=color;
        //定义高宽
        smalldiv.style.width = (this.parentFrame.unit - 2) + "px";
        smalldiv.style.height = (this.parentFrame.unit - 2) + "px";
        //设置小div的top
        smalldiv.style.top = ((smallarr[i] - 0) * this.parentFrame.unit) + "px";
        //设置小div的left
        smalldiv.style.left = (((smallarr[i + 1] - 0) + startleft) * this.parentFrame.unit) + "px";
        //保存小div的引用
        this.divs.push(smalldiv);        
        //加入到外部容器
        document.getElementById("MainFrame").appendChild(smalldiv);
      }
      //执行自动向下移动
      //this.parentFrame.intervalid = setInterval(autoMoveDown, this.parentFrame.speed);
    }
    //左移动
  this.moveleft = function() {
      //    var canmove = true;
      //    //判断能否左移动
      //    
      //    for(var i=0;i<this.divs.length;i++)
      //    {
      //        var left=parseInt(this.divs[i].style.left); //div目前的left
      //        if(left - this.parentFrame.unit <0) //减去一个单位的像素是否小于0
      //        {
      //          canmove = false; //不能向左移动了
      //          break;
      //        }
      //    }
      if (canMove(this.zb, this.x, this.y, this.parentFrame, 2)) //可以移动
      {
        this.x -= 1;
        for (var i = 0; i < this.divs.length; i++) //循环小div,把每个div的left减去一个单位的像素
        {
          var left = parseInt(this.divs[i].style.left);
          this.divs[i].style.left = (left - this.parentFrame.unit) + "px";
        }
      }
    }
    //右移动
  this.moveright = function() {
    //    var canmove = true;
    //      //判断能否右移动
    //    for(var i=0;i<this.divs.length;i++)
    //    {
    //      var left=parseInt(this.divs[i].style.left);
    //      if(left + this.parentFrame.unit >=parseInt(this.parentFrame.Content.style.width))
    //      {
    //        canmove = false;
    //        break;
    //      }
    //    }
    var temp = canMove(this.zb, this.x, this.y, this.parentFrame, 1);
//    alert(temp);
    console.log(temp);
    if (canMove(this.zb, this.x, this.y, this.parentFrame, 1)) {
      this.x += 1;
      for (var i = 0; i < this.divs.length; i++) {
        var left = parseInt(this.divs[i].style.left);
        this.divs[i].style.left = (left + this.parentFrame.unit) + "px";
      }
    }
  }
  //变形
  this.change = function() {
    //变形的公式
    //小div的2个相对坐标点改变  x = y ; y= 3-x; 比如 (0,1) 变化之后 就是  x=1,y=3-0 -> (1,3)
    //循环4个小div
    if (!canMove(this.zb, this.x, this.y, this.parentFrame, 4)) {
      if (this.x < 0) {
        this.x += 1;
      } else {
        this.x -= 1;
      }
    }
    for (var i = 0; i < this.divs.length; i++) {
      //根据公式改变每个div的相对偏移量,2个一改
      var temp = this.zb[i * 2]
      this.zb[i * 2] = this.zb[i * 2 + 1];
      this.zb[i * 2 + 1] = 3 - temp;
      //根据改变后的偏移量计算图形的当前left和top
      this.divs[i].style.top = ((this.y + parseInt(this.zb[i * 2])) * this.parentFrame.unit) + "px";
      this.divs[i].style.left = ((this.x + parseInt(this.zb[i * 2 + 1])) * this.parentFrame.unit) + "px";
    }
  }
  this.movedown = function() {
    var $this = this =="window" ? this.frame.samlldiv : this;
    if (canMove($this.zb, $this.x, $this.y, $this.parentFrame, 3)) {
      $this.y += 1;
      for (var i = 0; i < $this.divs.length; i++) {
        var top = parseInt($this.divs[i].style.top);
        $this.divs[i].style.top = (top + $this.parentFrame.unit) + "px";
      }
      return false;
    } else {
      clearInterval($this.parentFrame.intervalid);
//      var temp = $this.parentFrame.Content.getElementsByTagName("div");
      for (var i=0;i<$this.divs.length;i++) {
        //div变灰
        //$this.divs[i].className ="smallDivblack";
        var $y = $this.y + parseInt($this.zb[i*2]);
        var $x = $this.x+parseInt($this.zb[i*2+1]);
//        debugger;
        $this.parentFrame.datas[$y*$this.parentFrame.row+ $x] =1;
        $this.divs[i].dataset.row=$y;  //记录div所在的行
        $this.divs[i].dataset.col=$x;  //记录div所在的列
        $this.divs[i].className="smallDivblack";
        $this.divs[i].style.backgroundColor="black";
        //$this.parentFrame.datas[]
      }
        //消行并计分
        for (var i= 0;i<$this.parentFrame.col;i++) {    //i为行
          //判断是否满足消行条件
          for (var j=0;j<$this.parentFrame.row;j++) {    //j为列
            if($this.parentFrame.datas[i*$this.parentFrame.row+ j] !=1){
              break;
            }
          }
          //消行,将该行上面的所有div下移一行
          if(j==$this.parentFrame.row){
            var x;    //记录div在哪一列
            var y;    //记录div在哪一行
            var getsmalldiv=document.getElementById("TFrime").getElementsByClassName("smallDivblack");//得到小div
            for (var a=0;a<getsmalldiv.length;a++){
              y=parseInt(getsmalldiv[a].dataset.row);
              x=parseInt(getsmalldiv[a].dataset.col);
              if(y==i){    //消除该行
                debugger;
                $this.parentFrame.datas[y*$this.parentFrame.row+ x]=0;
                getsmalldiv[a].remove();
                a--;
              }
            }
            for (var a=i-1;a>0;a--) {
              for (var b=0;b<getsmalldiv.length;b++) {
                y=parseInt(getsmalldiv[b].dataset.row);
                x=parseInt(getsmalldiv[b].dataset.col);
                if(y==a){    //将上面的div下移一行
//                debugger;
                var divtop=parseInt(getsmalldiv[b].style.top);
                getsmalldiv[b].style.top=(divtop+$this.parentFrame.unit)+"px";
                getsmalldiv[b].dataset.row++;
                $this.parentFrame.datas[y*$this.parentFrame.row+ x]=0;
                $this.parentFrame.datas[(y+1)*$this.parentFrame.row+ x]=1;
                }
              }
            }
            $this.line++;
//            for (var a=0;a<getsmalldiv.length;a++) {
//              y=parseInt(getsmalldiv[a].dataset.row);
//              x=parseInt(getsmalldiv[a].dataset.col);
////              alert(getsmalldiv[a].dataset.row);
//              if(y<i){    //将上面的div下移一行
////                debugger;
//                var divtop=parseInt(getsmalldiv[a].style.top);
////                alert(getsmalldiv[a].style.top);
//                getsmalldiv[a].style.top=(divtop+$this.parentFrame.unit)+"px";
//                getsmalldiv[a].dataset.row++;
//                debugger;
//                $this.parentFrame.datas[y*$this.parentFrame.row+ x]=0;
//                $this.parentFrame.datas[(y+1)*$this.parentFrame.row+ x]=1;
//              }
////              }else if(y==i){    //消除该行
////                debugger;
////                $this.parentFrame.datas[y*$this.parentFrame.row+ x]=0;
////                getsmalldiv[a].className="MainFramediv";
////              }
//            }
          }
        }
      return true;
    }
  }
//  function autoMoveDown() {
//    
//    var small = this.frame.samlldiv;
//    var f = this.frame;
//    
//    if (canMove(small.zb, small.x, small.y, 0, f.col, 3)) {
//      small.y += 1;
//      for (var i = 0; i < small.divs.length; i++) {
//        var top = parseInt(small.divs[i].style.top);
//        small.divs[i].style.top = (top + f.unit) + "px";
//      }
//    } else {
//      clearInterval(f.intervalid);
//    }
//
//  }
  //预判能否移动或变化,action:1.右移,2.左移,3.下移,4.变化
  //zb是4个小图形的相对偏移,x是图形左偏移,y是top偏移,f是外部frame
  function canMove(zb, x, y, f, action) {
    //datas[parseInt(zb[i + 1]) + x + 1)+(this.y-1)*row] !=0
    switch (action) {
      case 1:
//        debugger;
        for (var i = 0; i < zb.length; i += 2) {
          if (parseInt(zb[i + 1]) + x + 1 >= f.row)
          {
            return false;
          }else if(f.datas[(parseInt(zb[i + 1]) + x + 1)+(y+parseInt(zb[i]))*f.row] !=0)
          {
            return false;
          }
        }
        break;
      case 2:
        for (var i = 0; i < zb.length; i += 2) {
          if (parseInt(zb[i + 1]) + x - 1 < 0 ) {
            return false;
          }else if(f.datas[(parseInt(zb[i + 1]) + x - 1)+(y+parseInt(zb[i]))*f.row] !=0)
          {
            return false;
          }
        }
        break;
      case 3:
        for (var i = 0; i < zb.length; i += 2) {
          if (parseInt(zb[i]) + y + 1 >= f.col ||
          f.datas[(parseInt(zb[i + 1]) + x)+(parseInt(zb[i]) + y+1)*f.row] !=0) {
            return false;
          }
        }
        break;
      case 4:
        for (var i = 0; i < zb.length; i += 2) {
          var temp = 3 - zb[i];
          if (temp + x < 0 || temp + x >= f.row) {
            return false;
          }
        }
        break;
    }
    return true;
  }
  this.rescore=function(){
    var gamescore=document.getElementById("score");
    gamescore.innerHTML=parseInt(gamescore.innerHTML)+this.parentFrame.score[this.line];
  }
}

 index.js

var frame;
function initGame()
{
  frame = new GameFrame(16,20,38);
  frame.init();
  document.body.addEventListener("keydown",MoveOrChange)
}
function changespeed(){
  frame.changespeed();
}
function regame(){
  location.reload();
}
function MoveOrChange()
{
  switch(event.keyCode)
  {
    case 38: //变形(上方向键)
      frame.Change();
      break;
    case 37: //左移动
      frame.MoveLeft();
      break;
    case 39://右移动
      frame.MoveRight();
      break;
    case 40: //向下
      frame.MoveDown();
      break;
  }
}

总结

以上所述是小编给大家介绍的使用JS代码实现俄罗斯方块游戏,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
JavaScript iframe的相互操作浅析
Oct 14 Javascript
用jQuery扩展自写的 UI导航
Jan 13 Javascript
JS动态创建Table,Tr,Td并赋值的具体实现
Jul 05 Javascript
js用正则表达式来验证表单(比较齐全的资源)
Nov 17 Javascript
javascript模拟实现C# String.format函数功能代码
Nov 25 Javascript
SinaEditor使用方法详解
Dec 28 Javascript
jquery序列化表单去除指定元素示例代码
Apr 10 Javascript
javascript限制用户只能输汉字中文的方法
Nov 20 Javascript
javascript禁止访客复制网页内容的实现代码
Aug 05 Javascript
微信小程序 chooseImage选择图片或者拍照
Apr 07 Javascript
vue 数组和对象不能直接赋值情况和解决方法(推荐)
Oct 25 Javascript
layui实现数据表格隐藏列的示例
Oct 25 Javascript
小程序tab页无法传递参数的方法
Aug 03 #Javascript
详解Webpack多环境代码打包的方法
Aug 03 #Javascript
浅析vue-router jquery和params传参(接收参数)$router $route的区别
Aug 03 #jQuery
浅析Vue 和微信小程序的区别、比较
Aug 03 #Javascript
Vue 项目分环境打包的方法示例
Aug 03 #Javascript
如何在vue里添加好看的lottie动画
Aug 02 #Javascript
原生js实现form表单序列化的方法
Aug 02 #Javascript
You might like
php遍历CSV类实例
2015/04/14 PHP
PHP strip_tags() 去字符串中的 HTML、XML 以及 PHP 标签的函数
2016/05/22 PHP
php设计模式之工厂模式用法经典实例分析
2019/09/20 PHP
input的focus方法使用
2010/03/13 Javascript
JavaScript 选中文字并响应获取的实现代码
2011/08/28 Javascript
js实现在文本框光标处添加字符的方法介绍
2012/11/24 Javascript
Eclipse去除js(JavaScript)验证错误
2014/02/11 Javascript
JavaScript数字和字符串转换示例
2014/03/26 Javascript
js获取select默认选中的Option并不是当前选中值
2014/05/07 Javascript
用jquery修复在iframe下的页面锚点失效问题
2014/08/22 Javascript
完美兼容IE,chrome,ff的设为首页、加入收藏及保存到桌面js代码
2014/12/17 Javascript
jquery mobile开发常见问题分析
2016/01/21 Javascript
AngularJS服务service用法总结
2016/12/13 Javascript
简单谈谈原生js的math对象
2017/06/27 Javascript
详解VUE中常用的几种import(模块、文件)引入方式
2018/07/03 Javascript
详解Nuxt.js部署及踩过的坑
2018/08/07 Javascript
bootstrap动态调用select下拉框的实例代码
2018/08/09 Javascript
详解Vue This$Store总结
2018/12/17 Javascript
使用微信SDK自定义分享的方法
2019/07/03 Javascript
JavaScript this在函数中的指向及实例详解
2019/10/14 Javascript
[42:32]VP vs RNG 2019国际邀请赛淘汰赛 败者组 BO3 第一场 8.21.mp4
2020/07/19 DOTA
Django1.7+python 2.78+pycharm配置mysql数据库教程
2014/11/18 Python
12个步骤教你理解Python装饰器
2019/07/01 Python
你应该知道的Python3.6、3.7、3.8新特性小结
2020/05/12 Python
Python-for循环的内部机制
2020/06/12 Python
python脚本使用阿里云slb对恶意攻击进行封堵的实现
2021/02/04 Python
美国婴儿和儿童服装购物网站:PatPat
2020/10/01 全球购物
软件测试面试题
2015/10/21 面试题
内科护士实习自我鉴定
2013/10/17 职场文书
回门宴新郎答谢词
2014/01/12 职场文书
电气个人求职信范文
2014/02/04 职场文书
大专生自荐书范文
2014/06/22 职场文书
授权委托书怎么写
2014/09/25 职场文书
党员个人整改措施
2014/10/24 职场文书
纪检干部学习心得体会
2016/01/23 职场文书
导游词之任弼时故居
2020/01/07 职场文书