【问题标题】:Inverting an angle on the Y-axis, X works在 Y 轴上反转一个角度,X 起作用
【发布时间】:2015-05-21 09:07:11
【问题描述】:

我在 GameDev 上问过这个问题,但到目前为止没有得到回应,不幸的是这个问题有点时间敏感。

我很确定这只是我在做一些愚蠢的事情或不理解我应该做的事情,但我无法弄清楚这里有什么问题。

我在将弹丸从精灵上弹回时遇到问题,我们被要求使用运动方程移动弹丸,这使事情变得更加困难,但据我所知,我应该可以工作。

我正在尝试做的是根据它来自哪个方向来改变碰撞射弹的角度。

这是一个视频,希望不会太迟到让您看到正在发生的事情:

Link

当射弹与精灵的左侧或右侧碰撞时,一切都按预期进行,它只是切换 X 方向。

当它击中精灵的顶部或底部但它没有改变时,它只是沿着顶部滚动并射出。

这是运动代码:

float nX = get_x() + cos(nGetAngle() * 3.14 / 180) * getU() * getT();
float nY = get_y() - sin(nGetAngle() * 3.14 / 180) * getU() * getT() + 0.5 * 9.8 * getT() * getT();
set_world_position(nX, nY);

其中 U 是初始速度,T 是时间,nGetAngle() 是以度为单位的角度(无论何时设置角度,都会设置为弧度)。

这是我对播放器顶部的碰撞:

//如果射弹以任何方式与玩家精灵发生碰撞

if (projectiles[currProj]->get_y() < player->get_y()) // top of player
{
    float vx = cos(projectiles[currProj]->nGetAngle());
    float vy = sin(projectiles[currProj]->nGetAngle());

    float newAngle = atan2(-vy, vx) * 180 / 3.14;

    projectiles[currProj]->nSetAngle(newAngle);
    projectiles[currProj]->set_world_position_y(player->get_y() - projectiles[currProj]->get_height() - 1);
}

这是我对玩家左侧的碰撞:

else if (projectiles[currProj]->get_x() < player->get_x()) // left of player
{
    projectiles[currProj]->set_world_position_x(player->get_x() - projectiles[currProj]->get_width());

    float vx = cos(projectiles[currProj]->nGetAngle());
    float vy = sin(projectiles[currProj]->nGetAngle());

    float newAngle = atan2(vy, -vx) * 180 / 3.14;

    projectiles[currProj]->nSetAngle(newAngle);
}

左侧碰撞有效,顶部无效,我不知道为什么。

如有必要,我可以将整个项目发布到某个地方。

玩家的完整碰撞代码:

void Game::playerCollision()
{
    if (projectiles[currProj]->bb_collision(player))
    {
        if (projectiles[currProj]->get_y() < player->get_y()) // top of player
        {
            float vx = cos(projectiles[currProj]->nGetAngle());
            float vy = sin(projectiles[currProj]->nGetAngle());


            float newAngle = atan2(-vy, vx) * 180 / 3.14;

            projectiles[currProj]->nSetAngle(newAngle);
            projectiles[currProj]->set_world_position_y(player->get_y() - projectiles[currProj]->get_height() - 1);
        }
        else if (projectiles[currProj]->get_y() + projectiles[currProj]->get_height() > player->get_y() + player->get_height() + 1) // bottom of player
        {
            projectiles[currProj]->set_world_position_y(player->get_y() + player->get_height());
            float vx = cos(projectiles[currProj]->nGetAngle());
            float vy = sin(projectiles[currProj]->nGetAngle());

            float newAngle = atan2(-vy, vx) * 180 / 3.14;

            projectiles[currProj]->nSetAngle(newAngle);
        }
        else if (projectiles[currProj]->get_x() < player->get_x()) // left of player
        {

            projectiles[currProj]->set_world_position_x(player->get_x() - projectiles[currProj]->get_width());

            float vx = cos(projectiles[currProj]->nGetAngle());
            float vy = sin(projectiles[currProj]->nGetAngle());

            float newAngle = atan2(vy, -vx) * 180 / 3.14;

            projectiles[currProj]->nSetAngle(newAngle);
        }

        else if (projectiles[currProj]->get_x() > player->get_x()) // right of player
        {
            projectiles[currProj]->set_world_position_x(player->get_x() + player->get_width());

            float vx = cos(projectiles[currProj]->nGetAngle());
            float vy = sin(projectiles[currProj]->nGetAngle());

            float newAngle = atan2(vy, -vx) * 180 / 3.14;

            projectiles[currProj]->nSetAngle(newAngle);
        }
    }
}

【问题讨论】:

  • 您是否尝试过在冲突期间使用调试器单步执行代码?
  • 我有,问题是我真的不知道我在找什么。碰撞发生了,它没有被跳过或任何东西,角度从正变为负,我认为这是有道理的。我只是不明白为什么击中侧面效果很好,但顶部每次都失败。
  • 请发布您的碰撞检测的完整 if-else-if 链。检测发生的碰撞可能存在缺陷。
  • 为玩家添加了完整的碰撞代码。
  • 你还记得任何角度atan(a) = tan(a+180°)吗?您必须确定初始角度的四分之一,并检查是否必须将 +180° 添加到 atan2 的结果中。

标签: c++ game-physics


【解决方案1】:

我认为您的碰撞检测还不够。不知道你的详细陈述

  • 您不检查弹丸 (pr) 的来源。玩家 (pl) 左上角的碰撞可能是从顶部或从左侧进入的
  • 你不会立即反弹 pr,你只是改变方向。根据进入深度,它可能无法在下一次迭代中退出。这种情况尤其发生在 pr 向下加速但向上减速的顶部。

所以你必须

  • 检测入口表面(确定角度)
  • 最重要的是立即反弹

【讨论】:

  • 我已经尝试移除所有其他碰撞检查,以便只考虑在顶部击中它的弹丸,set_world_position 应该处理进入深度,它移动弹丸使其位于底部正在触摸播放器的顶部,然后再将其移动 1,我也尝试立即添加位置更新,它仍然给我相同的结果。
  • set_world_position() 应在碰撞检测后设置位置和角度,并应用正确的反弹。
猜你喜欢
  • 2021-12-02
  • 2022-06-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多