Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Can't change shape's attributes outside of int main()  (Read 412 times)

0 Members and 1 Guest are viewing this topic.

bobojoeho

  • Newbie
  • *
  • Posts: 11
    • View Profile
Can't change shape's attributes outside of int main()
« on: February 13, 2024, 09:27:17 pm »
Hi guys its me again.  So I got SFML to work and everything, but I have an interesting issue.  Some certain SFML commands only work if they are placed inside the int main() function.  I can create shapes outside of the main loop, but whenever I try to change their size, or any other attribute, I get an error saying "this declaration has no storage class or type specifier".  So far, the commands that don't work are any command that modifies or sets attributes to my shapes or window.  I made sure that when I tried to change my shape's attributes I created the shape also outside the main loop and above my script so I wasn't changing a nonexistent shape.

Any ideas on how to fix this?  I think its kinda weird since I can create shapes wherever I want, but it appears I can only set their attributes inside int main().

Hapax

  • Hero Member
  • *****
  • Posts: 3351
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: Can't change shape's attributes outside of int main()
« Reply #1 on: February 14, 2024, 01:00:07 am »
Glad you got it to work!  :)

First thing to note is that SFML objects shouldn't be global. It's not clear whether you mean this or not.
e.g. this is BAD:
sf::RenderWindow window;
int main()
{
}
The objects should be created inside the main function:
int main()
{
    sf::RenderWindow window;
}
It's still okay to create an object elsewhere as long as it still called by main:
sf::RenderWindow* createRenderWindow()
{
    sf::RenderWindow* pWindow = new sf::RenderWindow;
    return pWindow;
}
int main()
{
    sf::RenderWindow* pWindow = createRenderWindow();
}
Note that a pointer was used here for simplicity but this is not the safest way to do it. Use a smart pointer if you do it this way.

It's usually better to create them and then pass them:
void createRenderWindow(sf::RenderWindow& window)
{
    window.create(sf::VideoMode(960u, 540u), "");
}
int main()
{
    sf::RenderWindow window;
    createRenderWindow(window);
}

You don't need to pass objects back if you're using them temporarily:
void loadAFontButThenThrowItAway()
{
    sf::Font font;
    font.loadFromFile("fonts/arial.ttf"); // I am not checking whether it loads or not for simplicity and since it does not really matter here but you should always do that!
}
int main()
{
    loadAFontButThenThrowItAway();
}


With all that said, another thing to consider is that SFML needs to be included before using an object so, if you're doing something in a separate file, you'll likely need to include SFML headers from that file too.
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

bobojoeho

  • Newbie
  • *
  • Posts: 11
    • View Profile
Re: Can't change shape's attributes outside of int main()
« Reply #2 on: February 14, 2024, 08:20:44 pm »
This problem occurs whether or not I create the shape inside of int main.  I am using only one file, and I include SFML at the very beginning.  I am just confused as some of SFML's commands work outside of int main, but not others.

I am trying to make a platformer, and I want a function that will create an object, by adding its attributes to a few arrays.  Later on in my script, I will create the shapes in the arrays and draw them.  This would allow me to store my object's positions so that I can detect collisions too.

Hapax

  • Hero Member
  • *****
  • Posts: 3351
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: Can't change shape's attributes outside of int main()
« Reply #3 on: February 14, 2024, 08:35:02 pm »
I think I was slightly confused by your mention of it working only in main.

Could you provide a small example* code of what you mean?
*A complete and minimal example would be great if possible.
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

bobojoeho

  • Newbie
  • *
  • Posts: 11
    • View Profile
Re: Can't change shape's attributes outside of int main()
« Reply #4 on: February 14, 2024, 11:25:35 pm »
Ok sure.


Here is a script that does run for me:
_______________________________
#include <SFML/Graphics.hpp>

int main() {

sf::CircleShape shape(200);
shape.setFillColor(sf::Color(150, 150, 150));

}
_______________________________


A script that doesn't run would be:
_______________________________
#include <SFML/Graphics.hpp>

sf::CircleShape shape(200);

shape.setFillColor(sf::Color(150, 150, 150));  // this line here creates the error, apparently "this declaration
                                                                  //has no storage class or type specifier"
int main() {

shape.setPosition(sf::Vector2f(5, 5));

}
______________________________


As you can see, creating the object works fine, but trying to change its attributes causes an error.  This also happens when I am trying to change the attributes of a window.
If this helps at all, I can detect key presses just fine using SFML.

Hapax

  • Hero Member
  • *****
  • Posts: 3351
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: Can't change shape's attributes outside of int main()
« Reply #5 on: February 14, 2024, 11:48:16 pm »
That piece of code is not being called by anything; it's not enclosed.

When the app is started, the first code to be executed is main().
At no point can main call this command.

It brings me to my first example: avoid using objects globally (as is your sf::CircleShape).
However, "global code" is impossible. When should it be executed?


If you want to call a separate piece of code, you can create a function:
#include <SFML/Graphics.hpp>

void setCircleFillColor(sf::CircleShape& circle)
{
    circle.setFillColor(sf::Color(150, 150, 150));
}

int main()
{
    sf::CircleShape shape(200);
    shape.setPosition(sf::Vector2f(5, 5));
    setCircleFillColor(shape);
}
Note that the code is enclosed in a function and that function is called from main.

Another option is to enclose it in a class. Note that the class would need to be instantiated (an objected created of it) and that would be within main (or one of its functions).
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

bobojoeho

  • Newbie
  • *
  • Posts: 11
    • View Profile
Re: Can't change shape's attributes outside of int main()
« Reply #6 on: February 15, 2024, 01:09:33 am »
Ok....

So I did a little more testing and I think I know the problem.  Whenever I create a shape, I can do whatever I want with it as long as I am working in the same function that the shape was created in.

Up till now, I was creating shapes in int main, and trying to change them in other functions, or vice versa.

So you mentioned passing objects back and forth between functions.  If I create an object in int main, but pass it to another function, then I can work with it in that other function?  If so, then I have all the answers I need (until the next bug at least).

Hapax

  • Hero Member
  • *****
  • Posts: 3351
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: Can't change shape's attributes outside of int main()
« Reply #7 on: February 15, 2024, 02:13:28 am »
Yes, using the example I posted in my most recent reply, you can see that you can pass the object to the function, modify it, and then when you return to main, it will be changed.

Note - VERY IMPORTANT - that you must pass by reference* to be able to modify it. If you pass it by value, it will make a copy, modify the copy and then the copy is lost when the function ends.

* if you don't know what this means, it's part of C++ and means that you can act directly upon the actual passed object rather than a copy. That's what the "&" is for next to the parameter type in my example. See https://en.cppreference.com/w/cpp/language/reference for more information of references.
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*