如何让Tetris块每秒都掉下来(错误)

时间:2015-11-25 21:38:22

标签: java swing

初学Java开发人员。试图将俄罗斯方块小程序作为我个人项目的一部分。

我就是这样,我可以在屏幕上画出俄罗斯方块,但我不能每秒都垂直向下移动。

代码:

 public class InitialScreen extends JApplet implements ActionListener {
 public JPanel cards = new JPanel();
 private JPanel introPanel = new JPanel();
 public CardLayout c1 = new CardLayout();

public void init() {
    initiateIntroScreen();
    //game();
    add(cards, BorderLayout.NORTH);
    setSize(500, 100);
}



private void initiateIntroScreen() {
    Frame title = (Frame)this.getParent().getParent();


    cards.setLayout(c1);

    JLabel centralWords = new JLabel("Click the following button options: 'Play' or 'Instructions'.");
    JButton playBtn = new JButton("Play!");
    JButton instructionsBtn = new JButton("Instructions!");

    introPanel.add(centralWords);
    introPanel.add(playBtn);
    introPanel.add(instructionsBtn);
    cards.add(introPanel,"1");

    playBtn.addActionListener(this);
    playBtn.addActionListener(new MainGame(cards,c1));


}

@Override
public void actionPerformed(ActionEvent e) {
    setSize(300,410);
    getContentPane().setBackground(Color.BLACK);
}

所以这是JApplet的初始屏幕。有两个按钮。当您按下“播放”按钮时,它会进入主游戏屏幕。

public class MainGame extends JApplet implements ActionListener {
private JPanel cards;
private CardLayout c1;
private JPanel gamePanel = new JPanel();

public MainGame(JPanel cards, CardLayout c1) {
    this.c1 = c1;
    this.cards = cards;
    gamePanel.add(new Tetris_Block(new int[10][20]));
}


@Override
public void actionPerformed(ActionEvent e) {
    JLabel scoreLbl = new JLabel("Score:");
    gamePanel.add(scoreLbl);
    cards.add(gamePanel,"game");
    c1.show(cards,"game");

}

这是俄罗斯方块播放的游戏画面。在构造函数中,它调用了俄罗斯方块。

public class Tetris_Block extends JComponent implements ActionListener {
static Color[] colors =
        {darkGray, green, blue, red,
                yellow, magenta, pink, cyan};
int[][] a;
int w, h;
static int horizontalPos, verticalPos = 0;
static int size = 20;
private int verticalPos1 = 1;

public Tetris_Block(int[][] a) {
    this.a = a;
    w = a.length;
    h = a[0].length;
    square_Block();
    startTimer();
}

private void nextMove() {
    verticalPos++;
    verticalPos1++;
}

 public void square_Block(){ //Horizontal || Vertical || Colour

    //Horizontal never changes for this as I just want the blocks to go down.
    a[0][verticalPos] = 3;
    a[0][verticalPos1] = 3;
    a[1][verticalPos] = 3;
    a[1][verticalPos1] = 3;
}


@Override
public void actionPerformed(ActionEvent e) {
    nextMove();
    square_Block();
    System.out.println(verticalPos);
}


public void startTimer(){
    Timer timer = new Timer(1000,this);
    timer.start();
}


public void paintComponent(Graphics g) {
    for (int i = 0; i < w; i++) {
        for (int j = 0; j < h; j++) {
                g.setColor(colors[a[i][j]]);
                g.fill3DRect(i * size, j * size,
                        size, size, true);

            }
        }
    }


public Dimension getPreferredSize() {
    return new Dimension(w * size, h * size);
}

我的目标是让每秒的垂直位置增加1(所以它会在第二个时间间隔内向下移动。

我认为Timer功能不是问题所在。当我打印verticalPos时,它每秒打印出递增的值,但它只是在屏幕上显示新的位置 - 这就是问题。

现在窗口的图像。

[IMG] http://i.imgur.com/au5fceO.png?1[/img]

2 个答案:

答案 0 :(得分:4)

首先,在repaint

actionPerformed方法中添加对Tetris_Block的调用
@Override
public void actionPerformed(ActionEvent e) {
    nextMove();
    square_Block();
    System.out.println(verticalPos);
    // This is important
    repaint();
}

这将在事件队列上安排一个paint事件,最终将调用paintComponent方法(间接)

这将使块开始移动。你将遇到的下一个问题是你实际上并没有&#34;删除&#34;从它的前一个位置开始阻止,所以它将继续在屏幕上流血/长大

Bleeding blocks

您可以通过将块的颜色传递给square_Block来解决此问题,例如......

public void square_Block(int color) { //Horizontal || Vertical || Colour

    //Horizontal never changes for this as I just want the blocks to go down.
    a[0][verticalPos] = color;
    a[0][verticalPos1] = color;
    a[1][verticalPos] = color;
    a[1][verticalPos1] = color;
}

然后&#34;休息&#34;当前位置的块,更新位置,然后设置新的块颜色;

@Override
public void actionPerformed(ActionEvent e) {
    square_Block(0);
    nextMove();
    square_Block(3);
    System.out.println(verticalPos);
    repaint();
}

Falling

答案 1 :(得分:0)

您的设计可能有问题。你需要有一个在一个单独的线程中运行的游戏循环。它必须是与主线程分开的线程,因此用户仍然可以单击按钮。一旦你在单独的线程中有一个循环,你需要有一个方法,你可以为每个游戏滴答调用。在那种方法中,您可以更新块的坐标。

游戏循环的工作方式如下: 1.阅读游戏状态并绘制块 2.处理用户输入。 3.更新游戏状态

我知道这是抽象的,但我希望它有所帮助。 Google关于java游戏和游戏循环。