redone representation of shapes

master
obneq 2010-04-13 09:12:46 +02:00
parent 5a82790651
commit 9daba643aa
3 changed files with 102 additions and 291 deletions

190
shapes.js
View File

@ -1,190 +0,0 @@
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]] ], //|
[ [[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
[ [[0,0],[1,0],[0,1],[0,2]], //r
[[0,0],[0,1],[1,1],[2,1]],
[[1,0],[1,1],[0,2],[1,2]],
[[0,0],[1,0],[2,0],[2,1]] ],
[ [[0,0],[0,1],[0,2],[1,2]],
[[0,1],[1,1],[2,1],[2,0]],
[[0,0],[1,0],[1,1],[1,2]],
[[0,0],[1,0],[2,0],[0,1]] ], //l
[ [[0,0],[1,0],[2,0],[1,1]],
[[0,0],[0,1],[1,1],[0,2]],
[[0,1],[1,1],[2,1],[1,0]],
[[1,1],[2,0],[2,1],[2,2]] ], //t
];
// var b_shape = {
// "color" : 1,
// "rotations" : 1,
// "data": [
// { "x" : 2,
// "y" : 2,
// "val" : [ [1, 1, 0, 0],
// [1, 1, 0, 0],
// [0, 0, 0, 0],
// [0, 0, 0, 0] ] }
// ]
// }
// var s_shape = {
// "color" : 2,
// "rotations" : 2,
// "data": [
// { "x" : 2,
// "y" : 3,
// "val" : [ [1, 0, 0, 0],
// [1, 1, 0, 0],
// [0, 1, 0, 0],
// [0, 0, 0, 0] ] },
// { "x" : 3,
// "y" : 2,
// "val" : [ [0, 1, 1, 0],
// [1, 1, 0, 0],
// [0, 0, 0, 0],
// [0, 0, 0, 0] ] },
// ]
// }
// var z_shape = {
// "color" : 3,
// "rotations" : 2,
// "data": [
// { "x" : 2,
// "y" : 3,
// "val" : [ [0, 1, 0, 0],
// [1, 1, 0, 0],
// [1, 0, 0, 0],
// [0, 0, 0, 0] ] },
// { "x" : 3,
// "y" : 2,
// "val" : [ [1, 1, 0, 0],
// [0, 1, 1, 0],
// [0, 0, 0, 0],
// [0, 0, 0, 0] ] },
// ]
// }
// var i_shape = {
// "color" : 4,
// "rotations" : 2,
// "data": [
// { "x" : 1,
// "y" : 4,
// "val" : [ [1, 0, 0, 0],
// [1, 0, 0, 0],
// [1, 0, 0, 0],
// [1, 0, 0, 0] ] },
// { "x" : 4,
// "y" : 1,
// "val" : [ [1, 1, 1, 1],
// [0, 0, 0, 0],
// [0, 0, 0, 0],
// [0, 0, 0, 0] ] },
// ]
// }
// var r_shape = {
// "color" : 5,
// "rotations" : 4,
// "data": [
// { "x" : 2,
// "y" : 3,
// "val" : [ [1, 1, 0, 0],
// [1, 0, 0, 0],
// [1, 0, 0, 0],
// [0, 0, 0, 0] ] },
// { "x" : 3,
// "y" : 2,
// "val" : [ [1, 1, 1, 0],
// [0, 0, 1, 0],
// [0, 0, 0, 0],
// [0, 0, 0, 0] ] },
// { "x" : 2,
// "y" : 3,
// "val" : [ [0, 1, 0, 0],
// [0, 1, 0, 0],
// [1, 1, 0, 0],
// [0, 0, 0, 0] ] },
// { "x" : 3,
// "y" : 2,
// "val" : [ [1, 0, 0, 0],
// [1, 1, 1, 0],
// [0, 0, 0, 0],
// [0, 0, 0, 0] ] },
// ]
// }
// var l_shape = {
// "color" : 6,
// "rotations" : 4,
// "data": [
// { "x" : 2,
// "y" : 3,
// "val" : [ [1, 0, 0, 0],
// [1, 0, 0, 0],
// [1, 1, 0, 0],
// [0, 0, 0, 0] ] },
// { "x" : 3,
// "y" : 2,
// "val" : [ [1, 1, 1, 0],
// [1, 0, 0, 0],
// [0, 0, 0, 0],
// [0, 0, 0, 0] ] },
// { "x" : 2,
// "y" : 3,
// "val" : [ [1, 1, 0, 0],
// [0, 1, 0, 0],
// [0, 1, 0, 0],
// [0, 0, 0, 0] ] },
// { "x" : 3,
// "y" : 2,
// "val" : [ [0, 0, 1, 0],
// [1, 1, 1, 0],
// [0, 0, 0, 0],
// [0, 0, 0, 0] ] },
// ]
// }
// var t_shape = {
// "color" : 7,
// "rotations" : 4,
// "data": [
// { "x" : 3,
// "y" : 2,
// "val" : [ [0, 1, 0, 0],
// [1, 1, 1, 0],
// [0, 0, 0, 0],
// [0, 0, 0, 0] ] },
// { "x" : 2,
// "y" : 3,
// "val" : [ [1, 0, 0, 0],
// [1, 1, 0, 0],
// [1, 0, 0, 0],
// [0, 0, 0, 0] ] },
// { "x" : 3,
// "y" : 2,
// "val" : [ [1, 1, 1, 0],
// [0, 1, 0, 0],
// [0, 0, 0, 0],
// [0, 0, 0, 0] ] },
// { "x" : 2,
// "y" : 3,
// "val" : [ [0, 1, 0, 0],
// [1, 1, 0, 0],
// [0, 1, 0, 0],
// [0, 0, 0, 0] ] },
// ]
// }

View File

@ -1,7 +1,7 @@
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>tetris</title>
<script type="text/javascript" src="shapes.js"></script>
<!-- <script type="text/javascript" src="shapes.js"></script> -->
<script type="text/javascript" src="tetris.js"></script>
<style type="text/css" media="screen">
body {
@ -23,9 +23,12 @@
background-color:gray;
}
</style>
<canvas id="canvas" width="200" height="400"></canvas>
<canvas id="preview" width=80 height=80></canvas>
reload to start a new game. use a/f keys to rotate and h/l to go
<canvas id="canvas" width=200 height=400></canvas>
<canvas id="preview" width=100 height=120></canvas>
<br />
reload to start a new game.
<br />
use a/f keys to rotate and h/l to go
left or right, space to drop.
</div>
<div id="status">

192
tetris.js
View File

@ -1,16 +1,40 @@
//really simple tetris in canvas element
//2009 obneq
//2009, 2010 obneq
document.onkeyup=key;
var shapes = [b_shape, s_shape, z_shape, i_shape, l_shape, r_shape, t_shape];
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 = [888, 666, 555, 444, 404, 333, 303, 222, 202, 111, 101];
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){
//constructs a new empty board
@ -22,24 +46,15 @@ function board(x, y){
board[i]=new Array(y);
return board;
}(x, y);
this.max_pos = y;
this.add = function(s){
//shapes get added to the board only after
//shapes are added to the board after
//they cant be moved anymore
//d is a shortcut, this "pattern" is used
//everywhere...
var d = s.Shape.data[s.Rotation];
for(var i=0; i<d.x; i++)
for(var j=0; j<d.y; j++)
//FIXME: indexing of shapes and board is braindamaged.
//its [y][x] for shapes and [x][y] for the board!
if(d.val[j][i])
this.val[s.Xpos+i][s.Ypos+j] = s.Shape.color;
var d=s.Shape[s.Rotation]
for(var i=0; i<4; i++)
this.val[s.Xpos+d[i][0]][s.Ypos+d[i][1]]=s.Color;
}
this.check_lines=function(){
//this function checks the board
//for full lines and collapses them
@ -53,12 +68,11 @@ function board(x, y){
for(var i=0; i<this.x; i++)
if(!this.val[i][l])
return false;
this.max_pos++;
status.lines++;
status.check_level();
return true;
}
this.scroll=function(l){
while(--l)
for(var i=0; i<this.x; i++)
@ -70,37 +84,36 @@ function shape (){
//constructs a new random shape
this.Xpos = 4;
this.Ypos = 0;
this.Shape=shapes[Math.floor(Math.random()*7)]
var id = Math.floor(Math.random()*7);
this.Color=id+1;
this.Shape=shapes[id];
this.Rotation = 0;
this.move=function(x,y){
//move if new position is valid
var d=this.Shape.data[this.Rotation];
var newX = this.Xpos + x;
var newY = this.Ypos + y;
//enforce board bounds
newX=Math.max(0, Math.min(newX, board.x - d.x));
newY=Math.max(0, Math.min(newY, board.y - d.y));
//check for obstacles on board
if(this.check_move(newX, newY)){
this.Xpos = newX;
this.Ypos = newY;
}
if(!this.check_position(newX, newY, this.Rotation))
return;
this.Xpos = newX;
this.Ypos = newY;
view.update();
}
this.rotate = function(r){
//rotate if new position is valid
//make cw and ccw rotation work
var newrot = (this.Rotation+r)%this.Shape.rotations;
var newrot = (this.Rotation+r)%this.Shape.length;
if (newrot<0)
newrot=this.Shape.rotations+newrot;
newrot=this.Shape.length+newrot;
//check for obstacles on board
if (this.check_rotation(newrot))
this.Rotation = newrot;
if (!this.check_position(this.Xpos, this.Ypos, newrot))
return;
this.Rotation = newrot;
view.update();
}
this.drop=function(){
while(!this.stuck())
this.Ypos+=1;
@ -108,36 +121,22 @@ function shape (){
}
}
//dont mind the weird indexes, see above...
shape.prototype.check_move=function(newX, newY){
var d = this.Shape.data[this.Rotation];
for(var i=0; i<d.x; i++)
for(var j=0; j<d.y; j++)
if(d.val[j][i] && board.val[newX + i][newY + j])
return false;
return true;
}
shape.prototype.check_rotation=function (r){
var d = this.Shape.data[r];
if(this.Ypos+d.y > board.y || this.Xpos+d.x > board.x)
return false;
for(var i=0; i<d.x; i++)
for(var j=0; j<d.y; j++)
if(d.val[j][i] && board.val[this.Xpos + i][this.Ypos + j])
return false;
shape.prototype.check_position=function(newX, newY, newR){
var d = this.Shape[newR];
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))
return false;
if(board.val[newX+d[i][0]][newY+d[i][1]])
return false;
}
return true;
}
shape.prototype.stuck=function (){
var d = this.Shape.data[this.Rotation];
if(this.Ypos + d.y==board.y)
return true;
for(i=0; i<d.x; i++)
for(j=0; j<d.y; j++)
if(d.val[j][i] && board.val[this.Xpos + i][this.Ypos + j + 1])
return true;
return false;
if(this.check_position(this.Xpos, this.Ypos+1, this.Rotation))
return false;
return true;
}
function view(size){
@ -147,32 +146,35 @@ function view(size){
this.ctx.strokeStyle = colors[0];
this.xsize=board.x*size;
this.ysize=board.y*size;
this.update=function(){
this.update=function() {
//draw the board and the current shape
var d=current.Shape.data[current.Rotation];
this.ctx.clearRect(0, 0, this.xsize, this.ysize);
this.draw_board();
for (var i=0; i<d.y; i++)
for (var j=0; j<d.x; j++)
if(d.val[i][j]) {
this.ctx.fillStyle = colors[current.Shape.color];
this.ctx.fillRect((current.Xpos + j) * size,
(current.Ypos + i) * size, size, size);
this.ctx.strokeRect((current.Xpos + j) * size,
(current.Ypos + i) * size, size, size);
}
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.Xpos)*size,
(c[i][1]+current.Ypos)*size,
size, size);
this.ctx.strokeRect((c[i][0]+current.Xpos)*size,
(c[i][1]+current.Ypos)*size,
size, size);
}
}
this.draw_board=function(){
//draw the board
for (var i=board.max_pos; i<board.y; i++)
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);
this.ctx.fillRect(j*size, i*size, size, size);
this.ctx.strokeRect(j*size, i*size, size, size);
}
}
}
@ -185,22 +187,21 @@ function preview(size){
this.ctx.strokeStyle = colors[0];
this.update=function(){
this.ctx.clearRect(0, 0, 4*size, 4*size);
var d=next.Shape.data[next.Rotation];
for (var i=0; i<d.y; i++)
for (var j=0; j<d.x; j++)
if(d.val[i][j]) {
this.ctx.fillStyle = colors[next.Shape.color];
this.ctx.fillRect(j*size, i*size, size, size);
this.ctx.strokeRect(j*size, i*size, size, size);
}
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=0;
this.level=1;
var s=document.getElementById("status");
this.check_level=function(){
if(this.lines%10==0){
clearInterval(run);
@ -215,12 +216,13 @@ function status(){
}
function key(e){
//stolen from the internet...
//next 4 lines stolen from the internet...
var evt=(e)?e:(window.event)?window.event:null;
if(evt){
var key=(evt.charCode)?evt.charCode:
var key=(evt.charCode)?evt.charCode:
((evt.keyCode)?evt.keyCode:((evt.which)?evt.which:0));
//vi-style keys. you are allowed to move a shape up for now.
//vi-style keys. you are allowed
//to move a shape up for now.
if(key=="74")
current.move(0, 1);
else if(key=="75")
@ -241,13 +243,12 @@ function key(e){
function step(){
//the main loop
if(current.stuck()){
//the board starts at top left... more braindamage
board.max_pos=Math.min(current.Ypos, board.max_pos);
board.add(current);
if(board.max_pos<=0)
if(current.Ypos==0)
clearInterval(run);
//FIXME: add scoring
board.add(current);
board.check_lines();
if(!next.check_position(next.Xpos, next.Ypos, next.Rotation))
return;
current = next;
next = new shape();
preview.update();
@ -258,9 +259,7 @@ function step(){
}
function new_game(){
//board size
board = new board(10,20);
//size of one unit in pixel
next = new shape();
current = new shape();
view = new view(20);
@ -271,6 +270,5 @@ function new_game(){
preview.update();
view.update();
//go!
run=setInterval(step, 666);
run=setInterval(step, levels[0]);
}