【问题标题】:Problems with interaction between player movement and collisions玩家移动和碰撞之间的交互问题
【发布时间】:2018-11-21 02:31:46
【问题描述】:

我一直在尝试制作一款类似于“狂神境界”的自上而下的游戏。我在让我的球员运动与我的球员运动相适应时遇到了一些问题。

需要记住的一些事情。我的播放器每侧有 4 个缓冲区,厚度为 1 像素。当玩家以 1 像素的速度撞到墙壁时,玩家将停止并按预期行为。

这就是问题所在。我希望我的播放器移动速度超过 1 像素,但是当我将播放器速度提高到 4 像素时,播放器会移动到墙上。这是有道理的,但我已采取措施避免这种情况,但到目前为止还没有成功。

代码示例 1 显示了运动代码。

代码示例 2 显示了移动触发代码。

我已经把剩下的代码放在了GitHub上,可以通过以下链接找到:https://github.com/Quinn-R/top-down-tech-demo

感谢我收到的任何帮助。

编辑:我的播放器没有完全超越墙壁。播放器和墙都是 32 像素的盒子。

EDIT2:代码示例 3 是显示游戏循环的代码。

代码示例 1

void player::move(std::string direction, std::vector<wall> walls)
{
    if(direction == "left")
    {
        for(int i = 0; i < walls.size(); i++)
        {
            if(leftBuf.getGlobalBounds().intersects(walls[i].wall1.getGlobalBounds())/* || leftBuf.getGlobalBounds().intersects(walls2[i].wall1.getGlobalBounds())*/)
            {
                //collideTop = 0;
                //collideBottom = 0;
                collideLeft = 1;
                //collideRight = 0;
            }
        }
        if(collideLeft != 1)
        {
            character.move(-1, 0);
            collideTop = 0;
            collideBottom = 0;
            collideLeft = 0;
            collideRight = 0;
        }
    }

    if(direction == "right")
    {
        for(int i = 0; i < walls.size(); i++)
        {
            if(rightBuf.getGlobalBounds().intersects(walls[i].wall1.getGlobalBounds())/* || rightBuf.getGlobalBounds().intersects(walls2[i].wall1.getGlobalBounds())*/)
            {
                //collideTop = 0;
                //collideBottom = 0;
                //collideLeft = 0;
                collideRight = 1;
            }
        }
        if(collideRight != 1)
        {
            character.move(1, 0);
            collideTop = 0;
            collideBottom = 0;
            collideLeft = 0;
            collideRight = 0;
        }
    }

    if(direction == "up")
    {
        for(int i = 0; i < walls.size(); i++)
        {
            if(topBuf.getGlobalBounds().intersects(walls[i].wall1.getGlobalBounds())/* || topBuf.getGlobalBounds().intersects(walls2[i].wall1.getGlobalBounds())*/)
            {
                collideTop = 1;
                //collideBottom = 0;
                //collideLeft = 0;
                //collideRight = 0;
            }
        }
        if(collideTop != 1)
        {
            character.move(0, -1);
            collideTop = 0;
            collideBottom = 0;
            collideLeft = 0;
            collideRight = 0;
        }
    }

    if(direction == "down")
    {
        for(int i = 0; i < walls.size(); i++)
        {
            if(bottomBuf.getGlobalBounds().intersects(walls[i].wall1.getGlobalBounds())/* || bottomBuf.getGlobalBounds().intersects(walls2[i].wall1.getGlobalBounds()*/)
            {
                //collideTop = 0;
                collideBottom = 1;
                //collideLeft = 0;
                //collideRight = 0;
            }
        }
        if(collideBottom != 1)
        {
            character.move(0, 1);
            collideTop = 0;
            collideBottom = 0;
            collideLeft = 0;
            collideRight = 0;
        }
    }
}

代码示例 2

void sfml1::buttonPressed()
{

    if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
    {
        for(int i = 0; i < speed; i++)
        {
            players[0].move("left", walls);
        }
    }

    if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
    {
        for(int i = 0; i < speed; i++)
        {
            players[0].move("right", walls);
        }
    }

    if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
    {
        for(int i = 0; i < speed; i++)
        {
            players[0].move("up", walls);
        }
    }

    if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
    {
        for(int i = 0; i < speed; i++)
        {
            players[0].move("down", walls);
        }
    }
}    

代码示例 3

void sfml1::sfmlLoop()
{
    setWalls();
    while(window.isOpen())
    {

        update();
        buttonPressed();
        update();

        while(window.pollEvent(event))
        {
            if(event.type == sf::Event::Closed)
                window.close();

                /*if (event.type == sf::Event::Resized)
                {
                    // update the view to the new size of the window
                    //event.size.width, event.size.height);
                    //view1.setWidth();
                    //view1.setViewport(sf::FloatRect(0, 0, 1, 1.5f));
                    view1.scale(1, 1);
                    window.setView(view1);
                }*/
        }

        draw();

    }
}

【问题讨论】:

    标签: c++ linux g++ sfml


    【解决方案1】:

    在 buttonPressed() 函数内部时,角色的状态由其碰撞缓冲区定义。当您拨打此电话时:

    for(int i = 0; i < speed; i++)
    {
        players[0].move("right", walls);
    }
    

    move() 函数有可能改变玩家的状态,但这不会反映在玩家的碰撞缓冲区中。在从初始位置开始进行碰撞检查时,您向右移动 speed 次。

    您需要做的就是在 move() 函数结束时调用 bufUpdate()。这将确保在解决移动后,您的碰撞缓冲区会更新。

    【讨论】:

    • 嗨。感谢您的回复。我的墙是 32 像素厚。我的角色没有穿墙,但坚持了 4 个像素。我已经使用了 getGlobalBounds() 函数。缓冲区确实会进入墙壁,但如上所述,我试图阻止这种情况。我将更新我的问题以提及墙壁的厚度以及我的角色不会穿过墙壁。
    • P.S.如果我对我的玩家的整个周边进行碰撞检查,它将无法向任何方向移动。如果我让播放器向后移动几个像素,播放器就会开始在两个位置之间闪烁。
    • 啊,我明白了问题所在。我将编辑我的原始答案。
    • 嗨。我的缓冲区实际上是在玩家移动事件之前和之后更新的。我将通过将此代码添加为“代码示例 3”来更新我的答案
    • 哦,拿着电话。你是对的。我刚刚意识到在按钮按下事件循环期间缓冲区没有更新。感谢您的建议!
    猜你喜欢
    • 2013-05-01
    • 1970-01-01
    • 2013-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-24
    • 1970-01-01
    相关资源
    最近更新 更多