0

By now I feel like I have tried everything. I am trying to get this simple Tetris game running but even though I am having no exeptions there, it still shows JFrame window as black with a small white rectangle on top left corner.

This is what I have already tried:

  1. play around with f.setVisible(true); as suggested by many ppl.
  2. check for possible infinite loops (changing =+1 to +=1)
  3. Tried to include also: //f.add(panel); //f.pack();

My Code:

package fritol.sevela.java;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.Collections;

import javax.swing.JFrame;
import javax.swing.JPanel;




public class Tetris002 extends JPanel {        


    /**
     * 
     */
    private static final long serialVersionUID = 1L;


    /**
     * 
     */



    private final Point[][][] myPoint= {
            {

                {new Point(0,1),new Point(1,1),new Point(2,1),new Point(3,1)}, 
                {new Point(1,0),new Point(1,1),new Point(1,2),new Point(1,3)}, 
                {new Point(0,1),new Point(1,1),new Point(2,1),new Point(3,1)}, 
                {new Point(1,0),new Point(1,1),new Point(1,2),new Point(1,3)}, 
            },  



            {

                {new Point(0,1),new Point(1,1),new Point(2,1),new Point(2,0)}, 
                {new Point(1,0),new Point(1,1),new Point(1,2),new Point(2,2)}, 
                {new Point(0,1),new Point(1,1),new Point(2,1),new Point(0,1)}, 
                {new Point(1,0),new Point(1,1),new Point(1,2),new Point(0,3)}, 
            },  


            {

                {new Point(0,1),new Point(1,1),new Point(2,1),new Point(2,0)}, 
                {new Point(1,0),new Point(1,1),new Point(1,2),new Point(2,2)}, 
                {new Point(0,1),new Point(1,1),new Point(2,1),new Point(0,0)}, 
                {new Point(1,0),new Point(1,1),new Point(1,2),new Point(2,0)}, 
            },  

            {

                {new Point(0,0),new Point(0,1),new Point(1,0),new Point(1,1)}, 
                {new Point(0,0),new Point(0,1),new Point(1,0),new Point(1,1)}, 
                {new Point(0,0),new Point(0,1),new Point(1,0),new Point(1,1)}, 
                {new Point(0,0),new Point(0,1),new Point(1,0),new Point(1,1)}, 
            },  

    };  


    //Defining COLOURS
    private final Color[] myColor= {Color.CYAN, Color.magenta,Color.orange,Color.yellow,Color.black,Color.pink,Color.red};


    private Point pt;
    private int currentPiece;
    private int rotation;
    private ArrayList<Integer> nextPiece=new ArrayList<Integer>();
    private long score;
    private Color[][] well;



    private void init() {
            well=new Color[12][24];   
            for(int i=0; i<12;i++) {  
                for(int j=0;j<23;j++) { 
                    if(i==0||i==11||i==22) {
                        well[i][j]=Color.pink;
                    }else{
                        well[i][j]=Color.black; 
                    }                               

                }
            }

            newPiece();   
        }   


    public void newPiece() {
        pt=new Point(5,2);
        rotation=0;
        if(nextPiece.isEmpty()) {   
            Collections.addAll(nextPiece, 0,1,2,3);   
            Collections.shuffle(nextPiece);  
        }
    }

    rotation.
    private boolean collidesAt(int x, int y, int rotation) {

        for(Point p: myPoint[currentPiece][rotation]) {
            if(well[p.x+x][p.y+y]!=Color.black) {
                return true;

            }

        }
        return false;
    }

    private void rotate(int i) {    
    int newRotation=(rotation+i)%4;
    if(newRotation<0) {
        newRotation=3;

        }

    if(!collidesAt(pt.x,pt.y, newRotation)){
        rotation=newRotation;

    }
    repaint(); //Some repaint function?

    }   

            //move and move only??
    public void move(int i) {
        if(!collidesAt(pt.x,pt.y,rotation)) {
        pt.x+=i;    
        }

        repaint();

    }
    public void drop() {           
        if(!collidesAt(pt.x,pt.y,rotation)) {
        pt.y+=1;
        }else {
            fixToWell();
        }
        repaint();
        }


    public void  fixToWell() {
        for(Point p: myPoint[currentPiece][rotation]) {
        well[pt.x+p.x]  [pt.y+p.y]=myColor[currentPiece];

        }
        clearRows();
        newPiece();

    }

    public void deleteRow(int row) {         
        for(int j=row-1;j>0;j--) {
            for (int i=1; i<11;i++){
                well[i][j+1]=well[i][j];

            }
        }
    }

    //Now we will create Row

    public void clearRows() {
        boolean gap;
        int numClear=0;
        for(int j=21; j>0; j--) {
            gap=false;
            for(int i=1;i<11;i++) {
                if(well[i][j]==Color.black) {
                gap=true;
                    break;

                }
            }       
        if(!gap) {
            deleteRow(numClear);
            j+=1;
            numClear+=1;    
        }
        }
        switch(numClear) {            //score stuff
            case 1:
                score+=100;
                break;

            case 2:
                score+=300;
                break;

            case 3:
                score+=500;
                break;  

            case 4:
                score+=800;
                break;
            }   


        } //now we provide function to draw the piece //<>[]{}

        private void drawPiece(Graphics g) {
            g.setColor(myColor[currentPiece]);
            for(Point p:myPoint[currentPiece][rotation]) {
            g.fillRect((p.x+pt.x)*26,(pt.y+p.y)*26,25,25);

            }       
        }

        public void paintComponent(Graphics g) {    
            g.fillRect(0, 0, 26*12, 26*23);
            for(int i=0; i<23;i++) {
            for (int j=0;j<23;j++)  {
                g.setColor(well[i][j]);
                g.fillRect(26*i,26*j, 25,25);

                }   
            }   
            g.setColor(Color.WHITE);
            g.drawString("Score:"+score, 19*12, 25);        
            drawPiece(g);

        }


    public static void main(String[] args) {



        JFrame f=new JFrame("Tetris002");         
        //JPanel panel=new JPanel(); //Added by me
        //f.setContentPane(panel);  //added by me
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setSize(12*26+10, 26*23+25);
        //f.add(panel);
        //f.pack();
        f.setVisible(true);


        final Tetris002 game=new Tetris002();  


        game.init();
        f.add(game);



        //Now Controls and Keys
        f.addKeyListener(new KeyListener() {

        @Override
        public void keyTyped(KeyEvent e) { 

        }

        public void keyReleased(KeyEvent e) { 



        }

        public void keyPressed(KeyEvent e) { 
            switch(e.getKeyCode()) {
            case KeyEvent.VK_UP:
                game.rotate(-1);
                break;

            case KeyEvent.VK_DOWN:
                game.rotate(+1);
                break;      


            case KeyEvent.VK_LEFT:
                game.move(-1);
                break;  

            //case KeyEvent.VK_RIGHT:        
                //game.move(+1);
                //break;

            case KeyEvent.VK_SPACE:
                game.drop();
                game.score+=1;

                break;

                }
            }
    });
    new Thread() {
        public void run() {
            while(true) {
                try {
                    Thread.sleep(1000); 

            } catch (InterruptedException e) {

                e.printStackTrace();

            }
            game.drop();


            }
        }

        }.start();


        }

}
George Z.
  • 6,643
  • 4
  • 27
  • 47
  • With the code you posted, I'm not seeing the same error as you say you are. I get an exception in `paintComponent`, because `i` goes up to 24, while the array is only 12 items long. But if that out-of-bounds exception is fixed, the game begins to run (mostly) correctly. – resueman Sep 10 '19 at 19:16

2 Answers2

2

Did you see the console for any possible errors? Because when I ran your code, I got an ArrayIndexOutOfBounds exception in this line (inside paintComponent method): g.setColor(well[i][j]);. Your outer loop is for (int i = 0; i < 23; i++) while well array is new Color[12][24]. No wonder why it takes place. Changing the loop to for (int i = 0; i < 12; i++) will let the frame get visible.

Some notices though.

  1. All swing applications must run on their own thread, called EDT (Event-Dispatch-Thread). Call SwingUtilities#invokeLater in your main and let the app run there.

    SwingUtilities.invokeLater(()->{
        JFrame f = new JFrame("Tetris002");
        ....
    });
    
  2. Instead of creating a new Thread, take a look on how can i pause/sleep/wait in a java swing app. Using javax.swing.Timer looks better (from code perspective), and it is created for such cases since the task will run in EDT. With few words, the awful (code-looking) Thread part becomes:

    new Timer(1000, e -> {
        game.drop();
    }).start();
    
  3. When you @Override paintComponent, always call super.paintComponent(g). Let the component be painted "normally" and then do your stuff:


@Override
public void paintComponent(Graphics g) {
    super.paintComponent(g);
    //My custom painting
}
George Z.
  • 6,643
  • 4
  • 27
  • 47
  • This really helped out, thank you for your detailed advice! Changing the outer loop did the thing, I only need to put it on fullscreen everytime so that it starts working. Nevertheless, I will go through your other suggestions and see how this works out + how can I learn from it. – Marek Ševela Sep 10 '19 at 19:48
0

The issue was function paintComponent. Wen you were assigning values to array well. You were going outofbounds. When looping over array I suggest use array.length function instead of putting its length manually. Anyway if you change you function like this it should work.

public void paintComponent(Graphics g) {
    g.fillRect(0, 0, 26 * 12, 26 * 23);
    for (int i = 0; i < well.length; i++) {
        for (int j = 0; j < well[i].length; j++) {
            g.setColor(well[i][j]);
            g.fillRect(26 * i, 26 * j, 25, 25);
        }
    }
    g.setColor(Color.WHITE);
    g.drawString("Score:" + score, 19 * 12, 25);
    drawPiece(g);
}
Yoshikage Kira
  • 1,070
  • 1
  • 12
  • 20
  • Hmmm, this does not seem to help, still need to do manual resizing. I have also noticed that my shapes are not random, only L shape keeps falling. – Marek Ševela Sep 10 '19 at 19:58
  • @MarekŠevela I have only fixed the `indexoutofbound`exception. Which is equivalent of putting 12 in outer loop. – Yoshikage Kira Sep 10 '19 at 20:00