Давайте начнем с ...
@Override
public void paint(Graphics g) {
super.paintComponent(g);
g.setColor(Color.RED);
g.fillRect(appleXPosition, appleYPosition, 10, 10);
g.setColor(Color.GREEN);
g.fillRect(snakeXPosition, snakeYPosition, 10, 10);
if (checkDirection == 0) {
snakeXPosition = right(snakeXPosition);
} else if(checkDirection == 1) {
snakeXPosition = left(snakeXPosition);
} else if (checkDirection == 2) {
snakeYPosition = up(snakeYPosition);
} else {
snakeYPosition = down(snakeYPosition);
}
}
Вы переопределяете paint
, но звоните super.paintComponent
. paint
сам выполняет много важных заданий, а paintComponent
- только одна из них.
Вместо этого вы должны переопределить paintComponent
напрямую (и назвать его super
)
Подробнее см. Выполнение пользовательской живописи и Рисование в AWT и Swing
Живопись не должна принимать логические решения, она должна просто рисовать текущее состояние модели. Вместо этого эти решения должны приниматься как часть этапа «обновления», выполняемого как часть «основного цикла»
«Основной цикл» будет проверять состояние входных данных, принимать решения о том, как следует обновлять состояние, и планировать проход рендеринга.
Простым местом для начала может быть использование Swing Timer
Я бы также рекомендовал использовать API привязок клавиш вместо KeyListener
, это исправит проблемы с ненадежностью, связанные с KeyListener