Хорошо, так что проблема сводится к некоторым основным математикам ...
Если мы посмотрим на метод draw
для BodyPart
, вы найдете ...
g.fillRect(xCoor * width, yCoor * height, width, height);
Хорошо, довольно просто, но действительно ли все эти значения установлены?
Если мы посмотрим на метод tick
(где создаются BodyPart
s), мы можем найти ...
b = new BodyPart(xCoor, yCoor, 10);
snake.add(b);
Хорошо, значит width
и height
- это 10
, но как насчет xCoor
и yCoor
?
Сначала они инициализируются как поля экземпляров вместе с классом ...
private int xCoor = 100, yCoor = 100, size = 10;
Итак, небольшое количество математики говорит нам, что начальное местоположение BodyPart
равно 100 * 10
, что равно 1000x1000
.
Если мы тоже посмотрим на ...
public static final int WIDTH = 1000, HEIGHT = 1000; //Dimensions of the panel (Will be set by user input later)
и
setPreferredSize(new Dimension(WIDTH, HEIGHT));
мы можем видеть, что BodyPart
изначально отключен от экрана.
Итак, если мы изменим исходную позицию на что-то более похожее ...
private int xCoor = 10, yCoor = 10, size = 10;
вы найдете пропавшую змею.
Общие советы ...
Вам следует избегать переопределения paint
. Это высоко в цепочке краски, и это легко испортить. Вместо этого предпочтите paintComponent
вместо этого (и убедитесь, что вы звоните super.paintComponent
). JPanel
очистит для вас контекст Graphics
(с цветом фона компонента).
Swing не безопасен для потоков. Вы не должны изменять пользовательский интерфейс или любое другое состояние, на которое полагается пользовательский интерфейс, вне контекста потока диспетчеризации событий.
Текущий «основной» цикл находится под угрозой введения грязных обновлений, которые могут вызвать проблемы позже. См. Параллельность в Swing . В качестве «общего» предпочтения вы должны рассмотреть возможность использования Swing Timer
. Он не будет блокировать EDT, но внутри EDT генерируются «галочки», что делает более безопасным обновление интерфейса и / или его состояния изнутри.
Вы должны избегать использования "магических чисел" при выполнении ваших операций ...
for (int i = 0; i < WIDTH/10; i++) {
g.drawLine(i*10, 0, i*10, HEIGHT);
}
Здесь WIDTH
и HEIGHT
могут не соответствовать фактическому размеру компонента. Вместо этого используйте JPanel#getWidth
и JPanel#getHeight
.
Как общая рекомендация, вам следует избегать использования setPreferred/Minimum/MaximumSize
, кому-то еще легко изменить их в состояние, которое вы не хотите. Вместо этого переопределите getPreferred/Minimum/MaximumSize
, вместо этого вы сохраните контроль.