[Java] Поворот картинки, обработка клавиатуры и движений мышки
Как обрабатывать нажатия на клавиатуре
Раньше мы обрабатывали взаимодействия мышкой. Но для управления в играх часто используется и клавиатура - например для игры вроде Flappy Bird было бы удобно прыгать по пробелу.
Раньше клики мышки были привязаны к панели рисования. Но обрабатывать клавиатуру для игры хотелось бы не зависимо от того где находится мышка и т.п.. Иначе говоря - хотелось бы чтобы обработка клавиатуры была глобальной.
Чтобы это сделать, нужно создать объект, который олицетворяет клавиатуру: KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
А затем добавить к нему обработчик нажатий: manager.addKeyEventDispatcher(new MyDispatcher())
, где в скобочках передается объект вашего нового класса, который должен реализовывать интерфейс KeyEventDispatcher
(с единственным методом: public boolean dispatchKeyEvent(KeyEvent e)
).
Теперь вы сможете в этом методе обработать нажатия кнопок клавиатуры, например:
@Override
public boolean dispatchKeyEvent(KeyEvent e) {
System.out.println("Новое событие кнопок клавиатуры!");
String typeOfEvent = "unknown";
if (e.getID() == KeyEvent.KEY_PRESSED) {
typeOfEvent = "pressed";
} else if (e.getID() == KeyEvent.KEY_RELEASED) {
typeOfEvent = "released";
} else if (e.getID() == KeyEvent.KEY_TYPED) {
typeOfEvent = "typed";
}
String key = "unknown";
if (e.getKeyCode() == KeyEvent.VK_SPACE) {
key = "space";
} else if (e.getKeyCode() == KeyEvent.VK_ENTER) {
key = "enter";
} else {
key = "code#" + e.getKeyCode();
}
System.out.println("type=" + typeOfEvent + " keyCode=" + key);
return false;
}
Задание:
добавьте в вашу Flappy Bird дополнительное управление - пусть птица машет крыльями и при нажатии на мышку, и при нажатии на пробел. Можете как создать новый класс MyDispatcher
, так и можете добавить эту функциональность в вашу панель - достаточно сказать что она implements KeyEventDispatcher
(а если она уже implements MouseListener
, то эти два интерфейса нужно перечислить через запятую).
Как поворачивать картинку
Такого рода вещи легко найти в интернете, например по запросу “java swing как поворачивать картинку” (напоминаю, что Swing
- название пакета который мы используем для создания графического интерфейса).
Но гораздо лучше и всмысле эффективности и всмысле пользы для вас в будущем - привыкать гуглить на английском - “java swing how to rotate image”.
Окажется, что достаточно:
1) Загрузить на диск из интернета какую-нибудь картинку, например эту.
2) Добавить поле BufferedImage unicornImage;
в класс MyPanel
.
3) Инициализировать его в конструкторе MyPanel, загрузив картинку с диска, например так: this.unicornImage = ImageIO.read(new File("C:\\downloads\\unicorn.png"));
4) Не забыть сделать все импорты всех новых классов через Alt+Enter.
5) Т.к. загрузка картинки может кинуть ошибку (например если файл не будет найден), поэтому вы будете видеть ошибку Unhandled exception: java.io.IOException
- поправьте ее кинув ошибку выше через Alt+Enter
(Add exception to method signature) - выше появится throws IOException
- это означает что теперь текущий метод (или конструктор) может кинуть ошибку связанную с IO - т.е. связанную с Input Output, т.е. связанную с чтением с диска.
6) Теперь надо нарисовать загруженную картинку - достаточно в отрисовке MyPanel
(в методе paintComponent
) добавить например g.drawImage(this.unicornImage, centerX, centerY, null);
.
7) И наконец чтобы рисовать картинку повернутой на некоторый угол:
double angleInDegrees = 45.0; // Угол поворота в градусах
double angleInRadians = Math.toRadians(angleInDegrees);
double locationX = unicornImage.getWidth() / 2;
double locationY = unicornImage.getHeight() / 2;
AffineTransform tx = AffineTransform.getRotateInstance(angleInRadians, locationX, locationY);
AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR);
g.drawImage(op.filter(unicornImage, null), 100, 100, null);
Обратите внимание что поворот выполняется вокруг центра картинки, поэтому например пятки единорога или его рог могут вывалиться за пределы картинки при повороте на 45 градусов и из-за этого они не будут отрисованы (картинка как будто будет обрезана).
Чтобы такого не случалось - картинка должна быть с достаточным запасом пустых пикселей вокруг объекта изображенного в центре. Грубо говоря объект не должен выходить за пределы окружности вписанной в картинку, чтобы свободно при повороте картинки оставаться в пределах этой окружности - а значит не вылезать за границы картинки и не быть обрезанным по краю.
Задание:
попробуйте добавить в вашу игру с летающей птицей следующий спецэффект - пусть она будет наклонена пропорционально текущей скорости:
- Если птица взмывает вверх - то пусть она направлена в небеса например под 30 градусов.
- Если птица сильно падает - то пусть она смотрит на землю под 30 градусов.
- Во всех промежуточных вертикальных скоростях - пусть птица гладко кренится между этими двумя крайностями (пропорционально скорости).
Как обрабатывать жесты мышки
Чтобы обрабатывать движения мышки (например полезно в игре где можно было бы перетаскивать шарики) - достаточно загуглить “java how to handle mouse motion”.
Окажется достаточно подобно тому как мы делали addMouseListener
сделать addMouseMotionListener
, и теперь нам нужно реализовать другой интерфейс
не MouseListener
- а как вы уже могли догадаться - MouseMotionListener
.
Задание:
можете попробовать в Flappy Bird заменить управление по клику мышки на управление по жесту - пусть птица
взмывает вверх только если пользователь зажал левую кнопку мышки и расчертил в окошке что-то вроде жеста “взмах вверх”. Можете даже сделать скорость птицы пропорционально тому насколько сильный игрок сделал взмах.