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

Author Topic: [Solved] Position a sprite relative to another  (Read 7585 times)

0 Members and 1 Guest are viewing this topic.

Guido_Ion

  • Newbie
  • *
  • Posts: 42
    • View Profile
    • Flow Soccer development
[Solved] Position a sprite relative to another
« on: October 21, 2021, 10:03:22 pm »
Hi, I'm trying to position a sprite relative to another. I have 2 sprites, one for the character and one for the head. The view is top down, when he is standing the head and character are aligned but when I do a slide the head remains in the center, I need to position the head in the correct place applying and offset form the center. How can I achieve this? I leave a beautiful image discribing the problem  ;)

I have this code but the translation isn't working, I can't see the head (it might be outside the screen)
Code: [Select]
void FieldPlayer::draw()
{
m_sprite.setPosition(Game::SCALE * m_body->GetPosition().x, Game::SCALE * m_body->GetPosition().y);
m_sprite.setRotation(Game::RadiansToDegrees(m_body->GetAngle()));
Game::GetWindow()->draw(m_sprite);

head_sprite.setPosition(Game::SCALE * m_body->GetPosition().x, Game::SCALE * m_body->GetPosition().y);
head_sprite.setRotation(Game::RadiansToDegrees(m_body->GetAngle()));
// move the head back if sliding
if (PlayerState.sliding) {
sf::Transform t = head_sprite.getTransform();
t.translate(-52.f, -10.f); ???
Game::GetWindow()->draw(head_sprite, t);
}
else {
Game::GetWindow()->draw(head_sprite);
}
}

Note: I need the code to consider rotations also
« Last Edit: October 25, 2021, 08:12:02 pm by Guido Bisocoli »

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11027
    • View Profile
    • development blog
    • Email
Re: Position a sprite relative to another
« Reply #1 on: October 22, 2021, 08:29:23 am »
So are the values set for the transform not being applied at all or are the values just wrong?
You probably should also multiple the translation by the game scale.

Also you can make use of the factor overload for vectors, which would require SCALE to be of type float, but then you can just write m_sprite.setPosition(Game::SCALE * m_body->GetPosition());
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Guido_Ion

  • Newbie
  • *
  • Posts: 42
    • View Profile
    • Flow Soccer development
Re: Position a sprite relative to another
« Reply #2 on: October 22, 2021, 06:49:08 pm »
The values are aproximatelly, I've tested several values, later when it works I'll put the correct values.
I've made some progress with this code:

Code: [Select]
void FieldPlayer::draw()
{
m_sprite.setPosition(Game::SCALE * m_body->GetPosition().x, Game::SCALE * m_body->GetPosition().y);
m_sprite.setRotation(Game::RadiansToDegrees(m_body->GetAngle()));
Game::GetWindow()->draw(m_sprite);

sf::Vector2f offset(0.f, 0.f);
if (PlayerState.sliding) offset = sf::Vector2f(-1.4f, -0.8f);

head_sprite.setPosition(Game::SCALE * (m_body->GetPosition().x + offset.x), Game::SCALE * (m_body->GetPosition().y + offset.y));
head_sprite.setRotation(Game::RadiansToDegrees(m_body->GetAngle()));
Game::GetWindow()->draw(head_sprite);
}

The head moves but in world coordinates, I have to take into consideration rotation yet, I can't figure out how.
GIF: [https://gfycat.com/recklesssoupycollardlizard]

And about the vector overload, it won't let me do this  ???:
Code: [Select]
m_sprite.setPosition(Game::SCALE * m_body->GetPosition());

Guido_Ion

  • Newbie
  • *
  • Posts: 42
    • View Profile
    • Flow Soccer development
Re: Position a sprite relative to another
« Reply #3 on: October 25, 2021, 08:11:46 pm »
Solved with heading and side vectors using Box2D

Code: [Select]
void FieldPlayer::draw()
{
sf::Vector2f spritePos = sf::Vector2f(Game::SCALE * m_body->GetPosition().x, Game::SCALE * m_body->GetPosition().y);
float degreesOfRotation = Game::RadiansToDegrees(m_body->GetAngle());

m_sprite.setPosition(spritePos);
m_sprite.setRotation(degreesOfRotation);
Game::GetWindow()->draw(m_sprite);

if (PlayerState.sliding) {
// 80cm to the back of the player (local y axis)
b2Vec2 headPosSliding = m_body->GetPosition() - (0.8 * getHeading());
// 24cm to the left of the player (local x axis)
headPosSliding -= 0.24f * getSide(false);
spritePos = Game::BoxVecToSfVec(headPosSliding);
// slightly to the right of the body
degreesOfRotation += 30.f;
}

head_sprite.setPosition(spritePos);
head_sprite.setRotation(degreesOfRotation);
Game::GetWindow()->draw(head_sprite);
}

 :D