千家信息网

怎么用JavaScript做俄罗斯方块游戏

发表于:2025-01-19 作者:千家信息网编辑
千家信息网最后更新 2025年01月19日,这篇文章主要为大家展示了"怎么用JavaScript做俄罗斯方块游戏",内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下"怎么用JavaScript做俄罗斯方块游
千家信息网最后更新 2025年01月19日怎么用JavaScript做俄罗斯方块游戏

这篇文章主要为大家展示了"怎么用JavaScript做俄罗斯方块游戏",内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下"怎么用JavaScript做俄罗斯方块游戏"这篇文章吧。

最终游戏效果


一开始我们先搭个框架,以便后期使用

编写外部框架

                                                                                        
分数:0 时间:0

框架效果如下:


添加内部画布,以及绘制地图

首先创建线的构造函数Line

function Line(ctx,o){                this.x=0,//x坐标                this.y=0,//y坐标                this.startX=0,//开始点x位置                this.startY=0, //开始点y位置                this.endX=0,//结束点x位置                this.endY=0;//结束点y位置                this.thin=false;//设置变细系数                this.ctx=ctx;                                this.init(o);        }        Line.prototype.init=function(o){                for(var key in o){                        this[key]=o[key];                }        }        Line.prototype.render=function(){                innerRender(this);                                function innerRender(obj){                        var ctx=obj.ctx;                        ctx.save()                        ctx.beginPath();                        ctx.translate(obj.x,obj.y);                        if(obj.thin){                                ctx.translate(0.5,0.5);                        }                        if(obj.lineWidth){//设定线宽                                ctx.lineWidth=obj.lineWidth;                        }                        if(obj.strokeStyle){                                ctx.strokeStyle=obj.strokeStyle;                        }                        //划线                      ctx.moveTo(obj.startX, obj.startY);                      ctx.lineTo(obj.endX, obj.endY);                      ctx.stroke();                      ctx.restore();                }                            return this;        }

设定参数、执行绘制等相关方法

代码如下:

function Game(el){                this.renderArr=[];//待渲染对象存储数组                this.aliveModel=[];//用来存到底的model组合                                this.score=0;//分数                this.time=0;//时间                this.moveCount=1;//计时控制器        }                Game.prototype.init=function(el,score,time){                if(!el) return ;                this.el=el;                this.scoreEL=score;                this.timeEL=time;                var canvas = document.createElement('canvas');//创建画布                canvas.style.cssText="background:darkgrey;border:1px solid grey;";//设置样式                var W = canvas.width = 300; //设置宽度                var H = canvas.height = 400;//设置高度                                el.appendChild(canvas);//添加到指定的dom对象中                                this.ctx = canvas.getContext('2d');                this.canvas=canvas;                this.w=W;                this.h=H;                                this.disX=20;//每个格子的x方向大小                this.disY=20;//每个格子的y方向大小                this.maxX=15;//x方向格子总数                this.maxY=20;//y方向格子总数                                this.control();//                this.draw();//绘制        }                //绘制地图        Game.prototype.createMap=function(){                var renderArr = this.renderArr;                var disX = this.disX;                var disY = this.disY;                var maxX=this.maxX;                var maxY=this.maxY;                var rectW = this.w;                var rectH = this.h;                var rect=null;                var color;                                for(var i=1;i

此时游戏区域的格子以及绘制如下:


再来绘制模型

模型定义:分别是一字形、田字形、二字形2种、七字形2种、凸字形等共7种。


变形定义:1字形可以变形2种、田字形不能变形,其他的都可以变形4种

模型的组成:模型是有4个小方块来组成,每个模型里面有数组blocks来存取4个小方块的x、y坐标,然后绘制出来就是模型了。

模型的变形:变形的时候就只要切换每个方块的X\Y坐标就可以达到变形的效果。

下面来创建模型的构造函数

 //模型构造函数        function Model(o){                this.blocks=[],//存储方块的数组,绘制的时候根据数组来绘制                this.type=1,//模型的形状,默认是一字形(共7种)                this.dir=1,//方向默认为1,总共4种,其中一字形为2种,田字形为1种,其他为4种                this.x=0,//x坐标(只传入第一个x,根据这个x来生成其他的x)                this.y=0,//y坐标(只传入第一个y,根据这个y来生成其他的y)                                this.init(o);        }        //初始化        Model.prototype.init=function(o){                for(var key in o){                        this[key]=o[key];                }        }

举例

添加一个创建七字形的方法(因为七字形有4种摆放方式,所以有dir来区分,怎么摆放)

//创建七字形1        Model.prototype.createQi1=function(){                var blocks=this.blocks,x=this.x,y=this.y;                switch(this.dir){                        case 1://                                blocks.push({x:x,y:y});                                blocks.push({x:x,y:y-1});                                blocks.push({x:x,y:y-2});                                blocks.push({x:x+1,y:y-2});                                break;                        case 2://                                blocks.push({x:x+2,y:y});                                blocks.push({x:x+1,y:y});                                blocks.push({x:x,y:y});                                blocks.push({x:x,y:y-1});                                break;                          case 3://                                blocks.push({x:x+1,y:y-2});                                blocks.push({x:x+1,y:y-1});                                blocks.push({x:x+1,y:y});                                blocks.push({x:x,y:y});                                break;                          case 4://                                blocks.push({x:x-2,y:y-1});                                blocks.push({x:x-1,y:y-1});                                blocks.push({x:x,y:y-1});                                blocks.push({x:x,y:y});                                break;                  }        }

创建一个七字形试试(传入的x、y是第一个放个的位置)

var model = new Model({//创建1字        x:6,y:6,fillStyle:'#0370BD',fill:true,game:this,type:5,dir:1});this.renderArr.push(model);//当前的模型this.currentModel=model;

编写变形方法(每一次变形都是按前一个模样逆时针旋转90度,修改每个小方块x、y来修改就行)

------------------------ >>>

左边这个图形要变成右边的图形,需要怎么变更呢?

-------------------->>>

标上号码就很容易明白,1还是对应的1,2还是对应的2,以此类推,只不过X\Y变了

1方块:只要x+2就可以移到指定的位置;

2方块:x、y都需要加1

3方块:y+2就可以

4方块:x-1和y+1即可

其他都是一样的道理,来写一下变形的方法

//七1变形        Model.prototype.transformQi1=function(){                var blocks = this.blocks,block2=blocks[1];                switch(this.dir){                        case 1://竖着的                                tran1();                                this.dir=2;                                break;                        case 2://横着的                                tran2();                                this.dir=3;                                break;                          case 3://竖着的                                tran3();                                this.dir=4;                                break;                        case 4://横着的                                tran4();                                this.dir=1;                                break;                                  }                 function tran1(){//变成横着的                        for(var i=0;i

给 w 和向上键添加为变形事件,同时左移动、右移动、下加速也添加好事件

//按键的控制        Game.prototype.control=function(){                var that=this;                global.addEventListener('keydown',function(e){                        //if(!that.timmer) return ;                        switch (e.keyCode){                                case 87://w                                case 38://上                                        that.currentModel.transform();//变形                                        break;                                case 83://s                                case 40://下                                        that.currentModel.move('d');//移动                                        break;                                case 65://a                                case 37://左                                        that.currentModel.move('l');//移动                                        break;                                case 68://d                                case 39://右                                        that.currentModel.move('r');//移动                                        break;                                                }                        //测试用,记得删除                        that.render();                });        }

接下来变形试试


添加移动方法

//移动        Model.prototype.move=function(dir){                var cur = this.game.currentModel,dis=1,blocks = this.blocks;                if(dir=='r'||dir=='ld'){                        dis=1                }else if(dir=='l'){                        dis=-1;                }else if(dir=='d'){                        dis=3;                }                                var stopMoveObj = this.stopMove(dir,dis),                        val=stopMoveObj.val,resDis=stopMoveObj.resDis;                if(val) {                        if(dir=='d'||dir=='ld'){//到底了                                [].push.apply(this.game.aliveModel,cur.blocks);//放到已到底的组合中                                this.game.renderArr.pop();//当前模型弹出                                this.game.clearBlock();//消除                                this.game.createModel();//绘制一个新图形                        }                                                return ;//如果返回true 则不能再往这个方向移动                }                 if(resDis>0){                        dis=resDis;                }                //更新每一个block的位置                for(var i=0;i

加入边界判断和碰撞检测(边界检测比较简单、碰撞检测在快进的时候要注意处理一下,看代码吧)

//停止移动        Model.prototype.stopMove=function(dir,dis){                var cur = this.game.currentModel,blocks = this.blocks;                                var maxX = this.game.maxX,maxY = this.game.maxY,res,temp;                for(var i=0;i=maxY-1){//到底了                                        return {val:true};                                }                        }else if(dir=='r'){                                if(block.x>=maxX-1){//到右边界了                                        return {val:true};                                }                        }else if(dir=='l'){                                if(block.x<=0){//到左边界了                                        return {val:true};                                }                        }                        //碰撞检测                        temp=this.collide(block,dis,dir);                        if(temp.val){                                return temp;                        }                        if(!res || res.resDis==0 || (temp.resDis!=0 && temp.resDis0){                                for(var i=0;i


到底后的处理


  1. 给当前的游戏对象的aliveModel数组,存取当前到底的模型所对应的4个小方块(执行render方法的时候就绘制出来)

  2. 在renderArr数组中此模型要删除

  3. 每次触底需要加入消除判断,符合条件就消除

  4. 绘制一个新的模型

绘制触底的模型方块

//绘制存底的图形        Game.prototype.aliveModelRender=function(){                var context=this.ctx;                var disX=this.disX,disY=this.disY;                context.save();                context.beginPath();                _.each(this.aliveModel,function(item){                        if(item){                                context.rect(item.x*disX+1,item.y*disY+1,disX-1,disY-1);                                //context.fillStyle='';                                context.fill();                        }                });                context.restore();        }

消除行、积分、以及下降

//消除行        Game.prototype.clearBlock=function(){                var maxX=this.maxX,aliveModel=this.aliveModel;                //将y相同的放在一起                var rowArr=[],rowObj={};                _.each(aliveModel,function(item,index){                        if(item) {                                if(!rowObj[item.y]){                                        rowObj[item.y]=[];                                }                                rowObj[item.y].push(index);                        }                });                                var that=this;                var keys = Object.keys(rowObj),row,num=0;                _.each(keys,function(k){                        row = rowObj[k];                        if(row.length>=maxX){//消除这行                                _.each(row,function(r){                                        aliveModel.splice(r,1,undefined);//先用undefined代替                                })                                                                num++;//行数计数器                                that.down(k,1);//清楚当前行                        }                })                                //完成消除                for(var i=0;i

自动往下移动、更新、显示时间、分数

//显示分数        Game.prototype.calcuScore=function(s){                this.score+=s;                this.scoreEL.innerText='分数:'+this.score;        }        //显示时间        Game.prototype.calcuTime=function(){                if(this.moveCount%4==0){                        this.time++;                        this.time_flag=false;                        this.timeEL.innerText='时间:'+this.time;                }                                this.moveCount++;        }        //向下移动        Game.prototype.move=function(dir){                var curModel= this.currentModel;                this.calcuTime();                                var endFlag = this.end();                if(endFlag) {                        this.stop();                        this.hasEnd=true;                        return ;                }                                 this.update();                this.render();        }        //更新        Game.prototype.update=function(){                this.currentModel.move('ld');        }

给开始、结束按钮加入事件

   var mainDiv = document.getElementById('mainDiv');        var score= document.getElementById('score');        var time= document.getElementById('time');                game.init(mainDiv,score,time);                function start(){                game.start()        }                function stop(){                game.stop()        }
Game.prototype.start=function(){                if(this.timmer) return ;                if(this.hasEnd){//如果是结束则需要重新开始,暂停的话就继续游戏                        this.restart();                }                this.hasEnd=false;                this.timmer = setInterval(this.move.bind(this),250);//开始定时任务        }                //重新开始        Game.prototype.restart=function(){                this.renderArr=[];//待渲染对象存储数组                this.aliveModel=[];//用来存到底的model组合                                this.score=0;//分数                this.time=0;//时间                this.moveCount=1;//计时控制器                                this.clearCanvas();                this.draw();        }        //停止任务          Game.prototype.stop=function(){                if(!this.timmer) return ;                clearInterval(this.timmer);//清除定时任务                this.timmer=null;        }        //结束        Game.prototype.end=function(){                var aliveModel = this.aliveModel;                for(var i=0;i

源码如下:

HTML

                                                                                        
分数:0 时间:0

JS

;(function(global){        var game= new Game();                function Game(el){                this.renderArr=[];//待渲染对象存储数组                this.aliveModel=[];//用来存到底的model组合                                this.score=0;//分数                this.time=0;//时间                this.moveCount=1;//计时控制器        }                Game.prototype.init=function(el,score,time){                if(!el) return ;                this.el=el;                this.scoreEL=score;                this.timeEL=time;                var canvas = document.createElement('canvas');//创建画布                canvas.style.cssText="background:darkgrey;border:1px solid grey;";//设置样式                var W = canvas.width = 300; //设置宽度                var H = canvas.height = 400;//设置高度                                el.appendChild(canvas);//添加到指定的dom对象中                                this.ctx = canvas.getContext('2d');                this.canvas=canvas;                this.w=W;                this.h=H;                                this.disX=20;//每个格子的x方向大小                this.disY=20;//每个格子的y方向大小                this.maxX=15;//x方向格子总数                this.maxY=20;//y方向格子总数                                this.control();//                this.draw();//绘制        }                //绘制地图        Game.prototype.createMap=function(){                var renderArr = this.renderArr;                var disX = this.disX;                var disY = this.disY;                var maxX=this.maxX;                var maxY=this.maxY;                var rectW = this.w;                var rectH = this.h;                var rect=null;                var color;                                for(var i=1;i=maxX){//消除这行                                _.each(row,function(r){                                        aliveModel.splice(r,1,undefined);//先用undefined代替                                })                                                                num++;//行数计数器                                that.down(k,1);//清楚当前行                        }                })                                //完成消除                for(var i=0;i0){                        dis=resDis;                }                //更新每一个block的位置                for(var i=0;i=maxY-1){//到底了                                        return {val:true};                                }                        }else if(dir=='r'){                                if(block.x>=maxX-1){//到右边界了                                        return {val:true};                                }                        }else if(dir=='l'){                                if(block.x<=0){//到左边界了                                        return {val:true};                                }                        }                        //碰撞检测                        temp=this.collide(block,dis,dir);                        if(temp.val){                                return temp;                        }                        if(!res || res.resDis==0 || (temp.resDis!=0 && temp.resDis0){                                for(var i=0;i

以上是"怎么用JavaScript做俄罗斯方块游戏"这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注行业资讯频道!

0