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

Author Topic: Anchor a pixel to a sprite?  (Read 2833 times)

0 Members and 1 Guest are viewing this topic.

bucknasty189

  • Newbie
  • *
  • Posts: 23
    • View Profile
Anchor a pixel to a sprite?
« on: June 11, 2011, 01:15:19 am »
I have a sprite that shoots a bullet. However, the bullet currently starts in the middle of the sprite.I want bullet to shoot from the barrel of the gun. Is there a way I can anchor a vector to a pixel on the sprite so that it remains there after rotating?

This is what I've tried so far, but it just doesn't work right. I feel like I'm overlooking something simple.

Code: [Select]

sf::Vector2f Collision::RotatePoint(const sf::Vector2f& Point, float Angle) {
Angle = Angle * RADIANS_PER_DEGREE;
sf::Vector2f RotatedPoint;
RotatedPoint.x = Point.x * cos(Angle) + Point.y * sin(Angle);
RotatedPoint.y = -Point.x * sin(Angle) + Point.y * cos(Angle);
return RotatedPoint;
}

void PlayerEntity::SetBarrel(sf::Vector2f relPosition)
{
m_Barrel = this->GetPosition() + relPosition;
}


//This code is inside my update for the PlayerEntity which derives from sf::Sprite

// Rotate the sprite towards the mouse
float theta = ((-1* 360 / PI_f * ( atan2((PlayerPos.y - gameTemp->m_Mouse.y),(PlayerPos.x - gameTemp->m_Mouse.x)) ) ) / 2) + 90;
this->SetRotation(theta);

SetBarrel(21.f, 0.f);
Collision::RotatePoint(m_Barrel, theta);

if (inputUser.IsMouseButtonDown(sf::Mouse::Left))
{
m_curWeapon->Shoot(gameTemp, &m_Barrel);
}


The shoot function starts the bullet at the given vector and goes towards where the mouse was at click.
Knowledge Speaks,
Wisdom Listens
                       -JH

WitchD0ctor

  • Full Member
  • ***
  • Posts: 100
    • View Profile
    • http://www.teleforce-blogspot.com
Anchor a pixel to a sprite?
« Reply #1 on: June 11, 2011, 11:57:17 am »
2 things, your rotatePoint functions is wrong, and your not even setting its return to a variable, so its being called, but not doing anything.

try
Code: [Select]

scaler = 2
RotatedPoint.x = Point.x + (cos(Angle) * scaler;
RotatedPoint.y = Point.y + (-sin(Angle)* scaler;

//and then later in the update function
m_Barrel = Collison.RotatePoint(m_Barrel, theta);



This may take some adjusting, scaler is how far from the origin of the sprite, the barrel end is, you'll have to adjust this yourself for what works in your game, the rest SHOULD work, but its kinda late and i might not be thinking straight, let me know what your results are
John Carmack can Divide by zer0.

bucknasty189

  • Newbie
  • *
  • Posts: 23
    • View Profile
Anchor a pixel to a sprite?
« Reply #2 on: June 14, 2011, 06:56:43 am »
Quote
your not even setting its return to a variable

Wow, I can't believe I didn't notice that.  :oops:
However, it's still not working...
Code: [Select]

void PlayerEntity::SetBarrel(sf::Vector2f relPosition)
{
m_Barrel = relPosition;
}

sf::Vector2f PlayerEntity::UpdateBarrel(float theta)
{
sf::Vector2f point = this->GetPosition() + m_Barrel;
sf::Vector2f RotatedPoint;
int scaler = 2;
RotatedPoint.x = point.x + (cos(theta) * scaler);
RotatedPoint.y = point.y + (-sin(theta)* scaler);
return RotatedPoint;
}

//In the update()

sf::Vector2f Barrel = UpdateBarrel(theta);
m_curWeapon->Shoot(gameTemp, &Barrel);
Knowledge Speaks,
Wisdom Listens
                       -JH

section_two

  • Newbie
  • *
  • Posts: 19
    • View Profile
Anchor a pixel to a sprite?
« Reply #3 on: June 25, 2011, 05:39:17 am »
Hi, Im not programming right now, but i think.

I dont know if rotate works like this, im just mind-programming
When you rotate a sprite, you read each pixel in the sprite, like if it was not rotated i think. So, if you know the coords (x,y) in the sprite, where you want the bullet get out, after rotated, the coord(x,y) is the same. But when you convert this point to windowCoord, it will give you the correct (x,y).

I dont know if rotate works like that.


Sorry.....my English :(

Tell me/us if you solve this in any way.

Bye.

OniLinkPlus

  • Hero Member
  • *****
  • Posts: 500
    • View Profile
Anchor a pixel to a sprite?
« Reply #4 on: June 25, 2011, 06:05:10 am »
Quote from: "WitchD0ctor"
2 things, your rotatePoint functions is wrong, and your not even setting its return to a variable, so its being called, but not doing anything.

try
Code: [Select]

scaler = 2
RotatedPoint.x = Point.x + (cos(Angle) * scaler;
RotatedPoint.y = Point.y + (-sin(Angle)* scaler;

//and then later in the update function
m_Barrel = Collison.RotatePoint(m_Barrel, theta);



This may take some adjusting, scaler is how far from the origin of the sprite, the barrel end is, you'll have to adjust this yourself for what works in your game, the rest SHOULD work, but its kinda late and i might not be thinking straight, let me know what your results are
How much math do you know? Because his rotation code was... almost correct. It's
x'=cos(angle)*x-sin(angle)*y
y'=cos(angle)*y+sin(angle)*x
where x' and y' are the new x and y values. He just had a couple of signs off.
EDIT: Actually, his was correct considering SFML flips the y axis.
I use the latest build of SFML2

section_two

  • Newbie
  • *
  • Posts: 19
    • View Profile
Anchor a pixel to a sprite?
« Reply #5 on: June 26, 2011, 05:26:55 am »
Hi, i dont know if I had understood the question.

This way, you can know where is a pixel in a sprite, even if it is rotated.
I draw a Sprite, and a Circle Shape. The center of the circle follow the pixel assigned in barrelPos(vector2f).

Not my Sprite


Code: [Select]
#include <SFML/Graphics.hpp>
#include <iostream>

int main()
{
    sf::RenderWindow App(sf::VideoMode(800,600, 32), "SFML Graphics");

    sf::Image image;
    image.LoadFromFile("player.png");
    image.SetSmooth(false);

    sf::Sprite sprite;
    sprite.SetImage(image);
    sprite.SetPosition(400,300);

    sf::Vector2f barrelPos;
    sf::Vector2f GlobalBarrelPos;

    barrelPos.x=30; //The pixel(x,y) in the sprite you want to follow
    barrelPos.y=15;

    sf::Shape Circle = sf::Shape::Circle(0,0, 6, sf::Color(255, 0, 0),1,sf::Color(255, 0, 0));
    Circle.EnableFill(false);

    App.UseVerticalSync(true);
    App.SetFramerateLimit(60);

    while (App.IsOpened())
    {
        sf::Event Event;
        while (App.GetEvent(Event))
        {
            if (Event.Type == sf::Event::Closed)
                App.Close();
            if ((Event.Type == sf::Event::KeyPressed) && (Event.Key.Code == sf::Key::Escape))
                App.Close();
        }

        sprite.Rotate(2);
        sprite.Move(-1,0.5);

        GlobalBarrelPos=sprite.TransformToGlobal(barrelPos);
        Circle.SetPosition(GlobalBarrelPos.x,GlobalBarrelPos.y);
        std::cout << "(" << GlobalBarrelPos.x << "," << GlobalBarrelPos.y << ")" << std::endl;

        App.Clear(sf::Color(255,255,255));
        App.Draw(sprite);
        App.Draw(Circle);

        App.Display();
    }

    return EXIT_SUCCESS;
}