Witam. Wciąż pracuję nad programem z tego wątku. Niestety, nie jestem w stanie wymyślić niczego, co byłoby w stanie współpracować z timeline
. Postanowiłem napisać metodę ruchu od nowa i stworzyłem coś takiego:
void move()
{
if(position_x-ballRadius<=usingMinLimit_x || position_x+ballRadius>=usingMaxLimit_x)
{
dx*=-1;
}
if(position_y-ballRadius<=usingMinLimit_y || position_y+ballRadius>=usingMaxLimit_y)
{
dy*=-1;
}
/*if(position_x+ballRadius>=box.getOuterSquareMinX() && position_x-ballRadius<=box.getOuterSquareMaxX() &&
position_y+ballRadius>=box.getOuterSquareMinY() && position_y-ballRadius<=box.getOuterSquareMaxY() &&
!isInTheBox) {
//timeline.pause();
try {
wait();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}*/
position_x += dx*speed;
position_y += dy*speed;
ball.setCenterX(position_x);
ball.setCenterY(position_y);
}
A to mam w metodzie run()
:
while(true)
{
synchronized (this) {
move();
try {
sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Dla jednej kulki wszystko działa jak należy. Problem pojawia się, gdy kulek jest więcej. W pewnym momencie wszystkie się zatrzymują i program zaczyna sypać wyjątkami:
Exception in thread "JavaFX Application Thread" java.lang.IndexOutOfBoundsException: Index -1 out of bounds for length 2
at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)
at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:248)
at java.base/java.util.Objects.checkIndex(Objects.java:372)
at java.base/java.util.ArrayList.get(ArrayList.java:458)
at javafx.base/com.sun.javafx.collections.ObservableListWrapper.get(ObservableListWrapper.java:89)
at javafx.base/com.sun.javafx.collections.VetoableListDecorator.get(VetoableListDecorator.java:306)
at javafx.graphics/javafx.scene.Parent.updateCachedBounds(Parent.java:1701)
at javafx.graphics/javafx.scene.Parent.recomputeBounds(Parent.java:1645)
at javafx.graphics/javafx.scene.Parent.doComputeGeomBounds(Parent.java:1498)
at javafx.graphics/javafx.scene.Parent.access$200(Parent.java:79)
at javafx.graphics/javafx.scene.Parent$1.doComputeGeomBounds(Parent.java:115)
at javafx.graphics/com.sun.javafx.scene.ParentHelper.computeGeomBoundsImpl(ParentHelper.java:84)
at javafx.graphics/com.sun.javafx.scene.layout.RegionHelper.superComputeGeomBoundsImpl(RegionHelper.java:78)
at javafx.graphics/com.sun.javafx.scene.layout.RegionHelper.superComputeGeomBounds(RegionHelper.java:62)
at javafx.graphics/javafx.scene.layout.Region.doComputeGeomBounds(Region.java:3289)
at javafx.graphics/javafx.scene.layout.Region.access$300(Region.java:147)
at javafx.graphics/javafx.scene.layout.Region$1.doComputeGeomBounds(Region.java:168)
at javafx.graphics/com.sun.javafx.scene.layout.RegionHelper.computeGeomBoundsImpl(RegionHelper.java:89)
at javafx.graphics/com.sun.javafx.scene.NodeHelper.computeGeomBounds(NodeHelper.java:115)
at javafx.graphics/javafx.scene.Node.updateGeomBounds(Node.java:3837)
at javafx.graphics/javafx.scene.Node.getGeomBounds(Node.java:3799)
at javafx.graphics/javafx.scene.Node.updateBounds(Node.java:771)
at javafx.graphics/javafx.scene.Parent.updateBounds(Parent.java:1832)
at javafx.graphics/javafx.scene.Scene$ScenePulseListener.pulse(Scene.java:2497)
at javafx.graphics/com.sun.javafx.tk.Toolkit.lambda$runPulse$2(Toolkit.java:412)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at javafx.graphics/com.sun.javafx.tk.Toolkit.runPulse(Toolkit.java:411)
at javafx.graphics/com.sun.javafx.tk.Toolkit.firePulse(Toolkit.java:438)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:519)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:499)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulseFromQueue(QuantumToolkit.java:492)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$11(QuantumToolkit.java:320)
at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
at javafx.graphics/com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
at javafx.graphics/com.sun.glass.ui.gtk.GtkApplication.lambda$runLoop$11(GtkApplication.java:277)
at java.base/java.lang.Thread.run(Thread.java:834)
Wnioskuję, że moje rozwiązanie "nie lubi" wielowątkowości.
Stąd też mam do Was kolejną prośbę o pomoc. Mam jeszcze jeden pomysł: dodać obiekt klasy Canvas
, zmienić sporą część kodu i używać GraphicsContext.fillOval()
. Czy powyższy kod da się uratować, czy może lepiej od razu przejść do rozwiązania z poprzedniego zdania. Problem tkwi w tym, że nie mogę używać żadnych "automatów" typu timeline
, AnimationTimer
, itp.