I'm working on a project, similar to the mobile Game "Clash Royale", currently the program is moving the Character on the Anchorpane through an Animationtimer, to simulate a battle between two Characters I'm using an Thread, who is checking the damage & health of the two participants
The error appears when dragging multiple characters on the board
Exception in thread "JavaFX Application Thread" java.lang.IllegalThreadStateException
at java.base/java.lang.Thread.start(Thread.java:789)
at clash.royale/clash.royale.model.ActiveCards.fight(ActiveCards.java:157)
at clash.royale/clash.royale.model.ActiveCards$1.handle(ActiveCards.java:141)
at javafx.graphics/javafx.animation.AnimationTimer$AnimationTimerReceiver.lambda$handle$0(AnimationTimer.java:57)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at javafx.graphics/javafx.animation.AnimationTimer$AnimationTimerReceiver.handle(AnimationTimer.java:56)
at javafx.graphics/com.sun.scenario.animation.AbstractMasterTimer.timePulseImpl(AbstractMasterTimer.java:357)
at javafx.graphics/com.sun.scenario.animation.AbstractMasterTimer$MainLoop.run(AbstractMasterTimer.java:267)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:515)
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.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:829)
CODE
public class ActiveCards extends Thread {
double health;
double damage;
int path;
ProgressBar healthBar;
Pane whole = new Pane();
static ArrayList<ActiveCards> active = new ArrayList<>();
boolean enemydetected = false;
boolean samewidths;
boolean sameheights;
Pane enemie;
boolean exit = false;
boolean started = false;
ArrayList<ActiveCards> onBoardCards = new ArrayList<>();
AnimationTimer move = new AnimationTimer() {
private long lastUpdate = 0;
private long walk = 0;
@Override
public void handle(long l) {
if(l-walk >= 800_000_000.0) {
if (whole.getRotate() == -3 || whole.getRotate() == 0 && !enemydetected) {
whole.setRotate(5);
}else if (whole.getRotate() == 5) {
whole.setRotate(-3);
}
walk = l;
}
if (l - lastUpdate >= 12_000_000) {
if (!enemydetected) {
if (whole.getLayoutX() < 240) {
whole.setLayoutX(whole.getLayoutX() + 1.5);
}
if (whole.getLayoutY() <= 150) {
path = 60;
} else if (whole.getLayoutY() > 150) {
path = 240;
}
if (whole.getLayoutY() > path - 2 && whole.getLayoutY() < path + 1) {
if (whole.getLayoutX() < 500 && whole.getLayoutX() >= 240) {
whole.setLayoutX(whole.getLayoutX() + 1.5);
}
} else if (whole.getLayoutY() < path) {
whole.setLayoutY(whole.getLayoutY() + 1.5);
} else if (whole.getLayoutY() > path) {
whole.setLayoutY(whole.getLayoutY() - 1.5);
}
for (ActiveCards a : active) {
double underX = whole.getLayoutX() - 95;
double overY = whole.getLayoutY() - 95;
double overX = whole.getLayoutX() + 95;
double underY = whole.getLayoutY() + 95;
if (a.whole != whole && !a.enemydetected && !enemydetected) {
if (a.whole.getLayoutY() >= overY && a.whole.getLayoutY() <= whole.getLayoutY() && a.whole.getLayoutX() >= underX && a.whole.getLayoutX() <= overX) {
enemydetected = true;
synchronized (a) {
a.enemydetected = true;
}
a.started = true;
enemie = a.whole;
a.enemie = whole;
} else if (a.whole.getLayoutY() <= underY && a.whole.getLayoutY() >= whole.getLayoutY() && a.whole.getLayoutX() >= underX && a.whole.getLayoutX() <= overX) {
enemydetected = true;
synchronized (a) {
a.enemydetected = true;
}
enemie = a.whole;
a.enemie = whole;
a.started = true;
}
}
}
}
if (enemydetected) {
//Reset movement Rotation
if(whole.getRotate() == 5 || enemie.getRotate() == -5 ||whole.getRotate() == -5 || enemie.getRotate() == 5){
whole.setRotate(0);
enemie.setRotate(0);
}
if (whole.getLayoutY() < enemie.getLayoutY() - 1) {
whole.setLayoutY(whole.getLayoutY() + 1);
} else if (whole.getLayoutY() > enemie.getLayoutY() + 1) {
whole.setLayoutY(whole.getLayoutY() - 1);
} else {
samewidths = true;
}
if (whole.getLayoutX() < enemie.getLayoutX() - 32) {
whole.setLayoutX(whole.getLayoutX() + 1);
} else if (whole.getLayoutX() > enemie.getLayoutX() + 32) {
whole.setLayoutX(whole.getLayoutX() - 1);
} else {
sameheights = true;
}
if (sameheights && samewidths && !started) {
started = true;
onBoardCards = active;
try {
fight();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
lastUpdate = l;
}
};
public void fight() throws InterruptedException {
if(!this.isAlive()) {
this.start();
}
}
ActiveCards(int health, int damage, Image p, double x, double y, Pane playable) {
ImageView iv = new ImageView();
iv.setImage(p);
iv.setFitHeight(30);
iv.setFitWidth(30);
whole.setPrefWidth(30);
whole.setPrefHeight(30);
whole.setLayoutX(x - 130);
whole.setLayoutY(y - 70);
healthBar = new ProgressBar();
healthBar.setLayoutY(33);
healthBar.setPrefHeight(10);
healthBar.setPrefWidth(32);
healthBar.setProgress(1);
whole.getChildren().add(healthBar);
whole.getChildren().add(iv);
playable.getChildren().add(whole);
playable.toFront();
this.health = health;
this.damage = damage;
}
public void run() {
int i = 0;
while (onBoardCards.size() > i && !exit) {
ActiveCards a = onBoardCards.get(i);
i++;
if (a.whole == enemie) {
double setHealthBar = damage / a.health;
double setHealthBarThis = a.damage / health;
while (a.health > 0 && health > 0) {
Platform.runLater(new Runnable() {
@Override
public void run() {
a.healthBar.setProgress(a.healthBar.getProgress() - setHealthBar);
}
});
a.health = a.health - damage;
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
if (a.health > 0) {
Platform.runLater(new Runnable() {
@Override
public void run() {
healthBar.setProgress(healthBar.getProgress() - setHealthBarThis);
}
});
health = health - a.damage;
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
if (a.health <= 0) {
a.whole.setVisible(false);
a.whole.setDisable(true);
a.move.stop();
active.remove(a);
enemydetected = false;
this.started = false;
exit = true;
}
if (health <= 0) {
whole.setVisible(false);
whole.setDisable(true);
active.remove(this);
move.stop();
a.enemydetected = false;
a.started = false;
exit = true;
}
}
}
}
}