Визуальное убийство захватчиков не работает в переполнении стека

Я знаю, что для того, чтобы убивать захватчиков в C ++, мне нужно создать коллайдер.
Однако ничто никогда не убьет захватчиков в этой игре.
Вот код в шапке:

bool DoCollision(float Xbpos, float Ybpos, int BulWidth, int BulHeight, float Xipos, float Yipos, int InvWidth, int InvHeight);

Это функция, которую я инициализирую:

bool Game::DoCollision(float Xbpos, float Ybpos, int BulWidth, int BulHeight, float Xipos, float Yipos, int InvWidth, int InvHeight) {
if (Xbpos+BulWidth < Xipos || Xbpos > Xipos+InvWidth) return false;
if (Ybpos+BulHeight < Yipos || Ybpos > Yipos+InvHeight) return false;

return true;
}

И это то, что происходит, если кто-то нажимает клавишу пробела:

if (code == 57) { //Space
myKeyInvader.MeBullet.Active = true;
myKeyInvader.MeBullet.Xpos = myKeyInvader.Xpos + 10;
myKeyInvader.MeBullet.Ypos = myKeyInvader.Ypos - 10;
myKeyInvader.MeBullet.yvuel = 0.2;
myKeyInvader.MeBullet.BulletP->CopyTo(m_Screen,myKeyInvader.Xpos,myKeyInvader.Ypos);

if (DoCollision(Invaders[counter].MyBullet.Xbpos,Invaders[counter].MyBullet.Ybpos,Invaders[counter].MyBullet.BulWidth,
Invaders[counter].MyBullet.BulHeight,Invaders[counter].Xipos,Invaders[counter].Yipos,Invaders[counter].InvWidth,Invaders[counter].InvHeight)) {
//myKeyInvader.Ypos = 100;
Invaders[counter].Active = false;
printf("Collide!\n");
}
}

Кто-нибудь знает, что идет не так?

9

Решение

Проблема не в C ++. Проблема в том, как вы используете это. Единственный способ получить уничтожение с помощью написанного кода, если захватчик находится прямо над вами. Но уже слишком поздно. Инопланетный захватчик уже убил тебя.

Что вам нужно сделать, это превратить эти маркеры в объекты, которые вы распространяете со временем, точно так же, как ваши захватчики — это объекты, которые вы распространяете со временем. В ответ на нажатие клавиши пробела пользователь должен добавить новый экземпляр маркера в набор активных маркеров. Каждая из этих активных пуль имеет положение, которое меняется со временем. На каждом временном шаге вы должны улучшать состояния активных захватчиков в соответствии с правилами, которые определяют, как захватчики перемещаются, и улучшать состояния активных маркеров в соответствии с правилами, которые определяют, как перемещаются маркеры. Удалите пули, когда они достигнут верхней части экрана, и если инопланетный захватчик достигнет нижней части экрана, игра окончена.

После распространения, удаления закадровых маркеров и проверки на окончание игры вы хотите проверить наличие столкновений между каждой из N маркеров с каждым из M захватчиков. При обнаружении столкновения удалите маркер из набора активных пуль и удалите инопланетного захватчика из набора активных захватчиков. И, конечно, вы захотите, чтобы какая-то изящная графика показала пользователю, что другой инопланетянин укусил пыль.

В стороне: Будучи проблемой NxM, эта проверка может быть самым большим расходом ресурсов процессора. Вы можете ускорить это с помощью простой эвристики.

Вы можете управлять коллекциями инопланетных захватчиков и пуль самостоятельно, тщательно используя new а также delete чтобы ваши захватчики и пули не убивали вашу программу утечкой памяти. Вам не нужно делать это. C ++ предоставляет вам несколько отличных инструментов для управления этими коллекциями. Используйте одну из стандартных библиотек C ++ вместо того, чтобы катить свою собственную коллекцию. Например, std::vector<AlienInvader> invaders; или же std::list<AlienInvader> invadersи то же самое для пуль. Вы будете удалять из середины много, что говорит о том, что std::list или же std::deque может быть более подходящим, чем std::vector Вот.

3

Другие решения

Вы проверяете столкновение для обстрелянных предметов, когда они создаются

Не должно ли тестовое столкновение выполняться в основном цикле для каждого существующего элемента в каждом кадре?

2

Не волнуйтесь, в C ++ есть все, что нужно, чтобы убивать захватчиков :)))

Нелегко давать советы, основанные на таком небольшом количестве кода, но здесь единственная логическая ошибка, по-видимому, заключается в том, что вы проверяете столкновение только при нажатии пробела; Вы должны проверить это во внешнем цикле:

if (code == 57) { //Space
myKeyInvader.MeBullet.Active = true;
myKeyInvader.MeBullet.Xpos = myKeyInvader.Xpos + 10;
myKeyInvader.MeBullet.Ypos = myKeyInvader.Ypos - 10;
myKeyInvader.MeBullet.yvuel = 0.2;
myKeyInvader.MeBullet.BulletP->CopyTo(m_Screen,myKeyInvader.Xpos,myKeyInvader.Ypos);
}

С логической точки зрения, нажатие пробела должно запустить пулю: начальная позиция пули установлена, а также ее скорость на оси Y (так, чтобы она поднималась).

Код, который проверяет наличие столкновений, должен выходить за пределы этого if блок. Фактически, этот блок кода выполняется, только если вы все еще нажимаете пробел, то есть: still обжиг-. Стоит ли проверять столкновение, только если вы все еще стреляете? Помогает ли тот факт, что вы выпустили пулю и начали ждать, пока она уничтожит захватчика, как-то мешает тому факту, что эта пуля может достичь захватчика и даже уничтожить его? Конечно, нет!

if (DoCollision(Invaders[counter].MyBullet.Xbpos,Invaders[counter].MyBullet.Ybpos,Invaders[counter].MyBullet.BulWidth,
Invaders[counter].MyBullet.BulHeight,Invaders[counter].Xipos,Invaders[counter].Yipos,Invaders[counter].InvWidth,Invaders[counter].InvHeight)) {
//myKeyInvader.Ypos = 100;
Invaders[counter].Active = false;
printf("Collide!\n");
}

Вы хотите, чтобы столкновение проверялось во внешнем цикле, то же самое, что, вероятно, также содержит проверки для нажатия клавиш. Таким образом, даже если вы просто смотрите на экран и ждете, программа продолжает тестировать условие, и, когда оно выполнено, выполняется код, связанный с событием столкновения (то есть захватчик «деактивирован»).

1

Ты говоришь //Space Это то, что это или должно быть 32 (если ASCII) вместо 57? Программа перетекает в блок if == 57?

0

Ваш код выглядит хорошо, но вам нужно два цикла вокруг проверки столкновений: один для проверки всех захватчиков (не только одного из них), а другой — для проверки каждой позиции пули на ее траектории, а не только момента, когда он покидает пистолет.

Я предполагаю, что у нас есть вспомогательная функция, которая перемещает пулю и возвращает ли она все еще внутри экрана:

bool BulletIsInScreen ();

Тогда мы можем написать циклы:

if (code == 57) { // Space
while (BulletIsInScreen()) {
for (size_t i = 0; i < counter; ++i) { // counter is the number of invaders,
// according to your comment to your own answer
myKeyInvader.MeBullet.Active = true;
myKeyInvader.MeBullet.Xpos = myKeyInvader.Xpos + 10;
myKeyInvader.MeBullet.Ypos = myKeyInvader.Ypos - 10;
myKeyInvader.MeBullet.yvuel = 0.2;
myKeyInvader.MeBullet.BulletP->CopyTo(m_Screen,myKeyInvader.Xpos,myKeyInvader.Ypos);

if (DoCollision(Invaders[i].MyBullet.Xbpos, Invaders[i].MyBullet.Ybpos,
Invaders[i].MyBullet.BulWidth, Invaders[i].MyBullet.BulHeight,
Invaders[i].Xipos, Invaders[i].Yipos,
Invaders[i].InvWidth, Invaders[i].InvHeight)) {
//myKeyInvader.Ypos = 100;
Invaders[i].Active = false;
printf("Collide!\n");
}
}
}
}

Теперь это должно работать как ожидалось.

0
По вопросам рекламы [email protected]