2

So I'm working on a game with JavaFX where the characters move by themselves, however, for some reason they move for a certain amount of time (seems random as well), and then I get the following exception:

Exception in thread "JavaFX Application Thread" java.lang.IndexOutOfBoundsException: Index -1 out of bounds for length 8
    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:373)
    at java.base/java.util.ArrayList.get(ArrayList.java:427)
    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:1704)
    at javafx.graphics/javafx.scene.Parent.recomputeBounds(Parent.java:1648)
    at javafx.graphics/javafx.scene.Parent.doComputeGeomBounds(Parent.java:1501)
    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$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:3844)
    at javafx.graphics/javafx.scene.Node.getGeomBounds(Node.java:3806)
    at javafx.graphics/javafx.scene.Node.getLocalBounds(Node.java:3754)
    at javafx.graphics/javafx.scene.Node.updateTxBounds(Node.java:3908)
    at javafx.graphics/javafx.scene.Node.getTransformedBounds(Node.java:3700)
    at javafx.graphics/javafx.scene.Node.updateBounds(Node.java:762)
    at javafx.graphics/javafx.scene.Parent.updateBounds(Parent.java:1835)
    at javafx.graphics/javafx.scene.Parent.updateBounds(Parent.java:1833)
    at javafx.graphics/javafx.scene.Scene$ScenePulseListener.pulse(Scene.java:2491)
    at javafx.graphics/com.sun.javafx.tk.Toolkit.lambda$runPulse$2(Toolkit.java:413)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
    at javafx.graphics/com.sun.javafx.tk.Toolkit.runPulse(Toolkit.java:412)
    at javafx.graphics/com.sun.javafx.tk.Toolkit.firePulse(Toolkit.java:439)
    at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:563)
    at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:543)
    at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulseFromQueue(QuantumToolkit.java:536)
    at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$11(QuantumToolkit.java:342)
    at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
    at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:174)
    at java.base/java.lang.Thread.run(Thread.java:832)

Also, for some reason the length of the message changes, like it throws this:

Index -1 out of bounds for length 1

And then this:

Index -1 out of bounds for length 3

And so on...

Which I don't really understand since I'm using properly the Arraylist of the game characters, to use them as threads:

public void startTroops(){

        for (GameCharacter gameCharacter : army) {
            gameCharacter.start();
        }
    }

The following codes are the run() method for the thread, and the moveTroops() that make the labels move randomly around its container pane:

   @Override
    public void run() {

        System.out.println(""+ getX() + getY());
        while (running) {
            try {
                refController.moveTroops(this);
                Thread.sleep(1000);
            } catch (InterruptedException ex) {}

            while (paused && running) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException ex) {}
            }
        }
    
    public void moveTroops(GameCharacter unit){

        double x = unit.getX();
        double y = unit.getY();
        int direction= ThreadLocalRandom.current().nextInt(0, 3);

        switch (direction){
            case 0: // up
                if (y >= 100) y -= 50;
                break;

            case 1: // down
                if (y <= 900) y += 50;
                break;

            case 2: // left
                if (x >= 100) x -= 50;
                break;

            case 3: // right
                if (x <= 900) x += 50;
                break;
        }

        if (posIsAvailable(x, y)){
            System.out.println(String.format(unit.getunitName() + ": walking (%s, %s)", x, y));
            unit.getSprite().relocate(x, y);
        }
    }

Is there a clear reason on what does that error comes from? Thanks in advance!

Eddy22
  • 23
  • 5

1 Answers1

1

You are moving the labels around in a worker thread?
Chances are this is caused by not updating UI elements on the JavaFX Platform thread. Consider using an Animation timer to update the game state. For now, see if the problem goes away when you wrap the call to:

unit.getSprite().relocate(x, y);

like so:

int newX = x; // need to be effectively final
int newY = y; // for the runLater
Platform.runLater(() -> { unit.getSprite().relocate(newX, newY); });
swpalmer
  • 3,890
  • 2
  • 23
  • 31