public TetrisPanel() {
        //Initialize the TetrisEngine object.
        engine = new TetrisEngine(this);

        //This is the bg-image.
        try {
            bg = ImageIO.read(getResURL("/image/background.png"));
            fg = ImageIO.read(getResURL("/image/backlayer.png"));

            // Actually, the background is the actual background plus
            // the meta image.
            Image meta = ImageIO.read(getResURL("/image/metalayer.png"));
            Graphics g = bg.getGraphics();
            g.drawImage(meta, 0, 0, null);

        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("Cannot load image.");
        }

        //Animation loop. Updates every 40 milliseconds (25 fps).
        new Thread() {
            @Override
            public void run() {
                while (true) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException ex) {
                        //Logger.getLogger(TetrisPanel.class.getName()).log(Level.SEVERE, null, ex);
                    }
                    repaint();
                }
            }
        }.start();

        //Add all these key functions.
        KeyPressManager kpm = new KeyPressManager();
        kpm.putKey(KeyEvent.VK_LEFT, new Runnable() {
            public void run() {
                TetrisPanel.this.engine.keyleft();
            }
        });
        kpm.putKey(KeyEvent.VK_RIGHT, new Runnable() {
            public void run() {
                TetrisPanel.this.engine.keyright();
            }
        });
        kpm.putKey(KeyEvent.VK_DOWN, new Runnable() {
            public void run() {
                TetrisPanel.this.engine.keydown();
            }
        });
        kpm.putKey(KeyEvent.VK_SPACE, new Runnable() {
            public void run() {
                TetrisPanel.this.engine.keyslam();
            }
        });
        kpm.putKey(KeyEvent.VK_UP, new Runnable() {
            public void run() {
                TetrisPanel.this.engine.keyrotate();
            }
        });
        kpm.putKey(KeyEvent.VK_Z, new Runnable() {
            public void run() {
                TetrisPanel.this.engine.keyrotate();
            }
        });
        kpm.putKey(KeyEvent.VK_SHIFT, new Runnable() {
            @Override
            public void run() {
                if (engine.state != GameState.GAMEOVER && controller != null && !controller.thread.isAlive()) {
                    controller.send_ready(engine.score);
                }
                if (engine.state == GameState.PAUSED) {
                    engine.state = GameState.PLAYING;
                } else {
                    engine.state = GameState.PAUSED;
                    //System.out.println(controller.thread.isAlive());
                }
            }
        });

        addKeyListener(kpm);

        //Focus when clicked.
        addMouseListener(new MouseAdapter() {

            public void mousePressed(MouseEvent me) {
                TetrisPanel.this.requestFocusInWindow();
            }
        });

        setFocusable(true);
        engine.state = GameState.PAUSED;

        if (!isHumanControlled) {
            if(ProjectConstants.BASIC_AI){
                controller = new TetrisAI(this);
                genetic = new GeneticAIFinder(engine);
                genetic.setAIValues((TetrisAI) controller);
            } else {
                controller = new ReinforcementAI(this);
            }
        }
    }