<!DOCTYPE html>
<html>
<head><meta http-equiv="Content-Type" content="text/html; charset=gb2312" /><title>俄罗斯方块</title><script type="text/javascript">var TETRIS_ROWS = 20;var TETRIS_COLS = 14;var CELL_SIZE = 24;// 没方块是0var NO_BLOCK = 0;var tetris_canvas;var tetris_ctx;// 记录当前积分var curScore = 0;// 记录当前速度var curSpeed = 1;// 记录曾经的最高积分var maxScore = 0;var curScoreEle, curSpeedEle, maxScoreEle;var curTimer;// 记录当前是否游戏中的旗标var isPlaying = true;// 记录正在下掉的四个方块var currentFall;// 该数组用于记录底下已经固定下来的方块。var tetris_status = [];for (var i = 0; i < TETRIS_ROWS ; i++) {tetris_status[i] = [];for (var j = 0; j < TETRIS_COLS ; j++) {tetris_status[i][j] = NO_BLOCK;}}// 定义方块的颜色colors = ["#fff", "#f00", "#0f0", "#00f", "#c60", "#f0f", "#0ff", "#609"];// 定义几种可能出现的方块组合var blockArr = [// 代表第一种可能出现的方块组合:Z[{ x: TETRIS_COLS / 2 - 1, y: 0, color: 1 },{ x: TETRIS_COLS / 2, y: 0, color: 1 },{ x: TETRIS_COLS / 2, y: 1, color: 1 },{ x: TETRIS_COLS / 2 + 1, y: 1, color: 1 }],// 代表第二种可能出现的方块组合:反Z[{ x: TETRIS_COLS / 2 + 1, y: 0, color: 2 },{ x: TETRIS_COLS / 2, y: 0, color: 2 },{ x: TETRIS_COLS / 2, y: 1, color: 2 },{ x: TETRIS_COLS / 2 - 1, y: 1, color: 2 }],// 代表第三种可能出现的方块组合: 田[{ x: TETRIS_COLS / 2 - 1, y: 0, color: 3 },{ x: TETRIS_COLS / 2, y: 0, color: 3 },{ x: TETRIS_COLS / 2 - 1, y: 1, color: 3 },{ x: TETRIS_COLS / 2, y: 1, color: 3 }],// 代表第四种可能出现的方块组合:L[{ x: TETRIS_COLS / 2 - 1, y: 0, color: 4 },{ x: TETRIS_COLS / 2 - 1, y: 1, color: 4 },{ x: TETRIS_COLS / 2 - 1, y: 2, color: 4 },{ x: TETRIS_COLS / 2, y: 2, color: 4 }],// 代表第五种可能出现的方块组合:J[{ x: TETRIS_COLS / 2, y: 0, color: 5 },{ x: TETRIS_COLS / 2, y: 1, color: 5 },{ x: TETRIS_COLS / 2, y: 2, color: 5 },{ x: TETRIS_COLS / 2 - 1, y: 2, color: 5 }],// 代表第六种可能出现的方块组合 : 条[{ x: TETRIS_COLS / 2, y: 0, color: 6 },{ x: TETRIS_COLS / 2, y: 1, color: 6 },{ x: TETRIS_COLS / 2, y: 2, color: 6 },{ x: TETRIS_COLS / 2, y: 3, color: 6 }],// 代表第七种可能出现的方块组合 : ┵[{ x: TETRIS_COLS / 2, y: 0, color: 7 },{ x: TETRIS_COLS / 2 - 1, y: 1, color: 7 },{ x: TETRIS_COLS / 2, y: 1, color: 7 },{ x: TETRIS_COLS / 2 + 1, y: 1, color: 7 }]];// 定义初始化正在下掉的方块var initBlock = function () {var rand = Math.floor(Math.random() * blockArr.length);// 随机生成正在下掉的方块currentFall = [{x: blockArr[rand][0].x, y: blockArr[rand][0].y, color: blockArr[rand][0].color},{x: blockArr[rand][1].x, y: blockArr[rand][1].y, color: blockArr[rand][1].color},{x: blockArr[rand][2].x, y: blockArr[rand][2].y, color: blockArr[rand][2].color},{x: blockArr[rand][3].x, y: blockArr[rand][3].y, color: blockArr[rand][3].color}];};// 定义一个创建canvas组件的函数var createCanvas = function (rows, cols, cellWidth, cellHeight) {tetris_canvas = document.createElement("canvas");// 设置canvas组件的高度、宽度tetris_canvas.width = cols * cellWidth;tetris_canvas.height = rows * cellHeight;// 设置canvas组件的边框tetris_canvas.style.border = "1px solid black";// 获取canvas上的绘图APItetris_ctx = tetris_canvas.getContext('2d');// 开始创建路径tetris_ctx.beginPath();// 绘制横向网络对应的路径for (var i = 1 ; i < TETRIS_ROWS ; i++) {tetris_ctx.moveTo(0, i * CELL_SIZE);tetris_ctx.lineTo(TETRIS_COLS * CELL_SIZE, i * CELL_SIZE);}// 绘制竖向网络对应的路径for (var i = 1 ; i < TETRIS_COLS ; i++) {tetris_ctx.moveTo(i * CELL_SIZE, 0);tetris_ctx.lineTo(i * CELL_SIZE, TETRIS_ROWS * CELL_SIZE);}tetris_ctx.closePath();// 设置笔触颜色tetris_ctx.strokeStyle = "#aaa";// 设置线条粗细tetris_ctx.lineWidth = 0.3;// 绘制线条tetris_ctx.stroke();}// 绘制俄罗斯方块的状态var drawBlock = function () {for (var i = 0; i < TETRIS_ROWS ; i++) {for (var j = 0; j < TETRIS_COLS ; j++) {// 有方块的地方绘制颜色if (tetris_status[i][j] != NO_BLOCK) {// 设置填充颜色tetris_ctx.fillStyle = colors[tetris_status[i][j]];// 绘制矩形tetris_ctx.fillRect(j * CELL_SIZE + 1, i * CELL_SIZE + 1, CELL_SIZE - 2, CELL_SIZE - 2);}// 没有方块的地方绘制白色else {// 设置填充颜色tetris_ctx.fillStyle = 'white';// 绘制矩形tetris_ctx.fillRect(j * CELL_SIZE + 1, i * CELL_SIZE + 1, CELL_SIZE - 2, CELL_SIZE - 2);}}}}// 当页面加载完成时,执行该函数里的代码。window.onload = function () {// 创建canvas组件createCanvas(TETRIS_ROWS, TETRIS_COLS, CELL_SIZE, CELL_SIZE);document.body.appendChild(tetris_canvas);curScoreEle = document.getElementById("curScoreEle");curSpeedEle = document.getElementById("curSpeedEle");maxScoreEle = document.getElementById("maxScoreEle");// 读取Local Storage里的tetris_status记录var tmpStatus = localStorage.getItem("tetris_status");tetris_status = tmpStatus == null ? tetris_status : JSON.parse(tmpStatus);// 把方块状态绘制出来drawBlock();// 读取Local Storage里的curScore记录curScore = localStorage.getItem("curScore");curScore = curScore == null ? 0 : parseInt(curScore);curScoreEle.innerHTML = curScore;// 读取Local Storage里的maxScore记录maxScore = localStorage.getItem("maxScore");maxScore = maxScore == null ? 0 : parseInt(maxScore);maxScoreEle.innerHTML = maxScore;// 读取Local Storage里的curSpeed记录curSpeed = localStorage.getItem("curSpeed");curSpeed = curSpeed == null ? 1 : parseInt(curSpeed);curSpeedEle.innerHTML = curSpeed;// 初始化正在下掉的方块initBlock();// 控制每隔固定时间执行一次向下”掉“curTimer = setInterval("moveDown();", 500 / curSpeed);}// 判断是否有一行已满var lineFull = function () {// 依次遍历每一行for (var i = 0; i < TETRIS_ROWS ; i++) {var flag = true;// 遍历当前行的每个单元格for (var j = 0 ; j < TETRIS_COLS ; j++) {if (tetris_status[i][j] == NO_BLOCK) {flag = false;break;}}// 如果当前行已全部有方块了if (flag) {// 将当前积分增加100curScoreEle.innerHTML = curScore += 100;// 记录当前积分localStorage.setItem("curScore", curScore);// 如果当前积分达到升级极限。if (curScore >= curSpeed * curSpeed * 500) {curSpeedEle.innerHTML = curSpeed += 1;// 使用Local Storage记录curSpeed。localStorage.setItem("curSpeed", curSpeed);clearInterval(curTimer);curTimer = setInterval("moveDown();", 500 / curSpeed);}// 把当前行的所有方块下移一行。for (var k = i ; k > 0 ; k--) {for (var l = 0; l < TETRIS_COLS ; l++) {tetris_status[k][l] = tetris_status[k - 1][l];}}// 消除方块后,重新绘制一遍方块drawBlock();      //②}}}// 控制方块向下掉。var moveDown = function () {// 定义能否下掉的旗标var canDown = true;    //①// 遍历每个方块,判断是否能向下掉for (var i = 0 ; i < currentFall.length ; i++) {// 判断是否已经到“最底下”if (currentFall[i].y >= TETRIS_ROWS - 1) {canDown = false;break;}// 判断下一格是否“有方块”, 如果下一格有方块,不能向下掉if (tetris_status[currentFall[i].y + 1][currentFall[i].x] != NO_BLOCK) {canDown = false;break;}}// 如果能向下“掉”if (canDown) {// 将下移前的每个方块的背景色涂成白色for (var i = 0 ; i < currentFall.length ; i++) {var cur = currentFall[i];// 设置填充颜色tetris_ctx.fillStyle = 'white';// 绘制矩形tetris_ctx.fillRect(cur.x * CELL_SIZE + 1, cur.y * CELL_SIZE + 1, CELL_SIZE - 2, CELL_SIZE - 2);}// 遍历每个方块, 控制每个方块的y坐标加1。// 也就是控制方块都下掉一格for (var i = 0 ; i < currentFall.length ; i++) {var cur = currentFall[i];cur.y++;}// 将下移后的每个方块的背景色涂成该方块的颜色值for (var i = 0 ; i < currentFall.length ; i++) {var cur = currentFall[i];// 设置填充颜色tetris_ctx.fillStyle = colors[cur.color];// 绘制矩形tetris_ctx.fillRect(cur.x * CELL_SIZE + 1, cur.y * CELL_SIZE + 1, CELL_SIZE - 2, CELL_SIZE - 2);}}// 不能向下掉else {// 遍历每个方块, 把每个方块的值记录到tetris_status数组中for (var i = 0 ; i < currentFall.length ; i++) {var cur = currentFall[i];// 如果有方块已经到最上面了,表明输了if (cur.y < 2) {// 清空Local Storage中的当前积分值、游戏状态、当前速度localStorage.removeItem("curScore");localStorage.removeItem("tetris_status");localStorage.removeItem("curSpeed");if (confirm("您已经输了!是否参数排名?")) {// 读取Local Storage里的maxScore记录maxScore = localStorage.getItem("maxScore");maxScore = maxScore == null ? 0 : maxScore;// 如果当前积分大于localStorage中记录的最高积分if (curScore >= maxScore) {// 记录最高积分localStorage.setItem("maxScore", curScore);}}// 游戏结束isPlaying = false;// 清除计时器clearInterval(curTimer);return;}// 把每个方块当前所在位置赋为当前方块的颜色值tetris_status[cur.y][cur.x] = cur.color;}// 判断是否有“可消除”的行lineFull();// 使用Local Storage记录俄罗斯方块的游戏状态localStorage.setItem("tetris_status", JSON.stringify(tetris_status));// 开始一组新的方块。initBlock();}}// 定义左移方块的函数var moveLeft = function () {// 定义能否左移的旗标var canLeft = true;for (var i = 0 ; i < currentFall.length ; i++) {// 如果已经到了最左边,不能左移if (currentFall[i].x <= 0) {canLeft = false;break;}// 或左边的位置已有方块,不能左移if (tetris_status[currentFall[i].y][currentFall[i].x - 1] != NO_BLOCK) {canLeft = false;break;}}// 如果能左移if (canLeft) {// 将左移前的每个方块的背景色涂成白色for (var i = 0 ; i < currentFall.length ; i++) {var cur = currentFall[i];// 设置填充颜色tetris_ctx.fillStyle = 'white';// 绘制矩形tetris_ctx.fillRect(cur.x * CELL_SIZE + 1, cur.y * CELL_SIZE + 1, CELL_SIZE - 2, CELL_SIZE - 2);}// 左移所有正在下掉的方块for (var i = 0 ; i < currentFall.length ; i++) {var cur = currentFall[i];cur.x--;}// 将左移后的每个方块的背景色涂成方块对应的颜色for (var i = 0 ; i < currentFall.length ; i++) {var cur = currentFall[i];// 设置填充颜色tetris_ctx.fillStyle = colors[cur.color];// 绘制矩形tetris_ctx.fillRect(cur.x * CELL_SIZE + 1, cur.y * CELL_SIZE + 1, CELL_SIZE - 2, CELL_SIZE - 2);}}}// 定义右移方块的函数var moveRight = function () {// 定义能否右移的旗标var canRight = true;for (var i = 0 ; i < currentFall.length ; i++) {// 如果已到了最右边,不能右移if (currentFall[i].x >= TETRIS_COLS - 1) {canRight = false;break;}// 如果右边的位置已有方块,不能右移if (tetris_status[currentFall[i].y][currentFall[i].x + 1] != NO_BLOCK) {canRight = false;break;}}// 如果能右移if (canRight) {// 将右移前的每个方块的背景色涂成白色for (var i = 0 ; i < currentFall.length ; i++) {var cur = currentFall[i];// 设置填充颜色tetris_ctx.fillStyle = 'white';// 绘制矩形tetris_ctx.fillRect(cur.x * CELL_SIZE + 1, cur.y * CELL_SIZE + 1, CELL_SIZE - 2, CELL_SIZE - 2);}// 右移所有正在下掉的方块for (var i = 0 ; i < currentFall.length ; i++) {var cur = currentFall[i];cur.x++;}// 将右移后的每个方块的背景色涂成各方块对应的颜色for (var i = 0 ; i < currentFall.length ; i++) {var cur = currentFall[i];// 设置填充颜色tetris_ctx.fillStyle = colors[cur.color];// 绘制矩形tetris_ctx.fillRect(cur.x * CELL_SIZE + 1, cur.y * CELL_SIZE + 1, CELL_SIZE - 2, CELL_SIZE - 2);}}}// 定义旋转方块的函数var rotate = function () {// 定义记录能否旋转的旗标var canRotate = true;for (var i = 0 ; i < currentFall.length ; i++) {var preX = currentFall[i].x;var preY = currentFall[i].y;// 始终以第三个方块作为旋转的中心,// i == 2时,说明是旋转的中心if (i != 2) {// 计算方块旋转后的x、y坐标var afterRotateX = currentFall[2].x + preY - currentFall[2].y;var afterRotateY = currentFall[2].y + currentFall[2].x - preX;// 如果旋转后所在位置已有方块,表明不能旋转if (tetris_status[afterRotateY][afterRotateX + 1] != NO_BLOCK) {canRotate = false;break;}// 如果旋转后的坐标已经超出了最左边边界if (afterRotateX < 0 || tetris_status[afterRotateY - 1][afterRotateX] != NO_BLOCK) {moveRight();afterRotateX = currentFall[2].x + preY - currentFall[2].y;afterRotateY = currentFall[2].y + currentFall[2].x - preX;break;}if (afterRotateX < 0 || tetris_status[afterRotateY - 1][afterRotateX] != NO_BLOCK) {moveRight();break;}// 如果旋转后的坐标已经超出了最右边边界if (afterRotateX >= TETRIS_COLS - 1 ||tetris_status[afterRotateY][afterRotateX + 1] != NO_BLOCK) {moveLeft();afterRotateX = currentFall[2].x + preY - currentFall[2].y;afterRotateY = currentFall[2].y + currentFall[2].x - preX;break;}if (afterRotateX >= TETRIS_COLS - 1 ||tetris_status[afterRotateY][afterRotateX + 1] != NO_BLOCK) {moveLeft();break;}}}// 如果能旋转if (canRotate) {// 将旋转移前的每个方块的背景色涂成白色for (var i = 0 ; i < currentFall.length ; i++) {var cur = currentFall[i];// 设置填充颜色tetris_ctx.fillStyle = 'white';// 绘制矩形tetris_ctx.fillRect(cur.x * CELL_SIZE + 1, cur.y * CELL_SIZE + 1, CELL_SIZE - 2, CELL_SIZE - 2);}for (var i = 0 ; i < currentFall.length ; i++) {var preX = currentFall[i].x;var preY = currentFall[i].y;// 始终以第三个方块作为旋转的中心,// i == 2时,说明是旋转的中心if (i != 2) {currentFall[i].x = currentFall[2].x +preY - currentFall[2].y;currentFall[i].y = currentFall[2].y +currentFall[2].x - preX;}}// 将旋转后的每个方块的背景色涂成各方块对应的颜色for (var i = 0 ; i < currentFall.length ; i++) {var cur = currentFall[i];// 设置填充颜色tetris_ctx.fillStyle = colors[cur.color];// 绘制矩形tetris_ctx.fillRect(cur.x * CELL_SIZE + 1, cur.y * CELL_SIZE + 1, CELL_SIZE - 2, CELL_SIZE - 2);}}}window.focus();// 为窗口的按键事件绑定事件监听器window.onkeydown = function (evt) {switch (evt.keyCode) {// 按下了“向下”箭头case 40:if (!isPlaying)return;moveDown();break;// 按下了“向左”箭头case 37:if (!isPlaying)return;moveLeft();break;// 按下了“向右”箭头case 39:if (!isPlaying)return;moveRight();break;// 按下了“向上”箭头case 38:if (!isPlaying)return;rotate();break;}}</script><style type="text/css">body > div {font-size: 13pt;padding-bottom: 8px;}span {font-size: 20pt;color: red;}</style>
</head>
<body><h2>俄罗斯方块</h2><div style="width:336px;">&nbsp;<div style="float:left;">速度:<span id="curSpeedEle"></span> 当前积分:<span id="curScoreEle"></span></div><div style="float:right;">最高积分:<span id="maxScoreEle"></span></div></div>
</body>
</html>

Javascript 设计游戏相关推荐

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

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

  2. 视频教程-JavaScript拼图游戏视频教程-JavaScript

    JavaScript拼图游戏视频教程 拥有6年web前端和后端开发经验,4年授课经验,还曾在百度专业培训过网络营销课程,曾就职于联想集团和当当网,不仅有丰富的项目实战经验还有营销经验,综合实力较强,后 ...

  3. HTML5期末大作业:游戏网页设计——游戏大全6页(代码质量好) 学生DW网页设计作业源码 web课程设计网页规划与设计

    HTML5期末大作业:游戏网页设计--游戏大全6页(代码质量好) 学生DW网页设计作业源码 web课程设计网页规划与设计 HTML+CSS+JavaScript(毕业设计) 常见网页设计作业题材有 个 ...

  4. HTML5游戏开发进阶指南(亚马逊5星畅销书,教你用HTML5和JavaScript构建游戏!)

    HTML5游戏开发进阶指南(亚马逊5星畅销书,教你用HTML5和JavaScript构建游戏!) [印]香卡(Shankar,A.R.) 著 谢光磊 译 ISBN 978-7-121-21226-0 ...

  5. 《JavaScript设计与开发新思维》——1.7 JavaScript编程目标

    本节书摘来自异步社区<JavaScript设计与开发新思维>一书中的第1章,第1.7节,作者:[美]Larry Ullman著,更多章节内容可以访问云栖社区"异步社区" ...

  6. 少儿编程:玩游戏不如设计游戏!

    当手机成为必须品之后,不仅是成人开始对它产生依赖,作为下一代的孩子,也深受其影响.手机.平板电脑取代了洋娃娃小汽车在孩子们心中的位置,游戏.动画成为日常,家长在感叹孩子聪明的同时,又担心孩子会&quo ...

  7. 如何高效设计游戏——塔防游戏设计方案

    前言 目前国内市场的游戏普遍为一些带有"快餐特色的RPG"游戏居多,并且这一类型的游戏的设计思路已经发展成为游戏开发者们"月经"一样的存在,有很多人" ...

  8. 某公司要开发新游戏,请用面向对象的思想,设计游戏中的蛇怪和蜈蚣精

    某公司要开发新游戏,请用面向对象的思想,设计游戏中的蛇怪和蜈蚣精 设定 蛇怪类: 属性包括:怪物名字,生命值,攻击力 方法包括:攻击,移动(曲线移动),补血(当生命值<10时,可以补加20生命值 ...

  9. MySQL - 设计游戏用户信息表

    设计游戏用户信息表 实现用户登陆模块,具体需求如下: 游戏玩家访问游戏客户端,通过客户端界面输入用户名和密码 在游戏玩家点击"确认"后,客户端连接至数据库服务器对用户名和密码进行确 ...

最新文章

  1. careercup-高等难度 18.5
  2. 计算机在外语专业中有哪些应用,CALL(3):计算机在外语教学中的应用
  3. 计算机主机组成实验,计算机组成原理实验-运算器组成实验报告
  4. FPGA数字信号处理(27)卷积编码器与Viterbi译码器设计
  5. 笔记本计算机运行程序,这几招让你的笔记本电脑运行速度变快 必学技巧
  6. 《阵列信号处理及MATLAB实现》绪论、矩阵代数相关内容总结笔记
  7. 新计算机如何用光盘安装系统,无光驱怎么重装系统|新电脑无光驱重装系统步骤...
  8. HC-05,HC-06AT指令
  9. 做了两年P7面试官,谈谈我认为的阿里人才画像,你配吗?
  10. Microsoft CSP简介
  11. WWDC22:“花里胡哨”的苹果又会给我们带来什么惊喜呢?
  12. java地图点线面_点线面类型互转
  13. 二叉树的深度和平衡二叉树的深度
  14. 百度地图API批量地址转坐标(支持Excel上传,附案例)
  15. Disql、Dexp、Dimp使用
  16. viper4android md,DCS F-16CM VIPER毒蛇 中文指南 14.2AN/ARC-164 UHF无线电
  17. Elasticsearch插件之分词器
  18. 第一范式、第二范式、第三范式、巴斯-科德范式、第四范式、主码、候选码、码详解
  19. 易语言写微信群AI人工智能机器人,自动对话、聊天、发消息
  20. Window11移动硬盘无法正常弹出怎么办?

热门文章

  1. 50. 测试题(答案详析)
  2. STM32的心率监测装置+OLED心率波形显示
  3. 封装了一些 python 爬虫技巧,开箱即用
  4. 魔域富甲天下mysql打不开_《魔域》魔域3.2无敌版之富甲天下心得
  5. 如何穷养儿子,富养女儿
  6. 优雅编程之这样取名字,你就正常了!
  7. 自如房源爬取及简单分析——python语言实现
  8. Windows 11彻底禁用IE浏览器,银行、政府、学校等老网站该怎么办?
  9. Mac隐藏显示隐藏文件方法
  10. symfony nusoap complextype