Advertisement

[SDL,Box2D] drawing a sprite with rotation

Started by October 24, 2011 09:59 AM
0 comments, last by Petris Rodrigo Fernandes 12 years, 7 months ago
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);
}
}
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.

This topic is closed to new replies.

Advertisement