前言
最近网上上映一部名叫《俄罗斯方块》电影,想起自己学习JS时,编写《俄罗斯方块》小游戏程序作为练习,现在分享一下,看能不能蹭一下热度。: )
效果图
按键说明
- ↑:旋转方块
- ↓:加快方块下坠
- ←:左移方块
- →:右移方块
- D:直接让方块坠底
放马过来
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<title>Tetris</title>
<style type="text/css">
.basic{
height:20px;
width:20px;
background-color:#DBDBDB;
float:left;
margin:1px;
}
.row{
height:20px;
clear:both;
}
</style>
</head>
<body>
<div id="main">
<div id="pool" style="float:left;"></div>
<div id="nextOne" style="float:left;"></div>
<div id="sample" class="basic" style='opacity: 0;clear:right;'></div>
<div style="float:left;width:60px;">score:
<span id='score' style="font-size:200%;font-weight:bold;"></span>
level:
<span id='level' style="font-size:200%;font-weight:bold;"></span>
</div>
<div style="float:left;width:60px;">
<button id='go'>Start/Restart</button>
</div>
<div>
<script type="text/javascript" >
var tetris = {
alive:true,
init:function(){
this.view.loadBackground();
this.model.initAllFourBlockTemplate();
this.reset();
var self = this;
document.addEventListener('keydown', function(event){
self.controller.listenKeyDown4UpDownLeftRight(event, self);
});
document.getElementById('go').addEventListener("click", function(){
if(confirm("Are You Sure?")){
self.reset();
self.controller.updateTimer(self.model.level2ScoreAndInterval[self.model.level - 1][1], self);
}
});
this.controller.startTimer(this);
this.view.refreshAll(this.model);
},
reset:function(){
this.model.initAccumulatedBlocks(tetris.view);
this.model.fallingBlock = this.model.generateFourBlock(this.view);
this.model.prepareBlock = this.model.generateFourBlock(this.view);
this.model.centerFourBlock(this.view, this.model.fallingBlock);
this.alive = true;
this.model.score = 0;
this.model.level = 1;
this.model.nextScoreLine = this.model.level2ScoreAndInterval[this.model.level][0];
document.removeEventListener('keydown',this.controller.alertGameOver);
},
view:{
rowNum:25,
colNum:17,
zoneTwoRowNum:4,
zoneTwoColNum:4,
loadBackground:function(){
var pool = document.getElementById("pool");
var sample = document.getElementById("sample");
var nextOne = document.getElementById("nextOne");
var margin = 2;
var dotWidth = parseFloat(sample.offsetWidth) + margin;//基本方块宽度 + margin
function calcWidth(cNum){
return (cNum * (dotWidth + margin));
}
var poolWidth = calcWidth(this.colNum) + 'px';
var nextOneWidth = calcWidth(4) + 'px';
pool.style.width = poolWidth;
nextOne.style.width = nextOneWidth;
function createBlocks(rNum, idPrefix, cNum, rowWidth, context){
for(var i = 0; i < rNum; i++){
//
//创建行
var rDiv = document.createElement("div");
rDiv.setAttribute('id',idPrefix + 'r' + i);//
rDiv.setAttribute('class','row');
for(var j = 0; j < cNum; j++){
//
var cDiv = document.createElement("div");
cDiv.setAttribute('id', idPrefix + 'c' + j + '_r' + i);//
cDiv.setAttribute('class','basic');
rDiv.appendChild(cDiv);
}
rDiv.setAttribute('width', rowWidth);//
context.appendChild(rDiv);
}
}
createBlocks(this.rowNum, '', this.colNum, poolWidth, pool);
createBlocks(this.zoneTwoRowNum, 'n', this.zoneTwoColNum, nextOneWidth, nextOne);
document.getElementById("main").style.width
= parseFloat(poolWidth) + parseFloat(nextOneWidth) + 'px';
},
colour:['#DBDBDB','#56A36C','#EFCEE8',
'#81C2D6','#8192D6','#D9B3E6',
'#DCF7A1','#83FCD8','#E8F2FF',
'#91C6FF','#B8F788','#58D2E8',
'#F2B6B6','#E8ED51','#FFE3FB',
'#E8FF8C','#FFDEC9','#F5A433',
'#E6109B','#96C4E6','#E560CD'],
refreshScore:function(score){
document.getElementById('score').innerHTML = score;
},
refreshLevel:function(level){
document.getElementById('level').innerHTML = level;
},
refreshZoneOne:function(accumulatedBlocks, fallingBlock){
//显示 积累块组
for(var i = 0; i < accumulatedBlocks.length; i++){
for(var j = 0; j < accumulatedBlocks[i].length; j++){
document.getElementById('c' + j + '_r' + i).style.backgroundColor
= this.colour[accumulatedBlocks[i][j]];
}
}
//显示下降块
for(var i = 0; i < fallingBlock.coordinateGroup.length; i++){
var x = fallingBlock.coordinateGroup[i][0];
var y = fallingBlock.coordinateGroup[i][1];
if(y >= 0){
document.getElementById('c' + x + '_r' + y).style.backgroundColor
= this.colour[fallingBlock.colorIndex];
}
}
},
refreshZoneTwo:function(fourBlock){
for(var i = 0; i < this.zoneTwoRowNum; i++){
for(var j = 0; j < this.zoneTwoColNum; j++){
document.getElementById('nc' + i + '_r' + j).style.backgroundColor = this.colour[0];
}
}
for(var k = 0 ; k < fourBlock.coordinateGroup.length; k++){
if(fourBlock.coordinateGroup[k][1] >= 0){
document.getElementById('nc' + fourBlock.coordinateGroup[k][0] + '_r' + fourBlock.coordinateGroup[k][1]).style.backgroundColor = this.colour[fourBlock.colorIndex];
}
}
},
refreshAll:function(model){
this.refreshLevel(model.level);
this.refreshScore(model.score);
this.refreshZoneOne(model.accumulatedBlocks, model.fallingBlock);
this.refreshZoneTwo(model.prepareBlock);
},
clear:function(){
//
var pool = document.getElementById("pool");
var nextOne = document.getElementById("nextOne");
while (pool.hasChildNodes()) {
pool.removeChild(pool.childNodes[0]);
}
while(nextOne.hasChildNodes()) {
nextOne.removeChild(nextOne.childNodes[0]);
}
}
},
model:{
score:0,
level:1,
nextScoreLine:0,
accumulatedBlocks:[],//容器内堆积的块 的属性[colorIndex...]
initAccumulatedBlocks:function(view){
var result = [];
for(var i = 0; i< view.rowNum; i++){
var tmp = [];//y
for(var j = 0; j < view.colNum; j++){
tmp.push(