C++ 使用向量和多重贴图在特定瓷砖和精灵之间创建边界框碰撞

C++ 使用向量和多重贴图在特定瓷砖和精灵之间创建边界框碰撞,c++,sdl,game-physics,sdl-2,C++,Sdl,Game Physics,Sdl 2,我生成了一组随机的x和y坐标值,并将它们存储到多重映射中,然后将x坐标值列表复制到向量x,将y坐标值列表复制到向量y,然后在函数中迭代传递它们 bool Sprite::collisionExists( int x, int y, SDL_Rect b ) 我将它传递到mycheckCollisions函数中的if语句中,如下所示 collisionExists( x[k],y[l],sprite) 其中,sprite是我在该函数中创建的SDL_Rect类型 我创建了一个填充了岩石的平铺

我生成了一组随机的x和y坐标值,并将它们存储到多重映射中,然后将x坐标值列表复制到向量x,将y坐标值列表复制到向量y,然后在函数中迭代传递它们

bool Sprite::collisionExists( int x, int y, SDL_Rect b  )
我将它传递到mycheckCollisions函数中的if语句中,如下所示

 collisionExists( x[k],y[l],sprite)
其中,sprite是我在该函数中创建的SDL_Rect类型

我创建了一个填充了岩石的平铺贴图,我希望精灵在贴图中四处移动,但如果下一个平铺中有岩石,则无法前进

我面临的问题是,当我创建一个向量并比较每个值时,我似乎无法检测到任何冲突,而在之前,当它仅使用两个图像进行测试时,代码工作得非常好

下面是我随机插入平铺贴图的x和y坐标值的代码

//randomly set positions of the rocks
void setRandomRockPositions()
{
for(int i=0;i<40;i++)
{
    int x,y;

    int minX=3;
    int maxX=8;
    x=roll(minX,maxX);


    int minY=1;
    int maxY=9;
    y=roll(minY,maxY);

    //if x and y are not the location for the house tile, add a rock
    if((x!=9 && y!=5))
    {
        rocks.insert(std::pair<int, int>(x, y));

    }
 }

}
一些变量和常量声明

  //Screen attributes
const int SCREEN_WIDTH  = 1024;
const int SCREEN_HEIGHT = 728;

// Scaling the tiles to be 80x80
const int TILE_SIZE = 80;

std::multimap<int, int> rocks;
static const int SPRITE_WIDTH = 104;
static const int SPRITE_HEIGHT = 96;
检测精灵与岩石碰撞的代码

bool Sprite::checkCollisions()
{
SDL_Rect sprite;
sprite.x= mPosX;
sprite.y=mPosY;
sprite.w=SPRITE_WIDTH;
sprite.h=SPRITE_HEIGHT;

std::vector<int> x(rocks.size());
std::vector<int> y(rocks.size());

std::multimap<int,int>::iterator it=rocks.begin();

while(it!=rocks.end())
{
    for(int i=0;i<rocks.size();i++)
    {
        x[i]= (*it).first;
        ++it;
    }
}

std::multimap<int,int>::iterator it2=rocks.begin();
while(it2!=rocks.end())
{
    for(int j=0;j<rocks.size();j++)
    {
        y[j]=(*it2).second;
        ++it2;
    }
}

for(int k=0;k<rocks.size();k++)
{
    for(int l=0; l<rocks.size();l++)
    {
        if(collisionExists( x[k],y[l],sprite))
        {
            return true;
            std::cout<<"Collision Detected!"<<std::endl;
        }
    }
}

return false;
}
基本碰撞检测码

bool Sprite::collisionExists( int x, int y, SDL_Rect b  )
{
//The sides of the rectangles
int leftA, leftB;
int rightA, rightB;
int topA, topB;
int bottomA, bottomB;

//Calculate the sides of rect A
leftA = x;
rightA = x + SPRITE_WIDTH;
topA = y;
bottomA = y + SPRITE_HEIGHT;

//Calculate the sides of rect B
leftB = b.x;
rightB = b.x + b.w;
topB = b.y;
bottomB = b.y + b.h;

//If any of the sides from A are outside of B
if( bottomA <= topB)//-50 )
{
    return false;
}

if( topA >= bottomB)//-50 )
{
    return false;
}

if( rightA <= leftB)//+50 )
{
    return false;
}

if( leftA >= rightB)//-50 )
{
    return false;
}

//If none of the sides from A are outside B
return true;
}
我认为我的问题在于checkCollisions函数,因为控制台上从未显示检测到的输出冲突。我已经尝试了许多不同的循环,并将它们从地图存储到向量,但我仍然不明白为什么碰撞检测停止工作

我认为我的问题在于checkCollisions函数,因为控制台上从未显示检测到的输出冲突

这可能是因为checkCollisions在显示检测到的碰撞之前返回!消息将返回线向下移动一步,它可能会按预期工作:

if(collisionExists( x[k],y[l],sprite))
{
    std::cout << "Collision Detected!" << std::endl;
    return true;
}
如果您真的想使用每个x和每个y,您至少可以在单个循环中填充单独的向量:

for( const auto & coords : rocks ) {
    x.push_back( coords.first );
    y.push_back( corrds.second );
}

警告:所有代码仅在浏览器中编写-未编译且未测试

我现在意识到的解决方案其实非常简单。我必须将x和y的每个元素乘以瓷砖的大小

碰撞存在x[k]*瓷砖大小,y[l]*瓷砖大小,精灵


我将x和y坐标传递给函数,这是我的一个基本错误。

是的,你是对的,不知为什么我完全没有注意到,但现在,在交换了两行代码后,我的控制台收到4条消息,在我开始移动播放器之前检测到碰撞,我仍然在岩石中移动,因此可能存在一些逻辑错误,我还看不到。而且,我不知道我能做到这一点。rocks是一个多重映射,我想我只能通过迭代器访问它。我不知道我可以通过引用和点表示法来实现。实际上我不知道“const auto”,以前我把它称为引用和点表示法,但我做了一些搜索,现在它更有意义了。虽然我仍然不明白为什么您使用了“const auto&coords”,并且没有通过迭代器访问“multimap rocks”。for elem:container是C++11中新增的一个范围,您可以添加辅助属性,如const,or&for引用。编写const&elem:container而不是container\u type::const\u迭代器iter=container.begin;iter!=容器端++iter清楚地表明,您希望对容器中的每一个元素都做些什么,但不改变其中任何一个。
for( const auto & coords : rocks ) {
    x.push_back( coords.first );
    y.push_back( corrds.second );
}