Сама ошибка:
Exception in thread "JavaFX Application Thread" java.lang.IndexOutOfBoundsException: Index 0 out of bounds for length 0
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:426)
at com.javarush.games.snake.Snake.createNewHead(Snake.java:89)
at com.javarush.games.snake.Snake.move(Snake.java:56)
at com.javarush.games.snake.SnakeGame.onTurn(SnakeGame.java:42)
at com.javarush.engine.cell.Game.lambda$setTurnTimer$4(Game.java:344)
at javafx.graphics/com.sun.scenario.animation.shared.TimelineClipCore.visitKeyFrame(TimelineClipCore.java:239)
at javafx.graphics/com.sun.scenario.animation.shared.TimelineClipCore.playTo(TimelineClipCore.java:180)
at javafx.graphics/javafx.animation.Timeline.doPlayTo(Timeline.java:175)
at javafx.graphics/javafx.animation.AnimationAccessorImpl.playTo(AnimationAccessorImpl.java:39)
at javafx.graphics/com.sun.scenario.animation.shared.InfiniteClipEnvelope.timePulse(InfiniteClipEnvelope.java:108)
at javafx.graphics/javafx.animation.Animation.doTimePulse(Animation.java:1101)
at javafx.graphics/javafx.animation.Animation$1.lambda$timePulse$0(Animation.java:186)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
at javafx.graphics/javafx.animation.Animation$1.timePulse(Animation.java:185)
at javafx.graphics/com.sun.scenario.animation.AbstractMasterTimer.timePulseImpl(AbstractMasterTimer.java:344)
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:559)
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)
Код класса Snake (похоже проблемы в нем)
public class Snake {
private List<GameObject> snakeParts = new ArrayList<>(); //сигменты змеи
private static final String HEAD_SIGN = "\uD83D\uDC7E"; //отрисовка головы змеи
private static final String BODY_SIGN = "\u26AB"; //отрисовка тела змеи
public boolean isAlive = true; //змея жива
private Direction direction = Direction.LEFT; //направление
//
//конструктор Snake
//
public Snake(int x, int y) {
GameObject snake = new GameObject(x, y);
GameObject snake1 = new GameObject(x + 1, y);
GameObject snake2 = new GameObject(x + 2, y);
snakeParts.add(snake);
snakeParts.add(snake1);
snakeParts.add(snake2);
}
//
//НАПРАВЛЕНИЕ
//
public void setDirection(Direction direction) {
if (this.direction==direction.getOpposite()) return;
this.direction = (Direction) direction;
}
//
//ОТРИСОВКА ЗМЕИ
//
public void draw(Game game) {
// if (!isAlive) //если змея мертва - закрасить её голову
Color color = isAlive ? Color.BLACK : Color.RED; //если isAlive то Color.BLACK, else Color.RED
game.setCellValueEx(snakeParts.get(0).x, snakeParts.get(0).y, Color.NONE, HEAD_SIGN, color, 75); // рисуем голову
for (int i = 1; i < snakeParts.size(); i++) { //закашиваем каждый кусочек змеи
game.setCellValueEx(snakeParts.get(i).x, snakeParts.get(i).y, Color.NONE, BODY_SIGN, color, 75); //рисуем все остальное тело
}
}
//
//ДВИЖЕМСЯ
//
public void move() {
GameObject gameObject = createNewHead();
if( gameObject.x > SnakeGame.WIDTH-1 || //проверяем, если голова змеи выходит за пределы поля
gameObject.x < 0 ||
gameObject.y > SnakeGame.HEIGHT-1 ||
gameObject.y < 0) {
isAlive = false; //змея умерает
return;
} else { //иначе добавляем голову в остальным сегментам, в самое начало
snakeParts.set(0, gameObject);
removeTail(); //а задний сегмент хвоста удаляем
}
}
//
//УДАЛЯЕМ ХВОСТ
//
public void removeTail() {
snakeParts.remove(snakeParts.size() - 1); //удаляем последний сегмент хвоста змейки
}
//
//CОЗДАЁМ НОВУЮ ГОЛОВУ
//
public GameObject createNewHead() { //создаем новую голову в нужном нам направлении
GameObject gameObject = null;
if (direction == Direction.UP)
gameObject = new GameObject(snakeParts.get(0).x, snakeParts.get(0).y - 1); //если змейка движ вврх
if (direction == Direction.DOWN)
gameObject = new GameObject(snakeParts.get(0).x, snakeParts.get(0).y + 1); //если змейка движ вниз
if (direction == Direction.RIGHT)
gameObject = new GameObject(snakeParts.get(0).x + 1, snakeParts.get(0).y); //если змейка движ вправо
if (direction == Direction.LEFT)
gameObject = new GameObject(snakeParts.get(0).x - 1, snakeParts.get(0).y); //если змейка движ влево
return gameObject;
}
}