Урок 20 SFML Притяжение персонажа к земле, еще чуть ООП

Такая вещь как притяжение спрайта к земле существует в играх типа Марио, Tiny Toon ещё помню:-) Всё довольно просто реализуется, приступим:

Видеоверсия: https://youtu.be/yHrJdhjRnlw

Вторая часть видео: https://youtu.be/M4MvHAlwmqQ

 

К сожалению, нам многое придется переделать с прошлого урока в плане игровой логики. Ну, всё потому, что у нас игра стала превращаться в стратегию, а это ни разу не платформер Марио )) В этом уроке мы изменим движение, реализуя лишь два направления – вправо и влево, к этим направлениям добавим прыжок.

В классе игрока добавим логическую переменную , которая будет отвечать за состояние нахождения объекта на земле:

Для себя я оставлю переменные из прошлых уроков ( isMove,isSelect ), хоть они, возможно, и не годятся для платформера, но для создания дальнейших уроков мне ещё понадобятся. Удалите их, если они вам не нужны.

В конструкторе класса инициализируем эту переменную:

 

Я немного изменил высоту картинки спрайта чтобы не было пустоты (было 96, стало 54. видно будет в ф-ции int main при создании объекта player p). В конструкторе изменил так же sprite.setTextureRect(IntRect(0, 134, w, h)); т.к нам нужно загрузить одно из направлений движения(картинку льва) при первом появлении его на экране.

Как мы помним у нас есть строка sprite.setOrigin(w/2, h/2); , которую мы перенесем в конструктор класса в самый конец (если она где-то в другом месте). Так вот эта строка задает середину спрайту. То есть его основная точка теперь не левый верхний угол, а середина. И когда наш спрайт коснется земли – он будет приподнят над ней из-за этой середины, потому что мы уже рисуем от середины, а у нас раньше рисование было сверху слева, значит при рисовании сместимся ниже и правее. Вобщем появится пустое пространство и будет пропасть между спрайтом и землей. Нам просто нужно убрать эту пропасть (или можно убрать setOrigin, но я думаю удобнее когда основная точка спрайта в середине). В ф-ции update изменим строку задания позиции спрайту на такую:

Таким образом графически и логически подружатся setOrigin и SetPosition.

Теперь в классе добавим переменную перечисляемого типа:

у нашего персонажа может быть несколько состояний. мы уходим от переменной направления dir и надо её удалить. Инициализируем в конструкторе state = stay;

Немного переходя к ООП перенесем управление персонажем из функции int main в метод класса игрока. Назовем этот метод control(), он будет отвечать за нажатие клавиш. Вызовем его мы потом внутри метода update.

Итак, я просто перенес из int main управление в метод control, пока что оставив закомментированной анимацию, с ней мы потом разберемся.

Мы видим, что при каждом нажатии клавиши у нас переменная состояния объекта (state) принимает различные значения. Так же легко видеть, что анимация сейчас занимает довольно много строк кода и хорошо бы её где-то описать и потом просто вызвать. Что-то подобное сделаем на следующем уроке, а пока займемся логикой прыжка. (анимацию пока кинул в комменты)

Если вы посмотрите выше на код для кнопки вверх, то увидите, что нажимать кнопку вверх мы можем только тогда, когда находимся на земле. Если мы на земле и нажали вверх, то переменная состояния равна “прыжку”, dy=-0.5 это и есть высота прыжка, и тут же сообщение, что мы не на земле (благодаря этому активируется притяжение к земле дальше в update увидите).

Далее функция update возьмет на себя некоторые изменения, ведь у нас больше не будет dir, у нас теперь состояния. Так же необходимо обрабатывать коллизии (столкновения с объектами карты) по Х и по Y отдельно, иначе будут глюки и выход за предел массива. Дело в том, что у нас появилось пересечение по диагонали (прыжок и движение вправо например), поэтому нам нужно после каждого движения персонажа (х+=,у+=) делать проверку на столкновение. Иначе персонаж как бы застрянет в карте (глазами не увидим т.к ошибка вылетит моментально, но программно это так) и вылетит ошибка.

Таким образом, ф-цию update (см комментарии) :

 

Все, теперь осталось реализовать ф-цию столкновений с картой. Я создал новую ф-цию checkCollisionWithMap вместо старой iteractionWithMap. Они похожи друг на друга, но взаимодействие с картой сделаем уже в этой новой функции, а ту можем удалить. Ф-ция chechCollisionWithMap выглядит вот так:

На этом всё, на следующем уроке еще больше перейдем к ООП и будем готовиться к созданию врага.




Для вопросов есть форум (ссылка наверху)

 

 

 

 

 

Буду благодарен, если поделитесь:
SFML вопросы, прошу, задавайте на форуме.
  1. Извините, если вопрос глупый. Как можно сделать двойной прыжок в игре? Я пробовал сделать еще одно условие в условии прыжка, но ничего не подошло. Может вы подскажите?

    1. В следующий раз пишите вопрос на форум, пожалуйста. А ещё было бы не плохо увидеть в разделе форумы “советы и готовые решения” – как же у вас все таки получилось. Другим будет полезно знать, а наш форум видят поисковики.

Добавить комментарий