Justiciar
Justiciar

Reputation: 376

Adding additional shapes in a tetris project. loop logic assistance

I am creating a tetris clone as a personal project to help me get better at drawing images, moving them, and to learn collision detection.

Everything is going fine but I am stumped at the logic behind getting the program to add a new tetrimino shape to the frame when the first has stopped moving. So far I use a random number generator to create a tetrimino at random, and can add that to the frame. I just can't figure out how to loop it so that once that shape stops moving it adds another shape at the top of the screen.

This is a pre alpha build and in its current implementation I have not yet added the collision detection, any scoring, backgrounds, ability to rotate shapes, etc. I just can't get past this logic roadblock. Please help!

Some code:

    public class tetrisGame extends JFrame
{
    //Frame dimensions
    private static final int FRAME_WIDTH = 600;
    private static final int FRAME_HEIGHT = 600;

    private final int MAX_VALUE = 7; //RNG MAX VALUE
    private final int MIN_VALUE = 1; //RNG MIN VALUE
    private static int dy = 10;
    private static int dx = 0;

    private JLabel welcomeLabel, imageLabel, blankLabel, blankLabel2, creditsLabel1, creditsLabel2, creditsLabel3;
    private JButton startButton, creditsButton, exitButton, returnButton, leftButton, rightButton;
    private Shapes component; //Tetrimino Shape

    private JPanel totalGUI, buttonPanel, startPanel, creditsPanel, gamePanel, movePanel;

    public tetrisGame()
    {
        createComponents();
        setSize(FRAME_WIDTH, FRAME_HEIGHT);
        setTitle("Tetris");
    }

    //Moves tetrimino's down using a timer
    class TimerListener implements ActionListener
    {
        public void actionPerformed(ActionEvent e)
        {
            component.moveRectangleBy(dx,dy);
        }
    }

    //Moves the tetrimino to the right 
    class moveRightListener implements ActionListener
    {
        public void actionPerformed(ActionEvent e)
        {
            dy = 0;
            component.moveRectangleBy(dx+10,dy);
            dy = 10;
        }
    }

    //Moves the tetrimino to the left.
    class moveLeftListener implements ActionListener
    {
        public void actionPerformed(ActionEvent e)
        {
            dy = 0;
            component.moveRectangleBy(dx-10,dy);
            dy = 10;
        }
    }

    //Executed when a new game is started.  The heart of the program.
    class newGameListener implements ActionListener
    {
        public void actionPerformed(ActionEvent e)
        {
            int  randomNum = createRNG(MAX_VALUE, MIN_VALUE);

            if (randomNum == 1)
            {
                component = new SquareShape();
            }
            else if (randomNum == 2)
            {
                component = new RectangleShape();
            }
            else if (randomNum == 3)
            {
                component = new JShape();
            }
            else if (randomNum == 4)
            {
                component = new SShape();
            }
            else if (randomNum == 5)
            {
                component = new TShape();
            }
            else if (randomNum == 6)
            {
                component = new LShape();
            }
            else
            {
                component = new ZShape();
            }

            //Creates and starts timer that moves shapes
            int delay = 1000;
            ActionListener timerListener = new TimerListener();
            javax.swing.Timer t = new javax.swing.Timer(delay, timerListener);
            t.start();

            remove(totalGUI);
            add(component, BorderLayout.CENTER);
            add(movePanel, BorderLayout.SOUTH);
            repaint();
            revalidate();

        }   
    }

    //Adds components of the credit screen when button is pressed
    class creditsListener implements ActionListener
    {
        public void actionPerformed(ActionEvent e)
        {
            totalGUI.remove(startPanel);
            totalGUI.add(creditsPanel);
            repaint();
            revalidate();
        }
    }

    //Exits the program
    class exitListener implements ActionListener
    {
        public void actionPerformed(ActionEvent e)
        {
            System.exit(0);
        }
    }

    //returns to the main menu screen. 
    class returnListener implements ActionListener
    {
        public void actionPerformed(ActionEvent e)
        {
            totalGUI.remove(creditsPanel);
            totalGUI.add(startPanel);
            repaint();
        }
    }

    //Creates all components of the GUI
    private void createComponents()
    {
        //Imports Tetris image
        try
        {
            String path = "http://static3.gamespot.com/uploads/screen_kubrick/1179/11799911/2550560-tetris.jpg";
            URL url = new URL(path);
            BufferedImage image = ImageIO.read(url);
            Image newImage = image.getScaledInstance(300,120,java.awt.Image.SCALE_SMOOTH);
            imageLabel = new JLabel(new ImageIcon(newImage));
        } catch(Exception e){}
        //Creates welcome prompt and new game buttons
        welcomeLabel = new JLabel("                                Welcome to Tetris!");
        Font boldFont = welcomeLabel.getFont();
        welcomeLabel.setFont(boldFont.deriveFont(boldFont.getStyle() ^ Font.BOLD));
        welcomeLabel.setForeground(Color.orange);
        blankLabel = new JLabel("");
        blankLabel2 = new JLabel("");
        startButton = new JButton("New Game");
        creditsButton = new JButton("Credits");
        exitButton = new JButton("Exit");

        //Adds action listeners to new game buttons
        ActionListener newGameListener = new newGameListener();
        startButton.addActionListener(newGameListener);
        ActionListener creditsListener = new creditsListener();
        creditsButton.addActionListener(creditsListener);
        ActionListener exitListener = new exitListener();
        exitButton.addActionListener(exitListener);

        //Adds new game buttons to panel
        buttonPanel = new JPanel();
        buttonPanel.setLayout(new GridLayout(6,1));
        buttonPanel.setBackground(Color.black);
        buttonPanel.add(blankLabel);
        buttonPanel.add(blankLabel2);
        buttonPanel.add(welcomeLabel);
        buttonPanel.add(startButton);
        buttonPanel.add(creditsButton);
        buttonPanel.add(exitButton);

        //Buttons that move the tetrimino's
        leftButton = new JButton("<--");
        ActionListener leftListener = new moveLeftListener();
        leftButton.addActionListener(leftListener);
        rightButton = new JButton("-->");
        ActionListener rightListener = new moveRightListener();
        rightButton.addActionListener(rightListener);
        //Panel that contains movement buttons
        movePanel = new JPanel();
        movePanel.add(leftButton);
        movePanel.add(rightButton);

        //Continue to add elements to panel
        startPanel = new JPanel();
        startPanel.setLayout(new BorderLayout());
        startPanel.add(imageLabel, BorderLayout.NORTH);
        startPanel.add(buttonPanel, BorderLayout.CENTER);

        //Create elements of credits screen
        creditsLabel1 = new JLabel("The Tetris logo, block shapes, and dimensions are registered trademarks of The Tetris Company.");
        creditsLabel1.setFont(boldFont.deriveFont(boldFont.getStyle() ^ Font.BOLD));
        creditsLabel1.setForeground(Color.orange);
        creditsLabel2 = new JLabel("                   This product is an academic work intended for individual use only.");
        creditsLabel2.setFont(boldFont.deriveFont(boldFont.getStyle() ^ Font.BOLD));
        creditsLabel2.setForeground(Color.orange);
        creditsLabel3 = new JLabel("                         All programming written in the Java language by NAME REMOVED.");
        creditsLabel3.setFont(boldFont.deriveFont(boldFont.getStyle() ^ Font.BOLD));
        creditsLabel3.setForeground(Color.orange);
        returnButton = new JButton("Return");
        ActionListener returnListener = new returnListener();
        returnButton.addActionListener(returnListener);
        creditsPanel = new JPanel();
        creditsPanel.setLayout(new GridLayout(5,1));
        creditsPanel.setBackground(Color.black);
        creditsPanel.add(creditsLabel1);
        creditsPanel.add(creditsLabel2);
        creditsPanel.add(blankLabel);
        creditsPanel.add(creditsLabel3);
        creditsPanel.add(returnButton);

        //Initial game panel
        totalGUI = new JPanel();
        totalGUI.add(startPanel);
        totalGUI.setBackground(Color.black);

        add(totalGUI, BorderLayout.CENTER);
    }

    //generates a random number.
    private int createRNG(int MAX_VALUE, int MIN_VALUE)
    {
        Random rand = new Random();
        int randomNum = rand.nextInt(MAX_VALUE - MIN_VALUE + 1) + MIN_VALUE;

        return randomNum;
    }
}

And here is the code of one of the shapes classes in case you need to reference that:

public class SquareShape extends Shapes
{
    private static final int RECTANGLE_WIDTH = 40;
    private static final int RECTANGLE_HEIGHT = 40;

    private int xLeft;
    private int yTop;
    boolean stopped = false;

    public SquareShape()
    {
        xLeft = 280;
        yTop = 0;
    }

    public void paintComponent(Graphics g)
    {
        //draws 1 large square
        g.setColor(Color.cyan);
        g.fillRect(xLeft,yTop,RECTANGLE_WIDTH,RECTANGLE_HEIGHT);

        //Divides the square into parts
        g.setColor(Color.black);
        g.drawLine(xLeft,yTop,xLeft+40,yTop);
        g.drawLine(xLeft,yTop,xLeft,yTop+40);
        g.drawLine(xLeft,yTop+40,xLeft+40,yTop+40);
        g.drawLine(xLeft+40,yTop+40,xLeft+40,yTop);
        g.drawLine(xLeft,yTop+20,xLeft+40,yTop+20);
        g.drawLine(xLeft+20,yTop,xLeft+20,yTop+40);        
    }

    public void moveRectangleBy(int dx, int dy)
    { 
        if (yTop < 450)
        {
            xLeft += dx;
            yTop += dy;
            if (xLeft < 0)
            {
                xLeft = 0;
            }
            if (xLeft > 500)
            {
                xLeft = 500;
            }
        }
        repaint();
    }


}

Thanks in advance for any help. I'm confident I can implement the rest of the program once I get past this issue where I just can't seem to figure out how to get the shapes to keep coming down.

Upvotes: 0

Views: 703

Answers (1)

camickr
camickr

Reputation: 324147

I just can't figure out how to loop it so that once that shape stops moving it adds another shape at the top of the screen.

Well in your Timer logic you have:

component.moveRectangleBy(dx,dy);

So this assumes you always have an "active" component. You need the ability to determine when the component is at the bottom so you can reset the component.

So you might restructure your listener code to look something like:

if (component == null)
    component = // a new random shape
else
{
    component.moveRectangleBy(...);

    if (component.isAtBottom()) // a method you will need to write
        component == null;
}

For what its worth, I have also played with my own Tetris game. It currently:

  1. adds random pieces
  2. moves pieces down the board
  3. usees the 4 arrow keys to move/rotate a tetris piece
  4. removes full lines

The basic design is in 4 classes:

  1. TetrisIcon - paints a square with a border
  2. TetrisPiece - a 4x4 array representation of a tetris piece. A value of 1 indicates the TetricIcon should be painted.
  3. TetrisBoard - Contains a List of TetrisIcons to be painted as well as the current TetrisPiece that moves down the board. When the TetrisPiece reaches the bottom, its individual TetrisIcons are moved to the board.
  4. Tetris - builds the frame and starts the game.

If you want to play with it, have fun:

Tetris:

import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.border.*;
import java.awt.geom.*;

public class Tetris extends JPanel
{
    private final static int TETRIS_ICON_SIZE = 20;

    private List<TetrisPiece> tetrisPieces = new ArrayList<TetrisPiece>();
    private TetrisBoard board;
    private Random random = new Random();

    public Tetris()
    {
        setLayout( new BorderLayout() );

        createTetrisPieces();

        board = new TetrisBoard(20, 10, 20);
        add(board, BorderLayout.LINE_START);
/*
        board.setTetrisIconAt(new TetrisIcon(Color.RED, TETRIS_ICON_SIZE), 5, 5);
        board.setTetrisIconAt(new TetrisIcon(Color.RED, TETRIS_ICON_SIZE), 5, 6);
        board.setTetrisIconAt(new TetrisIcon(Color.RED, TETRIS_ICON_SIZE), 6, 5);
        board.setTetrisIconAt(new TetrisIcon(Color.RED, TETRIS_ICON_SIZE), 0, 0);
        board.setTetrisIconAt(new TetrisIcon(Color.RED, TETRIS_ICON_SIZE), 0, 19);
        board.setTetrisIconAt(new TetrisIcon(Color.RED, TETRIS_ICON_SIZE), 9, 0);
        board.setTetrisIconAt(new TetrisIcon(Color.RED, TETRIS_ICON_SIZE), 9, 19);

        board.setTetrisPiece( tetrisPieces.get(1) );
*/
        JButton start = new JButton( new StartAction() );
        add(start, BorderLayout.PAGE_END);
    }

    private void createTetrisPieces()
    {
        int[][] shape =
        {
            {0, 1, 0, 0},
            {0, 1, 0, 0},
            {0, 1, 0, 0},
            {0, 1, 0, 0}
        };

        tetrisPieces.add( new TetrisPiece(shape, new TetrisIcon(Color.RED, TETRIS_ICON_SIZE)) );

        shape = new int[][]
        {
            {0, 1, 0, 0},
            {0, 1, 0, 0},
            {0, 1, 1, 0},
            {0, 0, 0, 0}
        };

        tetrisPieces.add( new TetrisPiece(shape, new TetrisIcon(Color.YELLOW, TETRIS_ICON_SIZE)) );

        shape = new int[][]
        {
            {0, 0, 1, 0},
            {0, 0, 1, 0},
            {0, 1, 1, 0},
            {0, 0, 0, 0}
        };

        tetrisPieces.add( new TetrisPiece(shape, new TetrisIcon(Color.MAGENTA, TETRIS_ICON_SIZE)) );

        shape = new int[][]
        {
            {0, 0, 0, 0},
            {0, 1, 1, 0},
            {0, 1, 1, 0},
            {0, 0, 0, 0}
        };

        tetrisPieces.add( new TetrisPiece(shape, new TetrisIcon(Color.CYAN, TETRIS_ICON_SIZE)) );

        shape = new int[][]
        {
            {0, 0, 0, 0},
            {0, 1, 0, 0},
            {1, 1, 1, 0},
            {0, 0, 0, 0}
        };

        tetrisPieces.add( new TetrisPiece(shape, new TetrisIcon(Color.WHITE, TETRIS_ICON_SIZE)) );

        shape = new int[][]
        {
            {0, 0, 0, 0},
            {0, 1, 1, 0},
            {1, 1, 0, 0},
            {0, 0, 0, 0}
        };

        tetrisPieces.add( new TetrisPiece(shape, new TetrisIcon(Color.BLUE, TETRIS_ICON_SIZE)) );

        shape = new int[][]
        {
            {0, 0, 0, 0},
            {1, 1, 0, 0},
            {0, 1, 1, 0},
            {0, 0, 0, 0}
        };

        tetrisPieces.add( new TetrisPiece(shape, new TetrisIcon(Color.GREEN, TETRIS_ICON_SIZE)) );
    }

    class StartAction extends AbstractAction
    {
        public StartAction()
        {
            super("Start Game");
        }

        @Override
        public void actionPerformed(ActionEvent e)
        {
            new Timer(1000, new AbstractAction()
            {
                @Override
                public void actionPerformed(ActionEvent e2)
                {
                    if (board.getTetrisPiece() == null)
                    {
                        int piece = random.nextInt( tetrisPieces.size() );
                        board.setTetrisPiece( tetrisPieces.get( piece ) );
                    }
                    else
                    {
                        board.moveShapeDown();
                    }
                }
            }).start();
        }
    }


    private static void createAndShowGUI()
    {

        JFrame frame = new JFrame("Tetris");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new Tetris());
        frame.setLocationByPlatform( true );
        frame.pack();
        frame.setVisible( true );
    }

    public static void main(String[] args)
    {
        EventQueue.invokeLater( () -> createAndShowGUI() );
/*
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                createAndShowGUI();
            }
        });
*/
    }
}

TetrisBoard:

import java.awt.*;
import java.awt.event.*;
import java.util.List;
import java.util.ArrayList;
import javax.swing.*;

class TetrisBoard extends JPanel
{
    private List<TetrisIcon[]> board;

    private int rows;
    private int columns;
    private int size;

    private TetrisPiece tetrisPiece;

    public TetrisBoard(int rows, int columns, int size)
    {
        this.rows = rows;
        this.columns = columns;
        this.size = size;

        board = new ArrayList<TetrisIcon[]>(rows);

        for (int i = 0; i < rows; i++)
            board.add( new TetrisIcon[columns] );

        setBackground( Color.BLACK );

        addKeyBindings();
    }

    private void addKeyBindings()
    {
        InputMap inputMap = getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
        ActionMap actionMap = getActionMap();

        String leftName = "LEFT";
        KeyStroke leftKeyStroke = KeyStroke.getKeyStroke( leftName );
        inputMap.put(leftKeyStroke, leftName);
        actionMap.put(leftName, new AbstractAction()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                moveShapeLeft();
            }
        });

        String rightName = "RIGHT";
        KeyStroke rightKeyStroke = KeyStroke.getKeyStroke( rightName );
        inputMap.put(rightKeyStroke, rightName);
        actionMap.put(rightName, new AbstractAction()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                moveShapeRight();
            }
        });

        String downName = "DOWN";
        KeyStroke downKeyStroke = KeyStroke.getKeyStroke( downName );
        inputMap.put(downKeyStroke, downName);
        actionMap.put(downName, new AbstractAction()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
//              moveShapeDown();
                dropShape();
            }
        });

        String upName = "UP";
        KeyStroke upKeyStroke = KeyStroke.getKeyStroke( upName );
        inputMap.put(upKeyStroke, upName);
        actionMap.put(upName, new AbstractAction()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                rotateShape();
            }
        });
    }

    public TetrisPiece getTetrisPiece()
    {
        return tetrisPiece;
    }

    public void setTetrisPiece(TetrisPiece tetrisPiece)
    {
        this.tetrisPiece = new TetrisPiece(tetrisPiece.getShape(), tetrisPiece.getIcon());
        this.tetrisPiece.setLocation( new Point(4, 0) );
        repaint();
    }

    public void setTetrisIconAt(TetrisIcon icon, int x, int y)
    {
        TetrisIcon[] row = board.get(y);
        row[x] = icon;
    }

    public TetrisIcon getTetrisIconAt(int x, int y)
    {
        TetrisIcon[] row = board.get(y);

        return row[x];
    }

    public void moveShapeLeft()
    {
        if (tetrisPiece == null) return;

        Point possibleLocation = new Point(tetrisPiece.getX() - 1, tetrisPiece.getY());

        if ( canMoveShape(possibleLocation, tetrisPiece.getShape()) )
        {
            tetrisPiece.setLocation( possibleLocation );
            repaint();
        }
    }

    public void moveShapeRight()
    {
        if (tetrisPiece == null) return;

        Point possibleLocation = new Point(tetrisPiece.getX() + 1, tetrisPiece.getY());

        if ( canMoveShape(possibleLocation, tetrisPiece.getShape()) )
        {
            tetrisPiece.setLocation( possibleLocation );
            repaint();
        }
    }

    public void dropShape()
    {
        if (tetrisPiece == null) return;

        Point possibleLocation = new Point(tetrisPiece.getX(), tetrisPiece.getY() + 1);

        while ( canMoveShape(possibleLocation, tetrisPiece.getShape()) )
        {
            moveShapeDown();
            possibleLocation = new Point(tetrisPiece.getX(), tetrisPiece.getY() + 1);
        }

//      addTetrisPieceToBoard();
//      tetrisPiece = null;
    }

    public void moveShapeDown()
    {
        if (tetrisPiece == null) return;

        Point possibleLocation = new Point(tetrisPiece.getX(), tetrisPiece.getY() + 1);

        if ( canMoveShape(possibleLocation, tetrisPiece.getShape()) )
        {
            tetrisPiece.setLocation( possibleLocation );
            repaint();
        }
        else
        {
            tetrisPieceAtBottom();
        }
    }

    private void tetrisPieceAtBottom()
    {
        Point location = tetrisPiece.getLocation();
        int row = Math.min(rows, location.y + 4);
        row--;

        addTetrisPieceToBoard();

        int rowsRemoved = 0;


        for (; row >= location.y; row--)
        {
//          System.out.println(row);
            TetrisIcon[] icons = board.get(row);

            if ( fullRow(row) )
            {
                board.remove(row);
                rowsRemoved++;
            }
        }

        for (int i = 0; i < rowsRemoved; i++)
            board.add(0, new TetrisIcon[columns]);

        if (rowsRemoved > 0)
            repaint();
    }

    private boolean fullRow(int row)
    {
        for (int column = 0; column < columns; column++)
        {
//          System.out.println(row + " : " + column);
            if ( getTetrisIconAt(column, row) == null)
                return false;
        }

        return true;
    }

    private void addTetrisPieceToBoard()
    {
        int x = tetrisPiece.getX();
        int y = tetrisPiece.getY();

        for (int r = 0; r < tetrisPiece.getRows(); r++)
        {
            for (int c = 0; c < tetrisPiece.getColumns(); c++)
            {
                TetrisIcon icon = tetrisPiece.getIconAt(r, c);

                if (icon != null)
                {
                    setTetrisIconAt(icon, x, y);
                }

                x++;
            }

            x = tetrisPiece.getX();
            y++;
        }

        tetrisPiece = null;
    }

    public void rotateShape()
    {
        if (tetrisPiece == null) return;

        int[][] rotatedShape = tetrisPiece.getRotatedShape();

        if ( canMoveShape(tetrisPiece.getLocation(), rotatedShape) )
        {
            tetrisPiece.setShape( rotatedShape );
            repaint();
        }
    }

    private boolean canMoveShape(Point location, int[][] shape)
    {
        for (int r = 0; r < shape.length; r ++)
        {
            for (int c = 0; c < shape.length; c++)
            {
                if (shape[r][c] == 1)
                {
                    int x = location.x + c;
                    int y = location.y + r;

                    //  Past left edge

                    if (x < 0) return false;

                    //  Past right edge

                    if (x >= columns) return false;

                    //  Past bottom edge

                    if (y >= rows) return false;

                    //  Collision with TetrisIcon

                    if (getTetrisIconAt(x, y) != null) return false;
                }
            }
        }

        return true;
    }

    @Override
    public Dimension getPreferredSize()
    {
        int width = (columns * size) + columns - 1;
        int height = (rows * size) + rows - 1;

        return new Dimension(width, height);
    }

    @Override
    protected void paintComponent(Graphics g)
    {
        super.paintComponent( g );

        int x = 0;
        int y = 0;
        int offset = size + 1;

        for (int r = 0; r < rows; r++)
        {
            TetrisIcon[] row = board.get(r);

            for (int c = 0; c < row.length; c++)
            {
                TetrisIcon icon = row[c];

                if (icon != null)
                {
                    icon.paintIcon(this, g, x, y);
                }

                x += offset;
            }

            x = 0;
            y += offset;
        }

        // paint shape

        if (tetrisPiece != null)
        {
            paintShape(g, offset);
        }
    }

    private void paintShape(Graphics g, int offset)
    {
        int x = tetrisPiece.getX() * offset;
        int y = tetrisPiece.getY() * offset;

        for (int r = 0; r < tetrisPiece.getRows(); r++)
        {
            for (int c = 0; c < tetrisPiece.getColumns(); c++)
            {
                TetrisIcon icon = tetrisPiece.getIconAt(r, c);

                if (icon != null)
                {
                    icon.paintIcon(this, g, x, y);
                }

                x += offset;
            }

            x = tetrisPiece.getX() * offset;
            y += offset;
        }
    }
}

TetrisPiece:

import java.awt.Point;

public class TetrisPiece
{
    private int[][] shape;
    private TetrisIcon icon;
    private Point location = new Point();

    public TetrisPiece(int[][] shape, TetrisIcon icon)
    {
        setShape(shape);
        this.icon = icon;
    }

    public TetrisIcon getIcon()
    {
        return icon;
    }

    public int[][] getShape()
    {
        return shape;
    }

    public void setShape(int[][] shape)
    {
        this.shape = shape;
    }

    public TetrisIcon getIconAt(int x, int y)
    {
        return  (shape[x][y] == 1) ? icon : null;
    }

    public Point getLocation()
    {
        return location;
    }

    public void setLocation(Point location)
    {
        this.location = location;
    }

    public int getX()
    {
        return location.x;
    }

    public int getY()
    {
        return location.y;
    }

    public int getRows()
    {
        return shape.length;
    }

    public int getColumns()
    {
        return shape[0].length;
    }

    public int[][] getRotatedShape()
    {
        int[][] rotatedShape = new int[shape.length][shape[0].length];

        int x = 0;
        int y = 0;

        for (int c = shape.length - 1; c >= 0; c--)
        {
            for (int r = 0; r < shape[0].length; r++)
            {
                rotatedShape[x][y] = shape[r][c];
                y++;
            }

            x++;
            y = 0;
        }

        return rotatedShape;
    }

}

TetrisIcon:

import java.awt.*;
import javax.swing.*;

public class TetrisIcon implements Icon
{
    private Color color;
    private int size;

    public TetrisIcon(Color color, int size)
    {
        this.color = color;
        this.size = size;
    }

    public int getIconWidth()
    {
        return size;
    }

    public int getIconHeight()
    {
        return size;
    }

    public void paintIcon(Component c, Graphics g, int x, int y)
    {
        int width = getIconWidth() - 1;
        int height = getIconHeight() - 1;

        g.translate(x, y);

        g.setColor(color);
        g.fillRect(0, 0, width, height);

        g.setColor(Color.LIGHT_GRAY);
        g.drawLine(0, 0, width, 0);
        g.drawLine(0, 0, 0, height);

        g.setColor(Color.DARK_GRAY);
        g.drawLine(width, 0, width, height);
        g.drawLine(0, height, width, height);

        g.translate(-x, -y);
    }
}

Upvotes: 1

Related Questions