Вот и добрался я до реализации стрельбы в своей маленькой игрушке.
Взаимодействие различных объектов, в игровом движке MagicEngine, построено на сигналах. Каждый объект имеет некоторые слоты, которые могут получать параметры и сигналы.
Каждый сигнал может быть подключен к одному и более слотам, что позволяет обрабатывать от одного сигнала несколько действий, например сигнал отрисовки нового кадра привязан к слотам счетчика кадров, управления движением снарядов, счетчика фпс (в будущем).
Система сигналов построена так, что сцены получают сигналы верхнего уровня — от видео драйвера и перенаправляют их объектам сцены.
В такой схеме сцена обязана получать сигнал нажатия мышькой чтобы уметь правильно выделить объект, на который было произведено нажатие мышкой. При нахождении такого объекта он становится активным и ему посылаются все остальные сигналы (движение мышки, нажатие кнопок) кроме сигнала нажатия кнопки мыши, потомучто при нажатии мыши мы могли хотеть сделать чтото другое, например нажать другую кнопку меню. Фактически это означает что объект «корабль» не может получить сигнал нажатия мыши и произвести выстрел на прямую. Поэтому для реализации стрельбы был использован промежуточный сигнал, что, кстати, очень удобно. Теперь появилась возможность посылать этот сигнал нескольким объектам. Конечно это осложняет задачу hot-seat, но она решается с привязыванием сигналов к игроку.
Итак, реализация стрельбы в архитектуре сигнал-слот.
Имеется два объекта: Hero(это кораблик которым управляет игрок) и Ammo( это собственно говоря и есть сам выстрел, картинка выстрела).
По логике вещей при выстреле игрока объект Hero должен создать новый объект типа Ammo, который должен привязаться к сигналу нового кадра, и забыть про него. Дальнейшие действия выпущенного снаряда решаются самим объектом Ammo, к примеру именно он будет определять столкнулся ли он с врагом и посылать врагу сигнал hit(попадание).
Для реализации этого были сделаны следующее:
- Был перегружен объект scene (сцена) чтобы получить контроль над сигналом нажатия мышки (mouse_press). При получении этого сигнала посылается сигнал shoot(выстрел) с которым связан слот on_shoot(при выстреле) объекта Hero.
- При получении сигнала shoot объект Hero его обрабатывает (к примеру смотрит — а остыло ли оружие, есть ли еще заряды) и создает (или не создает) новый объект типа Ammo который сам связывается с сигналом нового кадра.
- Для того, чтобы можно было стрелять несколько раз пока один снаряд еще летит — было решено завести счетчик выстрелов и создавать объекты по этому счетчику, можно конечно было воспользоваться концепцией 300 пуль, но пока что в этом нет особой необходимости, да и сами сцены неумеют скрывать неиспользуемые объекты)