Jump to content
  • Advertisement
Sign in to follow this  
sheep19

[SDL,Box2D] drawing a sprite with rotation

This topic is 2352 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello. I am new to box2d and I am trying some things to find how things work.

I managed to create some polygon (triangles, rectangles, circles) and draw them on the screen using SDL_GFX add-on to SDL library. This was easy because I only needed to pass the vertices of the shapes to sdl_gfx and it drew them.

Now I want to draw an image on top of a rectangle (a crate image). However the problem here is that the function that draws the rotated image, takes a double that indicates the rotation of the shape, but the angle is for the TOP LEFT point. If I do body->GetAngle() it works when the image is not rotated by is messed up when it rotates.

How can I calculate the position where it should be(topLeft)?

Here are some images to show what's going on:
2zz01vc.jpg

As you can see the red rectangle is exactly around the crate image (actually it is on top, the rectangle is draw after the image, which is the way it should be).

70xr9l.jpg

In this one the image is not where it should be. It rotates correctly, but its position is wrong.
Sometimes it goes all out of the rectangle!

Here's my code:
void Crate::Draw(SDL_Surface *targetSurface)
{
// get the shape attached to the body, which is always a polygon (just one)
b2PolygonShape *shape = static_cast<b2PolygonShape*>(body->GetFixtureList()[0].GetShape());

// top left point of the rectangle
b2Vec2 topLeft = body->GetWorldPoint(shape->GetVertex(3));

// convert meters to screen coordinates
SDL_Point p = toScreenCoords(topLeft.x, topLeft.y, targetSurface->w/2, targetSurface->h-1, METERS_TO_PIXELS);
sprRect.x = p.x;
sprRect.y = p.y;

// calculate width, height (used to scale the image because texture might be bigger/smaller)
float width = abs(shape->GetVertex(0).x - shape->GetVertex(1).x),
height = abs(shape->GetVertex(0).y - shape->GetVertex(2).y);

// zoom/rotate the surface
SDL_Surface *s = zoomSurface(spr, width * METERS_TO_PIXELS / spr->w, height * METERS_TO_PIXELS / spr->h, 0);
SDL_Surface *s2 = rotozoomSurface(s, body->GetAngle() * 180 / 3.14156, 1.0, 0); // function takes degrees

// draw
SDL_BlitSurface(s2, NULL, targetSurface, &sprRect);
SDL_FreeSurface(s);
SDL_FreeSurface(s2);

// draw the polygon to see if the texture and the polygon are exactly at the same position
{
b2Fixture *l = body->GetFixtureList();
b2PolygonShape *s = (b2PolygonShape*)l[0].GetShape();
SDL_Point p2;

Sint16 xPos[4], yPos[4];
for(Uint8 i = 0; i < 4; ++i)
{
p2 = toScreenCoords(body->GetWorldPoint(s->GetVertex(i)).x, body->GetWorldPoint(s->GetVertex(i)).y, targetSurface->w/2, targetSurface->h-1, METERS_TO_PIXELS);
xPos = p2.x;
yPos = p2.y;
}

polygonRGBA(targetSurface, xPos, yPos, s->GetVertexCount(), 255, 0, 0, 255);
}
}

Share this post


Link to post
Share on other sites
Advertisement
First: Sorry my english (isn't my native language).

When you use the function rotozoomSurface, you must have a central point to draw your image. Why?

Get a square of dimensions 40x40.

When you rotate this square 45 degrees, you will notice the height and the width are bigger than the original dimensions (40x40)

To draw it on the right position on the screen, you must define a point to be the center of the image. So when you call the function, you will pass these coordinates

x = imageCenterX - (imagewidth/2);
y = imageCenterY - (imageHeight/2);

I think this can help you.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!