So I'm gonna try SFML...

closed account (L6b7X9L8)
Well it's 5:13am and I'm trying to go through the SFML API to learn some of the functions..

Here is my code to make a snowman!

I would like to know if anyone with any experience in SFML could think of a way to make a function for the circles to follow under each other without me trying to have to figure out the offset with trial and error ( Or is this the only way to do it? )

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
  #include <SFML/Graphics.hpp>



int main()
{

	sf::RenderWindow window(sf::VideoMode(800,600), "Snowman :)");

	while(window.isOpen())
	{

		sf::CircleShape shape(50);
		sf::CircleShape shape2(75);
		sf::CircleShape shape3(100);

		// set the shape color to green
		shape.setFillColor(sf::Color(255, 255, 255));
		shape2.setFillColor(sf::Color(255,255,255));
		shape3.setFillColor(sf::Color(255,255,255));

		shape.setPosition(40,0);    // My attempt at positioning the circles
		shape2.setPosition(20,100);
		shape3.setPosition(0,200);

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

		window.clear(sf::Color::Black);
		window.draw(shape);
		window.draw(shape2);
		window.draw(shape3);
		window.display();
	}

	return 0;
}

Less trial and error and more math.

If you know radius in pixels of each circle you should know how far down the next circle should be.

for example, circle A has radius 3 and circle B has radius 5.

if A is at (200,200), B would need to be at (200,208) to be underneath circle A. 5+3=8.

Just think about where you want things to be and try and plan things out before hand.
closed account (L6b7X9L8)
sf::CircleShape shape(50);

The integer seems to be the radius, so I had to double it to get the diameter.

3 shapes with a radius at 30 had to be positioned and 0,60 and 120 respectively to be be under each other.

However when I increase the circle's radius by small increments I have to position the smaller circles X coord slightly more to the right to compensate for this increase, any idea for the maths of that?
closed account (L6b7X9L8)
1
2
3
4
5
6
7
sf::CircleShape shape(30);
sf::CircleShape shape2(45);
sf::CircleShape shape3(60);

shape.setPosition(25,0);
shape2.setPosition(12.5f,60);
shape3.setPosition(0,120);


I think that's as close as I can get it, how does the correlation work between the x and y offsets as the circle gets bigger? My maths isn't too great.
The question is... what is the origin point for this circle?

I would expect the origin to be the center point of the circle -- ie, if you setPosition(100,100), the center point of the circle would be at 100,100. But after a quick experiment, I found out that is not the case.

It turns out the origin of the circle is the upper-left corner of the bounding box for the circle. So setPosition(100,100) puts the upper-left corner of the bounding rect at 100,100. This is a little clunky.

This means if all of your circles have the same X coordinate, they will align to the left, rather than on their center.

Fortunately, you can change this with the setOrigin function. By doing shape.setOrigin(radius,radius); you can move the origin to the center of the circle. After you do this... circles with the same X coord will align on their center.

To stack 2 circles on top of each other with no overlap, you'd need to space them out on the Y axis by the sum of their radii. Or, if you want a little overlap, you could put them a bit closer together.

Here's some changes to your program with all of this employed, and a few other cleanups. All my notes are commented:

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
// convenience function to generate a white circle that is origined on the center
sf::CircleShape createSnowmanCircle(float radius)
{
    sf::CircleShape shape(radius);          // create the circle with the given radius
    shape.setOrigin(radius,radius);         // move the origin point to the center
    shape.setFillColor(sf::Color::White);   // make it white

    return shape;
}

int main()
{
	sf::RenderWindow window(sf::VideoMode(800,600), "Snowman :)");

    // Move the creation of these circles outside the loop.  They do not need to be created
    //  and destroyed each time the loop runs -- that is inefficient.
    //  Just create them once and keep them alive for the duration of the program
    //
    // Also... I changed this to an array.  Any time you find yourself naming things
    //  foo1, foo2, foo3, etc... you're probably doing it wrong.  Reconsider.
    sf::CircleShape snowman[3] = {
        createSnowmanCircle(50),
        createSnowmanCircle(75),
        createSnowmanCircle(100)
    };

    // Put the head at 200,100
    snowman[0].setPosition(200,100);

    // Build the upper and lower body in relation to the head:
    for(int i = 1; i < 3; ++i)
    {
        sf::Vector2f pos = snowman[i-1].getPosition();      // get the previous portion's position
        pos.y += snowman[i-1].getRadius();                  // offset Y coord by previous portion's radius
        pos.y += snowman[i  ].getRadius();                  // and this portion's radius
        pos.y -= 20;                                        // subtract a bit so the portions overlap a bit

        snowman[i].setPosition(pos);
    }

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

        window.clear(sf::Color::Black);
        for(auto& i : snowman)      // draw all portions of the snowman in a loop
            window.draw(i);
        window.display();
    }
	return 0;
}
closed account (L6b7X9L8)
Wow this is excellent!

Thanks Disch. I'm just getting used to SFML over these past couple of hours but my girlfriend is upset about something and won't tell me so she's stalling my progress (Women...).

I was also going to try and think of a while loop to get this thing moving about the screen? I'm unsure of this library for animation so any pointers will be helpful.

Cheers buddy.
closed account (L6b7X9L8)
Uhh...

Using your code I have this error:

1>------ Build started: Project: SMFL, Configuration: Debug Win32 ------
1> main.cpp
1>d:\documents and settings\i-gunner-i\my documents\visual studio 2010\projects\smfl\main.cpp(55): error C2143: syntax error : missing ',' before ':'
1>d:\documents and settings\i-gunner-i\my documents\visual studio 2010\projects\smfl\main.cpp(55): error C2530: 'i' : references must be initialized
1>d:\documents and settings\i-gunner-i\my documents\visual studio 2010\projects\smfl\main.cpp(55): error C3531: 'i': a symbol whose type contains 'auto' must have an initializer
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
It's a range based for loop from C++11 that isn't supported in VS until 2012 and later.

You can update VS to use it... or replace it with the same C++03 for loop:

1
2
3
4
5
6
7
8
// change this:
        for(auto& i : snowman)
            window.draw(i);


// to this:
        for(int i = 0; i < 3; ++i)
            window.draw(snowman[i]);
closed account (L6b7X9L8)
I'll go for the usual for loop I am used to, thanks man your a legend.

Works great though, I'm not sure if it's my eyes because I am tired, but it looks to me like the snowman slightly leans to the right?
Looks fine to me. Might be tired eyes.

EDIT: just took a screenshot in paint and measured the pixels. The circles are aligned dead center.
Last edited on
closed account (L6b7X9L8)
I guess that's my queue to get some sleep. I appreciate the help, this stuff is pretty confusing. I'll probably be spamming the forums tomorrow with more SFML help, I sure hope you are around.
Topic archived. No new replies allowed.