我知道为了在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");
}
}
有人知道出了什么问题吗?
答案 0 :(得分:3)
问题不在于C ++。问题是你如何使用它。你写代码的唯一方法就是如果入侵者就在你身上。但那太晚了。外星入侵者已经杀了你。
您需要做的是将这些项目符号放入您随时间传播的对象中,就像您的入侵者是您随时间传播的对象一样。对用户按空格键的响应应该是将子弹的新实例添加到活动子弹集。每个活跃的子弹都有一个随时间变化的位置。在每个时间步骤中,您应该根据规则来推进活动入侵者的状态,这些规则规定入侵者如何根据规定子弹移动的规则移动和推进活动子弹的状态。当子弹到达屏幕顶部时移除子弹,如果外星入侵者到达屏幕底部,则游戏结束。
在传播,移除屏幕外的子弹并检查游戏结束后,您需要检查每个M个入侵者的每个N子弹之间的碰撞。检测到碰撞时,从活动子弹集中删除子弹,并从活动入侵者集中删除外星入侵者。当然,你会想要一些漂亮的图形向用户展示另一个外星人的位置。
除此之外:作为NxM问题,此检查可能是CPU使用率的最大消耗。您可以通过一些简单的启发式方法加快速度。
您可以自己使用new
和delete
来管理外星入侵者和子弹的集合,以防止您的入侵者和子弹因内存泄漏而杀死您的程序。你不必这样做。 C ++为您提供了一些管理这些集合的漂亮工具。使用其中一个C ++标准库集合而不是滚动您自己的集合。例如,std::vector<AlienInvader> invaders;
或std::list<AlienInvader> invaders
,以及子弹相同。您将从中间删除很多内容,这表明std::list
或std::deque
可能比std::vector
更合适。
答案 1 :(得分:2)
您可以在创建项目时测试已触发项目的碰撞
不应该是每个帧中每个现有项目在主循环中完成的测试冲突吗?
答案 2 :(得分:1)
别担心,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
块。实际上,只有当你仍在按空格时才会执行这段代码 - 即:仍然触发 - 。只有当你“还在射击”时才应该检查碰撞吗?事实上你发射子弹并开始等待它来摧毁入侵者以某种方式干扰这个子弹可以到达入侵者的事实,并且确实摧毁了它?当然不是!
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");
}
您希望在外部循环中检查碰撞,同样可能还包含按键检查。通过这种方式,即使您只是在查看屏幕并等待,程序也会继续测试条件,并且当它完成时,执行与碰撞事件相关的代码(即:入侵者“未激活”)。
答案 3 :(得分:0)
你说//Space
,它是什么或应该是32(如果是ASCII)而不是57?程序是否流入if == 57块?
答案 4 :(得分: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");
}
}
}
}
现在这应该按预期工作。