简单的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 <; 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 <) {
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实现俄罗斯方块游戏的更多相关文章

  1. [前端 3]纯Js制作俄罗斯方块游戏

    导读:在别人文章里看到了,然后写了一遍.结果出错了,然后调出来了,然后理解了一下,加了点注释,有一些想法.忘了在 哪一篇上面看的了,就贴不出来链接地址.原谅.呃,真没自己的东西,权当练打字了吧.其实, ...

  2. 经典 HTML5 & Javascript 俄罗斯方块游戏

    Blockrain.js 是一个使用 HTML5 & JavaScript 开发的经典俄罗斯方块游戏.只需要复制和粘贴一段代码就可以玩起来了.最重要的是,它是响应式的,无论你的显示屏多么宽都能 ...

  3. electron写俄罗斯方块游戏(Tetris)

    背景 在折腾ES6,突然想起大学时用c语言写过俄罗斯方块,本项目中主要是利用ES6的Class特性进行面向对象编程.项目采用node.js v6.2.0 + electron v1.1.0 进行桌面开 ...

  4. JS开发HTML5游戏《神奇的六边形》(一)

    近期出现一款魔性的消除类HTML5游戏<神奇的六边形>,今天我们一起来看看如何通过开源免费的青瓷引擎(www.zuoyouxi.com)来实现这款游戏. (点击图片可进入游戏体验) 因内容 ...

  5. 从零开始---控制台用c写俄罗斯方块游戏(1)

    从零开始---控制台用c写俄罗斯方块游戏(1) 很少写博文,一来自身知识有限,二来自己知道,已经有很多这样的博文了,三就是因为懒,文笔也一般,四来刚出来工作,时间也不多 之所以写这篇博文,是因为应群里 ...

  6. JS开发HTML5游戏《神奇的六边形》(二)

    近期出现一款魔性的消除类HTML5游戏<神奇的六边形>,今天我们一起来看看如何通过开源免费的青瓷引擎(www.zuoyouxi.com)来实现这款游戏. (点击图片可进入游戏体验) 因内容 ...

  7. 用C写的俄罗斯方块游戏 By: hoodlum1980 编程论坛

    /************************************ * Desc: 俄罗斯方块游戏 * By: hoodlum1980 * Email: jinfd@126.com * Dat ...

  8. java俄罗斯方块游戏代码

    java俄罗斯方块游戏代码: package com; import java.awt.Color; import java.awt.Graphics; import java.awt.event.K ...

  9. JS开发HTML5游戏《神奇的六边形》(四)

    近期出现一款魔性的消除类HTML5游戏<神奇的六边形>,今天我们一起来看看如何通过开源免费的青瓷引擎(www.zuoyouxi.com)来实现这款游戏. (点击图片可进入游戏体验) 因内容 ...

随机推荐

  1. PPT 遥控器

    1. 下载 最新版本: 百度袋鼠输入: http://daishu.baidu.com/?from=pptweb 百度PPT遥控器:http://ppt.baidu.com/ 2. 安装过程忽略 3. ...

  2. 查看Jira 使用的H2数据库 数据结构以及内容的方法

    1. 同事在研究jira 想看看jira的数据库 数据结构, 告知使用的是java的H2数据库. 如图示 2. 然后根据此内容 进行百度等. 下载 可以进行数据库连接的工具,主要找到两个,下载地址分别 ...

  3. v-if 和 v-show的区别

    简单来说,v-if 的初始化较快,但切换代价高:v-show 初始化慢,但切换成本低 1.共同点 都是动态显示DOM元素 2.区别 (1)手段: v-if是动态的向DOM树内添加或者删除DOM元素:  ...

  4. CF86D Powerful array

    题意翻译 题意:给出一个n个数组成的数列a,有t次询问,每次询问为一个[l,r]的区间,求区间内每种数字出现次数的平方×数字的值 的和. 输入:第一行2个正整数n,t. 接下来一行n个正整数,表示数列 ...

  5. SPOJ DQUERY - D-query (莫队算法|主席树|离线树状数组)

    DQUERY - D-query Given a sequence of n numbers a1, a2, ..., an and a number of d-queries. A d-query ...

  6. Rust 阴阳谜题,及纯基于代码的分析与化简

    Rust 阴阳谜题,及纯基于代码的分析与化简 雾雨魔法店专栏 https://zhuanlan.zhihu.com/marisa 来源 https://zhuanlan.zhihu.com/p/522 ...

  7. 【转】Keil ARM开发 error L6236E错误解决

    顺利创建了第一个Keil工程却发现不能完成链接,出现了一个下面这样的报错: .\Objects\demo_simple.sct(7): error: L6236E: No section matche ...

  8. suoi22 WRX知识树(dfs序)

    把一条路径拆成到根的四个链(两端点.lca和fa[lca]),然后给dfs序中链的端点做单点修改.区间查询它的子树和再加上它原来的权值就可以了 #include<bits/stdc++.h> ...

  9. java旋转图片

    /** * 旋转角度 * @param src 源图片 * @param angel 角度 * @return 目标图片 */ public static BufferedImage rotate(I ...

  10. 浅谈移动端 View 的显示过程

    作者:个推安卓开发工程师 一七 随着科技的发展,各种移动端早已成为人们日常生活中不可或缺的部分,人们使用移动端产品工作.社交.娱乐……移动端界面的流畅性已经成为影响用户体验的重要因素之一.那么你是否思 ...