Тема урока
Часто встречаются игры, в которых нужно управлять персонажем, передвигающемуся по поверхностям, и если под ногами ничего нет - персонаж падает вниз. Так же можно ползать по стенкам. Например, вот такая игра:
Логика (и код) такого персонажа довольно сложная. Но к счастью этот код уже написан. Все что нам нужно - подключить искуственный интеллект под названием GravityAI, во время регистрации спрайта.
"Скелет" игры
Для начала зарегистрируем все нужные спрайты:
register('#', WallSprite::new)
.onInit(w -> w.setColor(WallColor.BLUE));
register('*', PortalSprite::new);
register('H', LadderSprite::new);
register('T', ManSprite::new);
Подключение искусственного интеллекта пишется в строчке регистрации:
register('T', ManSprite::new, new GravityAI().wall('#').ladder('H'));
Теперь человечек будет падать вниз, если там пустое пространство. При промощи метода wall
и ladder
мы настраиваем, какие спрайты будут являтся стенками, а какие лестницами.
Осталось только добавить управление клавишами "вверх", "вниз", "вправо" и "влево", а так же прыжок клавишей "пробел".
Движение вправо и влево
Начнем с передвижения вправо и влево. Когда мы нажимаем клавишу вправо или влево, надо установить скорость (setSpeed), повернуть спрайт в нужном направлении (setRotation), задать направление движения (setDirection) и двигать спрайт по этому направлению (followDirection). Это довольн много операций, поэтому чтобы сократить код - напишем это в отдельном методе:
private void move(Sprite sprite, Direction dir) {
sprite.setSpeed(3);
sprite.setDirection(dir);
sprite.setRotation(dir);
ai.followDirection(sprite);
}
Этот метод будем вызывать тогда, когда нажата клавиша вправо или влево. А когда клавишу отпускаем - нужно установить скорость в 0:
register('T', ManSprite::new, new GravityAI().wall('#').ladder('H'))
.onKeyHold(t -> move(t, Direction.E), KeyCode.RIGHT)
.onKeyReleased(t -> t.setSpeed(0), KeyCode.RIGHT)
.onKeyHold(t -> move(t, Direction.W), KeyCode.LEFT)
.onKeyReleased(t -> t.setSpeed(0), KeyCode.LEFT);
Если все сделали как надо - человечек будет двигаться вправо и влево при нажатии соответствующих клавиш.
Движение вверх и вниз по лестнице
Все то же самое можно сделать для клавиши вверх и вниз:
.onKeyHold(t -> move(t, Direction.N), KeyCode.UP)
.onKeyReleased(t -> t.setSpeed(0), KeyCode.UP)
.onKeyHold(t -> move(t, Direction.S), KeyCode.DOWN)
.onKeyReleased(t -> t.setSpeed(0), KeyCode.DOWN);
Наш человечек теперь может ползать по лестнице!
Прыжки
Осталось добавить реакцию на клавишу "пробел" для прыжка.
.onKeyPressed(t -> t.activate("jump"), KeyCode.SPACE);
Теперь, при нажатии на "пробел" человечек "переключается" в режим прыжка, взлетая вверх на несколько клеток, а потом опять падает вниз.
Код целиком
Вот что должно было получится:
public class MyGame extends Game {
@Override
public void setup() {
setBackground(new SpaceBackground());
register('#', WallSprite::new)
.onInit(w -> w.setColor(WallColor.BLUE));
register( '*', PortalSprite::new);
register('H', LadderSprite::new);
register('T', ManSprite::new, new GravityAI().wall('#').ladder('H'))
.onKeyHold(t -> move(t, Direction.E), KeyCode.RIGHT)
.onKeyReleased(t -> t.setSpeed(0), KeyCode.RIGHT)
.onKeyHold(t -> move(t, Direction.W), KeyCode.LEFT)
.onKeyReleased(t -> t.setSpeed(0), KeyCode.LEFT)
.onKeyHold(t -> move(t, Direction.N), KeyCode.UP)
.onKeyReleased(t -> t.setSpeed(0), KeyCode.UP)
.onKeyHold(t -> move(t, Direction.S), KeyCode.DOWN)
.onKeyReleased(t -> t.setSpeed(0), KeyCode.DOWN)
.onKeyPressed(t -> t.activate("jump"), KeyCode.SPACE);
load("/level.txt");
}
private void move(Sprite sprite, Direction dir) {
sprite.setSpeed(3);
sprite.setDirection(dir);
sprite.setRotation(dir);
ai.followDirection(sprite);
}
@Override
public void loop() {
}
}