首页 > 解决方案 > SFML 前景碰撞

问题描述

我一直在尝试在 SFML 上制作 RPG 游戏,现在我在碰撞中挣扎。我的问题很简单,我有这 2 层,背景和前景。背景仅充当背景图像,前景 png 图像应充当碰撞,具有角色应该完全自由行走的部分(透明)并保持其余结构用作碰撞(此处的背景图像:https://imgur.com/gallery/DA3zGtD 我让地板透明,同时保持其余部分)。我尝试将 getGlobalBounds().intesect 与角色精灵一起使用,但没有任何成功。我想让它尽可能简单,这是我到目前为止所拥有的:


#include <iostream>
#include "Piso1.h"

using namespace std;
Piso1::Piso1(){

};

int Piso1::Draw(RenderWindow &window, Event &evento)
{
srand(time(nullptr));
Soundtrack.openFromFile("../Scenes/Piso1/Sounds/Neon District.wav");
    Soundtrack.setLoop(true);
    Soundtrack.play();

Texture BGTexture;
    BGTexture.loadFromFile("../Scenes/Piso1/Graphics/piso1background.png");
Sprite Background;
    Background.setTexture(BGTexture);
    Background.setScale(8,7.5);
    Background.setPosition(BackX,BackY);


Texture FGTexture;
    FGTexture.loadFromFile("../Scenes/Piso1/Graphics/piso1foreground.png");
Sprite Foreground;
    Foreground.setTexture(FGTexture);
    Foreground.setScale(8,7.5);
    Foreground.setPosition(BackX,BackY);

Texture ProtaTextura;
    ProtaTextura.loadFromFile("../Scenes/Piso1/Graphics/pSprite.png");
    IntRect SpriteBx(0,0,34,47);
Sprite Protagonista(ProtaTextura,SpriteBx);
    Protagonista.setPosition((window.getSize().x)/2.35,(window.getSize().y)/3);
    Protagonista.setScale(3,3);

while (window.isOpen()) {
    while (window.pollEvent(evento)) {
        switch (evento.type) {
            case Event::Closed:
                window.close();
                break;
            case Event::KeyPressed:
                EncounterValue = rand()%1000;
                if(EncounterValue > 5){
                    if(evento.key.code == Keyboard::Down) {
                        BackY -= 10;
                        Background.move(0,-10);
                        Foreground.move(0,-10);
                        //this is my failed attempt
                        if(Protagonista.getLocalBounds().intersects(Foreground.getLocalBounds()))
                        {
                            Collision.openFromFile("../Scenes/Piso1/Sounds/oof.ogg");
                            Collision.play();
                            BackY += 10;
                            Background.move(0, 10);
                            Foreground.move(0, 10);
                        }

                        if(clock1.getElapsedTime().asMilliseconds()>64){
                            SpriteBx.top = 0;
                            if (SpriteBx.left == 0)
                                SpriteBx.left = 34;
                            else if (SpriteBx.left==34)
                                SpriteBx.left= 68;
                            else if (SpriteBx.left== 68)
                                SpriteBx.left= 102;
                            else
                                SpriteBx.left=0;
                            Protagonista.setTextureRect(SpriteBx);
                            clock1.restart();
                        }
                        break;
                    }
                    else if (evento.key.code == Keyboard::Up) {
                        BackY += 10;
                        Background.move(0,10);
                        Foreground.move(0,10);
                        if (clock1.getElapsedTime().asMilliseconds()>64)
                        {
                            SpriteBx.top = 152;
                            if (SpriteBx.left == 0)
                                SpriteBx.left = 34;
                            else if (SpriteBx.left==34)
                                SpriteBx.left= 68;
                            else if (SpriteBx.left== 68)
                                SpriteBx.left= 102;
                            else
                                SpriteBx.left=0;
                            Protagonista.setTextureRect(SpriteBx);
                            clock1.restart();
                        }
                        break;
                    }
                    else if(evento.key.code == Keyboard::Left) {
                        BackX += 10;
                        Background.move(10,0);
                        Foreground.move(10,0);
                        if (clock1.getElapsedTime().asMilliseconds()>64)
                        {
                            SpriteBx.top = 53;
                            if (SpriteBx.left == 0)
                                SpriteBx.left = 34;
                            else if (SpriteBx.left==34)
                                SpriteBx.left= 68;
                            else if (SpriteBx.left== 68)
                                SpriteBx.left= 102;
                            else
                                SpriteBx.left=0;
                            Protagonista.setTextureRect(SpriteBx);
                            clock1.restart();
                        }
                        break;
                    }
                    else if(evento.key.code == Keyboard::Right){
                        BackX -= 10;
                        Background.move(-10,0);
                        Foreground.move(-10,0);
                        if (clock1.getElapsedTime().asMilliseconds()>64)
                        {
                            SpriteBx.top = 104;
                            if (SpriteBx.left == 0)
                                SpriteBx.left = 34;
                            else if (SpriteBx.left==34)
                                SpriteBx.left= 68;
                            else if (SpriteBx.left== 68)
                                SpriteBx.left= 102;
                            else
                                SpriteBx.left=0;
                            Protagonista.setTextureRect(SpriteBx);
                            clock1.restart();
                        }
                        break;
                    }
                    else if(evento.key.code == Keyboard::C){
                        Soundtrack.stop();
                        return 1;
                    }
                }
                else{
                    Soundtrack.stop();
                    return 0;
                }
        }
        window.clear();
        window.draw(Foreground);
        window.draw(Background);
        window.draw(Protagonista);
        window.display();
    }
}
}

我认为发生的事情是,当我想做时,如果它需要整个 png 而不是我想要的部分作为碰撞。我也想尝试颜色碰撞,但我真的不知道如何实现它,我对 SFML 有点陌生。提前致谢!

标签: colorscollisionsfmlforegroundintersect

解决方案


如果您希望在玩家和其他对象之间进行适当的碰撞检测,则 .intersect() 还不够好。它要么让你的角色永久卡在结构中,要么让它在没有玩家控制的情况下通过它,这取决于你为这种情况编写的行为。

有效的方法是检测玩家从哪个方向接近物体,并在此基础上让他向后移动一点,或者如果当前速度会让他更深入结构,则将速度设置为 0。

例如,像你一样使用 intersect(),以防玩家从左侧撞到墙:

if(velocity.x > 0 && player.getLocalBounds().intersect(wall.getLocalBounds()) && player.getLocalBounds().left > wall.getLocalBounds().left)

然后您可以使用此条件来停止播放器(将velocity.x 设置为0)、设置reverse 以使他后退或在发生碰撞时执行您希望的任何其他类型的行为。

(请注意,这不是一个理想的解决方案,但它应该可以工作并遵循您实现的类似逻辑。)


推荐阅读