1

I have started developing Tetris Game. Everything is working fine but how to retain rectangles at the bottom?

This is the Comp1 class in which the random shape is retrieved and move down with the timer

package buildblock;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
import buildblock.tetris;
public class Comp1 extends JPanel implements ActionListener {

int curx=10;
int cury=30;
int nx=0;
int ny=0;
int p=1;
 Timer t;
boolean EndofLine=false;
JLabel l1=new JLabel("");
int value=0;
int coords[][][]=new int[3][3][2];
int shape[][][][]={
        {{{0,0},{0,0},{0,0}},{{0,0},{0,0},{0,0}},{{0,0},{0,0},{0,0}}},
        {{{0,0},{100,20},{0,0}},{{0,0},{100,40},{0,0}},{{80,60},{100,60},{0,0}}},
        {{{0,0},{100,20},{0,0}},{{80,40},{100,40},{120,40}},{{0,0},{0,0},{0,0}}},
        {{{0,0},{100,20},{0,0}},{{0,0},{100,40},{0,0}},{{0,0},{100,60},{0,0}}},
        {{{80,20},{100,20},{0,0}},{{0,0},{100,40},{0,0}},{{0,0},{100,60},{0,0}}},
        {{{0,0},{100,20},{0,0}},{{80,40},{100,40},{0,0}},{{80,60},{0,0},{0,0}}},
        {{{80,20},{0,0},{0,0}},{{80,40},{100,40},{0,0}},{{0,0},{100,60},{0,0}}},
         {{{80,20},{100,20},{0,0}},{{80,40},{100,40},{0,0}},{{0,0},{0,0},{0,0}}},
        };

Comp1(tetris Parent)
{
   setVisible(true);
   setSize(400,900);
   curx=(400-curx)/2;
   setLayout(new BorderLayout());
   timer();
}

public void getShape(int a)
{
     for(int i=0;i<3;i++)
    {
        for(int j=0;j<3;j++)
        {
            for(int k=0;k<2;k++)
            {
            coords[i][j][k]=shape[a][i][j][k];
             repaint();
            }
        }
    }
}

public void paint(Graphics g)
{
    super.paint(g);

    for(int i=0;i<3;i++)
    {
        for(int j=0;j<3;j++)
        {
            for(int k=0;k<2;k++)
            {
                if(coords[i][j][k]!=0)
                {
                    if(k==0)
                    {
                        curx=coords[i][j][k]+nx;
                    }
                    else
                    {
                        cury=coords[i][j][k]+ny;
                        drawRec(g,curx,cury,20,20);

                    }
                }
            }
        }
    }              
}

 public void drawRec(Graphics g,int newx,int newy,int w,int h)
 {
             g.drawRect(newx, newy, 20, 20);
             g.drawLine(curx+1,cury+20-1,curx+20-1,cury+20-1);       
 }

public void timer()
{
t=new Timer(150,this);
  t.start();
}

public int Random()
{
    Random r=new Random();
    int n=Math.abs(r.nextInt()%7+1);
    return n;
}

public void lineDown()
{
    ny=ny+10;
    repaint();
}

public void actionPerformed(ActionEvent e) 
{
    if(value!=250&&!EndofLine)
    {     
        value=value+5;
        if(p==0)
        {
            p=Random();
        }
        getShape(p);
        lineDown();
    }
    else
    {
        p=Random();
        ny=0;
        EndofLine=false;
        value=0;
    }
}
}

The shape is a 4 dimensional array from which the width and height of particular rectangle is retrieved which collectively form a desired shape.Through random function we choose the particular shape with getShape() method and using drawRect function we draw the Rectangles.

Now the lineDown function move down the particular shape with increment of 10,and after reaching at the last line the repaint() method is called and new Random shape is falling down from top,The Problem is now how to retain the particular shape at bottom so that next operations can be carried out.

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
Akaal
  • 371
  • 3
  • 5
  • 1
    Make an `List` of shapes in the `Tetris` class that contains all shapes that are finished falling. After a shape falls add it to the finished array. You will likely need this array for collision checking anyway. – ug_ Jun 30 '14 at 07:25
  • 1
    Further tips: 1) To do animation properly in a Swing component, the easiest way is to establish a Swing `Timer` and call `repaint()` from the `actionPerformed(ActionEvent)` method of the `ActionListener`. 2) `setSize(400,900);` better to override the `getPreferredSize()` method of the panel, then `pack()` the parent container. 3) `public void paint(Graphics g) { super.paint(g);..` should be `public void paintComponent(Graphics g) { super.paintComponent(g);..` for any `JComponent` such as a `JPanel`. – Andrew Thompson Jun 30 '14 at 07:41
  • 1
    You might also consider making a class for each shape considering there are only 7 shapes in tetris, this would help you cleanup some code and not have that 4d array that makes my head spin. – ug_ Jun 30 '14 at 07:47
  • It really does seem easier to use a Class for a shape rather than a confusing 4-dimensional array. – EpicPandaForce Jun 30 '14 at 08:04
  • Also look at [Shape based collision detection](http://stackoverflow.com/a/14575043/418556). It uses Java 2D `Area` objects to test for intersection. – Andrew Thompson Jun 30 '14 at 09:39

1 Answers1

3

I would create a List of "shapes" that have already fallen down to the bottom of the Tetris board. This List would be held within your Tetris class and when the current falling item hits the bottom of the board or one of the already falled shapes then it should be stopped and added to the fallen list.

Other general tips:

From personal experience, try to stay away from arrays of size > 2 unless its necessary; they are bloated, confusing and hard to maintain. In your case there's a perfect interface to use called Shape. Check out this code

// java.awt.geom.Path2D implements java.awt.Shape
java.awt.geom.Path2D path = new Path2D.Double();
path.moveTo(0, 0);
path.lineTo(2, 0);
path.lineTo(2, 2);
path.lineTo(2, 0);
path.closePath();
path.transform(AffineTransform.getScaleInstance(20, 20));

This creates a Shape that is your basic square! You then have access to great features that you wont have to implement yourself.

PS: As Andrew suggests in the comments, "Also look at Shape based collision detection. It uses Java 2D Area objects to test for intersection."

Community
  • 1
  • 1
ug_
  • 11,267
  • 2
  • 35
  • 52
  • I have not worked much with the Graphics2D or geom Package's classes,but found this thing quite interesting and helpful now.By testing these methods and classes I found out that if I would make a Polygon array which will hold all the & shapes, and then refer them using Shape class reference variable,this will be more convenient to translate or rotate rather than Path2D. – Akaal Jun 30 '14 at 17:23
  • But I am still confused in choosing between the Path2D and Shape classes.Agian Need your suggestions,thanks ug_ :) – Akaal Jun 30 '14 at 17:37
  • @Akaal the `Shape` class you are referring to is actually an interface. Many types of shapes implement this interface some of which include `Path2D`, `Polygon`, `Rectangle` [and many more](http://docs.oracle.com/javase/7/docs/api/java/awt/Shape.html). You could use either one you like to build out your Tetris pieces I just used a `Path2D` because I am more familiar with them. – ug_ Jun 30 '14 at 18:35