使用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 相关文章推荐
Prototype使用指南之enumerable.js
Jan 10 Javascript
Jquery+JSon 无刷新分页实现代码
Apr 01 Javascript
angularJS 中$attrs方法使用指南
Feb 09 Javascript
使用AngularJS实现表单向导的方法
Jun 19 Javascript
jQuery实现hover合成事件的方法
Aug 06 Javascript
常用javascript表单验证汇总
Jul 20 Javascript
JSON字符串转换JSONObject和JSONArray的方法
Jun 03 Javascript
json的使用小结
Jun 08 Javascript
常用js,css文件统一加载方法(推荐) 并在加载之后调用回调函数
Sep 23 Javascript
ReactNative中使用Redux架构总结
Dec 15 Javascript
JS中移除非数字最多保留一位小数
May 09 Javascript
js实现无限瀑布流实例方法
Sep 16 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函数(ignore_user_abort)
2012/08/01 PHP
PHP实现根据浏览器跳转不同语言页面代码
2013/08/02 PHP
用php和jQuery来实现“顶”和“踩”的投票功能
2016/10/13 PHP
PHP数据库操作四:mongodb用法分析
2017/08/16 PHP
参考:关于Javascript中实现暂停的几篇文章
2007/03/04 Javascript
用js一次改变多个input的readonly属性值的方法
2014/06/11 Javascript
node.js中的events.emitter.once方法使用说明
2014/12/10 Javascript
javascript正则表达式使用replace()替换手机号的方法
2015/01/19 Javascript
Node.js中child_process实现多进程
2015/02/03 Javascript
jquery实现简单的无缝滚动
2015/04/15 Javascript
深入理解Java线程编程中的阻塞队列容器
2015/12/07 Javascript
一步步教大家编写酷炫的导航栏js+css实现
2016/03/14 Javascript
js实现为a标签添加事件的方法(使用闭包循环)
2016/08/02 Javascript
angular源码学习第一篇 setupModuleLoader方法
2016/10/20 Javascript
微信小程序 实现tabs选项卡效果实例代码
2016/10/31 Javascript
select下拉框插件jquery.editable-select详解
2017/01/22 Javascript
拖动时防止选中
2017/02/03 Javascript
js实现分页功能
2017/05/24 Javascript
js学习心得_一个简单的动画库封装tween.js
2017/07/14 Javascript
Express使用html模板的详细代码
2017/09/18 Javascript
js中apply()和call()的区别与用法实例分析
2018/08/14 Javascript
详解Vue中Axios封装API接口的思路及方法
2020/10/10 Javascript
[04:00]黄浦江畔,再会英雄——完美世界DOTA2 TI9应援视频
2019/07/31 DOTA
python实现根据图标提取分类应用程序实例
2014/09/28 Python
编写Python脚本把sqlAlchemy对象转换成dict的教程
2015/05/29 Python
获取python文件扩展名和文件名方法
2018/02/02 Python
Python中交换两个元素的实现方法
2018/06/29 Python
搞定这套Python爬虫面试题(面试会so easy)
2019/04/03 Python
Python 函数list&amp;read&amp;seek详解
2019/08/28 Python
python matplotlib画盒图、子图解决坐标轴标签重叠的问题
2020/01/19 Python
德国大型的家具商店:Pharao24.de
2016/10/02 全球购物
电气自动化自荐信
2013/10/10 职场文书
策划总监岗位职责
2014/02/16 职场文书
领导干部保密承诺书
2014/08/30 职场文书
教师工作决心书
2015/02/04 职场文书
2016年庆“七一”主题党日活动总结
2016/04/05 职场文书