자바스크립트로 테트리스를 만들어 보았다.
Javascript Tetris
← : left, → : right, ↑ : rotate, ↓ down, space: drop
Level:Score:
Javascript code - expand
<script type="text/javascript"> var VK_LEFT = 37; var VK_RIGHT = 39; var VK_DOWN = 40; var VK_UP = 38; var VK_SPACE = 32; function get(obj) { return (typeof obj == "string") ? document.getElementById(obj) : obj; } function Tetris(eltId, levelElt, scoreElt, gameoverElt, nextElt) { this.init(eltId, levelElt, scoreElt, gameoverElt, nextElt); } Tetris.prototype.init = function(eltId, levelElt, scoreElt, gameoverElt, nextElt) { // map size this.MAP_WIDTH = 12; this.MAP_HEIGHT = 20; // current block this.curTet = 0; this.curRot = 0; this.curPos = {x:0, y:0}; // tet this.tet = new Array(7); this.tet[0] = new Array(2); this.tet[0][0] = new Array({x:0,y:0},{x:1,y:0},{x:2,y:0},{x:3,y:0}); this.tet[0][1] = new Array({x:0,y:0},{x:0,y:1},{x:0,y:2},{x:0,y:3}); this.tet[1] = new Array(2); this.tet[1][0] = new Array({x:0,y:0},{x:1,y:0},{x:1,y:1},{x:2,y:1}); this.tet[1][1] = new Array({x:1,y:0},{x:1,y:1},{x:0,y:1},{x:0,y:2}); this.tet[2] = new Array(2); this.tet[2][0] = new Array({x:0,y:1},{x:1,y:1},{x:1,y:0},{x:2,y:0}); this.tet[2][1] = new Array({x:0,y:0},{x:0,y:1},{x:1,y:1},{x:1,y:2}); this.tet[3] = new Array(4); this.tet[3][2] = new Array({x:0,y:0},{x:1,y:0},{x:2,y:0},{x:2,y:1}); this.tet[3][3] = new Array({x:1,y:0},{x:1,y:1},{x:1,y:2},{x:0,y:2}); this.tet[3][0] = new Array({x:0,y:0},{x:0,y:1},{x:1,y:1},{x:2,y:1}); this.tet[3][1] = new Array({x:1,y:0},{x:0,y:0},{x:0,y:1},{x:0,y:2}); this.tet[4] = new Array(4); this.tet[4][2] = new Array({x:0,y:0},{x:1,y:0},{x:2,y:0},{x:0,y:1}); this.tet[4][3] = new Array({x:1,y:0},{x:1,y:1},{x:1,y:2},{x:0,y:0}); this.tet[4][0] = new Array({x:2,y:0},{x:0,y:1},{x:1,y:1},{x:2,y:1}); this.tet[4][1] = new Array({x:1,y:2},{x:0,y:0},{x:0,y:1},{x:0,y:2}); this.tet[5] = new Array(4); this.tet[5][0] = new Array({x:0,y:1},{x:1,y:1},{x:2,y:1},{x:1,y:0}); this.tet[5][1] = new Array({x:0,y:0},{x:0,y:1},{x:0,y:2},{x:1,y:1}); this.tet[5][2] = new Array({x:0,y:0},{x:1,y:0},{x:2,y:0},{x:1,y:1}); this.tet[5][3] = new Array({x:1,y:0},{x:1,y:1},{x:1,y:2},{x:0,y:1}); this.tet[6] = new Array(1); this.tet[6][0] = new Array({x:0,y:0},{x:1,y:0},{x:0,y:1},{x:1,y:1}); // map this.map = new Array(this.MAP_HEIGHT); for (var i = 0,limit = this.map.length; i < limit; i++) { this.map[i] = new Array(this.MAP_WIDTH); for (var x = 0, xlimit = this.map[i].length; x < xlimit; x++) { this.map[i][x] = 0; } } this.empty_line = new Array(this.MAP_WIDTH); for (var x = 0, xlimit = this.MAP_WIDTH; x < xlimit; x++) {this.empty_line[x] = 0;} // screen this.elt = get(eltId); this.inspire(this.elt); // level this.level_map = new Array(1000, 900, 800, 700, 600, 500, 400, 300, 200, 100); this.level = 0; this.levelElt = get(levelElt); // score this.score = 0; this.scoreElt = get(scoreElt); // game over this.gameoverElt = get(gameoverElt); // next this.next = null; this.nextElt = get(nextElt); this.inspireNext(this.nextElt); // status this.state = "ready"; } Tetris.prototype.inspire = function (elt) { this.elt = elt; this.elt.innerHTML = ""; for (var y = 0, ylimit = this.map.length; y < ylimit; y++) { this.elt.innerHTML += "<div class='line'>"; for (var x = 0, xlimit = this.map[y].length; x < xlimit; x++) { this.elt.innerHTML += "<span id='" + (x + "_" + y) + "' class='block'>0</span>"; } this.elt.innerHTML += "</div>"; } } Tetris.prototype.inspireNext = function(nextElt) { this.nextElt = nextElt; this.nextElt.innerHTML = ""; for (var y = 0; y < 4; y++) { this.nextElt.innerHTML += "<div class='line'>"; for (var x = 0; x < 4; x++) { this.nextElt.innerHTML += "<span id='next" + (x + "_" + y) + "' class='block'>0</span>"; } this.nextElt.innerHTML += "</div>"; } } Tetris.prototype.getMapBlock = function(x, y) { return this.map[y][x]; } Tetris.prototype.setMapBlock = function(x, y, type) { this.map[y][x] = type; } Tetris.prototype.clearMap = function() { // clear map for (var y = 0; y < this.MAP_HEIGHT; y++) { for (var x = 0; x < this.MAP_WIDTH; x++) { this.setMapBlock(x, y, 0); } } } Tetris.prototype.gen = function() { this.curPos = {x:(this.MAP_WIDTH / 2) - 2,y:0}; this.curRot = 0; if (this.next == null) { this.next = Math.floor(Math.random() * 10) % 7; } this.curTet = this.next; var n = Math.floor(Math.random() * 10) % 7; this.next = (n == this.curTet) ? ((n + (Math.floor(Math.random() * 10) % 6) + 1) % 7) : n; this.dropDelay(1000); if (this.checkCollid(this.curPos, this.curTet, this.curRot)) { this.gameOver(); } } Tetris.prototype.sideWalk = function(offset) { var nextPos = {x:(this.curPos.x + offset), y:this.curPos.y}; if (!this.checkCollid(nextPos, this.curTet, this.curRot)) this.curPos = nextPos; } Tetris.prototype.down = function() { var nextPos = {x:this.curPos.x, y:(this.curPos.y + 1)}; if (!this.checkCollid(nextPos, this.curTet, this.curRot)) { this.curPos = nextPos; this.dropDelay(this.level_map[this.level]); return true; } else { this.addToMap(); this.removeFull(); this.gen(); return false; } } Tetris.prototype.rotate = function(offset) { var cnt = this.tet[this.curTet].length; var nextRot = (this.curRot + offset) % cnt; if (!this.checkCollid(this.curPos, this.curTet, nextRot)) this.curRot = nextRot; } Tetris.prototype.checkCollid = function(pos, type, rot) { var b = this.tet[type][rot]; for (var i = 0, limit = b.length; i < limit; i++) { var x = pos.x + b[i].x; var y = pos.y + b[i].y; if (x < 0 || x >= this.MAP_WIDTH) { return true; } else if (y < 0 || y >= this.MAP_HEIGHT) { return true; } else if (this.getMapBlock(x, y) != 0) { return true; } } return false; } Tetris.prototype.addToMap = function() { var elt = this.tet[this.curTet][this.curRot]; for (var i = 0, limit = elt.length; i < limit; i++) { this.setMapBlock(this.curPos.x + elt[i].x, this.curPos.y + elt[i].y, this.curTet + 1); } } Tetris.prototype.removeFull = function() { for (var y = this.MAP_HEIGHT - 1; y >= 0; y--) { var cnt = 0; for (var x = 0; x < this.MAP_WIDTH; x++) { if (this.getMapBlock(x, y) == 0) break; cnt++; } if (cnt == this.MAP_WIDTH) { for (var cy = y; cy > 0; cy--) { this.map[cy] = this.map[cy-1].slice(); } this.map[0] = this.empty_line.slice(); this.score += 25; this.level = Math.min(Math.floor((this.score / 250)), this.level_map.length - 1); y++; } } } Tetris.prototype.dropTimer = null; Tetris.prototype.drop = function(interval) { if (this.state == "start") { var ret = this.down(); this.update(); if (ret) { var me = this; clearTimeout(this.dropTimer); this.dropTimer = setTimeout(function() {me.drop(interval);}, interval); } } } Tetris.prototype.dropDelay = function(interval) { var me = this; clearTimeout(this.dropTimer); this.dropTimer = setTimeout(function() {me.drop(me.level_map[me.level]);}, interval); } Tetris.prototype.start = function() { this.clearMap(); this.inspire(this.elt); this.inspireNext(this.nextElt); this.score = 0; this.level = 0; this.gen(); this.state = "start"; this.gameoverElt.innerHTML = ""; this.update(); var me = this; document.onkeydown = function(e) {me.handleInput(e);} } Tetris.prototype.gameOver = function() { // gray map for (var y = 0; y < this.MAP_HEIGHT; y++) { for (var x = 0; x < this.MAP_WIDTH; x++) { if (this.getMapBlock(x, y) != 0) { this.setMapBlock(x, y, 8); } } } clearTimeout(this.dropTimer); document.onkeydown = null; this.state = "gameover"; this.update(); } Tetris.prototype.stop = function() { this.clearMap(); for (var y = 0; y < 4; y++) { for (var x = 0; x < 4; x++) { get("next" + (x + "_" + y)).className = "block"; } } this.next = null; clearTimeout(this.dropTimer); this.score = 0; this.state = "stop"; document.onkeydown = null; this.gameoverElt.innerHTML = ""; this.update(); } Tetris.prototype.preventDefault = function(e) { (e.preventDefault) ? e.preventDefault() : e.returnValue = false; } Tetris.prototype.handleInput = function(e) { var ev = (window.event) ? window.event : e; var keycode = (window.event) ? window.event.keyCode : e.which; switch (keycode) { case VK_LEFT: this.sideWalk(-1); this.preventDefault(ev); break; case VK_RIGHT: this.sideWalk(1); this.preventDefault(ev); break; case VK_UP: this.rotate(1); this.preventDefault(ev); break; case VK_DOWN: this.down(); this.preventDefault(ev); break; case VK_SPACE: while (this.down()){} this.preventDefault(ev); break; default: break; } this.update(); } Tetris.prototype.render = function() { for (var y = 0, ylimit = this.map.length; y < ylimit; y++) { for (var x = 0, xlimit = this.map[y].length; x < xlimit; x++) { var type = this.getMapBlock(x, y); get(x + "_" + y).innerHTML = "0"; get(x + "_" + y).className = "block col" + type; } } if (this.state == "start") { this.drawTet(this.curPos, this.curTet, this.curRot); } else if (this.state == "gameover") { this.gameoverElt.innerHTML = "Game Over!!"; } this.scoreElt.innerHTML = this.score; this.levelElt.innerHTML = this.level + 1; if (this.next != null) this.drawNext(this.next); } Tetris.prototype.drawBlock = function(x, y, type) { get(x + "_" + y).className = "block col" + type; } Tetris.prototype.drawTet = function(pos, type, rot) { var t = this.tet[type][rot]; for (var i = 0, limit = t.length; i < limit; i++) { this.drawBlock(pos.x + t[i].x, pos.y + t[i].y, type + 1); } } Tetris.prototype.drawNext = function(type) { for (var y = 0; y < 4; y++) { for (var x = 0; x < 4; x++) { get("next" + (x + "_" + y)).className = "block"; } } var t = this.tet[type][0]; for (var i = 0, limit = t.length; i < limit; i++) { var n = get("next" + (t[i].x + "_" + t[i].y)); n.innerHTML = "0"; n.className = "block col" + (type + 1); } } Tetris.prototype.update = function() { this.render(); } </script>
소스를 통해서 공부를 해볼려고 합니다.
답글삭제좋은 글 감사합니다.