c++ 碰撞无法正常工作(使玩家卡住)[关闭]

oxiaedzo  于 10个月前  发布在  其他
关注(0)|答案(1)|浏览(92)

**已关闭。**此问题需要debugging details。目前不接受回答。

编辑问题以包括desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem。这将帮助其他人回答问题。
9天前关闭
Improve this question
我不能让碰撞恰到好处。玩家只是被卡在方块里,即使在方块上面。(顺便说一句,有重力)
我的碰撞依赖于玩家的“过去”位置
编辑:我在代码中犯了一个错误,所以我改变了它。
下面是我的代码:

#include <SFML/Graphics.hpp>
#include <iostream>
#include <math.h>
constexpr auto PI = 3.14159265;
bool rr(float x1, float y1, float w1, float h1, float x2, float y2, float w2, float h2) {
    return (x1 + w1 > x2 && y1 + h1 > y2 && x1 < x2 + w2 && y1 < y2 + h2);
};
//#include <string>
int main()
{
    
    //Player stuffs
    sf::Vector2f playerPos(0, 0);
    sf::Vector2f playerPastPos(0, 0);
    sf::Vector2f playerVel(0, 0);
    sf::RectangleShape playerRender;
    
    playerRender.setSize(sf::Vector2f(20, 20));
    playerRender.setFillColor(sf::Color(0, 255, 0));

    sf::RenderWindow window(sf::VideoMode(600, 400), "Platformer (SFML)");
    window.setFramerateLimit(60);
    sf::Vector2u windowSize = window.getSize();
    int block_map[] = {
        0,0,0,0,0,0,0,1,
        0,0,0,0,0,0,0,1,
        0,0,0,0,0,0,0,0,
        0,0,0,0,0,0,0,0,
        0,0,0,0,0,0,0,0,
        0,0,0,0,0,0,0,2,
        1,0,0,0,0,0,1,1,
        1,1,1,1,1,1,1,1,
    };
    int map_width = 8;
    int map_height = 8;
    sf::RectangleShape rect[sizeof(block_map) / sizeof(*block_map)];
    
    for (int i = 0; i < sizeof(block_map) / sizeof(*block_map); i++) {
            
            rect[i].setPosition(sf::Vector2f((i%(map_width))*20, std::floor(i/map_height)*20));
            rect[i].setFillColor(sf::Color(255, 255, 255, 0));
            switch(block_map[i]){
                case 1:
                    rect[i].setFillColor(sf::Color(255, 255, 255));
                    break;
                case 2:
                    rect[i].setFillColor(sf::Color(255, 0, 255));
                    break;
            }
            
            //std::cout <<"/"+std::to_string((a[i].at(j)));
            
            
        
        
        
    }
    
    int i = 0, j = 50, l = 0;
    while (window.isOpen()) {
        sf::Event event;
        while (window.pollEvent(event)) {
            if (event.type == sf::Event::Closed)
                window.close();
        }

        window.clear();
        windowSize = window.getSize();
        playerPastPos = playerPos;
        while (l < sizeof(rect) / sizeof(rect[0])) {
            
            rect[l].setSize(sf::Vector2f(20, 20));

            //rect[l].setPosition(i, j);

            window.draw(rect[l]);

            //i += 25;

            l++;
        }
        for (int i = 0; i < sizeof(block_map) / sizeof(*block_map); i++) {
            bool canColl = false;
            sf::Vector2f pos = sf::Vector2f((i % (map_width)) * 20, std::floor(i / map_height) * 20);

            if (rr(playerPos.x, playerPos.y, 20, 20, pos.x, pos.y, 20, 20)) {
                switch (block_map[i]) {
                case 1:
                    canColl = true;
                    break;
                case 2:
                    canColl = true;
                    break;
                }
                //0.0174532925
                if (canColl) {
                    
                        
                    if (playerPastPos.y < pos.y - 20) {
                        playerVel.y = 0;
                        playerPos.y = pos.y - 20;
                    }
                    if (playerPastPos.x > pos.x + 20) {
                        playerVel.x = 0;
                        playerPos.x = pos.x + 20;
                    }
                    if (playerPastPos.y > pos.y + 20) {
                        playerVel.y = 0;
                        playerPos.y = pos.y + 20;
                    }
                    if (playerPastPos.x < pos.x - 20) {
                        playerVel.x = 0;
                        playerPos.x = pos.x - 20;
                    }
                    
                }
            }

        }
        //Player in game stuffs
        playerVel.x *= 0.95;
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::D) && playerVel.x < 3) {
            playerVel.x += 0.5;
        }
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::A) && playerVel.x > -3) {
            playerVel.x -= 0.5;
        }
        playerVel.y += 0.3;
        playerPos += playerVel;
        
        
        playerRender.setPosition(playerPos);
        window.draw(playerRender);

        

        // Reset variables.
        l = 0;
        i = 0;
        // Copy the buffer to the window.
        window.display();
    }
}

字符串

von4xj4u

von4xj4u1#

请注意,默认情况下,矩形形状的原点位于其左上角。这意味着在检查冲突时,pos.xpos.y的值位于块的左上角。如果您的播放器继承了sf::Transformable,则也是如此。考虑到这一点,您的计算都是错误的。您应该:

bool rr(float x1, float y1, float w1, float h1, float x2, float y2, float w2, float h2) {
    // Is player pos x inside block pos x?
    // Yes if top right x of player is greater than top left x of block
    // and if top left x of player is lesser than top right x of block at the same time
    bool xIn = (x1 + w1 > x2) && (x1 < x2 + w2);
    
    // Is player pos y inside block pos y?
    // Yes if top left y of player is greater than bottom left y of block
    // and if bottom left y of player is lesser than top left y of block at the same time
    bool yIn = (y1 > y2 - h2) && (y1 - h1 < y2);

    return xIn && yIn;
};

字符串
现在你知道你有一个碰撞,你必须纠正球员的位置。现在你的实现很难遵循,可以改进。我将尝试改变这一点:

// Correct x pos
// Is player coming from left or right?
if ((playerVel.x > 0) && (playerPastPos.x + 20 < pos.x)) {
    // Coming from left
    playerVel.x = 0;
    playerPos.x = pos.x - 20;
}
else if ((playerVel.x < 0) && (playerPastPos.x > pos.x + 20)) {
    // Coming from right
    playerVel.x = 0;
    playerPos.x = pos.x + 20;
}

// Correct y pos
// Is player coming from top or bottom?
if ((playerVel.y > 0) && (playerPastPos.y < pos.y - 20)) {
    // Coming from bottom
    playerVel.y = 0;
    playerPos.y = pos.y - 20;
}
else if ((playerVel.y < 0) && (playerPastPos.y - 20 > pos.y)) {
    // Coming from top
    playerVel.y = 0;
    playerPos.y = pos.y + 20;
}


这显然不是最好的方法,但我试图遵循你的实现的基本思想。

相关问题