254 lines
6.3 KiB
JavaScript
254 lines
6.3 KiB
JavaScript
//really simple tetris in canvas element
|
|
//2009, 2010 obneq
|
|
|
|
document.onkeyup=key;
|
|
|
|
var colors = ["rgb(13, 13, 13)", "rgb(200, 13, 13)",
|
|
"rgb(13, 200, 13)", "rgb(13, 13, 200)",
|
|
"rgb(200, 200, 13)", "rgb(200, 13, 200)",
|
|
"rgb(13, 200, 200)", "rgb(200, 200, 200)"];
|
|
|
|
var levels = [777, 666, 555, 444, 404, 333, 303, 222, 202, 111, 101];
|
|
var run;
|
|
var shapes = [ [ [[0,0],[1,0],[0,1],[1,1]] ], //box
|
|
|
|
[ [[1,0],[1,1],[1,2],[1,3]],
|
|
[[0,1],[1,1],[2,1],[3,1]] ], //line
|
|
|
|
[ [[0,0],[0,1],[1,1],[1,2]],
|
|
[[1,0],[2,0],[0,1],[1,1]] ], //s
|
|
|
|
[ [[1,0],[0,1],[1,1],[0,2]],
|
|
[[0,0],[1,0],[1,1],[2,1]] ], //z
|
|
|
|
[ [[1,0],[2,0],[1,1],[1,2]],
|
|
[[0,0],[0,1],[1,1],[2,1]],
|
|
[[1,0],[1,1],[0,2],[1,2]],
|
|
[[0,1],[1,1],[2,1],[2,2]] ], //r
|
|
|
|
[ [[1,0],[1,1],[1,2],[2,2]],
|
|
[[0,1],[1,1],[2,1],[2,0]],
|
|
[[0,0],[1,0],[1,1],[1,2]],
|
|
[[0,1],[1,1],[2,1],[0,2]] ], //l
|
|
|
|
[ [[0,0],[1,0],[2,0],[1,1]],
|
|
[[0,0],[0,1],[1,1],[0,2]],
|
|
[[0,2],[1,2],[2,2],[1,1]],
|
|
[[1,1],[2,0],[2,1],[2,2]] ], ]; //t
|
|
|
|
function board(x, y){
|
|
this.x=x;
|
|
this.y=y;
|
|
this.val = function(x,y){
|
|
var board=new Array(x);
|
|
for(var i=0; i<x; i++)
|
|
board[i]=new Array(y);
|
|
return board;
|
|
}(x, y);
|
|
|
|
this.add = function(s){
|
|
var d=s.Shape[s.Rotation]
|
|
for(var i=0; i<4; i++)
|
|
this.val[s.x+d[i][0]][s.y+d[i][1]]=s.Color;
|
|
}
|
|
|
|
this.check_lines=function(){
|
|
for(var i=1; i<this.y; i++)
|
|
if (this.check_line(i))
|
|
this.scroll(i);
|
|
view.update();
|
|
}
|
|
|
|
this.check_line=function(l){
|
|
for(var i=0; i<this.x; i++)
|
|
if(!this.val[i][l])
|
|
return false;
|
|
status.lines++;
|
|
status.check_level();
|
|
return true;
|
|
}
|
|
|
|
this.scroll=function(l){
|
|
while(--l)
|
|
for(var i=0; i<this.x; i++)
|
|
this.val[i][l+1]=this.val[i][l];
|
|
}
|
|
}
|
|
|
|
function piece(){
|
|
this.x = 4;
|
|
this.y = 0;
|
|
var id = Math.floor(Math.random()*7);
|
|
this.Color=id+1;
|
|
this.Shape=shapes[id];
|
|
this.Rotation = 0;
|
|
|
|
this.move=function(dx,dy){
|
|
var newx = this.x + dx;
|
|
var newy = this.y + dy;
|
|
if(!this.check_position(newx, newy, this.Rotation))
|
|
return;
|
|
this.x = newx;
|
|
this.y = newy;
|
|
view.update();
|
|
}
|
|
|
|
this.rotate = function(dr){
|
|
//make cw and ccw rotation work
|
|
var newrot = (this.Rotation+dr)%this.Shape.length;
|
|
if (newrot<0)
|
|
newrot=this.Shape.length+newrot;
|
|
if (!this.check_position(this.x, this.y, newrot))
|
|
return;
|
|
this.Rotation = newrot;
|
|
view.update();
|
|
}
|
|
|
|
this.drop=function(){
|
|
while(!this.stuck())
|
|
this.y+=1;
|
|
view.update();
|
|
}
|
|
|
|
this.check_position=function(newx, newy, newrot){
|
|
var d = this.Shape[newrot];
|
|
for(var i=0; i<4; i++)
|
|
if(newx+d[i][0]<0 || newx+d[i][0]>=board.x ||
|
|
newy+d[i][1]<0 || newy+d[i][1]>=board.y ||
|
|
board.val[newx+d[i][0]][newy+d[i][1]])
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
this.stuck=function (){
|
|
if(this.check_position(this.x, this.y+1, this.Rotation))
|
|
return false;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
function view(size){
|
|
this.canvas = document.getElementById("canvas");
|
|
this.ctx = this.canvas.getContext("2d");
|
|
this.ctx.strokeStyle = colors[0];
|
|
this.xsize=board.x*size;
|
|
this.ysize=board.y*size;
|
|
|
|
this.update=function() {
|
|
this.ctx.clearRect(0, 0, this.xsize, this.ysize);
|
|
this.draw_board();
|
|
var c=current.Shape[current.Rotation];
|
|
|
|
this.ctx.fillStyle = colors[current.Color];
|
|
for(var i=0; i<4; i++){
|
|
this.ctx.fillRect((c[i][0]+current.x)*size,
|
|
(c[i][1]+current.y)*size,
|
|
size, size);
|
|
|
|
this.ctx.strokeRect((c[i][0]+current.x)*size,
|
|
(c[i][1]+current.y)*size,
|
|
size, size);
|
|
}
|
|
}
|
|
|
|
this.draw_board=function(){
|
|
for (var i=0; i<board.y; i++)
|
|
for(var j=0; j<board.x; j++){
|
|
var b=board.val[j][i];
|
|
if(b){
|
|
this.ctx.fillStyle=colors[b];
|
|
this.ctx.fillRect(j*size, i*size, size, size);
|
|
this.ctx.strokeRect(j*size, i*size, size, size);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function preview(size){
|
|
this.canvas = document.getElementById("preview");
|
|
this.ctx = this.canvas.getContext("2d");
|
|
this.ctx.strokeStyle = colors[0];
|
|
|
|
this.update=function(){
|
|
this.ctx.clearRect(0, 0, 5*size, 6*size);
|
|
var d=next.Shape[0];
|
|
for (var i=0; i<4; i++) {
|
|
this.ctx.fillStyle = colors[next.Color];
|
|
this.ctx.fillRect(size+d[i][0]*size, size+d[i][1]*size, size, size);
|
|
this.ctx.strokeRect(size+d[i][0]*size, size+d[i][1]*size, size, size);
|
|
}
|
|
}
|
|
}
|
|
|
|
function status(){
|
|
this.lines=0;
|
|
this.level=1;
|
|
var s=document.getElementById("status");
|
|
|
|
this.check_level=function(){
|
|
if(this.lines%10==0){
|
|
clearInterval(run);
|
|
this.level++;
|
|
run=setInterval(step, levels[this.level]);
|
|
this.update();
|
|
}
|
|
}
|
|
this.update=function(){
|
|
s.innerHTML="lines: "+this.lines+" level: "+this.level;
|
|
}
|
|
}
|
|
|
|
function key(e){
|
|
//next 4 lines stolen from the internet
|
|
var evt=(e)?e:(window.event)?window.event:null;
|
|
if(evt){
|
|
var key=(evt.charCode)?evt.charCode:
|
|
((evt.keyCode)?evt.keyCode:((evt.which)?evt.which:0));
|
|
if(key=="74")
|
|
current.move(0, 1);
|
|
else if(key=="75")
|
|
current.move(0, -1);
|
|
else if(key=="72")
|
|
current.move(-1, 0);
|
|
else if(key=="76")
|
|
current.move(1, 0);
|
|
else if(key=="65")
|
|
current.rotate(1);
|
|
else if(key=="70")
|
|
current.rotate(-1);
|
|
else if(key=="32")
|
|
current.drop();
|
|
}
|
|
}
|
|
|
|
function step(){
|
|
if(!current.check_position(current.x, current.y+1, current.Rotation)){
|
|
if(current.y==0)
|
|
clearInterval(run);
|
|
board.add(current);
|
|
board.check_lines();
|
|
if(!next.check_position(next.x, next.y, next.Rotation))
|
|
return;
|
|
current = next;
|
|
next = new piece();
|
|
preview.update();
|
|
status.update();
|
|
} else
|
|
current.y += 1;
|
|
view.update();
|
|
}
|
|
|
|
function new_game(){
|
|
board = new board(10,20);
|
|
next = new piece();
|
|
current = new piece();
|
|
view = new view(20);
|
|
preview = new preview(20);
|
|
status = new status();
|
|
|
|
status.update();
|
|
preview.update();
|
|
view.update();
|
|
//go!
|
|
run=setInterval(step, levels[0]);
|
|
} |