示例简单,运行地址为:http://chendd.cn/demo/html/canvas/elsfk.html,得需要支持html5浏览器的环境。
实现的功能:方块旋转(W键)、自动下落、移动(ASD)、消行、快速下落(空格键)、下落阴影、游戏结束。
为实现功能:消行时的计分、等级、以及不同等级的下落速度等。
学习了xiaoE的Java版本的俄罗斯方块后,自己动手使用html5的canvas实现的,
参考效果图如下:
详细代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>俄罗斯方块</title>
<style type="text/css">
/*整个画布*/
#tetris {
border: 6px solid grey;
}
/*游戏面板*/
</style>
</head>
<body>
<canvas id="tetris" width="565" height="576"></canvas>
<script type="text/javascript">
var canvas = document.getElementById("tetris");
var context = canvas.getContext("2d");
var padding = 6,
size = 32,
minX = 0,
maxX = 10,
minY = 0,
maxY = 18,
score = 0,
level = 1;
var gameMap = new Array(); //游戏地图,二维数组
var gameTimer;
initGameMap();
//绘制垂直线条
drawGrid();
var arrays = basicBlockType();
var blockIndex = getRandomIndex();
//随机画一个方块意思意思
var block = getPointByCode(blockIndex);
context.fillStyle = getBlockColorByIndex(blockIndex);
drawBlock(block);
/**
* 初始化游戏地图
*/
function initGameMap() {
for (var i = 0; i < maxY; i++) {
var row = new Array();
for (var j = 0; j < maxX; j++) {
row[j] = false;
}
gameMap[i] = row;
}
}
/**
* 方块旋转
* 顺时针:
* A.x =O.y + O.x - B.y
* A.y =O.y - O.x + B.x
*/
function round() {
//正方形的方块不响应旋转
if (blockIndex == 4) {
return;
}
//循环处理当前的方块,找新的旋转点
for (var i = 1; i < block.length; i++) {
var o = block[0];
var point = block[i];
//旋转后的位置不能与现有格子的方块冲突
var tempX = o.y + o.x - point.y;
var tempY = o.y - o.x + point.x;
if (isOverZone(tempX, tempY)) {
return; //不可旋转
}
}
clearBlock();
//可以旋转,设置新的旋转后的坐标
for (var i = 1; i < block.length; i++) {
var o = block[0];
var point = block[i];
//旋转后的位置不能与现有格子的方块冲突
var tempX = o.y + o.x - point.y;
var tempY = o.y - o.x + point.x;
block[i] = {
x: tempX,
y: tempY
};
}
drawBlock();
}
function moveDown() {
var overFlag = canOver();
if(overFlag){
//如果不能向下移动了,将当前的方块坐标载入地图
window.clearInterval(gameTimer);
add2GameMap();
//清除游戏区域内的不同颜色的格子,使用单一颜色重新绘制地图堆积物
redrawGameMap();
return;//游戏结束
}
var flag = moveTo(0, 1);
//如果可以移动,则继续移动
if (flag) {
return;
}
//如果不能向下移动了,将当前的方块坐标载入地图
add2GameMap();
//进行消行动作
clearLines();
//清除游戏区域内的不同颜色的格子,使用单一颜色重新绘制地图堆积物
redrawGameMap();
//如果不能向下移动,则继续下一个方块
nextBlock();
}
/**
* 消行动作,返回消除的行数
*/
function clearLines() {
var clearRowList = new Array();
for (var i = 0; i < maxY; i++) {
var flag = true;
for (var j = 0; j < maxX; j++) {
if (gameMap[i][j] == false) {
flag = false;
break;
}
}
if (flag) {
clearRowList.push(i); //记录消除行号的索引
}
}
var clearRows = clearRowList.length;
//所谓的消行就是将待消除行的索引,下方所有的格子上移动
for (var x = 0; x < clearRows; x++) {
var index = clearRowList[x];
for (var i = index; i > 0; i--) {
for (var j = 0; j < maxX; j++) {
gameMap[i][j] = gameMap[i - 1][j];
}
}
}
if (clearRows > 0) {
for (var i = 0; i < maxY; i++) {
//此处可以限制满足相关条件的方块进行清除操作&& j < clearRowList[clearRows - 1]
for (var j = 0; j < maxX; j++) {
if (gameMap[i][j] == false) {
clearBlockByPoint(i, j);
}
}
}
}
}
/**
* 重绘游戏地图
*/
function redrawGameMap() {
drawGrid();
for (var i = 0; i < maxY; i++) {
for (var j = 0; j < maxX; j++) {
if (gameMap[i][j]) {
roadBlock(j, i);
}
}
}
}
/**
* 打印阴影地图
*/
function drawShadowBlock() {
var currentBlock = block;
var shadowPoints = getCanMoveDown();
if (shadowPoints != null && shadowPoints.length > 0) {
for (var i = 0; i < shadowPoints.length; i++) {
var point = shadowPoints[i];
if (point == null) {
continue;
}
var start = point.x * size;
var end = point.y * size;
context.fillStyle = "#abcdef";
context.fillRect(start, end, size, size);
context.strokeStyle = "black";
context.strokeRect(start, end, size, size);
}
}
}
/**
* 返回最多可移动到的坐标位置(统计总共可以下落多少步骤)
* @return最多可移动到的坐标位置
*/
function getCanMoveDown() {
var nps = canMove(0, 1, block);
var last = null;
if (nps != null) {
last = new Array();
while ((nps = canMove(0, 1, nps)) != null) {
if (nps != null) {
last = nps;
}
}
}
return last;
}
function canOver(){
var flag = false;
for (var i = 0; i < block.length; i++) {
var point = block[i];
var x = point.x;
var y = point.y;
if(isOverZone(x , y)){
flag = true;
break;
}
}
return flag;
}
function drawLevelScore() {
}
/**
* 将不能移动的各种填充至地图
*/
function add2GameMap() {
for (var i = 0; i < block.length; i++) {
var point = block[i];
var x = point.x;
var y = point.y;
var gameMapRow = gameMap[y]; //获取到地图的一行
gameMapRow[x] = true; //将此行中的某个格子标记为堆积物
gameMap[y] = gameMapRow; //再将行给设置回来
}
}
function moveLeft() {
moveTo(-1, 0);
}
function moveRight() {
moveTo(1, 0);
}
function quickDown() {
while (moveTo(0, 1));
}
function moveTo(moveX, moveY) {
var move = canMove(moveX, moveY, block); //判定是否可以移动
if (move == null) {
return false;
}
clearBlock();
for (var i = 0; i < block.length; i++) {
var point = block[i];
point.x = point.x + moveX;
point.y = point.y + moveY;
}
drawBlock();
return true;
}
/**
* 下一个方块
*/
function nextBlock() {
blockIndex = getRandomIndex();
block = getPointByCode(blockIndex);
context.fillStyle = getBlockColorByIndex(blockIndex);
drawBlock();
}
document.onkeypress = function(evt) {
var key = window.event "#A00000", "#A05000", "#A0A000", "#00A000", "#00A0A0", "#0000A0", "#A000A0"];
}
function getBlockColorByIndex(typeCodeIndex) {
var arrays = basicBlockColor();
return arrays[typeCodeIndex];
}
/**
* 根据编号返回指定编号的方块
* @paramtypeCodeIndex 方块编号索引
*/
function getPointByCode(typeCodeIndex) {
var arrays = basicBlockType();
return arrays[typeCodeIndex];
}
/**
* 获取随即出现方块的范围值
* @paramlens 随机数的范围
*/
function getRandomIndex() {
return parseInt(Math.random() * (arrays.length - 1), 10);
}
/**
* 绘制方块,按格子单个绘制
*/
function drawBlock() {
drawGrid();
for (var i = 0; i < block.length; i++) {
var point = block[i];
var start = point.x * size;
var end = point.y * size;
context.fillStyle = getBlockColorByIndex(blockIndex);
context.fillRect(start, end, size, size);
context.strokeStyle = "black";
context.strokeRect(start, end, size, size);
}
drawShadowBlock();
}
/**
* 绘制障碍物
*/
function roadBlock(x, y) {
context.fillStyle = "darkgray";
var start = x * size;
var end = y * size;
context.fillRect(start, end, size, size);
}
/**
* 绘制新的方块先清除之前的方块
*/
function clearBlock() {
for (var i = 0; i < block.length; i++) {
var point = block[i];
var start = point.x * size;
var end = point.y * size;
context.clearRect(start, end, size, size);
}
}
/**
* 初始化一个新的行
*/
function initGameMapRow() {
var array = new Array();
for (var i = 0; i < maxX; i++) {
array[i] = false;
}
return array;
}
/**
* 根据坐标清除指定格子的内容
* @paramx 横坐标
* @paramy 纵坐标
*/
function clearBlockByPoint(x, y) {
var start = y * size;
var end = x * size;
context.clearRect(start, end, size, size);
}
/**
* 清掉所有位置的空白格的绘图
*/
function clearAllNullPoint() {
for (var i = 0; i < maxY; i++) {
for (var j = 0; j < maxX; j++) {
if (gameMap[i][j] == false) {
clearBlockByPoint(i, j);
}
}
}
}
/**
* 绘制网格线
* @paramcontext 绘图对象
*/
function drawGrid() {
clearAllNullPoint(); //清除掉当前方块下落位置造成的阴影
context.strokeStyle = "grey"; //画笔颜色
for (var i = 0; i <= maxX; i++) {
var start = i * size;
var end = start + size;
context.beginPath();
context.moveTo(start, 0);
context.lineTo(size * i, size * maxY);
context.stroke();
context.closePath();
}
//绘制水平线条
for (var i = 0; i <= maxY; i++) {
var start = i * size;
var end = start + size;
context.beginPath();
context.moveTo(0, size * i);
context.lineTo(size * maxX, size * i);
context.stroke();
context.closePath();
}
}
</script>
</body>
</html>
以上就是HTML5 实现的一个俄罗斯方块的实例,有兴趣的小伙伴可以参考下,谢谢大家对本站的支持!
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件!
如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
白云城资源网 Copyright www.dyhadc.com
暂无“HTML5 实现的一个俄罗斯方块实例代码”评论...
稳了!魔兽国服回归的3条重磅消息!官宣时间再确认!
昨天有一位朋友在大神群里分享,自己亚服账号被封号之后居然弹出了国服的封号信息对话框。
这里面让他访问的是一个国服的战网网址,com.cn和后面的zh都非常明白地表明这就是国服战网。
而他在复制这个网址并且进行登录之后,确实是网易的网址,也就是我们熟悉的停服之后国服发布的暴雪游戏产品运营到期开放退款的说明。这是一件比较奇怪的事情,因为以前都没有出现这样的情况,现在突然提示跳转到国服战网的网址,是不是说明了简体中文客户端已经开始进行更新了呢?
更新日志
2025年10月28日
2025年10月28日
- 小骆驼-《草原狼2(蓝光CD)》[原抓WAV+CUE]
- 群星《欢迎来到我身边 电影原声专辑》[320K/MP3][105.02MB]
- 群星《欢迎来到我身边 电影原声专辑》[FLAC/分轨][480.9MB]
- 雷婷《梦里蓝天HQⅡ》 2023头版限量编号低速原抓[WAV+CUE][463M]
- 群星《2024好听新歌42》AI调整音效【WAV分轨】
- 王思雨-《思念陪着鸿雁飞》WAV
- 王思雨《喜马拉雅HQ》头版限量编号[WAV+CUE]
- 李健《无时无刻》[WAV+CUE][590M]
- 陈奕迅《酝酿》[WAV分轨][502M]
- 卓依婷《化蝶》2CD[WAV+CUE][1.1G]
- 群星《吉他王(黑胶CD)》[WAV+CUE]
- 齐秦《穿乐(穿越)》[WAV+CUE]
- 发烧珍品《数位CD音响测试-动向效果(九)》【WAV+CUE】
- 邝美云《邝美云精装歌集》[DSF][1.6G]
- 吕方《爱一回伤一回》[WAV+CUE][454M]
