当前位置: 首页 > 知识库问答 >
问题:

SFML游戏C中的瓦片地图碰撞

东郭远航
2023-03-14

我用C语言用SFML库创建了一个游戏,在实现过程中出现了贴图冲突(我从txt文件中加载贴图- 1代表平台,0代表自由空间)。https://imgur.com/a/tQZc6

我在同时处理所有四种类型的碰撞时遇到了一个问题(从下、上、左和右)。我的意思是:当没有碰撞时,玩家可以正常移动,但是如果我们撞到墙上,碰撞只出现在FIRST中写的if()语句中(在我们的示例中只发生右碰撞,其余部分被省略)。这是我的代码(我只粘贴必要的东西)

class Player
{
public:
    Player();
    Player(sf::Texture* texture, sf::Vector2u imageCount, sf::Vector2f position, float switchTime, float speed, float jumpSpeed);
    ~Player();

    void UpdatePlayer(float deltaTime);

    float top, right, left, bottom;

private:
    sf::Vector2f _position;
    float groundHeight = 40; //i've added gravity and hardcoded the ground height to create jumping 
    float _jumpSpeed; // later on, it will be replaced with bottom collision
    const float gravity = 981.0f;
    sf::RectangleShape body;
    float _speed;

};

//Player.cpp
void Player::UpdatePlayer(float deltaTime)
{
    sf::Vector2f movement(0.0f, 0.0f);

    if (sf::Keyboard::isKeyPressed(sf::Keyboard::A))
    {
        movement.x -= _speed * deltaTime; //we are using delta time in order to move the object in according to time
    }
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::D))
    {
        movement.x += _speed * deltaTime;
    }

    if (sf::Keyboard::isKeyPressed(sf::Keyboard::W))
    {
        movement.y = -sqrt(5.0f * gravity * _jumpSpeed) * deltaTime;
    }
    if (body.getPosition().y + body.getSize().y < groundHeight || movement.y < 0)
    {
        movement.y += gravity * deltaTime;
    }
    else
    {
        body.setPosition(body.getPosition().x, groundHeight - body.getSize().y);
        movement.y = 0;
    }



    bottom = body.getPosition().y + body.getSize().y;
    left = body.getPosition().x;
    right = body.getPosition().x + body.getSize().x;
    top = body.getPosition().y;


    body.move(movement);

}

//Source.cpp

 void LoadCollisionMap(const char*filename)
{
    std::ifstream openfile(filename);
    std::vector<int> tempMap;
    CollMap.clear();

    if (openfile.is_open())
    {
        while (!openfile.eof())
        {
            std::string str, value;
            std::getline(openfile, str);
            std::stringstream stream(str);

            while (std::getline(stream, value, ' '))
            {
                if (value.length() > 0)
                {
                    int a = atoi(value.c_str());
                    tempMap.push_back(a);
                }
            }
            CollMap.push_back(tempMap);
            tempMap.clear();
        }
    }
}
int main()
{
    LoadCollisionMap("Map2.txt"); //Collision map

Player player(&playerTexture, sf::Vector2u(3, 9),sf::Vector2f(100.0f, 150.0f) ,0.3f, 400.0f, 555.0f);

    for (int i = 0; i < CollMap.size(); i++)
    {
        for (int j = 0; j < CollMap[i].size(); j++)
        {
            if (CollMap[i][j] == 1)
            {

                int CollBottom, CollRight, CollLeft, CollTop;
                CollBottom = i * 32 + 32;
                CollTop = i * 32;
                CollLeft = j * 32;
                CollRight = j * 32 + 32;

                if (player.right < CollLeft || player.left > CollRight || player.top > CollBottom || player.bottom < CollTop)
                {
                    //no collision
                }
                else
                {


                    if (player.right > CollLeft)
                    {
                        std::cout << "collision" << std::endl;
                        player.body.setPosition(player.body.getPosition().x - 1, player.body.getPosition().y);
                        break;

                    }


                    if (player.left < CollRight)
                    {
                        std::cout << "collision 2" << std::endl;
                        player.body.setPosition(player.body.getPosition().x + 1, player.body.getPosition().y);
                        break;
                    }


                    if (player.top < CollBottom)
                    {
                        std::cout << "collision 3" << std::endl;

                        player.body.setPosition(player.body.getPosition().x, player.body.getPosition().y + 1);


                        break;


                    }

                    if (player.bottom > CollTop)
                    {
                        std::cout << "collision 4" << std::endl;

                        player.body.setPosition(player.body.getPosition().x, player.body.getPosition().y - 1);
                        break;
                    }


                }

            }

        }
    }

共有1个答案

呼延高超
2023-03-14

运算符<code>中断

bool collisionDetected = false;

if (player.right > CollLeft)
{
    std::cout << "collision" << std::endl;
    player.body.setPosition(player.body.getPosition().x - 1, player.body.getPosition().y);

    collisionDetected = true;
}

...

if( collisionDetected ) 
    break;
 类似资料:
  • 我正在使用图块映射,并有我的地图类来使用精灵数组绘制地图。我让它设置精灵的位置,然后在它周围创建一个边界框数组,然后绘制精灵。 然后我有一个碰撞类,它获取玩家的边界框,并将其与精灵的每个边界框进行比较。我有一个名为Platform边界框的数组。这将每个精灵的每个边界框存储在数组中。然而,当我比较值时,平台边界框似乎在任何位置都没有值,我已经检查了每个精灵的值是否进入边界框数组。 这是我的地图课。看

  • 因此,我进行了一个测试,看看碰撞是如何在SFML中操作的。我制作了以下代码片段: 正如代码所提示的,马里奥在接触地板物体时会改变位置,并且会瞬移到地板上方。 注意,“绿框”是我前面提到的地板对象。还有,忽略图片1中的“左”字,我指的是“右”。 当然,这种行为是有意的(即不是bug),但它是不想要的。 所以我的问题是:我怎样才能消除这种“副作用”呢?我的意思是,我怎样才能修改我的代码,这样马里奥就不

  • 我正在用C /SFML制作一个类似超级马里奥的游戏,在试图为马里奥碰撞编写一些代码时,我遇到了一些问题:当角色在沿着水平轴移动的同时与一堆垂直的积木碰撞时,他会卡在积木的一边,就像是在一个看不见的积木上行走一样。我试图修改碰撞功能,就像让马里奥只有在他与块相关的位置包含在块坐标中时,才能与块水平碰撞。 我包含了一些运动代码(keyPree是一个返回按下的键的函数): 以及碰撞函数,其中块类在块精灵

  • 我的2D平台游戏有问题。由于我刚刚开始使用c,因此我在瓷砖碰撞方面遇到了麻烦。我能够阻止玩家进入图块,并且能够远离它,但不知何故,他不能沿着图块移动。 此功能用于检查新位置是否位于实心瓷砖内: 空地图::drawColMap(播放器 } 以下是移动播放器的代码: void Player::update() { } 感谢任何帮助! //编辑1 我试着记录碰撞,它显示即使我不按任何键,玩家仍然在碰撞区

  • 在游戏开发过程中,我们会遇到超过屏幕大小的地图,例如在即时战略游戏中,它使得玩家可以在地图中滚动游戏画面。这类游戏通常会有丰富的背景元素,如果直接使用背景图切换的方式,需要为每个不同的场景准备一张背景图,而且每个背景图都不小,这样会造成资源浪费。 瓦片地图就是为了解决这问题而产生的。一张大的世界地图或者背景图可以由几种地形来表示,每种地形对应一张小的的图片,我们称这些小的地形图片为瓦片。把这些瓦片

  • 我正在尝试用C重新创建游戏2048,但我无法让算法移动或合并瓷砖在一起以正常运作。在最初的2048游戏中,你会像这样移动瓷砖: 所以两个相同的瓷砖可以合并成一个两倍大小的瓷砖。我的版本几乎是相同的,但我没有使用数字,而是使用合并时递增1的字符,因此将合并到等。我这样做只是为了不必处理不同大小的瓷砖。 所以我的板存储为一个4*4字符数组,在一个我称之为网格的结构中(我知道可能有点多余) 我曾经尝试过