搜索
您的当前位置:首页正文

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

2020-11-27 来源:抵帆知识网

简单的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代码实现俄罗斯方块游戏,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!

Top