11 декабря 2016 г

Отправлено 3 янв. 2017 г., 10:40 пользователем Dimitrijs Fedotovs   [ обновлено 3 янв. 2017 г., 10:41 ]

Тема урока

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


Логика (и код) такого персонажа довольно сложная. Но к счастью этот код уже написан. Все что нам нужно - подключить искуственный интеллект под названием 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() {

}
}
Comments