SFML Help (Math calculation help)

Pages: 12
Ch1156 wrote:
Maybe the shapes themselves are cheap but when i put textures on them they may become expensive, im unsure, i'll have to test it with some textures.

The shape would only keep a pointer to the texture. It wouldn't get copied if you copied the shape.

SFML wrote:
void sf::Shape::setTexture ( const Texture * texture, bool resetRect = false )
...
The texture argument refers to a texture that must exist as long as the shape uses it. Indeed, the shape doesn't store its own copy of the texture, but rather keeps a pointer to the one that you passed to this function. If the source texture is destroyed and the shape tries to use it, the behavior is undefined.
...
https://www.sfml-dev.org/documentation/2.5.1/classsf_1_1Shape.php#af8fb22bab1956325be5d62282711e3b6

Ch1156 wrote:
Also is there any way to do this:
auto cornerSquare_1 { CreateRectangle(35, 35, sf::Color::Blue, 0, 0, cornerSquare_1->getSize().x / 2.0f, cornerSquare_1->getSize().y / 2.0f) };
Even though the variable is technically undeclared at that point? writing the set origin function for each seems like a waste of code when i can just do it in the function call.

No. I don't know how you expect getSize() to return anything sensible if the object haven't been initialized yet.

Shouldn't all rectangles have the origin in the middle? If so, why don't you calculate the origin inside the function instead of passing it as argument?
ok thank you, thats something to consider. Also does it matter if the origin is at the top left or the center? or is it just a matter of personal preference?

Also when it comes to calculating the sides of objects i think i might be getting it, i made an image that has my reasoning in it and hopefully its correct.

https://ibb.co/DkQn5Vf

I got all the squares on the corners, its still a bit confusing but its much clearer than it was, hopefully theres no unforseen issues with my logic.
Last edited on
current 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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
//Version 0.0.8

#include <iostream>
#include <string>
#include <sstream>
#include <SFML/Graphics.hpp>


sf::Text CreateText(const sf::Font& font, int characterSize, const sf::Color& color, float posX, float posY, const std::string& str)
{
    sf::Text text;
    text.setCharacterSize(characterSize);
    text.setFont(font);
    text.setFillColor(color);
    text.setPosition(sf::Vector2f(posX, posY));
    text.setString(str);

    return text;
}

std::unique_ptr<sf::RectangleShape> CreateRectangle(float width, float height, const sf::Color& color, float setXPos, float setYPos)
{
    std::unique_ptr<sf::RectangleShape> rectangle(new sf::RectangleShape);

    rectangle->setSize(sf::Vector2f(width, height));
    rectangle->setFillColor(color);
    rectangle->setPosition(sf::Vector2f(setXPos, setYPos));
    rectangle->setOrigin(sf::Vector2f(rectangle->getSize().x / 2, rectangle->getSize().y / 2));

    return rectangle;
}

//sf::RectangleShape CheckCollision(sf::RectangleShape& rectShape)
//{
//
//}

int main()
{
    sf::RenderWindow window(sf::VideoMode(1280, 720), "SFML Feature Testing");

    sf::Font Arial;
    Arial.loadFromFile("Resources/Fonts/arial.ttf");

    std::ostringstream oss;
    std::istringstream iss;

    float windowCenterX{ window.getSize().x / 2.0f };
    float windowCenterY{ window.getSize().y / 2.0f };

    sf::Text MouseXText{ CreateText(Arial,  32, sf::Color::White, 0.0f, 0.0f, "Mouse X Pos: ") };
    sf::Text MouseXValue{ CreateText(Arial, 32, sf::Color::White, 0.0f, 0.0f, "Mouse X Value: ") };
    sf::Text MouseYText{ CreateText(Arial,  32, sf::Color::White, 0.0f, 0.0f, "Mouse Y Pos: ") };
    sf::Text MouseYValue{ CreateText(Arial, 32, sf::Color::White, 204, 30,    "Mouse Y Value : ") };


    MouseXValue.setPosition(sf::Vector2f(MouseXText.getPosition().x + MouseXText.getGlobalBounds().width, 0.0f));
    MouseYText.setPosition(sf::Vector2f(0, MouseXText.getPosition().y + MouseXText.getGlobalBounds().height + 5));


    //Center Square
    auto square{ CreateRectangle(300, 300, sf::Color::White, windowCenterX, windowCenterY) };

    //Squares
    auto cornerSquare_1 { CreateRectangle(35, 35, sf::Color::Blue,  0, 0) };
    auto cornerSquare_2 { CreateRectangle(35, 35, sf::Color::Cyan,  0, 0) };
    auto cornerSquare_3 { CreateRectangle(35, 35, sf::Color::Green, 0, 0) };
    auto cornerSquare_4 { CreateRectangle(35, 35, sf::Color::Red,   0, 0) };

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

            if (event.type == sf::Event::Resized)
            {
                window.setView(sf::View(sf::FloatRect(0.0f, 0.0f, static_cast<float>(event.size.width), static_cast<float>(event.size.height))));
                square->setPosition(sf::Vector2f(window.getSize().x / 2, window.getSize().y / 2));
            }
        }

        oss << sf::Mouse::getPosition(window).x;

        MouseXValue.setString(oss.str());

        oss.str("");

        oss << sf::Mouse::getPosition(window).y;

        MouseYValue.setString(oss.str());

        oss.str("");

        std::cout << "square x position - x origin: " << square->getPosition().x - square->getOrigin().x << '\n';
        std::cout << "square x position + x origin: " << square->getPosition().x + square->getOrigin().x << '\n';
        std::cout << "square y position - y origin: " << square->getPosition().y - square->getOrigin().y << '\n';
        std::cout << "square y position + y origin: " << square->getPosition().y + square->getOrigin().y << "\n\n";

        if (   sf::Mouse::getPosition(window).x >= square->getPosition().x - square->getOrigin().x
            && sf::Mouse::getPosition(window).x <= square->getPosition().x + square->getOrigin().x
            && sf::Mouse::getPosition(window).y >= square->getPosition().y - square->getOrigin().y
            && sf::Mouse::getPosition(window).y <= square->getPosition().y + square->getOrigin().y 
            )
        {
            std::cout << "Within white square\n";
        }
        
        //NOTES:
        //GetPosition gets the position of the square in the window at its origin.

        float squareBottomRightCornerX{ square->getPosition().x + square->getOrigin().x };
        float squareBottomRightCornerY{ square->getPosition().y + square->getOrigin().y };
        float squareTopLeftCornerX{ square->getPosition().x - square->getOrigin().x };
        float squareTopLeftCornerY{ square->getPosition().y - square->getOrigin().y };

        //Set cornerSquare to one corner.
        //Bottom Right (Blue)
        cornerSquare_1->setPosition(sf::Vector2f(squareBottomRightCornerX + cornerSquare_1->getOrigin().x, squareBottomRightCornerY + cornerSquare_1->getOrigin().y));

        //Top Left (Cyan)
        cornerSquare_2->setPosition(sf::Vector2f(squareTopLeftCornerX - cornerSquare_2->getOrigin().x, squareTopLeftCornerY - cornerSquare_2->getOrigin().y));

        //Top Right (Green)
        cornerSquare_3->setPosition(sf::Vector2f(square->getPosition().x + square->getOrigin().x + cornerSquare_3->getOrigin().y, square->getPosition().y - square->getOrigin().y - cornerSquare_3->getOrigin().y));

        //Bottom Left (Red)
        cornerSquare_4->setPosition(sf::Vector2f(square->getPosition().x - square->getOrigin().x - cornerSquare_4->getOrigin().y, square->getPosition().y + square->getOrigin().y + cornerSquare_4->getOrigin().y));
        
        window.clear();
        window.draw(MouseXText);
        window.draw(MouseXValue);
        window.draw(MouseYText);
        window.draw(MouseYValue);
        window.draw(*square);
        window.draw(*cornerSquare_1);
        window.draw(*cornerSquare_2);
        window.draw(*cornerSquare_3);
        window.draw(*cornerSquare_4);
        window.display();
    }

    return 0;
}
Last edited on
Ch1156 wrote:
does it matter if the origin is at the top left or the center? or is it just a matter of personal preference?

It doesn't really matter in the sense that you could always calculate the top, left, right, bottom and center coordinates no matter what origin you use. I don't usually do this but you could create helper functions to let you do this quite easily (e.g. set_left_x, set_top_y, get_center_x, etc.).

In general, not speaking specifically about SFML, I would say it's a combination of personal preference and what is most convenient.

Personally I think top-left often makes sense for rectangular areas (e.g. GUI elements). It makes it quite easy to calculate the sides. I find it more cumbersome to calculate the sides when the coordinates refer to the center, especially when dealing with integer coordinates because it might not be possible to have the same amount on both sides.

1
2
3
4
5
6
7
8
9
10
11
// if (x,y) refers to the top-left corner
float left = x;
float right = x + w;
float top = y;
float right = y + h;

// if (x,y) refers to the center
float left = x - w / 2;
float right = x + w / 2;
float top = y - h / 2;
float right = y + h / 2;

For players and objects in a game I think it often makes more sense to use center coordinates (e.g. for bouncing balls and for games seen from above) or middle-bottom coordinates (in games seen from the side so that (x, y) refers to the center of where the object/player is standing on the ground).

Note that in a game you often have levels of abstraction. If you use your own game objects or a scripting language to program most of the things that happen in the game then it matter less what you do in the tiny bit of code that deals with SFML directly as long as it works. It's possible to for example use center coordinates for your game objects while using top-left coordinates for the sf::Shape and sf:Sprite objects behind the scenes.
Last edited on
Ok thank you for explaining that, I plan on making top down games, something like the legend of zelda but im gonna start much smaller first. Can i have a little more clarification on some things?

So down on the screen is +Y, up is -Y, left is -X and right is +X. So this code, assuming the origin is always at the center:

square->getPosition().x + square->getOrigin().x + cornerSquare_3->getOrigin().y, square->getPosition().y - square->getOrigin().y - cornerSquare_3->getOrigin().y

Gets the position of the square on the screen, then add the origin of the object to it, so this gets the top right corner on the x axis, and the second line goes up the right side to the top right corner to meet at that point, then we add/minus the origin of the smaller square on each axis so its corner will touch the white squares top corner correct?

When i add or subtract from an axis it moves it along the screen accordingly, and with this:

1
2
3
4
sf::Mouse::getPosition(window).x >= square->getPosition().x - square->getOrigin().x
            && sf::Mouse::getPosition(window).x <= square->getPosition().x + square->getOrigin().x
            && sf::Mouse::getPosition(window).y >= square->getPosition().y - square->getOrigin().y
            && sf::Mouse::getPosition(window).y <= square->getPosition().y + square->getOrigin().y 


using less than means if the squares position is less than the position + the origin going along the -x axis? and the greater than means going along the +X axis?
Last edited on
Ch1156 wrote:
im gonna start much smaller first

Good idea.

Ch1156 wrote:
So down on the screen is +Y, up is -Y, left is -X and right is +X.

Yes.

square->getPosition().x
square->getPosition().y
Gets the position of the square on the screen

Right.

... + square->getOrigin().x
... - square->getOrigin().y
then add the origin of the object to it, so this gets the top right corner

Add/subtract, but yeah, you now have the top-right corner of the big white square.

Note that this is only correct when the origin is in the middle. For arbitrary origin you would have to do something like:
 
square->getPosition().x - square->getOrigin().x + square->getSize().x // right x-coordinate 
 
square->getPosition().y - square->getOrigin().y // top y-coordinate 


... + cornerSquare_3->getOrigin().y
... - cornerSquare_3->getOrigin().y
then we add/minus the origin of the smaller square on each axis so its corner will touch the white squares top corner correct?

Yes, except that you probably meant to use .x instead of .y when calculating the x-coordinate. It doesn't make a difference since they are the same in this case but still...

When i add or subtract from an axis it moves it along the screen accordingly

You could think of it like that. Trying to visualize it helps a lot.

using less than means if the squares position is less than the position + the origin going along the -x axis? and the greater than means going along the +X axis?

I think you've got the right idea.
Last edited on
I cant seem to figure out whats wrong with my collision detection, I put the code for figuring out the sides in variable names just to make it easier to understand, but the player wont move correctly. I also posted here first: https://en.sfml-dev.org/forums/index.php?topic=28988.0

just to increase visibility and get other/different answers.

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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
//============================================================================
// Name             : SFML Game
// Author           : Chay Hawk
// Version          : 0.0.14
// Version Date     : March 24th 2023 @ 11:27 AM
// Date Created     : 
// Lines of Code    : 224
// Description      : 
//============================================================================

#include <iostream>
#include <string>
#include <sstream>
#include <SFML/Graphics.hpp>

sf::Text CreateText(const sf::Font& font, int characterSize, const sf::Color& color, float posX, float posY, const std::string& str)
{
    sf::Text text;
    text.setCharacterSize(characterSize);
    text.setFont(font);
    text.setFillColor(color);
    text.setPosition(sf::Vector2f(posX, posY));
    text.setString(str);

    return text;
}

std::unique_ptr<sf::RectangleShape> CreateRectangle(float width, float height, const sf::Color& color, float setXPos, float setYPos)
{
    std::unique_ptr<sf::RectangleShape> rectangle(new sf::RectangleShape);

    rectangle->setSize(sf::Vector2f(width, height));
    rectangle->setFillColor(color);
    rectangle->setPosition(sf::Vector2f(setXPos, setYPos));
    rectangle->setOrigin(sf::Vector2f(rectangle->getSize().x / 2, rectangle->getSize().y / 2));

    return rectangle;
}


int main()
{
    sf::RenderWindow window(sf::VideoMode(1280, 720), "SFML Feature Testing");
    window.setFramerateLimit(60);

    sf::Font Arial;
    Arial.loadFromFile("Resources/Fonts/arial.ttf");

    std::ostringstream oss;
    std::istringstream iss;

    float windowCenterX{ window.getSize().x / 2.0f };
    float windowCenterY{ window.getSize().y / 2.0f };

    sf::Text MouseXText{ CreateText(Arial,  32, sf::Color::White, 0.0f, 0.0f, "Mouse X Position: ") };
    sf::Text MouseXValue{ CreateText(Arial, 32, sf::Color::White, 0.0f, 0.0f, "Mouse X Value: ") };
    sf::Text MouseYText{ CreateText(Arial,  32, sf::Color::White, 0.0f, 0.0f, "Mouse Y Pos: ") };
    sf::Text MouseYValue{ CreateText(Arial, 32, sf::Color::White, 204, 30,    "Mouse Y Value : ") };


    MouseXValue.setPosition(sf::Vector2f(MouseXText.getPosition().x + MouseXText.getGlobalBounds().width, 0.0f));
    MouseYText.setPosition(sf::Vector2f(0, MouseXText.getPosition().y + MouseXText.getGlobalBounds().height + 5));


    //Center Square
    auto square{ CreateRectangle(300, 300, sf::Color::White, windowCenterX, windowCenterY) };

    float squareLeft{ };
    float squareTop{ };
    float squareRight{ };
    float squareBottom{ };

    //Squares
    auto cornerSquare_1 { CreateRectangle(35, 35, sf::Color::Blue,  0, 0) };
    auto cornerSquare_2 { CreateRectangle(35, 35, sf::Color::Cyan,  0, 0) };
    auto cornerSquare_3 { CreateRectangle(35, 35, sf::Color::Green, 0, 0) };
    auto cornerSquare_4 { CreateRectangle(35, 35, sf::Color::Red,   0, 0) };


    int playerX{ 150 };
    int playerY{ 150 };

    //Player
    auto player{ CreateRectangle(32, 32, sf::Color::Yellow, playerX, playerY) };

    float playerLeft{ };
    float playerTop{ };
    float playerRight{ };
    float playerBottom{ };

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

            if (event.type == sf::Event::Resized)
            {
                window.setView(sf::View(sf::FloatRect(0.0f, 0.0f, static_cast<float>(event.size.width), static_cast<float>(event.size.height))));
                square->setPosition(sf::Vector2f(window.getSize().x / 2, window.getSize().y / 2));
            }
        }

        oss << sf::Mouse::getPosition(window).x;

        MouseXValue.setString(oss.str());

        oss.str("");

        oss << sf::Mouse::getPosition(window).y;

        MouseYValue.setString(oss.str());

        oss.str("");


        /*std::cout << "Player X Position: " << player->getPosition().x << '\n';
        std::cout << "Player Y Position: " << player->getPosition().y << '\n';*/

        std::cout << "Player X Left Side:  " << player->getPosition().x - player->getOrigin().x << '\n';
        std::cout << "Player Y Top:        " << player->getPosition().y - player->getOrigin().y << '\n';
        std::cout << "Player X Right Side: " << player->getPosition().x + player->getOrigin().x << '\n';
        std::cout << "Player Y Bottom:     " << player->getPosition().y + player->getOrigin().y << '\n';

        if (   sf::Mouse::getPosition(window).x >= square->getPosition().x - square->getOrigin().x
            && sf::Mouse::getPosition(window).x <= square->getPosition().x + square->getOrigin().x
            && sf::Mouse::getPosition(window).y >= square->getPosition().y - square->getOrigin().y
            && sf::Mouse::getPosition(window).y <= square->getPosition().y + square->getOrigin().y 
            )
        {
            std::cout << "Within white square\n";
        }

        playerLeft = player->getPosition().x - player->getOrigin().x;
        playerTop = player->getPosition().y - player->getOrigin().y;
        playerRight = player->getPosition().x + player->getOrigin().x;
        playerBottom = player->getPosition().y + player->getOrigin().y;

        squareLeft = square->getPosition().x - square->getOrigin().x;
        squareTop = square->getPosition().y - square->getOrigin().y;
        squareRight = square->getPosition().x + square->getOrigin().x;
        squareBottom = square->getPosition().y + square->getOrigin().y;

        //player->setPosition();

        if (sf::Keyboard::isKeyPressed(sf::Keyboard::W))
        {
            if (playerTop >= squareBottom)
            {
                player->move(0, -5);
            }
        }

        if (sf::Keyboard::isKeyPressed(sf::Keyboard::A))
        {
            if (playerLeft <= squareRight)
            {
                player->move(-5, 0);
            }
        }

        if (sf::Keyboard::isKeyPressed(sf::Keyboard::S))
        {
            if (playerBottom <= squareTop)
            {
                player->move(0, 5);
            }
        }

        if (sf::Keyboard::isKeyPressed(sf::Keyboard::D))
        {
            if (playerRight >= squareLeft)
            {
                player->move(5, 0);
            }
        }

        //Set cornerSquare to one corner.
        //Bottom Right (Blue)
        cornerSquare_1->setPosition(sf::Vector2f(square->getPosition().x + square->getOrigin().x + cornerSquare_1->getOrigin().x, square->getPosition().y + square->getOrigin().y + cornerSquare_1->getOrigin().y));

        //Top Left (Cyan)
        cornerSquare_2->setPosition(sf::Vector2f(square->getPosition().x - square->getOrigin().x - cornerSquare_2->getOrigin().x, square->getPosition().y - square->getOrigin().y - cornerSquare_2->getOrigin().y));

        //Top Right (Green)
        cornerSquare_3->setPosition(sf::Vector2f(square->getPosition().x + square->getOrigin().x + cornerSquare_3->getOrigin().y, square->getPosition().y - square->getOrigin().y - cornerSquare_3->getOrigin().y));

        //Bottom Left (Red)
        cornerSquare_4->setPosition(sf::Vector2f(square->getPosition().x - square->getOrigin().x - cornerSquare_4->getOrigin().y, square->getPosition().y + square->getOrigin().y + cornerSquare_4->getOrigin().y));
        
        window.clear();
        window.draw(MouseXText);
        window.draw(MouseXValue);
        window.draw(MouseYText);
        window.draw(MouseYValue);
        window.draw(*player);
        window.draw(*square);
        window.draw(*cornerSquare_1);
        window.draw(*cornerSquare_2);
        window.draw(*cornerSquare_3);
        window.draw(*cornerSquare_4);
        window.display();
    }

    return 0;
}
Last edited on
This means the player is only allowed to move up if she is below the square:

1
2
3
4
5
6
7
if (sf::Keyboard::isKeyPressed(sf::Keyboard::W))
{
    if (playerTop >= squareBottom)
    {
        player->move(0, -5);
    }
}

But what if she's above, or on the side, don't you want to allow the player to move up then?
Last edited on
Im trying to just prevent the player from colliding with the square, I want them to be able to move freely around it, then ill use that code and make a function that will check the collision for the player against all on screen objects. I just want some simple AABB collision for now.
Last edited on
Topic archived. No new replies allowed.
Pages: 12