JavaRush /Курсы /Java Syntax Pro /Обработка Событий

Обработка Событий

Java Syntax Pro
19 уровень , 3 лекция
Открыта

1. Введение

От игрового движка было бы мало толку, если бы мы просто могли с его помощью рисовать что-то на экране. Для написания полноценной игры ей нужно взаимодействовать с пользователем! А если точнее, наша программа должна отслеживать действия пользователя и реагировать на них.

Для этого у игрового движка JavaRush есть специальные методы, которые он вызывает, когда пользователь нажимает клавиши мышки или кнопки на клавиатуре.

Весь класс в том, что пишите эти методы вы сами, а за вызов их отвечает игровой движок JavaRush. Все, что вам нужно — объявить эти методы в своем коде. Это работает еще проще, чем звучит.


2. Работа с мышкой

Для работы с мышкой у игрового движка есть два метода

void onMouseLeftClick(int x, int y)
void onMouseRightClick(int x, int y)

Вы просто объявляете эти методы в классе вашей игры, унаследованном от Game. И пишете в этих методах код, какой захотите. А игровой движок сам будет вызывать эти методы, когда пользователь будет нажимать кнопки мышки.

onMouseLeftClick(int x, int y) – вызывается движком при клике левой кнопкой мыши. В качестве аргументов получает координаты клетки игрового поля, где произошел клик. Левая верхняя ячейка имеет координаты (0,0). Для использования этого метода, его нужно переопределить: разместить перед именем метода аннотацию @Override.

onMouseRightClick(int x, int y) – вызывается при клике правой кнопкой мыши. Работает аналогично методу onMouseLeftClick(int x, int y).

Пример использования методов:

import com.javarush.engine.cell.Color;
import com.javarush.engine.cell.Game;
import com.javarush.engine.cell.Key;

public class MySuperGame extends Game {
   @Override
   public void initialize() {
      // Устанавливаем размер игрового поля 3x3
      setScreenSize(3, 3);

      // Закрашиваем игровое поле белым цветом
      for (int x = 0; x < 3; x++) {
         for (int y = 0; y < 3; y++) {
            setCellColor(x, y, Color.WHITE);
         }
      }
   }

   @Override
   public void onMouseLeftClick(int x, int y) {
      // Ставим символ "X" в клетку, по которой кликнули левой кнопкой мыши
      setCellValue(x, y, "X");
   }

   @Override
   public void onMouseRightClick(int x, int y) {
      // Очищаем клетку, по которой кликнули правой кнопкой мыши
      setCellValue(x, y, "");
   }
}

В примере выше мы объявили оба метода: onMouseLeftClick() и onMouseRightClick(). Первый метод будет вызваться, когда пользователь будет кликать левой кнопкой мыши по ячейкам игрового поля, второй метод будет вызываться при клике правой кнопкой мышки.

В параметры методов (x,y) игровой движок JavaRush передаст координаты ячейки игрового поля, на которой произошёл клик мышкой.



3. Работа с клавиатурой

Для работы с клавиатурой у игрового движка есть два метода

void onKeyPress(Key key);
void onKeyReleased(Key key);

Если вы хотите делать какие-либо действия, когда пользователь нажимает кнопки на клавиатуре, вам нужно просто объявить приведенные методы в классе вашей игры, унаследованном от Game.

Вы пишете в этих методах ваш код, а игровой движок сам их вызовет, когда пользователь нажмет (или отпустит) клавишу клавиатуры.

onKeyPress (Key key) – вызывается при нажатии любой клавиши клавиатуры. В качестве аргумента key в метод передается значение нажатой клавиши (или Key.UNKNOWN). Для использования этого метода, его нужно переопределить — разместить перед именем метода аннотацию @Override.

onKeyReleased (Key key) – вызывается при отпускании любой клавиши клавиатуры. В качестве аргумента key получает значение соответствующей клавиши (или Key.UNKNOWN). Для использования этого метода, его нужно переопределить — разместить перед именем метода аннотацию @Override.

Пример использования методов:

import com.javarush.engine.cell.Color;
import com.javarush.engine.cell.Game;
import com.javarush.engine.cell.Key;

public class MySuperGame extends Game {
   @Override
   public void initialize() {
      // Устанавливаем размер игрового поля 3x3
      setScreenSize(3, 3);

      // Закрашиваем игровое поле белым цветом
      for (int x = 0; x < 3; x++) {
         for (int y = 0; y < 3; y++) {
            setCellColor(x, y, Color.WHITE);
         }
      }
   }

   @Override
   public void onKeyPress(Key key) {
      // При нажатии пробела, центральная клетка становится желтой
      if (key == Key.SPACE) {
         setCellColor(1, 1, Color.YELLOW);
      }
   }

   @Override
   public void onKeyReleased(Key key) {
      // При отпускании пробела, центральной клетке возвращается белый цвет
      if (key == Key.SPACE) {
         setCellColor(1, 1, Color.WHITE);
      }
   }
}


4. Список поддерживаемых кнопок

Когда движок JavaRush вызывает методы onKeyPress() и onKeyReleased(), он передает в них информацию о нажатой клавише. Для этого в движке JavaRush есть специальный тип — Key.

В текущей версии движка тип Key может принимать только ограниченный набор значений (9 шт):

Значение Что нажал пользователь
Key.ENTER
Пользователь нажал кнопку Enter
Key.ESCAPE
Пользователь нажал кнопку Esc
Key.PAUSE
Пользователь нажал кнопку Pause
Key.SPACE
Пользователь нажал Пробел
Key.LEFT
Пользователь нажал Стрелку Влево
Key.RIGHT
Пользователь нажал Стрелку Вправо
Key.UP
Пользователь нажал Стрелку Вверх
Key.DOWN
Пользователь нажал Стрелку Вниз
Key.UNKNOWN
Любая клавиша, кроме вышеперечисленных

Если игрок нажмет пробел, то вызовется метод onKeyPress(), куда передастся параметр Key.SPACE, если пользователь нажмет стрелку влево, то передастся параметр Key.LEFT. Если же пользователь нажмет любую клавишу, которой нет в списке выше, метод onKeyPress() будет вызван с параметром Key.UNKNOWN.

Все дело в том, что существующие игры JavaRush спроектированы так, чтобы их можно было запускать на телефоне. Стандартная клавиатура при этом не показывается, а отображаются 8 виртуальных кнопок:


5. Как работать с таймером

Многие игры происходят в реальном времени: т.е. пользователь ничего не делает, а какие-то события в игре все-таки происходят. Чтобы вы могли реализовывать такие игры, мы добавили в игровой движок работу с таймером.

Работает это примерно так: вы включаете таймер и выставляете время, спустя которое он должен срабатывать. Например, 500 мс. И после этого каждые полсекунды Игровой Движок JavaRush вызывает метод onTurn(). Бесконечное число раз, пока таймер не выключат.

Как же пользоваться таймером?

1. Включаем таймер

Чтобы включить таймер, есть специальный метод void setTurnTimer(int timeMs). В качестве аргумента метод принимает длительность интервала между вызовами в миллисекундах (1/1000 секунды). Достаточно один раз вызвать этот метод, и игровой движок начнет вызывать метод onTurn() каждые timeMs миллисекунд.

2. Переопределить метод onTurn(int)

Для этого необходимо объявить метод void onTurn(int step) в классе, унаследованном от класса Game. Этот метод будет вызываться игровым движком. При этом движок каждый раз будет передавать в метод порядковый номер такого вызова (1, 2, 3, ...).

3. Выключаем таймер

Если таймер больше не нужен, например потому, что пользователь прошел игру, его можно выключить. Для этого нужно просто вызвать метод stopTurnTimer().

4 Ускоряем/меняем таймер

В некоторых играх события постоянно ускоряются, поэтому было бы удобно ускорять наш таймер (уменьшать время между вызовами). Нет ничего легче: просто вызовите setTurnTimer(int timeMs) еще раз с новым значением, и время между вызовами onTurn() изменится.

Пример:

import com.javarush.engine.cell.Color;
import com.javarush.engine.cell.Game;

public class MySuperGame extends Game {
   ...
   @Override
   public void initialize() {
      // Создаем игровое поле 3x3 клетки
      setScreenSize(3, 3);
      showGrid(false);
      setCellValueEx(1, 1, Color.BLUE, "X", Color.ORANGE, 50);

      setTurnTimer(500);   // Включаем таймер, интервал между вызовами — 500мс.
   }

   @Override
   public void onTurn(int step) {
      if(step == 100) {
         stopTurnTimer();  // если прошло 100 тактов, выключаем таймер
      }

      if (step % 2 == 1) {
         // Если данный такт нечётный, установить клетке красный фон
         setCellColor(1, 1, Color.RED);
      } else {
         // если данный такт чётный, установить клетке синий фон
         setCellColor(1, 1, Color.BLUE);
      }
   }
   ...
}

В этом простом примере мы создали поле 3×3 клетки. Затем включили таймер, который каждые полсекунды будет вызывать метод onTurn().

При этом каждые полсекунды будет меняться цвет центральной клетки. Текст клетки при этом не изменится. Через 50 секунд (100 шагов) цвет перестанет меняться — таймер выключится.


Комментарии (96)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Anonymous #3585174 Уровень 33
28 июля 2025
Like
16 мая 2025
1) Не используйте getScreenWight() и getScreenHight() - валидатор такое не прощает
Eternal Fire Уровень 30
6 июня 2025
странно, что на onKeyPressed не прощает, а на onKeyReleased - ему норм
ShadyLine Уровень 30
10 апреля 2025
Чисто скипаю этот уровень...
Kot9 Уровень 32
29 марта 2025
у меня вообще в одной из задач валидатор не принимал метод setScreenSize(3, 3); ХОТЯ я его проверял ПО БУКВАМ....копировал из условий задачи... не принимал...принял только когда я из Ответа скопировал....
6 декабря 2024
Объясните, пожалуйста, касаемо последней задачи "Таймер" почему в цикле нельзя написать: for (int i = 0; i < getScreenWidth(); i++) { for (int j = 0; j < getScreenHeight(); j++) { setCellColor(i, j, step % 2 == 0 ? Color.GREEN : Color.OGANGE); } } Почему правильно писать 3, а не getScreanHeight или getScreanWidth? то есть: for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { setCellColor(i, j, step % 2 == 0 ? Color.GREEN : Color.OGANGE); } } Первый вариант реально является ошибкой? Или это просто прихоть разработчика задачи?
Lord Leonidus Уровень 35
17 сентября 2024
Мда, что-то на 20м уровне валидатор совсем посыпался) Мало того, что не принимал всем уже известные getScreenHeight() и getScreenWidth(), заставляя затыкать циклы константами, так ещё и в задаче с обработкой кликов на клавиатуре не дал реализовать логику через switch-case, что в контексте задачи правильнее, нежели простые if-else конструкции. Надеюсь в дальнейшем со сложными задачами такого не будет)
GreyBeard Уровень 38
8 октября 2024
Видимо ты его чем-то другим раздраконил - у меня решение через switch-case прошло без замечаний)
RazdolbayZateynik Уровень 28 Expert
26 октября 2024
у меня тоже switch case не пропустило, а пропустило их заполнение, хотя на тестировании все норм было.
Евгений Маркин Уровень 24
9 августа 2024
В последней задаче все поле - это вся область, 3х3, а не только центральная клеточка😀
Юрий Уровень 20
4 марта 2025
Такая же ситуэйшнс
{Java_Shark} Уровень 36
13 июня 2024
Прикольные задачки))) всем добра и удачи!!!
Jumper Уровень 32
9 декабря 2024
Добра и удачки = )
Navin Уровень 23
24 мая 2024
почему мы сперва решаем задачу используя какой-нибудь метод, а в следующей лекции читаем описание этого метода?
Тимур Аскаров Уровень 25
30 октября 2025
на мой взгляд, что так даже лучше запоминается. ты увидел незнакомый метод и у тебя уже появился некий интерес к нему, который отложился в голове. и когда уже он раскрывается в следующей лекции, в памяти он откладывается повторно. заметь, что в задачах где не объясняли эти методы, ты с ними там и не работал и они не мешали решению задач
JavaRusher853 Уровень 36
10 марта 2024
Почему у данного движка все-еще нет метода, который закрашивает все поле в нужный цвет, это неудобно каждый раз делать вложенный цикл
Cвят Уровень 29
8 мая 2024

public void setFullColor(){
        for (int i=0; i<getScreenHeight(); i++){
            for (int j = 0; j < getScreenWidth(); j++) {
                setCellColor(i,j,Color.WHITE);
            }
        }
    }

 @Override
    public void initialize() {
        setScreenSize(5,5);
        setFullColor();
    }