自学html、css、js,欢迎指点。
游戏效果如下:
代码:Tetris.html
<!DOCTYPE html> <!-- PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" --> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <title>经典俄罗斯</title> <link rel = "stylesheet" type="text/css" href="./Tetris.css"> </head> <body background="./bg.jpg"> <!--标题模块--> <div id="title_div"><b>经典俄罗斯方块</b></div> <!--游戏区域--> <div id="left_panel"></div> <button id="start">开始</button> <button id="flush">刷新</button> <!--预告模块--> <div id="pre_tetris_div"> <div id="next_div"><b>下一个:</b></div> <div id="tetris_div"></div> </div> <!--分数模块--> <div id="info_div"> <h4>目前分数:<h4/> <div id="score_div"></div> </div> </body> <script type="text/javascript" src="Tetris.js"></script> </html>
Tetris.css
#title_div { top:70px; left:580px; font-size=28px; /*font-weight=200%;*/ position:absolute; } #left_panel { top:100px; left:450px; width:280px; height:420px; background:pink; position:absolute; border:blue solid thin; } #start { top:100px; left:740px; width:100px; height:30px; position:absolute; } #flush { top:130px; left:740px; width:100px; height:30px; position:absolute; } #pre_tetris_div { top:165px; left:740px; border:blue solid thin; background:pink; position:absolute; } #next_div { width:100px; height:20px; } #tetris_div { width:100px; height:80px; } #info_div { top:265px; left:740px; width:100px; height:255px; background:pink; border:blue solid thin; position:absolute; } #score_div { width:100px; height:20px; } .cbox { margin:1px; width:19px; height:19px; position:absolute; }
Tetris.js
var over = false, score = 0; var shapes = ("0,1,1,1,2,1,3,1;1,0,1,1,1,2,2,2;2,0,2,1,2,2,1,2;0,1,1,1,1,2,2,2;1,2,2,2,2,1,3,1;1,1,2,1,1,2,2,2;0,1,1,1,2,1,1,2").split(";"); //七种方块对应矩阵 var pre_random = Math.floor(Math.random() * shapes.length); //随机数 //预告随机数 var random = pre_random; var pre_tetris; //预告方块 function map(num) { //建立映射关系 switch (num) { case 0: //直线 return "Red"; break; case 1: //L return "Orange"; break; case 2: //反L return "Yellow"; break; case 3: //Z return "Green"; break; case 4: //反Z return "Blue"; break; case 5: //田 return "Purple"; break; case 6: //T return "Coral"; break; default: return "Yellow"; break; } //switch } //根据标签、样式创建元素 function create(tag, c) { var elm = document.createElement(tag); elm.className = c; document.body.appendChild(elm); return elm; } //预告函数:提前产生随机方块,并显示 function prediction() { random = pre_random; //保存前一个随机数 pre_random = Math.floor(Math.random() * shapes.length); //1-7 this.nextcolor = map(pre_random); this.sh = shapes[pre_random].split(","); //切记split if (pre_tetris) {} else { pre_tetris = [create("div", 'cbox'), create("div", 'cbox'), create("div", 'cbox'), create("div", 'cbox')]; } for (var i in pre_tetris) { pre_tetris[i].style.background = this.nextcolor; pre_tetris[i].style.left = this.sh[i * 2] * 20 + 745 + 'px'; pre_tetris[i].style.top = this.sh[i * 2 + 1] * 20 + 190 + 'px'; } } /** *俄罗斯方块对象模板 *包括方块行为的方法:显示、水平移动、下移、翻转、重置方块等 */ function Tetris(css, rs, x, y) { var c = css ? css : "cbox"; //样式 this.divs = [create("div", c), create("div", c), create("div", c), create("div", c)]; //this.another:重置方块 this.another = function() { //this.x = typeof x != 'undefined' ? x : 4; //this.y = typeof y != 'undefined' ? y : 0; this.x = 4; this.y = 0; this.color = map(random); //分配颜色 this.shape = rs ? rs : shapes[random].split(","); //指定或者随机方块矩阵 if (field && field.check(this.shape, this.x, this.y, 'v') == 'ban') { //判断 over = true; alert('Game over!本场你的得分为:' + score + '分'); but[1].disabled = false; return; } for (var i in this.divs) { this.divs[i].style.background = this.color; } this.show(); } //this.another //显示 this.show = function() { for (var i in this.divs) { //计算横坐标 this.divs[i].style.left = (this.shape[i * 2] * 1 + this.x) * 20 + 450 + 'px'; //450=document.getElementById("left_panel").left //计算纵坐标 this.divs[i].style.top = (this.shape[i * 2 + 1] * 1 + this.y) * 20 + 100 + 'px'; //100=document.getElementById("left_panel").top } } //this.show this.hMove = function(step) { var r = field.check(this.shape, this.x - -step, this.y, 'h'); if (r == 0) { this.x -= -step; this.show(); } } this.vMove = function() { if (field.check(this.shape, this.x, this.y - -1, 'v') == 'allow') { this.y++; this.show(); } else { score += 4; field.fixShape(this.shape, this.x, this.y); prediction(); field.findFull(); this.another(); document.getElementById("score_div").innerHTML = score; } } //逆时针翻转变换算法(Xo,Yo)->(X,Y):X=3-Yo Y=Xo this.rotate = function() { var s = this.shape; var newShape = [3 - s[1], s[0], 3 - s[3], s[2], 3 - s[5], s[4], 3 - s[7], s[6]]; var r = field.check(newShape, this.x, this.y, 'h'); if (r == 'ban') return; if (r == 0) { this.shape = newShape; this.show(); } else if (field.check(newShape, this.x - r, this.y, 'h') == 0) { this.x -= r; this.shape = newShape; this.show(); } } this.another(); } //Tetris /** *填充区域对象模板 *包含判断行满、消行、边界检测、填充面板等方法 */ function Field(w, h) { //默认值width =10,height = 20 this.width = w ? w : 10; this.height = h ? h : 20; //判断是否一行填充满 this.findFull = function() { for (var l = 0; l < this.height; l++) { var s = 0; for (var i = 0; i < this.width; i++) { s += this[l * this.width + i] ? 1 : 0; } if (s == this.width) { score += 14; this.removeLine(l); document.getElementById("score_div").innerHTML = score; } } } //消去一行算法 this.removeLine = function(line) { for (var i = 0; i < this.width; i++) { document.body.removeChild(this[line * this.width - -i]); } for (var l = line; l > 0; l--) { for (var i = 0; i < this.width; i++) { //上面的行都下移 this[l * this.width - -i] = this[(l - 1) * this.width - -i]; //如果是填充了方块的,设置其top样式 if (this[l * this.width - -i]) this[l * this.width - -i].style.top = l * 20 + 100 + 'px'; //100=document.getElementById("left_panel").top } } } //边界检测算法 this.check = function(shape, x, y, test) { var ho = 0, ve = 'allow'; for (var i = 0; i < 8; i += 2) { if (shape[i] - -x < 0 && shape[i] - -x < ho) { ho = shape[i] - -x; } else if (shape[i] - -x >= this.width && shape[i] - -x > ho) { ho = shape[i] - -x; } if (shape[i + 1] - -y >= this.height || this[shape[i] - -x + (shape[i + 1] - -y) * this.width]) { ve = 'ban'; } } if (test == 'h' && ve == 'allow') return ho > 0 ? ho - this.width - -1 : ho; else return ve; } //给面板涂上俄罗斯方块 this.fixShape = function(shape, x, y) { var fix_divs = [create("div", "cbox"), create("div", "cbox"), create("div", "cbox"), create("div", "cbox")]; var col = map(random); var j = 0; for (var i in fix_divs) { fix_divs[i].style.background = col; //计算横坐标 fix_divs[i].style.left = (shape[j * 2] * 1 - -x) * 20 + 450 + 'px'; //计算纵坐标 fix_divs[i].style.top = (shape[j * 2 + 1] * 1 - -y) * 20 + 100 + 'px'; j++; } for (var i = 0; i < 8; i += 2) { this[shape[i] - -x - -(shape[i + 1] - -y) * this.width] = fix_divs[i / 2]; } } } //Field //注册文档的方向键的onkeydown事件 document.onkeydown = function(e) { if (over) return; //Firefox只支持参数传入不支持其它方式 var e = window.event ? window.event : e; switch (e.keyCode) { case 38: //up s.rotate(); break; case 40: //down s.vMove(); break; case 37: //left s.hMove(-1); break; case 39: //right s.hMove(1); break; } } var but = document.getElementsByTagName("button"); //注册按钮事件 but[0].onclick = function game() { but[0].blur(); //按钮失焦 but[0].disabled = true; //禁用开始按钮 //but[1].disabled = true; //禁用重置按钮 s = new Tetris(); prediction(); window.setInterval("if(!over)s.vMove();", 500); } but[1].onclick = function reset() { //FF下开始按钮刷新后but[0].disabled依然是true but[0].disabled = false; location.reload(); } //创建Field的对象 var field = new Field(14, 21); //初始分数为0,完成一块+4,消去一行+14 document.getElementById("score_div").innerHTML = 0;