我正在用 Java 编写俄罗斯方块克隆,一切似乎都可以正常工作,直到我想要清除一整行并删除上面的所有内容。尽管我的所有数据都正确地表示了转换,但我的 paintComponent 方法似乎只清除了该行,但上面显示的所有内容都与 repaint() 调用之前一样。新碎片将穿过幻影块并落在底行的隐形块上,上面的碎片会掉下来。
这是我的油漆组件方法:
public void paintComponent(Graphics page)
{
super.paintComponent(page);
Graphics2D page2D = (Graphics2D) page;
for (int c = 0; c < 10; c++)
{
for (int r = 0; r < 18; r++)
{
if (well[c][r] != null) //Well is a 2D array of Block objects that have Rectangle object, coordinates and color
{
page2D.setColor(well[c][r].getColor());
page2D.fill(well[c][r].getSquare());
page2D.setColor(Color.gray);
page2D.draw(well[c][r].getSquare());
}
}
}
for (int i = 0; i < 4; i++) //tetro = the player's tetris piece
{
page2D.setColor(tetro.getColor());
page2D.fill(tetro.getBlock(i).getSquare());
page2D.setColor(Color.GRAY);
page2D.draw(tetro.getBlock(i).getSquare());
}
}
这是我的 Timer 侦听器中的 actionPerformed 方法的一部分,它检测/清除块并调用重绘方法。
int count = 0; //Number of occupied cells in well
int clears = 0; //number of rows to be clear
int lowestClear = -1; //Lowest row that was cleared, -1 if none
for (int row = 0; row < 18; row++)
{
for (int col = 0; col < 10; col++)
{
if (well[col][row] != null)
{
count++;
}
}
if (count == 10)
{
clears++;
if (lowestClear < 0)
{
lowestClear = row;
}
for (int col = 0; col < 10; col++)
{
well[col][row] = null;
}
}
count = 0;
}
if (clears > 0)
{
repaint(); //Doesn't call paintComponent()
for (int i = 1; i <= clears; i++)
{
for (int r = 16; r >= 0; r--)
{
if (r > lowestClear)
{
break;
}
for (int c = 0; c < 10; c++)
{
if (well[c][r] != null)
{
well[c][r+1] = well[c][r];
well[c][r] = null;
}
}
}
}
repaint(); //Does not call paintComponent()
}
tetro.fall();
repaint(); //DOES call paint component
在调用第一个 repaint() 方法时,井数组正确显示整行现在完全为空。我希望 repaint() 方法更新面板以显示此空行,但似乎没有调用 paintComponent()。这也是第二个 repaint() 方法的情况,我希望它更新框架以在清除一行并将它们放下后将块显示在新位置。同样,paintComponent() 没有被调用。然而,对于最后一次 repaint() 调用,我只想更新下落块的位置,而不管它之前可能需要或不需要进行的任何更新,repaint() 确实调用了 paintComponent()。所以:第一个问题是,为什么 paintComponent() 只在 repaint() 调用的这个实例中被调用。
但是,当调用paintComponent() 并到达该方法的末尾时,我会在调试模式下跟踪它以查看面板在哪一行反映了更改。一旦到达 :"Repaintmanager.paintDirtyRegions(Map< Component,Rectangle >)" line:856,它已经清除了行并显示了新的落块,但是有不可见的块和幻像块。
所以,我的第二个问题是,为什么 paintComponent() 会以这种方式表现。显然,我需要对 Repaintmanager 和 Java 绘画进行大量阅读,但如果有人可以向我解释这一点,我将不胜感激。
如果重要,这是主要方法:
import javax.swing.JFrame;
public class TetrisDriver
{
public static void main(String[] args)
{
JFrame frame = new JFrame("Tetris");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new Matrix()); //Matrix = jPanel class
frame.pack();
frame.setVisible(true);
}
}
如果这太长了,我很抱歉。