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

Author Topic: Rotation going nuts  (Read 2618 times)

0 Members and 1 Guest are viewing this topic.

Dincio

  • Newbie
  • *
  • Posts: 13
    • View Profile
Rotation going nuts
« on: July 07, 2017, 09:09:42 pm »
Hello again.

I'm trying to make a simple Entity system for a 2D bullet hell game. Each frame, I calculate the velocity and position of each entity and render it on the screen using a temporary sf::RectangleShape. All was going well untill I attempted to make an entity rotate. The first thing that came to mind was to pass the temporary
sf::RectangleShape to the draw function of the current render target (I'm refering to the parameter of the sf::Drawable::draw method, inherited by Entity) along with the transform of the entity (which of course also inherits from sf::Transformable) through the render states, and it all worked as expected... until I tyed to rotate an entity while it was moving. This made the entity suddenly change position by a drastic offset (often going offscreen) without any apparent reason. Initially, I thought that this had to do with the origin of the entity, but even by moving the origin every frame along with the position, the problem persisted.

Here is the draw function:
void Entity::draw(sf::RenderTarget& target, sf::RenderStates states) const {
    sf::RectangleShape rectangle(mHitBox);
    rectangle.setTexture(mTexture);

    states.transform = getTransform();
    target.draw(rectangle, states);
}

And here is the function where movement takes place:
void MovingEntity::handleLogic(sf::RenderWindow& window, const sf::Time& timeElapsed) {
    //accelerate entity
    mVelocity += mAcceleration * timeElapsed.asSeconds();

    //simulate next position
    auto displacement = mVelocity * timeElapsed.asSeconds();
    auto futurePos = getPosition() + displacement;

    //check border collisions
    auto borders = sf::Vector2f(window.getSize()) - mHitBox;
    if(futurePos.x < 0 || futurePos.x > borders.x) {
        mVelocity.x = 0;
        mAcceleration.x = 0;
        if(futurePos.x < 0)
            futurePos.x = 0;
        else if(futurePos.x > borders.x)
            futurePos.x = borders.x;
    }
    if(futurePos.y < 0 || futurePos.y > borders.y) {
        mVelocity.y = 0;
        mAcceleration.y = 0;
        if(futurePos.y < 0)
            futurePos.y = 0;
        else if(futurePos.y > borders.y)
            futurePos.y = borders.y;
    }

    //move entity
    move(displacement);
}

And here's where I do the rotation:
void Ferri::vHandleLogic(sf::RenderWindow& window, const sf::Time& timeElapsed) {
    //move Ferri
    if(sf::Keyboard::isKeyPressed(sf::Keyboard::W)) {
        mAcceleration.x = 0;
        mAcceleration.y = -1;
    }
    else if(sf::Keyboard::isKeyPressed(sf::Keyboard::D)) {
        mAcceleration.x = 1;
        mAcceleration.y = 0;
    }
    else if(sf::Keyboard::isKeyPressed(sf::Keyboard::S)) {
        mAcceleration.x = 0;
        mAcceleration.y = 1;
    }
    else if(sf::Keyboard::isKeyPressed(sf::Keyboard::A)) {
        mAcceleration.x = -1;
        mAcceleration.y = 0;
    }
    else if(sf::Keyboard::isKeyPressed(sf::Keyboard::R)) {
        rotate(1);
    }
    else {
        mAcceleration.x = 0;
        mAcceleration.y = 0;
    }
    mAcceleration *= mAccelerationIntensity;

    //don't get over the limit velocity
    float speed = std::sqrt(std::pow(mVelocity.x, 2) + std::pow(mVelocity.y, 2));
    if(speed >= mMaxSpeed) {
        mVelocity.x = mVelocity.x / speed * mMaxSpeed;
        mVelocity.y = mVelocity.y / speed * mMaxSpeed;
    }
}

That's all. I really hope I'm not missing a stupid bug or something...

Arcade

  • Full Member
  • ***
  • Posts: 230
    • View Profile
Re: Rotation going nuts
« Reply #1 on: July 07, 2017, 10:05:24 pm »
Can you show us the code where you were setting the origin of the entity?

Dincio

  • Newbie
  • *
  • Posts: 13
    • View Profile
Re: Rotation going nuts
« Reply #2 on: July 07, 2017, 11:24:48 pm »
Yes of course, here:

Ferri(float maxSpeed, float accelerationIntensity):
   MovingEntity(gTextureProvider.getMedia("ferri")),
   mMaxSpeed(maxSpeed),
   mAccelerationIntensity(accelerationIntensity) {
   setOrigin(mHitBox.x / 2.f + getPosition().x, mHitBox.y / 2.f + getPosition().y);
}

Dincio

  • Newbie
  • *
  • Posts: 13
    • View Profile
Re: Rotation going nuts
« Reply #3 on: July 07, 2017, 11:26:04 pm »
mHitBox is a vector containing the size the texture used by the entity (it is what happens by default om the MovingEntity constructor).
« Last Edit: July 07, 2017, 11:28:00 pm by Dincio »

Martin Sand

  • Newbie
  • *
  • Posts: 24
    • View Profile
    • Email
Re: Rotation going nuts
« Reply #4 on: July 07, 2017, 11:45:02 pm »
Quote
setOrigin(mHitBox.x / 2.f + getPosition().x, mHitBox.y / 2.f + getPosition().y);
Why do you add the position to the origin?

Arcade

  • Full Member
  • ***
  • Posts: 230
    • View Profile
Re: Rotation going nuts
« Reply #5 on: July 08, 2017, 12:03:09 am »
As Martin Sand pointed out, it looks like you are trying to treat the origin as an absolute global position, but it should instead be treated as a local position relative to your entity. From the SFML documentation:
Quote
The coordinates of this point must be relative to the top-left corner of the object, and ignore all transformations

Dincio

  • Newbie
  • *
  • Posts: 13
    • View Profile
Re: Rotation going nuts
« Reply #6 on: July 08, 2017, 12:27:52 am »
Oh yes sorry I haven't noticed that... Still, it would have become a problem later, since I only positioned one entity at position (0, 0) for testing purposes, and so the position did not interfere with the origin. So the problem persists... for some reason it only comes up when I rotate and translate at the same time... maybe that has something to do with it.