ООП (ДЗ часть 2)#
В файле GameScene.cpp
найдите конструктор класса GameScene *NewGameScene()
Обратите внимание, что в нем инциализируются элементы сцены, например Монеты
pLogic->coins = level.GetAllObjects("coin");
Добавьте инциализацию врагов
(enemies), препятствий
(block) со сцены.
Не забудьте в файле GameScene.h
обявить эти переменные как массива-атрибуты std::vector<TmxObject>
!
Добавьте также начальную позицию игрока как sf::Vector2f
. Чтобы запросить позицию игрока используйте следующий код:
sf::Vector2f startPosition = (pLogic->player.sprite.getPosition())
Теперь перейдем к функции void UpdateGameScene(void *pData, GameView &view, float deltaSec)
в файле GameScene.cpp
. В ней прописывается логика обработки объектов.
Реализуем три типа взаимодействия:
- С монетами
- С врагами
- С препятствиями
Монеты
должны исчезать при столкновении с игроком
. Один из путей решения данной задачи проверять циклом все моенты на факт столкновения с игрок во время перемещения.
Для этого необходимо вспомнить, что у кадлого Спрайта есть **границы*. Чтобы их запросить используется метод getGlobalBounds()
. Чтобы убрать объект с экрана используется метод erase
.
Tip
for (auto it = pLogic->coins.begin(); it != pLogic->coins.end();) {
if (pLogic->player.sprite.getGlobalBounds().intersects(it->sprite.getGlobalBounds())) {
// Игрок собирает монету
it = pLogic->coins.erase(it);
}
else {
++it;
}
}
Аналогичную операцию необходимо повторить для Врагов
. Враги
должны телепортировать игроком
при столкновении на startPosition
(начальную точку уровня). Вам уже хорошо известен метод setPosition
. На всякий случай приведем код телепортации на начало локации внутри цикла. Сам вы можете оформить пообразу и подобию проверки столкновения с монетами
.
pLogic->player.sprite.setPosition(pLogic->startPosition);
Теперь осталось релаизовать логику столкновения с объектами типа препятствий
. Обратите внимание на тот факт, что препятствия
зачастую не имеют своего Спрайта, поскольку некоторые зоны от игрока
отделяют невидимые стены (границы). В таком случае метод получения границ в цикле будет выглядеть,как :
sf::FloatRect blockRect = it->rect;
Примечание: В этом коде, it->rect предполагает, что it - это итератор, который указывает на объект, содержащий член rect
Также необходимо просчитать смещение спрайта Игрока
, проверить на пересечение и затем отменить (сдвинуть на oldPosition
) его или же осуществить движение.
Если испытываете сложность в написании кода, то ниже представлены заготовка, где есть две ошибкаи.
- Первая ошибка явная и будет предствовать компиляции кода (её очень сложно не заметить)
- Вторая ошибка логическая, из-за чего игрок будет очень странно двигаться (необходимо поменять две строки местами, чтобы её устранить)
Tip
int collision = false;
sf::Vector2f oldPosition = pLogic->player.sprite.getPosition();
for (auto it = pLogic->blocks.begin(); it != pLogic->blocks.end(); ++it) {
sf::FloatRect playerRect = pLogic->player.sprite.getGlobalBounds();
sf::FloatRect blockRect = it->rect;
sf::FloatRect newPlayerRect = playerRect;
newPlayerRect.left += movement.x;
newPlayerRect.top += movement.y;
if (newPlayerRect.intersects(blockRect)) {
collision = true;
pLogic->player.sprite.setPosition(oldPosition);
break;
}
}
if (!collision) {
pLogic->player.sprite.setPosition(oldPosition);
}
else {
pLogic->player.sprite.move(movement);
}
Структура второй главы#
1) Название пункта: Глава 2 "Разработка логики взаимодействия с объектами"
2) Описать логику инциализации сцены (GameScene *NewGameScene()) и логику обработки взаимодействия с объектами. Дать краткое описание каждого взаимодействия.
3) Опишите какими методами вы пользовались (какие из них стандартные методы библиотеки SFML, а какие реализованы в файле проекта)
4) Изменить код Хэдера в приложении (GameScene.h
) и код (GameScene.cpp
)
5) Выложите проект вместе с .exe
файлом на гитхаб. Проверьте, что .exe
работает!
Для желающих можете реализовать Гравитацию на уровне.