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

Author Topic: setPosition() for private sprites  (Read 5817 times)

0 Members and 1 Guest are viewing this topic.

Raincode

  • Full Member
  • ***
  • Posts: 118
    • View Profile
setPosition() for private sprites
« on: November 24, 2013, 06:29:43 pm »
Hey everyone,

can someone please show me how to move two sprites which are private members of a class through a member function? The relation between the position of these two should stay the same. By that I mean, if I have two vertical lines perfectly aligned, after the function call they still should be aligned.

so basically:

class foo
public:
    foo();

    void setPosition( double x, double y );

private:
    sf::Sprite a;
    sf::Sprite b;
 


Kind Regards,
Raincode

zsbzsb

  • Hero Member
  • *****
  • Posts: 1409
  • Active Maintainer of CSFML/SFML.NET
    • View Profile
    • My little corner...
    • Email
Re: setPosition() for private sprites
« Reply #1 on: November 24, 2013, 06:36:19 pm »
Ummm

void foo::setPosition( double x, double y )
{
    a.setPosition(x, y);
    b.setPosition(x, y); // maybe add offset for the vertical align?
}

???
Motion / MotionNET - Complete video / audio playback for SFML / SFML.NET

NetEXT - An SFML.NET Extension Library based on Thor

Raincode

  • Full Member
  • ***
  • Posts: 118
    • View Profile
Re: setPosition() for private sprites
« Reply #2 on: November 24, 2013, 06:43:15 pm »
Hi, thanks for your reply,

alright, so I didn't have a mistake thinking, but maybe I should add, that one of the sprites always disappears after the operation. I have a "Mana Bar" with one background sprite and one sprite representing the actual "filling", which changes. This "filling" is the part, which becomes invisible if you will.

This is really, really frustrating me, because I've tried solving this and it simply doesn't work. It's like being stuck behind a huge wall and not being able to reach what you want so much on the other side

I update and render them like so:

void Bar::update()
{
    sf::FloatRect gBounds = filling.getGlobalBounds();

    filling.setTextureRect( sf::IntRect(
                                gBounds.left, gBounds.top, step * current, gBounds.height ) );
}

void Bar::render( sf::RenderWindow& window )
{
    window.draw( container );
    window.draw( filling );
}
 

Any additional information needed?

greetz
Raincode

EDIT//: To clarify a little:
class Bar
{
public:
    Bar( sf::Texture const& container, sf::Texture const& filling, int max );

    void update();
    void render( sf::RenderWindow& window );

    void setPosition( double x, double y );

private:
    sf::Sprite container;
    sf::Sprite filling;
    int max;
    int current;
    double step;
};

void Bar::setPosition( double x, double y )
{
    container.setPosition( x, y );
    filling.setPosition( x, y );
}
 
http://img855.imageshack.us/img855/7606/yid2.png
« Last Edit: November 24, 2013, 08:37:30 pm by Raincode »

Raincode

  • Full Member
  • ***
  • Posts: 118
    • View Profile
Re: setPosition() for private sprites
« Reply #3 on: November 25, 2013, 08:30:00 pm »
So, unfortunately I don't seem to get any more answers. Is it because no one takes my problem seriously or because they simply don't have any answers? Or does my thread come off as a troll, because it seems rather obscure?

G.

  • Hero Member
  • *****
  • Posts: 1592
    • View Profile
Re: setPosition() for private sprites
« Reply #4 on: November 25, 2013, 08:46:41 pm »
You have two sprites which are not at the same position. Thus, there is an offset distance between them.
I don't see in your code where you define this distance (probably in the constructor), but the way you position your 2 sprites in the constructor is probably the same you want to do in your setPosition function. (which is what zsbzsb suggested)

Here's a snippet of code which set 2 sprites to a position, while keeping them at the same distance of each other. Note that if you already know the offset, you don't have to compute it.
void setPosition(sf::Vector2f position) {
   sf::Vector2f offset = sprite2.getPosition() - sprite1.getPosition();
   sprite1.setPosition(position);
   sprite2.setPosition(position + offset);
}

zsbzsb

  • Hero Member
  • *****
  • Posts: 1409
  • Active Maintainer of CSFML/SFML.NET
    • View Profile
    • My little corner...
    • Email
Re: setPosition() for private sprites
« Reply #5 on: November 25, 2013, 08:47:25 pm »
So, unfortunately I don't seem to get any more answers. Is it because no one takes my problem seriously or because they simply don't have any answers? Or does my thread come off as a troll, because it seems rather obscure?

The question is a bit obscure, so maybe we don't have time to sit down and figure out exactly what you want (doesn't mean we won't), so learn to have some patience  ;)

To be clear, you want your setPosition to move the bar around the screen?

If that is the case then you should note the comment I in the code of my first post here. When you call setPosition on the sprites just add whatever values it takes to keep them in relative position to themselves.

If you don't understand what I mean you should show us the sprite's original positions before you move them.
Motion / MotionNET - Complete video / audio playback for SFML / SFML.NET

NetEXT - An SFML.NET Extension Library based on Thor

Raincode

  • Full Member
  • ***
  • Posts: 118
    • View Profile
Re: setPosition() for private sprites
« Reply #6 on: November 26, 2013, 07:53:33 pm »
Hi,

thanks again for your answers guys, awesome! We just seem to be misunderstanding each other slightly.

And yes, I simply want to use the setPosition() to move both sprites at once to some given position.

To see the original Position (0,0) and the Position after movement, check out the imagelink at the end of my second post.

So about the offset, this maybe was irrelevant, i keep the offset by having the sprites perfectly overlap, if their top left corners are the same. So to clarify: If I move both sprites the same distance, they are automatically aligned. Problem is: the "filling" sprite, simply disappears. (Is it gone or just not in the screenbounds, I don't know, I'll check that in a minute). If I just leave everything in the top left corner of the screen (the default) everything is fine.

Here's what I said before as a picture (The differen sprites):
http://img5.imageshack.us/img5/7106/gpmx.png

So again: After the moving operation, the top "filling" Sprite is not visible any more (see link at end of my second post). I hope we can find the silly cause of my "problem"! :)

Edit: I tried to find out whether the disappeared sprite was just off screen. What I did was give it a certain velocity (various directions) and check if it moves across the screen sometime. I waited for about 30 seconds each and I didn't see anything...

Kind Regards,

Raincode

« Last Edit: November 26, 2013, 08:01:02 pm by Raincode »

zsbzsb

  • Hero Member
  • *****
  • Posts: 1409
  • Active Maintainer of CSFML/SFML.NET
    • View Profile
    • My little corner...
    • Email
Re: setPosition() for private sprites
« Reply #7 on: November 26, 2013, 10:25:19 pm »
Could you show a complete code example that causes the issue? Including your Bar class in its entirety?
Motion / MotionNET - Complete video / audio playback for SFML / SFML.NET

NetEXT - An SFML.NET Extension Library based on Thor

Raincode

  • Full Member
  • ***
  • Posts: 118
    • View Profile
Re: setPosition() for private sprites
« Reply #8 on: November 27, 2013, 02:54:20 pm »
I've already gotton rid of the original code, but I tried to reprocude my error. Now the "filling" sprite doesn't disappear, but it looks different/changes it's looks when you do the moving operation. It also seems to change in size. Man this is just so confusing :S

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

class Bar
{
public:
    Bar( sf::Texture const& container, sf::Texture const& filling, int max );

    void render( sf::RenderWindow& window );
    void update();
    void setPosition( double x, double y );

private:
    sf::Sprite container;
    sf::Sprite filling;
    int max;
    int current;
    double step;
};

Bar::Bar( sf::Texture const& cont, sf::Texture const& fill, int m )
    :max{m}
{
    container.setTexture( cont );
    filling.setTexture( fill );
    current = max;
    step = filling.getGlobalBounds().width / max;
}

void Bar::render( sf::RenderWindow& window )
{
    window.draw( container );
    window.draw( filling );
}

void Bar::update()
{
    sf::FloatRect bounds = filling.getGlobalBounds();

    filling.setTextureRect( sf::IntRect(
                                bounds.left, bounds.top, step * current, bounds.height ) );
}

void Bar::setPosition( double x, double y )
{
    container.setPosition( x, y );
    filling.setPosition( x, y );
}

int main()
{
    sf::RenderWindow window( sf::VideoMode( 640, 480 ), "Error reproduction" );

    sf::Texture container_tex;
    if( !container_tex.loadFromFile("assets/images/ManaBarContainer.png") )
        std::cerr << "Error: Could not load \"ManaBarContainer.png\"\n";

    sf::Texture filling_tex;
    if( !filling_tex.loadFromFile("assets/images/ManaBar.png") )
        std::cerr << "Error: Could not load \"ManaBar.png\"\n";

    Bar test_bar( container_tex, filling_tex, 100 );
    //test_bar.setPosition( 300, 0 );

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

        test_bar.update();

        window.clear();
        test_bar.render( window );
        window.display();
    }
}
 

Here are the two images:

http://img822.imageshack.us/img822/7714/dcp9.png
http://img19.imageshack.us/img19/303/g8l8.png

Rhimlock

  • Jr. Member
  • **
  • Posts: 73
    • View Profile
Re: setPosition() for private sprites
« Reply #9 on: November 27, 2013, 03:11:56 pm »
I guess your update-function is at fault:
void Bar::update()
{
    sf::FloatRect bounds = filling.getGlobalBounds();

    filling.setTextureRect( sf::IntRect(
                                bounds.left, bounds.top, step * current, bounds.height ) );
}

You update the TextureRect, but not the size of the Sprite. (So the sprite stays the same size and the texture gets stretched=

Depending on the direction you want to reduce the filling, you will have to resize the size of the sprite too.

Thats wrong, sorry. Just use getTextureRect instead of getGlobalBounds.
« Last Edit: November 28, 2013, 11:17:48 am by Ghosa »

Raincode

  • Full Member
  • ***
  • Posts: 118
    • View Profile
Re: setPosition() for private sprites
« Reply #10 on: November 27, 2013, 04:08:08 pm »
Hi,

thanks for your reply. Which function would I use in order to set a sprites size? I can't seem to figure it out.
I always thought that the texture rect was in some sort the size of the sprite, and also the "view" which the sprite has of its texture.

Kind Regards,
Raincode

Rhimlock

  • Jr. Member
  • **
  • Posts: 73
    • View Profile
Re: setPosition() for private sprites
« Reply #11 on: November 28, 2013, 11:17:08 am »
Whoops, my bad, you don't have to set the size of the sprite in that case.

But that function is still at fault.

You get get global bounds of the sprite (so the coordinates where it is drawn),
but use those bounds to set the TextureRect.

You should use getTextureRect instead of getGlobalBounds.

Raincode

  • Full Member
  • ***
  • Posts: 118
    • View Profile
Re: setPosition() for private sprites
« Reply #12 on: November 28, 2013, 08:47:36 pm »
Aaah now it is drawn correctly after movement. Thanks! I don't know about the disappearing, because I was dumb enough to delete the code. If I ever have such a problem again, I'll make the minimal example directly!

I was just thinking, it probally wasn't so good giving Floats as arguments to an IntRect either...

Anyway, I'm glad this has helped!

Kind Regards,
Raincode