JS如何实现简单俄罗斯方块游戏?(附源码)

本篇文章给大家带来的内容是JS如何实现简单俄罗斯方块游戏?(附源码)。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。

简单的JS俄罗斯方块游戏源码

效果图:

1.png-600

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

<!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;
    }
}

如果有更好的方法或更多的功能,可以和我们大家一起分享哦,如有错误,欢迎联系我改正,非常感谢!!!

更多web前端知识,请查阅 HTML中文网 !!

以上就是JS如何实现简单俄罗斯方块游戏?(附源码)的详细内容,更多请关注0133技术站其它相关文章!

赞(0) 打赏
未经允许不得转载:0133技术站首页 » JavaScript 教程