I am writing a game similar to Bejeweled, and after running the application for some time the blocks fail to be exactly at the right place visually but logically they are at the right place. The situation is as the picture below.
I don't know the cause of the bug.
here are the codes for the method erase and descend. Logically these methods do well.
public void erase()
{
for (int i = 0; i < BlockManager.length; i++)
{
Block block = BlockManager.blocks[BlockManager.erased[i][0]][BlockManager.erased[i][1]];
BlockManager.blocks[BlockManager.erased[i][0]][BlockManager.erased[i][1]] = null;
FadeTransition transition = new FadeTransition(Duration.seconds(1), block);
transition.setFromValue(1);
transition.setToValue(0);
transition.setOnFinished(e ->
{
blockGridPan.getChildren().remove(block);
descend();
BlockManager.resetArrays();
});
transition.play();
}
}
int[][] descend = new int[HEIGHT * WIDE][2];
int descendLength = 0;
public void descend()
{
int[] columnX = new int[10];
int[] theUpperOne = new int[10];
Arrays.fill(theUpperOne, 10);
Arrays.fill(columnX, 0);
for (int j = 0; j < BlockManager.length; j++)
{
columnX[BlockManager.erased[j][0]]++;
if (BlockManager.erased[j][1] < theUpperOne[BlockManager.erased[j][0]])
{
theUpperOne[BlockManager.erased[j][0]] = BlockManager.erased[j][1];
}
}
TranslateTransition transition = null;
for (int i = 0; i < 10; i++)
{
if (columnX[i] == 0)
continue;
for (int j = WIDE - 1; j >= 0; j--)
{
if (BlockManager.blocks[i][j] == null)
continue;
int dY = 0;
for (int k = j + 1; k < WIDE; k++)
{
if (BlockManager.blocks[i][k] == null)
dY++;
}
if (dY != 0)
{
int deltaY = dY * 60;
transition = new TranslateTransition(Duration.seconds(1), BlockManager.blocks[i][j]);
transition.setByY(deltaY);
BlockManager.blocks[i][j + dY] = BlockManager.blocks[i][j];
BlockManager.blocks[i][j + dY].setPosition(i, j + dY);
BlockManager.blocks[i][j] = null;
BlockManager.blocks[i][j + dY].setDescended(true);
transition.play();
}
}
for (int j = columnX[i] - 1; j >= 0; j--)
{
int deltYJ = j * 60;
createOneBlock(i, j);
BlockManager.setBlockColorWithoutCheck(BlockManager.blocks[i][j]);
blockGridPane.add(BlockManager.blocks[i][j], i, 0);
System.out.println("show it");
BlockManager.blocks[i][j].setDescended(true);
transition = new TranslateTransition(Duration.seconds(1), BlockManager.blocks[i][j]);
transition.setByY(deltYJ);
transition.play();
}
}
if (transition != null)
transition.setOnFinished(e ->
{
BlockManager.resetArrays();
if (BlockManager.check())
erase();
});
}
}
You didn't paste your codes for your layout, so I'm going to make a guess.
There is a potential problem when you do translate
and your layout depends on boundsInParent
. This is an abstract from the JavaDoc:
The rectangular bounds of this Node which include its transforms. boundsInParent is calculated by taking the local bounds (defined by boundsInLocal) and applying the transform created by setting the following additional variables
- transforms ObservableList
- scaleX, scaleY
- rotate
- layoutX, layoutY
- translateX, translateY
When your TranslateTransition
animates, it is changing the block's translateY
value, and if your layout is called at this time, this translate value is going to affect how the block's is going to be positioned. If your layout is managed by some kind of layout manager (i.e. pane), you need to check how they position their children.