Задание 33. Змейка и Мухоморы: финальные штрихи
Общее описание игры здесь. Первая часть здесь. Вторая часть здесь.
Обратите внимание
на статью про отладку приложения.
Дедлайны:
- 9-1: 8 февраля
- 10-1: 2 февраля
- 11-1: 2 февраля
После первой и второй части остались лишь некоторые мелкие детали и тестирование/отладка всей игры в целом.
Например метод update()
в World еще не готов - поэтому нужно его доделать по вашему собственному представлению.
Т.е. он должен проверять - прошло ли достаточно времени с предыдущего обновления, и если прошло, то:
- Продвинуть змейку на один шаг
- Проверить, не врезалась ли змейка в край игрового поля/свой хвост (а значит игра окончена, т.к. змейка заснула)
- Проверить, не наползла ли змейка на яблоко (а значит она стала длиннее на одну клетку)
Кроме этого еще не готово управление. Обработку кнопок осуществляет MainFrame
. Чтобы это сделать, он должен заявить себя “Великим Слушателем Кнопок” - KeyListener
, т.е.
обязаться реализовать три функции обработки нажатия кнопок: keyTyped
, keyPressed
, keyReleased
. Нас интересует нажатие кнопки - т.е. например метод keyTyped
или keyPressed
.
И наш “Великий Слушатель Кнопок” должен оповестить окно о том, что он хочет обрабатывать все нажатия кнопок в этом окне.
Теперь более подробно:
1) Надо релизовать интерфейс KeyListener
Было:
public class MainFrame extends JFrame {
...
}
Стало:
public class MainFrame extends JFrame implements KeyListener {
...
}
2) Реализация трех методов
Обратите внимание
что у вас сразу будет подсвечено красным implements KeyListener
. Т.к. теперь MainFrame
обязуется реализовать упомянутые три метода, но все еще не реализовал их.
Чтобы просто создать объявления этих реализаций с пустым кодом - достаточно поставить каретку ввода на implements KeyListener
(кликнув туда мышью), затем Alt+Enter
, затем Implement methods
, затем выделить все три метода и нажать Ok.
Появится что-то вроде:
public class MainFrame extends JFrame implements KeyListener {
// ...
// Какой-то ваш код
// ...
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
// TODO: обработать событие нажатой кнопки нужно здесь
}
@Override
public void keyReleased(KeyEvent e) {
}
// ...
// Какой-то ваш код
// ...
}
3) Обработка нажатой кнопки
Делается это примерно следующим образом - вы узнаете у события, какой int keyCode
описывает код нажатой кнопкой - сверяете его: “а не совпал ли он с одной из стрелочек”, и если совпал - делаете какую-нибудь логику (например выставляете соответствующее направление движения у Snake через World).
int keyCode = e.getKeyCode();
if (keyCode == KeyEvent.VK_UP) {
// Ваша обработка нажатия стрелки вверх (змейка должна теперь ползти вверх)
} else if (keyCode == KeyEvent.VK_RIGHT) {
// ...
} else if (keyCode == KeyEvent.VK_DOWN) {
// ...
} else if (keyCode == KeyEvent.VK_LEFT) {
// ...
}
Обратите внимание
что если пользователь при движении змейки вверх жмет стрелку вниз - то такие нажатия хочется игнорировать (змейка не умеет делать смертельный разворот на 180 градусов).
4) Оповещение окна о KeyListener
Теперь MainFrame является полноценным KeyListener. В целом обработку нажатия кнопок можно вынести в отдельный класс KeyHandler, но для простоты пусть обработка кнопок будет в MainFrame.
Осталось лишь сообщить окну о том, что у нас появился обработчик нажатия кнопок - это делается через метод addKeyListener(KeyListener listener)
.
Метод этот принадлежит JFrame, а значит наследуется и в MainFrame - нашем игровом окне (соответственно вызываться он будет у него).
Аргумент функции - обработчик нажатия кнопок, т.е. любой, кто реализует интерфейс KeyListener
, в данном случае это объект MainFrame
, поэтому может получиться слегка странный код this.addKeyListener(this)
.
5) Тестирование и отправка задания
Чтобы запустить приложение нужно нажать правой кнопкой на класс с функцией main
(вероятно MainFrame
) и там нажать Run
(или Debug
).
Чтобы отлаживать приложение:
- Нужно читать ошибки, и смотреть в каких строчках они упали (в случае runtime-exception, например
NullPointerException
(обращение кnull
-объекту через точку, т.е. не созданному объекту) илиIndexOutOfBoundsException
(выход за пределы массива)). - Можно запускать под отладчиком с выставленными точками остановки (так называемые breakpoints) - их можно выставить нажав левой кнопкой мыши в серое поле слева от строки исходника (чтобы запустить отладчик надо вместо
Run
нажатьDebug
)
Обратите внимание
на статью про отладку приложения.
Ваше приложение должно показывать примерно следующее: мир, в нем змея ползет, меняет направление от нажатия стрелочек, если змея наезжает на себя или край мира - игра замирает (змея перестает ползти). Съеденное яблоко должно увеличивать длину змейки.
Отправляйте выполненное задание ввиде zip-архива src
папки, и пожалуйста:
- Тему письма называйте правильно (номер этого задания, как написано в самом верху - 33)
- zip-архив (или 7zip) называйте по тем же правилам, как назывались патчи (только расширение файла теперь не
.patch
, а.zip
, например33_16_1_polyarniy_nikolay.zip
)
Т.е. формат такой же как и про патч, только вместо .patch
вы шлете .zip
.