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

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

Открыта

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 шагов) цвет перестанет меняться — таймер выключится.


Комментарии (100)
  • популярные
  • новые
  • старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
Grigoryvvv
Уровень 28
Expert
4 августа, 12:46
04.08.2026 / 20 уровень Что-то задачи стало решать все меньше и меньше человек. Крайнюю задачу всего 9182 человека решило. Может народ не увидел пользы в таких задачах. Посмотрим сколько человек будут решать задачи на JavaCore 🤔
Win32Trojan
Уровень 2
3 августа, 20:17
2026-08-03
Anonymous #3585174
Уровень 33
28 июля 2025, 10:58
Like
16 мая 2025, 10:25
1) Не используйте getScreenWight() и getScreenHight() - валидатор такое не прощает
Eternal Fire
Уровень 1
6 июня 2025, 06:50
странно, что на onKeyPressed не прощает, а на onKeyReleased - ему норм
ShadyLine
Уровень 51
10 апреля 2025, 07:47
Чисто скипаю этот уровень...
Kot9
Уровень 1
29 марта 2025, 07:22
у меня вообще в одной из задач валидатор не принимал метод setScreenSize(3, 3); ХОТЯ я его проверял ПО БУКВАМ....копировал из условий задачи... не принимал...принял только когда я из Ответа скопировал....
Patriek
Уровень 27
11 января, 09:09
Я, конечно, понимаю, что уже немного поздновато, но все таки: там размер поля 5 х 5
6 декабря 2024, 09:53
Объясните, пожалуйста, касаемо последней задачи "Таймер" почему в цикле нельзя написать: 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); } } Первый вариант реально является ошибкой? Или это просто прихоть разработчика задачи?
Viktoriko Team Lead
4 февраля, 13:36
Можно так писать но есть проблема с производительностью. Зачем вычислять на каждой итерации цикла чему равно поле? Если хочется уйти от хардкора, тогда просто инициализировать эти переменные, например
int width = getScreenWidth();
и уже переменную width использовать при ограничении цикла. 1. Ты ушел от "магических" чисел 2. Вычисляешь значение один раз. По этой же причине некорректно зашивать тернарник внутри цикла У тебя на каждом step'е будет 9 раз вычисляться значение и приниматься решение, хотя достаточно одного раза. А если поле не 3х3, а 1000х1000 ? А если вычисления более сложные? Смысла вычислять их каждый раз нет. Лучше такое выносить на более верхний уровень. То есть вычислить один раз на каждом step, так как именно эта переменная влияет на значение.
Lord Leonidus
Уровень 35
17 сентября 2024, 17:45
Мда, что-то на 20м уровне валидатор совсем посыпался) Мало того, что не принимал всем уже известные getScreenHeight() и getScreenWidth(), заставляя затыкать циклы константами, так ещё и в задаче с обработкой кликов на клавиатуре не дал реализовать логику через switch-case, что в контексте задачи правильнее, нежели простые if-else конструкции. Надеюсь в дальнейшем со сложными задачами такого не будет)
GreyBeard
Уровень 38
8 октября 2024, 12:45
Видимо ты его чем-то другим раздраконил - у меня решение через switch-case прошло без замечаний)
RazdolbayZateynikTeam Lead в GoogleExpert
26 октября 2024, 19:03
у меня тоже switch case не пропустило, а пропустило их заполнение, хотя на тестировании все норм было.
9 августа 2024, 19:18
В последней задаче все поле - это вся область, 3х3, а не только центральная клеточка😀
Юрий Frontend Developer
4 марта 2025, 09:48
Такая же ситуэйшнс
{Java_Shark}
Уровень 36
13 июня 2024, 07:30
Прикольные задачки))) всем добра и удачи!!!
Jumper
Уровень 32
9 декабря 2024, 01:06
Добра и удачки = )