javascript+html做一个俄罗斯方块的小游戏

原创 2016年09月17日 11:09:46

本来写了上篇的,可是写得不太好,而且方块的左右移动那里还有bug,索性把上篇删了,只用一篇来说。


效果图



源代码:

百度云:源码

不要用IE浏览器打开,不然会变成......

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>俄罗斯方块</title>
</head>

<style type="text/css">
.center
{
	position:absolute;
	left:50%;
	width:800px;
	margin-left:-200px;
}
</style>

<body onload="init()">
<h1 id="scene" class = "center" style="line-height:100%"></h1>
<div style="float:left">
<h2 id="msg" >score:0</h2>
<h2 id="nextBlocks" style="line-height:100%"></h2>
<button id = "btn" type="button" onclick="onBtnClick()">开始游戏</button>
</div>

<script>

var KEY_UP = 38;			//上箭头
var KEY_DOWN = 40;			//下箭头
var KEY_LEFT = 37;			//左箭头
var KEY_RIGHT = 39;			//右箭头
var KEY_SPACE = 32;			//空格键
var BLOCK_SOLID = "█";		//实心方块
var BLOCK_HOLLOW = "□";		//空心方块
var BLOCK_TYPE_NUM = 7;		//方块的种类

var width = 10;				//宽
var height = 20;			//高
var scene = new Array();	//场景
var sleepTime = 400;		//延时时间
var blocks;					//方块
var score = 0;				//分数
var highestScore = 0;		//最高分
var nextBlocksType;			//下一个方块的种类
var isGameOver = true;		//游戏是否已经结束
var interval;				//定时器

document.onkeydown = onKeyDown;

//按键监听
function onKeyDown(e){
	if(isGameOver) return;
	switch(e.which){
		case KEY_LEFT: 
			//向左移动
			moveBlocks(-1);
			break;
		case KEY_RIGHT:
			//向右移动
			moveBlocks(1);
			break;
		case KEY_DOWN:
			//跳到底部
			skipToBottom();
			break;
		case KEY_UP:
			//旋转方块
			rotateBlocks();
			break;
		case KEY_SPACE:
			//加速移动
			drop();
			break;
	}
	printScene();
}

//按钮
function onBtnClick(){
	isGameOver = false;
	document.getElementById("btn").disabled = true;
	//打开方块下落的定时器
	interval = window.setInterval(function(){drapBlock()}, sleepTime);
	getNextBlocksType();
	produceBlocks();
	printMsg("score:0");
	init();
}

//初始化
function init(){
	initScene();
	drawFrame();
	printScene();
}

//产生方块
function produceBlocks(){
	blocks = getBlocksByType(nextBlocksType);
	getNextBlocksType();
	printNextBlocks();
}

//随机获取下一次的方块
function getNextBlocksType(){
	do{
		nextBlocksType = Math.round(Math.random() * BLOCK_TYPE_NUM);
	}while(nextBlocksType == 0);
	nextBlocksType--;
}

//获取指定类型的方块
function getBlocksByType(type){
	var tBlocks = new Object();
	tBlocks.x = new Array();
	tBlocks.y = new Array();
	switch(type){
		case 0:	//T
			for(var i = 0; i < 3; i++){
				tBlocks.x[i] = width / 2 + i - 1;
				tBlocks.y[i] = -1; 
			}
			tBlocks.x[3] = width / 2;
			tBlocks.y[3] = -2;
			tBlocks.center = 1;
			break;
		case 1:	//I
			for(var i = 0; i <= 3; i++){
				tBlocks.x[i] = width / 2 - i + 1;
				tBlocks.y[i] = -1;
			}
			tBlocks.center = 1;
			break;
		case 2:	//O
			for(var i = 0; i < 4; i++){
				tBlocks.x[i] = width / 2 + i % 2 - 1;
				tBlocks.y[i] = -2 + parseInt(i / 2);
			}
			tBlocks.center = -1;
			break;
		case 3:	//L
			tBlocks.x[0] = width / 2 - 1;
			tBlocks.y[0] = -2;
			for(var i = 1; i < 4; i++){
				tBlocks.x[i] = width / 2 + i - 2;
				tBlocks.y[i] = -1;
			}
			tBlocks.center = 2;
			break;
		case 4:	//J
			tBlocks.x[0] = width / 2 + 1;
			tBlocks.y[0] = -2;
			for(var i = 1; i < 4; i++){
				tBlocks.x[i] = width / 2 + i - 2;
				tBlocks.y[i] = -1;
			}
			tBlocks.center = 2;
			break;
		case 5:	//Z
			tBlocks.x[0] = width / 2 - 1;
			tBlocks.y[0] = -2;
			tBlocks.x[1] = width / 2;
			tBlocks.y[1] = -2;
			tBlocks.x[2] = width / 2;
			tBlocks.y[2] = -1;
			tBlocks.x[3] = width / 2 + 1;
			tBlocks.y[3] = -1;
			tBlocks.center = 1;
			break;
		case 6:	//S
			tBlocks.x[0] = width / 2;
			tBlocks.y[0] = -2;
			tBlocks.x[1] = width / 2 + 1;
			tBlocks.y[1] = -2;
			tBlocks.x[2] = width / 2 - 1;
			tBlocks.y[2] = -1;
			tBlocks.x[3] = width / 2;
			tBlocks.y[3] = -1;
			tBlocks.center = 0;
			break;
	}
	return tBlocks;
}

//初始化屏幕数组
function initScene(){
    for(var i = 0; i < height + 2; i++){
        scene[i] = new Array();
        for(var j = 0; j < width + 2; j++){
            scene[i][j] = BLOCK_HOLLOW;
        }
    }
}

//在指定位置画点
function drawPointAt(x, y){
	drawChAt(x, y, BLOCK_SOLID);
}

//清除指定位置的点
function clearPointAt(x, y){
	drawChAt(x, y, BLOCK_HOLLOW);
}

//在指定位置是否是实心方块
function isSolidAt(x, y){
	return getChAt(x, y) == BLOCK_SOLID;
}

//在指定位置画字符
function drawChAt(x, y, s){
    scene[y + 1][x + 1] = s;
}

//获取指定位置的字符
function getChAt(x, y){
	return scene[y + 1][x + 1];
}

//画边框
function drawFrame(){	
	for(var i = 0; i < width; i++){
        drawChAt(i, -1, "─");
		drawChAt(i, height, "─");
	}
	
	for(var i = 0; i < height; i++){
        drawChAt(-1, i, "│");
		drawChAt(width, i, "│");
	}
	drawChAt(-1, height, "└");
	drawChAt(width, height, "┘");
	drawChAt(-1, -1, "┌");
	drawChAt(width, -1, "┐");
}

//绘制场景
function printScene(){
    var str = "";
    for(var i = 0; i < height + 2; i++){
        for(var j = 0; j < width + 2; j++){
			if(i > 0){
				var k;
				if(blocks != undefined){
					for(k = 0; k < blocks.x.length; k++){
						if(i == blocks.y[k] + 1 && j == blocks.x[k] + 1) break;
					}
				}
				if(blocks != undefined && k != blocks.x.length){
					str += BLOCK_SOLID;
				}else{
					str += scene[i][j];
				}
			}else{
				str += scene[i][j];
			}
        }
        str += "<br/>";
    }
    document.getElementById("scene").innerHTML = str;
}

//方块下落
function drapBlock(){
	if(isBump(0, 1)) fixBlocks();
	drop();
}

//左右移动方块,-1向左移,1向右移
function moveBlocks(dir){
	if(!isBump(dir, 0))
		move(dir);
	printScene();
}

//移动方块
function move(dir){
	for(var i = 0, count = blocks.x.length; i < count; i++){
		blocks.x[i] += dir;
	}
}

//方块跳到底部
function skipToBottom(){
	while(drop()){}
	fixBlocks();
}

//方块下落
function drop(){
	if(isBump(0, 1)) return false;
	
	for(var i = 0, count = blocks.x.length; i < count; i++){
		blocks.y[i]++;
	}
	printScene();
	return true;
}

//旋转方块
function rotateBlocks(){
	if(blocks.center == -1) return;	//不能旋转的方块

	rotate(1);
	//检测到碰撞,返回原来的位置
	if(isBump(0, 0)) rotate(-1);	//反向旋转,即返回原来的位置

	printScene();
}

//旋转, 1顺时针,-1逆时针
function rotate(dir){
	var cX = blocks.x[blocks.center];
	var cY = blocks.y[blocks.center];
	for(var i = 0, count = blocks.x.length; i < count; i++){
		var xt = blocks.x[i];
		if(dir == 1){
			blocks.x[i] = cX + cY - blocks.y[i];
			blocks.y[i] = xt - cX + cY;
		}else{
			blocks.x[i] = cX - cY + blocks.y[i];
			blocks.y[i] = cX + cY - xt;
		}
	}
}

//固定方块
function fixBlocks(){
	for(var i = 0, count = blocks.x.length; i < count; i++){
		if(blocks.y[i] < 0){	//游戏结束
			gameOver();
			return;
		}
		drawPointAt(blocks.x[i], blocks.y[i]);
	}
	produceBlocks();
	elimLine();
}

//消除方块检测,有填满一行的就消去
function elimLine(){
	for(var y = 0; y < height; y++){
		var x;
		for(x = 0; x < width; x++){
			if(getChAt(x, y) != BLOCK_SOLID) break;
		}
		if(x == width){
			clearLine(y);
			score++;
		}
	}
	printMsg("score:" + score);
}

//消除一行
function clearLine(y){
	for(; y > 1; y--){
		for(var x = 0; x < width; x++){
			drawChAt(x, y, getChAt(x, y - 1));
			drawChAt(x, y - 1, BLOCK_HOLLOW);
		}
	}
}

//输出信息
function printMsg(s){
	document.getElementById("msg").innerHTML = s;
}

//显示下一个方块
function printNextBlocks(){
	var tBlocks = getBlocksByType(nextBlocksType);
	var str = "";
	for(var i = 0; i < 4; i++){
		for(var j = 0; j < 4; j++){
			var k;
			var count = tBlocks.x.length;
			for(k = 0; k < count; k++){
				if(i == tBlocks.y[k] + 3 && j == tBlocks.x[k] - width / 2 + 2) break;
			}
			if(k == count) str += " ";
			else str += BLOCK_SOLID;
		}
		str += "<br/>";
	}
	document.getElementById("nextBlocks").innerHTML = str;
}

//是否有碰撞, dx和dy为偏移量
function isBump(dx, dy){
	var i;
	var count = blocks.x.length;
	for(i = 0; i < count; i++){
		if(	blocks.x[i] + dx < 0 || blocks.x[i] + dx >= width ||
			blocks.y[i] + dy >= height || 
			isSolidAt(blocks.x[i] + dx, blocks.y[i] + dy))
				return true;
	}
	return false;
}

//游戏结束
function gameOver(){
	if(highestScore < score) highestScore = score;
	printMsg("score:" + score + "<br/>highestScore:" + highestScore + "<br/>GameOver");
	isGameOver = true;
	score = 0;
	document.getElementById("btn").disabled = false;
	window.clearInterval(interval);
}

</script>
</body>

</html>



方块的种类:



方块的旋转




流程图

流程图


版权声明:本文为博主原创文章,未经博主允许不得转载。

github上的一个html5俄罗斯方块小游戏做了些简化

html 俄罗斯方块 --> --> html, body { background: #3b3d3b; ...
  • infinitewall
  • infinitewall
  • 2016年02月25日 10:23
  • 1371

使用Java实现小游戏:俄罗斯方块

使用Java实现小游戏:俄罗斯方块使用一个二维数组保存游戏的地图:// 游戏地图格子,每个格子保存一个方块,数组纪录方块的状态 private State map[][] = new State[ro...
  • zhliro
  • zhliro
  • 2015年05月15日 16:43
  • 3375

史上最短小精悍的javascript编写的俄罗斯方块游戏,仅仅60行代码

史上最短小精悍的javascript编写的俄罗斯方块游戏,仅仅60行代码,代码下载地址:http://www.zuidaima.com/share/1759652641295360.htm...
  • yaerfeng
  • yaerfeng
  • 2014年04月28日 09:52
  • 52417

Qt小游戏开发:俄罗斯方块

作为一个即将步入游戏行业的新人,手写经典小游戏是必备技能哦。 预览 由于录屏软件的问题,颜色和帧率与实际有所出入,不过不影响。 步骤 1 新建工程 建一个基类为QWidget的QT gui...
  • u012234115
  • u012234115
  • 2015年05月25日 10:43
  • 2977

shell版俄罗斯方块二:程序流程

Shell版俄罗斯方块 一、方块的表示      由于shell不能定义二维数组,所以只能用一维数组表示方块,俄罗斯方块主要可以分为7类,每一类方块都是由四类小方块构成,表示方法如下。        ...
  • Walker19900515
  • Walker19900515
  • 2015年07月28日 19:04
  • 614

as3 俄罗斯方块 优化 美化版

最近在研究俄罗斯方块(主要用于怀旧~))。下载了别人的代码来参考,发现一些bug,修改后再进行了一些美化(就是改改颜色,改改格子的形状)。 有问题可以回帖提问!!尽力回答!!希望对你有用。 要...
  • Yang9325
  • Yang9325
  • 2015年11月07日 16:15
  • 633

Java开发的游戏之四 俄罗斯方块 完整源代码

截图: 代码过长不在此贴出,所有的代码都打包在以下链接中压缩包里,包括背景图片。 源代码下载链接: http://download.csdn.net/detail/d...
  • destiny19960207
  • destiny19960207
  • 2017年02月25日 13:33
  • 568

PyQt5中文基础教程12 俄罗斯方块游戏

本章我们要制作一个俄罗斯方块游戏。 + Tetris 俄罗斯方块游戏是世界上最流行的游戏之一。是由一名叫Alexey Pajitnov的俄罗斯程序员在1985年制作的,从那时起,这个游戏就风靡了...
  • xfyangle
  • xfyangle
  • 2017年07月13日 00:04
  • 765

Shell编程实现俄罗斯方块游戏(一步步详解)一

#!/bin/bash box0=(0 0 0 1 1 0 1 1) left=5 top=5echo -e "\033[31m\033[1m"for((i = 0,j = 0;i < ${#box0...
  • jx1016038368
  • jx1016038368
  • 2016年06月04日 17:00
  • 397

JavaScript jQuery实现Tetris(俄罗斯方块)游戏代码

原文:JavaScript jQuery实现Tetris(俄罗斯方块)游戏代码 源代码下载地址:http://www.zuidaima.com/share/1882054152457216....
  • yaerfeng
  • yaerfeng
  • 2016年12月15日 10:17
  • 1346
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:javascript+html做一个俄罗斯方块的小游戏
举报原因:
原因补充:

(最多只允许输入30个字)