SFML 2.0 Pixel Perfect Collision

I have the code and it compiles fine but it doesn't work. (i am using the coding made easy sfml 2.0 tutorials)

Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#include <SFML/Graphics.hpp>
#include <iostream>
#include <algorithm>
#include <vector>

class Player
{
public:
    sf::Sprite player;
    sf::RectangleShape rect;
    float bottom, left, right, top;

    std::vector<std::vector<bool> > mask;

    Player(sf::Vector2f position, sf::Texture &texture)
    {
        sf::Image image;
        image = texture.copyToImage();

        for(int i = 0; i < image.getSize().x; i++)
        {
            std::vector<bool> tempMask;

            for (int j = 0; j < image.getSize().y; j++)
            {
            if (image.getPixel(i, j).a > 0)
                tempMask.push_back(true);
            else
                tempMask.push_back(false);
            }
            mask.push_back(tempMask);
        }
        player.setTexture(texture);
        player.setPosition(position);
    }

    void update()
    {
        bottom = rect.getPosition().y + rect.getSize().y;
        left = rect.getPosition().x;
        right = rect.getPosition().x + rect.getSize().x;
        top = rect.getPosition().y;
    }

    bool Collision(Player p)
    {
        if (right <= p.left || left >= p.right || top >= p.bottom || bottom <= p.top)
        {
        }
        else
        {
            float colBottom, colTop, colLeft, colRight;
            colBottom = std::min(bottom, p.bottom);
            colTop = std::max(top, p.top);
            colLeft = std::max(left, p.left);
            colRight = std::min(right, p.right);

            for (int i = colTop; i < colBottom; i++)
            {
                for(int j = colLeft; j < colRight; j++)
                {
                    if(mask[j - left][i - top] && p.mask[j - p.left][i - p.top])
                        return true;
                }
            }
        }
        return false;
    }
};

int main()
{
    sf::RenderWindow window(sf::VideoMode (800,600), "Pixel Perfect Collision");

    sf::Texture Tplayer;
    Tplayer.loadFromFile("Warrior.png");

    Player p1(Player(sf::Vector2f(10, 10), Tplayer)),
    p2(Player(sf::Vector2f(100, 100), Tplayer));

    while(window.isOpen())
    {
        sf::Event Event;
        while(window.pollEvent(Event))
        {
            switch (Event.type)
            {
                case sf::Event::Closed:
                window.close();
                break;
            }
        }
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
        {
            p1.player.move(0.1f, 0);
        }

        else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
        {
            p1.player.move(-0.1f, 0);
        }

        else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
        {
            p1.player.move(0, -0.1f);
        }

        else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
        {
            p1.player.move(0, 0.1f);
        }

        p1.update();
        p2.update();

        if (p1.Collision(p2))
            std::cout << "Collision!" << std::endl;

        window.clear(sf::Color(0, 240, 255));
        window.draw(p1.player);
        window.draw(p2.player);
        window.display();
    }
}


Please Help


Edit: updated code
Last edited on
Could you maybe be more specific than "it doesn't work?"

It would appear, given the way you built the mask in the loop that begins on line 20, that you've reversed which stands for the x and y coordinates in the loop on that begins on line 58.
so what should the loop look like?
nevermind found the problem i didn't change the update() function to this:

1
2
3
4
5
6
7
void update()
    {
        bottom = player.getPosition().y + player.getTextureRect().height;
        left = player.getPosition().x;
        right = player.getPosition().x + player.getTextureRect().width;
        top = player.getPosition().y;
    }


now to incorporate it into my game
Last edited on
now the code half works it can detect collision but it isn't pixel perfect, when it does register the program crashes.

edit: removed sentence because i fixed the problem

here is the important part of my code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
class character
{
public:


    sf::Sprite sprite;
    sf::Texture texture;

    std::vector<std::vector<bool> > mask;

    character(sf::Vector2f position, sf::Texture &Texture)
    {
        sf::Image image;
        image = texture.copyToImage();

        for(int i = 0; i < image.getSize().x; i++)
        {
            std::vector<bool> tempMask;

            for (int j = 0; j < image.getSize().y; j++)
            {
            if (image.getPixel(i, j).a > 0)
                tempMask.push_back(true);
            else
                tempMask.push_back(false);
            }
            mask.push_back(tempMask);
        }
        texture = Texture;
        sprite.setTexture(texture);
        sprite.setPosition(position);
    }


    float bottom, left, right, top;
    void update()
    {
        bottom = sprite.getPosition().y + sprite.getTextureRect().height;
        left = sprite.getPosition().x;
        right = sprite.getPosition().x + sprite.getTextureRect().width;
        top = sprite.getPosition().y;
    }

    bool Collision_Fighter(Fighter p) //fighter has been previously declared with same update()
    {
        if (right <= p.left || left >= p.right || top >= p.bottom || bottom <= p.top)
        {
        }
        else
        {
            float colBottom, colTop, colLeft, colRight;
            colBottom = std::min(bottom, p.bottom);
            colTop = std::max(top, p.top);
            colLeft = std::max(left, p.left);
            colRight = std::min(right, p.right);

            for (int i = colTop; i < colBottom; i++)
            {
                for(int j = colLeft; j < colRight; j++)
                {
                    if(mask[i - left][j - top] && p.mask[i - p.left][j - p.top])
                        return true;
                }
            }
        }
        return false;
    }
Last edited on
Hello?
closed account (o1vk4iN6)
Hi !
can you help me? i am getting frustrated
Last edited on
You really need to provide more information, what did you expect/want this code to do and what is it actually doing?
when it does register the program crashes.

When it registers what? How did you know it registered? Have you tried stepping through your code with a debugger? Have you at least tried writing logs to the console to see what's reached and what isn't?
Also what in the world is mask for?
well i think i have figured out it not being pixel perfect but it crashes when it registers collision. the game crashes and has to be closed down and that is the problem
closed account (N36fSL3A)
Yea, a 2 sentence reply is definitely going to help.

http://lazyfoo.net/SDL_tutorials/lesson18/index.php
Not SFML, but same concept.

Using a multidimensional vector (or array) are just going to cause you headaches.
Last edited on
the thing is though i have used this code on another program and it worked perfectly (although that program wasn't anywhere nearly as complex)
closed account (N36fSL3A)
Well your design is flawed, a telltale sign is you, the programmer can't understand it.
that doesn't tell me how to fix it though
closed account (N36fSL3A)
You're probably going to spend much more time fixing it than just rewriting to a more acceptable style.

I'm telling you 2D arrays are slower and much harder to manage.

now the code half works it can detect collision but it isn't pixel perfect, when it does register the program crashes.
Explain more please.
Last edited on
now the code half works it can detect collision but it isn't pixel perfect


i actually can't figure if this is true because of the other reason so just ignore it for now.

when it does register the program crashes.


how does this need explaining? when the collision registers the program crashes and needs to be closed
Never mind i discovered that pixel perfect collision wasn't more important then the entire game. the game started to crash regardless of what collision i use. so i have temporarily commented out the pixel perfect collision code
FWIW pixel-perfect collision usually isn't a good idea. Aside from being slow and difficult, it's usually completely unnecessary to have collision that precise. Bounding box and other more basic types of collision are usually a better route.
yeah i think i am going to try distance based
Topic archived. No new replies allowed.