Bootstrap

用JS写一个《俄罗斯方块》小游戏

前言

最近网上上映一部名叫《俄罗斯方块》电影,想起自己学习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(
;