Help understanding tetris.....

Hello,

I have been digging through an open source java applet (programmed for 1.0) and I have come across a problem. I understand most of what is being done but I have 1 problem... so far:

As shown in the code below the author makes an int [][][][] array to store pieces and 3 color arrays: colors, lcolors & dcolors. When a piece is initialized it is passed random random numbers to select the type of piece and another random number to set the orientation of the piece but I can not figure out how the color is being set.... any help would be greatly appreciated.

/*

* Tetris.java

*

* Copyright(c) 2002-2005, Particle Corp.

*

* Copying and distribution of this entire source code

* is permitted in any medium, provided this copyright

* notice is preserved.

*/

import java.applet.*;

import java.awt.*;

/**

* simple tetris applet

* (note: specifically made to be compatible with JDK 1.0)

*

* Note2: This applet works/looks best if applet size dimension

* ratios are 10:20 (width:height). On a web page, this means

* 200x400 is probably best.

*

* @author Alex S.

* @version 0.0.2

*/

publicclass Tetrisextends Appletimplements Runnable{

private Thread thread;

privateint[][] screen;

private Image doubleImage =null;

private Graphics doubleGraphics =null;

privateint frames = 0;

// piece fall speed (in milliseconds)

privateint speed;

// pieces; each piece has 4 'dots', we store model coordinates

// for those 'dots'. each piece also has 4 'orientations' (actually,

// some pieces have less, but we're using all 4).

privatestaticfinalint[][][][] pieces ={

{// ####

{{0,1},{0,0},{0,-1},{0,-2}},

{{-1,0},{0,0},{1,0},{2,0}},

{{0,1},{0,0},{0,-1},{0,-2}},

{{-1,0},{0,0},{1,0},{2,0}}

},

{// #

// ##

// #

{{-1,0},{0,1},{1,0},{0,0}},

{{0,1},{1,0},{0,-1},{0,0}},

{{1,0},{0,-1},{-1,0},{0,0}},

{{0,-1},{-1,0},{0,1},{0,0}}

},

{

// ##

// ##

{{0,0},{0,-1},{1,0},{1,-1}},

{{0,0},{0,-1},{1,0},{1,-1}},

{{0,0},{0,-1},{1,0},{1,-1}},

{{0,0},{0,-1},{1,0},{1,-1}}

},

{

// ##

// ##

{{-1,0},{0,0},{0,1},{1,1}},

{{1,-1},{1,0},{0,0},{0,1}},

{{-1,0},{0,0},{0,1},{1,1}},

{{1,-1},{1,0},{0,0},{0,1}}

},

{

// ##

// ##

{{-1,1},{0,1},{0,0},{1,0}},

{{0,-1},{0,0},{1,0},{1,1}},

{{-1,1},{0,1},{0,0},{1,0}},

{{0,-1},{0,0},{1,0},{1,1}}

},

{

// #

// ###

{{-1,-1},{-1,0},{0,0},{1,0}},

{{-1,1},{0,1},{0,0},{0,-1}},

{{1,1},{1,0},{0,0},{-1,0}},

{{1,-1},{0,-1},{0,0},{0,1}}

},

{

//#

// ###

{{-1,1},{-1,0},{0,0},{1,0}},

{{-1,-1},{0,-1},{0,0},{0,1}},

{{1,-1},{1,0},{0,0},{-1,0}},

{{1,1},{0,1},{0,0},{0,-1}}

}

};

// base color for piece

privatestaticfinal Color[] colors ={

new Color(0xBD,0x00,0x00),

new Color(0x73,0x71,0x73),

new Color(0x00,0xBE,0xBD),

new Color(0x00,0xBE,0x00),

new Color(0x00,0x00,0xBD),

new Color(0xBD,0x00,0xBD),

new Color(0xBD,0xBE,0x00)

};

// highlight color for piece (upper left corner)

privatestaticfinal Color[] lcolors ={

new Color(0xFF,0x00,0x00),

new Color(0x9C,0x9A,0x9C),

new Color(0x00,0xFF,0xFF),

new Color(0x00,0xFF,0x00),

new Color(0x00,0x00,0xFF),

new Color(0xFF,0x00,0xFF),

new Color(0xFF,0xFF,0x00)

};

// dark highlight color for piece (lower right corner)

privatestaticfinal Color[] dcolors ={

new Color(0x84,0x00,0x00),

new Color(0x4A,0x4D,0x4A),

new Color(0x00,0x82,0x84),

new Color(0x84,0x82,0x00),

new Color(0x00,0x00,0x84),

new Color(0x84,0x00,0x84),

new Color(0x84,0x82,0x00)

};

// empty location

privatestaticfinalint EMPTY = pieces.length + 1;

// current state of the game

privateint currentPiece;

privateint currentOrientation;

privateint currentX,currentY;

// flag to indicate that the game is over.

privateboolean gameOver;

/**

* constructs a tetris object

*/

public Tetris(){

thread =null;

screen =newint[20][10];

}

/**

* does initialization

*/

publicvoid init(){

startGame();

// create double buffer (prevents flicker)

doubleImage = createImage(size().width,size().height);

doubleGraphics = doubleImage.getGraphics();

}

/**

* picks next piece and orientation

*/

publicvoid pickPiece(){

currentPiece = (int)(Math.random()*pieces.length);

currentOrientation = (int)(Math.random()*pieces[currentPiece].length);

currentX = 5;

currentY = 2;

}

/**

* repaints the screen

*/

publicvoid paint(Graphics g){

int[] xs =newint[3];

int[] ys =newint[3];

int w = size().width,h = size().height;

int s = h / screen.length;

doubleGraphics.setColor(Color.black);

doubleGraphics.fillRect(0,0,w,h);

// paint score

String score ="["+(1000-speed)+"]";

doubleGraphics.setColor(Color.gray);

doubleGraphics.setFont(new Font("Monospaced",Font.PLAIN,10));

// score is 1000 - speed (since 'speed' decreases with every droping

// piece, this provides an accurate picture of how quickly the

// person can think/react to falling pieces.

doubleGraphics.drawString(score,10,10);

doubleGraphics.setColor(Color.gray);

doubleGraphics.setFont(new Font("Monospaced",Font.PLAIN,10));

doubleGraphics.drawString("debug: lcolors[screen[][]] " + screen[17][3],60,60);

if(gameOver){

// if game is over, display "game over" :-)

doubleGraphics.setColor(Color.yellow);

score ="Score: "+score;

Font f =new Font("Monospaced",Font.BOLD,20);

FontMetrics fm = getFontMetrics(f);

int x = w/2 - fm.stringWidth(score) / 2;

doubleGraphics.setFont(f);

doubleGraphics.drawString(score,x,h/2-30);

String gameOver ="GAME OVER";

f =new Font("Monospaced",Font.BOLD,30);

fm = getFontMetrics(f);

x = w/2 - fm.stringWidth(gameOver) / 2;

doubleGraphics.setFont(f);

doubleGraphics.drawString(gameOver,x,h/2);

String clickToPlayAgain ="(Click To Play Again)";

f =new Font("Monospaced",Font.BOLD,12);

fm = getFontMetrics(f);

x = w/2 - fm.stringWidth(clickToPlayAgain) / 2;

doubleGraphics.setFont(f);

doubleGraphics.drawString(clickToPlayAgain,x,h/2+30);

doubleGraphics.setColor(Color.lightGray);

String copyright ="(c) 2002-2005, Particle";

f =new Font("Monospaced",Font.PLAIN,12);

fm = getFontMetrics(f);

x = w/2 - fm.stringWidth(copyright) / 2;

doubleGraphics.setFont(f);

doubleGraphics.drawString(copyright,x,h/2+50);

}else{

// draw the pieces

doubleGraphics.setColor(Color.darkGray);

doubleGraphics.drawLine(0,4*s,w,4*s);

for (int i=0;i<screen.length;i++)

for (int j=0;j<screen[i].length;j++){

if (screen[i][j] != EMPTY){

doubleGraphics.setColor(lcolors[screen[i][j]]);

doubleGraphics.fillRect(j*s,i*s,s,s);

doubleGraphics.setColor(dcolors[screen[i][j]]);

xs[0] = j*s;ys[0] = i*s + s;

xs[1] = j*s+s; ys[1] = i*s;

xs[2] = j*s+s; ys[2] = i*s + s;

doubleGraphics.fillPolygon(xs,ys,3);

doubleGraphics.setColor(colors[screen[i][j]]);

doubleGraphics.fillRect(j*s+3,i*s+3,s-6,s-6);

doubleGraphics.setColor(Color.black);

doubleGraphics.drawRect(j*s,i*s,s,s);

}

}

}

// blit double buffer to frame buffer

g.drawImage(doubleImage,0,0,null);

}

/**

* updat4; just draw

*/

publicvoid update(Graphics g){

paint(g);

}

/**

* start a thread

*/

publicvoid start(){

if (thread ==null){

thread =new Thread(this);

thread.start();

}

}

/**

* allow GC to clean up thread

*/

publicvoid stop(){

thread =null;

}

/**

* does a piece move; given a vector where to move it

*/

privatesynchronizedboolean doPieceMove(int nextOr,int x,int y){

boolean retValue =true;

int oldOrient = currentOrientation,oldX = currentX,oldY = currentY;

setPiece(EMPTY);

if(nextOr > 0){

currentOrientation = (currentOrientation + 1) % pieces[currentPiece].length;

}elseif(nextOr < 0){

currentOrientation = (currentOrientation - 1 + pieces[currentPiece].length) % pieces[currentPiece].length;

}

currentX += x;

currentY += y;

if(collisions()){

currentOrientation = oldOrient;

currentX = oldX;

currentY = oldY;

retValue =false;

}

setPiece(currentPiece);

return retValue;

}

/**

* end the game

*/

privatevoid endGame(){

gameOver =true;

for (int i=0;i<screen.length;i++)

for (int j=0;j<screen[i].length;j++)

screen[i][j] = EMPTY;

}

/**

* start/restart the game

*/

privatevoid startGame(){

speed = 1000;

frames = 0;

for (int i=0;i<screen.length;i++)

for (int j=0;j<screen[i].length;j++)

screen[i][j] = EMPTY;

pickPiece();

gameOver =false;

}

/**

* clear pieces that fill a row

*/

privatevoid clearPieces(){

int i,j,k;

// drop speed by 5 milliseconds (until people fail :-)

speed -= 5;

if(speed >< 10)

speed = 10;

for (i=0;i<screen.length;i++){

for (j=0;j<screen[i].length;j++){

if(screen[i][j] == EMPTY)

break;

}

if(j == screen[i].length){

for(k=i;k>0;k--)

for(j=0;j<screen[k].length;j++){

screen[k][j] = screen[k-1][j];

screen[k-1][j] = EMPTY;

}

i--;

}

}

}

/**

* our thread run method

*/

publicvoid run(){

for (;;){

if(!gameOver){

if(!doPieceMove(0,0,1)){

clearPieces();

pickPiece();

if(collisions())

endGame();

else

setPiece(currentPiece);

}

repaint();

}

try{

Thread.sleep(speed);

}catch (InterruptedException e){

}

}

}

/**

* test for colisions of current piece

*/

privateboolean collisions(){

int[][] points = pieces[currentPiece][currentOrientation];

for(int i=0;i<points.length;i++){

// get 'model' points

int mx = points[i][0] + currentX;

int my = points[i][1] + currentY;

if(mx >< 0 || mx >= 10)

returntrue;

if(my < 0 || my >= 20)

returntrue;

if(screen[my][mx] != EMPTY)

returntrue;

}

returnfalse;

}

/**

* set piece

*/

privatevoid setPiece(int value){

int[][] points = pieces[currentPiece][currentOrientation];

for(int i=0;i<points.length;i++)

screen[points[i][1] + currentY][points[i][0] + currentX] = value;

}

/**

* a key handler; let users use many keys to play

*/

publicboolean keyDown(Event evt,int key){

if(gameOver)

returnfalse;

if (key == Event.UP || key =='i' || key =='I' || key =='w' || key =='W'){

doPieceMove(1,0,0);

}elseif (key =='e' || key =='E' || key =='O' || key =='o'){

doPieceMove(-1,0,0);

}elseif (key == Event.DOWN || key =='k' || key =='K' || key =='s' || key =='S'){

doPieceMove(0,0,1);

}elseif (key == Event.LEFT || key =='j' || key =='J' || key =='a' || key =='A'){

doPieceMove(0,-1,0);

}elseif (key == Event.RIGHT || key =='l' || key =='L' || key =='d' || key =='D'){

doPieceMove(0,1,0);

}

repaint();

returntrue;

}

/**

* restart game when mouse is clicked (when game is over)

*/

publicboolean mouseUp(Event evt,int x,int y){

if(gameOver){

startGame();

returntrue;

}

returnfalse;

}

}

so... any help would be great.>

[31930 byte] By [dr1zztth3hunt3ra] at [2007-11-26 17:31:21]
# 1
There are some arrays of colors that the color is selected from. Is that what you are asking?
zadoka at 2007-7-8 23:59:18 > top of Java-index,Java Essentials,Java Programming...
# 2

kind of....

I understand that there are 3 color arrays and that they are where the color comes from and I understand how the color is re-painted once the piece is on th applet. What I want to know is what part of the code selects the color for any given piece.... example a line piece - is always red..... where is that done and how....?

dr1zztth3hunt3ra at 2007-7-8 23:59:18 > top of Java-index,Java Essentials,Java Programming...
# 3
It looks like there is one color for each piece in the pieces array. And the first piece is line and the first color is red. If you search for the colors array it is used here:doubleGraphics.setColor(colors[screen[i][j]]);
zadoka at 2007-7-8 23:59:18 > top of Java-index,Java Essentials,Java Programming...
# 4

> It looks like there is one color for each piece in

> the pieces array. And the first piece is line and

> the first color is red.

>

> If you search for the colors array it is used here:

>

> [code]doubleGraphics.setColor(colors[screen[j]]);[/

> code]

I was under the impression that all that line of code did was go throught the applet one square at a time a paint pieces that were already on th board....

I know that the first piece is line but how is that associated with the first color? they are both arrays but I can't find where the code links them...

dr1zztth3hunt3ra at 2007-7-8 23:59:18 > top of Java-index,Java Essentials,Java Programming...
# 5

>

> I was under the impression that all that line of code

> did was go throught the applet one square at a time a

> paint pieces that were already on th board....

>

> I know that the first piece is line but how is that

> associated with the first color? they are both arrays

> but I can't find where the code links them...

The index to the piece array is the same index to the color. So there is no real link. When a piece is added to the screen[][]. Its index is added. This same index is used to set the color as well as determine which piece it is.

zadoka at 2007-7-8 23:59:18 > top of Java-index,Java Essentials,Java Programming...
# 6

What a horrible way to write tetris in java. Your task should be to write tetris using object oriented techniques. Not this mess of arrays ****.

Hint 1: Make a "Shape" interface that all complex block types implement.

Hint 2: Create a custom data structure for the board which holds stateful objects.

SpinozaQa at 2007-7-8 23:59:18 > top of Java-index,Java Essentials,Java Programming...
# 7
> What a horrible way to write tetris in java. Your> task should be to write tetris using object oriented> techniques. Not this mess of arrays ****.I agree.But I believe the OP is just looking at this code, trying to determine how it works.
zadoka at 2007-7-8 23:59:18 > top of Java-index,Java Essentials,Java Programming...
# 8

is it just me or does anyone else have a hard time visualizing what a

int[][][][] x = whatever....;

represents in the real word. you should really look at creating a Piece class and creating each of the Tetris Pieces. otherwise, have fun trying to debug a 4D int array living in a 3D world working on a 2D screen using a 1D brain -- oh no i've gone cross-eyed.

den2681a at 2007-7-8 23:59:18 > top of Java-index,Java Essentials,Java Programming...
# 9

> > What a horrible way to write tetris in java. Your

> > task should be to write tetris using object

> oriented

> > techniques. Not this mess of arrays ****.

>

> I agree.But I believe the OP is just looking at

> this code, trying to determine how it works.

You are both correct. I realize this is not a great way to go about this task but when I tried to google tetris java source codes this was the best I could find. If eihter of you can point me to a better source code to study that would be great.

The point of studying this code is so because I am trying to make a simple 2d game engine that allows for movement of objects in 2 directions.... if anyone can point me to a BASIC version of that then I will be more than happy.

by the way, thank you for spending your time helping. I appreciate it.

dr1zztth3hunt3ra at 2007-7-8 23:59:19 > top of Java-index,Java Essentials,Java Programming...
# 10

There are many ways you can go about it.

The example you posted is a good example of a procedural approach to Tetris, however the code is more manageable, easier to read, and much better to visualize in an OO approach.

I developed a version of Tetris where I extended Canvas for the game board, Rectangle for individual blocks, and created a special class for each shape.

They traversed the board by simply changing the coordinates of individual blocks and checking for collisions.

I used Timers to traverse blocks slowly down the Canvas, and KeyAdapter's to move them left to right.

maple_shafta at 2007-7-8 23:59:19 > top of Java-index,Java Essentials,Java Programming...
# 11

> There are many ways you can go about it.

>

> The example you posted is a good example of a

> procedural approach to Tetris, however the code is

> more manageable, easier to read, and much better to

> visualize in an OO approach.

>

> I developed a version of Tetris where I extended

> Canvas for the game board, Rectangle for individual

> blocks, and created a special class for each shape.

>

> They traversed the board by simply changing the

> coordinates of individual blocks and checking for

> collisions.

>

> I used Timers to traverse blocks slowly down the

> Canvas, and KeyAdapter's to move them left to right.

That sounds like a lot closer to what I am looking for. Is there anyway I can see your source code for learning purposes?

dr1zztth3hunt3ra at 2007-7-8 23:59:19 > top of Java-index,Java Essentials,Java Programming...
# 12

I guess I can just give it on good faith...

I don't normally do this but it really was just something I was doing as a proof of concept for a Street Fighter rip-off that I wanted to take a stab at in my free time.

Post your email address or make it visible in your profile and I will email you the source code.

I won't email you my actual applet code but I will show you my canvas, rectangle, and shape classes so you can get an idea.

maple_shafta at 2007-7-8 23:59:19 > top of Java-index,Java Essentials,Java Programming...
# 13

> What a horrible way to write tetris in java. Your task should be to

> write tetris using object oriented techniques. Not this mess of arrays ****.

Depends on the context. If the aim is to learn Java, then OO is the way to go. If the aim is to make a commercially successful browser-based game then a procedural approach which only uses a single class will be a smaller download, and if the game proves wildly successful will save you considerable bandwidth costs.

YAT_Archivista at 2007-7-8 23:59:19 > top of Java-index,Java Essentials,Java Programming...
# 14

> Depends on the context. If the aim is to learn Java,

> then OO is the way to go. If the aim is to make a

> commercially successful browser-based game then a

> procedural approach which only uses a single class

> will be a smaller download, and if the game proves

> wildly successful will save you considerable

> bandwidth costs.

But then someone decompiles your code, the entire Java community laughs at

your nest of snakes and you can never show up at a Star Trek convention again,

dressed as anything other than a Wookie.

Trust me, I know.

BigDaddyLoveHandlesa at 2007-7-8 23:59:19 > top of Java-index,Java Essentials,Java Programming...
# 15
> you can never show up at a Star Trek convention again,> dressed as anything other than a Wookie.u bad man racist
YAT_Archivista at 2007-7-21 17:05:50 > top of Java-index,Java Essentials,Java Programming...
# 16

> I guess I can just give it on good faith...

>

> I don't normally do this but it really was just

> something I was doing as a proof of concept for a

> Street Fighter rip-off that I wanted to take a stab

> at in my free time.

>

> Post your email address or make it visible in your

> profile and I will email you the source code.

>

> I won't email you my actual applet code but I will

> show you my canvas, rectangle, and shape classes so

> you can get an idea.

That would be more than helpful. My aim is only to understand that which I do not and get my head further around these concepts. Thank you

dr1zzt.do.urd3n@gmail.com

dr1zztth3hunt3ra at 2007-7-21 17:05:50 > top of Java-index,Java Essentials,Java Programming...