Jump to content
  • Advertisement
Sign in to follow this  
h3ro

Rotating sprites in homemade "2d engine"

This topic is 3802 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

Hallo everyone. Im working on a small project where I am trying to make a simple 2d game using a very limited API. The API only gives you the ability to create a window and return a pointer for all the pixels in the window. Then it is up to me to manipulate that pointer in order to create something useful. So far everything is good, but I am having troubles with getting my sprite rotation to work. The problem is that a screen pixel has a x,y integer value, and the rotated sprite has a x,y float value for all its pixels. Therefor roundoff errors cause some pixels to be on to of each other leaving some blank spaces where I am drawing. Does anyone know of a way to fix this? Here is a picture of the problem [img=http://img257.imageshack.us/img257/7503/spritetroublecf2.jpg] And here is the code
void rotatPixelList(std::vector<pixel> &list, float rotation)
{
	float PI =  3.14159265;

	float r = rotation * PI / 180.0;

	for(int i = 0; i < list.size(); i++)
	{
		float x = list.xPos;
		float y = list.yPos;

		list.xPos = x * cos(r) - y * sin(r);
		list.yPos = y * cos(r) + x * sin(r);
	}
}

void movePixelList(std::vector<pixel> &list, float x, float y)
{
	for(int i = 0; i < list.size(); i++)
	{
		list.xPos += x;
		list.yPos += y;
	}
}

void Visualisation::setPixel(std::vector<pixel> list)
{
	for(int i = 0; i < list.size(); i++)
	{
		int offset = 4 * (((int)list.yPos * screenRec.getWidth()) + (int)list.xPos);

		screenPnt[offset+0] = list.b;
		screenPnt[offset+1] = list.g;
		screenPnt[offset+2] = list.r;
	}
}

Thanks in advance

Share this post


Link to post
Share on other sites
Advertisement
Instead of rotating every pixel, you should rotate the sprites corners and use scanline rendering (http://en.wikipedia.org/wiki/Scanline_rendering) to display it on the screen.

Share this post


Link to post
Share on other sites
Instead of calculating where the pixels of the sprite image are in the screenbuffer, I'd fill the region on the screenbuffer and look up the sprite image to find what colour each pixel should be filled with.

For sprites I'd probably go for 2 triangles with affine texture mapping and possibly bi linear filtering.

Share this post


Link to post
Share on other sites
Thats sounded like a lot of work.

So basically I have to rewrite my "engine" to a scanline render? As it is now I dont have polygons at all and I am writing directly to the screen (I have a rectangle for each sprite, but the sprite is not really inside it, its just to pass position values around)

Thanks for the replies

Share this post


Link to post
Share on other sites
if dont want a scan line renderer, you could always use this approach, although i don't recommend it - scan line rendering would be much better.

rotate corners of sprite, calculate min-max along x and y directions for an axis aligned bounding box. then run through all the pixels in this box, determine whether pixel is inside the actual sprite rotated box or not, and if it is. look up what is the nearest pixel in the sprite image to this point.

Share this post


Link to post
Share on other sites
Quote:
Original post by luca-deltodesco
if dont want a scan line renderer, you could always use this approach, although i don't recommend it - scan line rendering would be much better.

Its for a introduction to games programming class which im not even taking, so I think that would be a bit over my current skill level. I might look into it though, I find rendering quite interesting.

Quote:
Original post by luca-deltodesco
rotate corners of sprite, calculate min-max along x and y directions for an axis aligned bounding box. then run through all the pixels in this box, determine whether pixel is inside the actual sprite rotated box or not, and if it is. look up what is the nearest pixel in the sprite image to this point.

Not sure if I fully understand what do to here.

1. Rotate the sprite using one of the corners (Does it only work using corners?)
2. Create a new boundingBox (The bounding box should not be rotated, but be aligned to the axis)
3. Not sure what do to here

Thanks for you reply :)

Share this post


Link to post
Share on other sites
heres an image to help describe what i mean:
http://www.ngup.net/view?file=527

the black box is your rotated sprite. the red box is the axis aligned bounding box for it calculated from the min-max values of the sprite's corners. the circles are the pixels.

from here, easiest way is that for each pixel, do the opposite rotation to take you into the sprite's coordinate system - this way its very easy to check whether the pixel is within the black sprite box or not, if it is, then you also have the coordinate to use for the texture look-up.

Share this post


Link to post
Share on other sites
Again, thank you.

Just let me see if I have gotten this right:

1. Rotate the texture
2. Create the bounding box
3. For each pixel(screen pixel, right?) inside the bounding box: Rotate back to get to texture space and find the right pixel in the texture.

Share this post


Link to post
Share on other sites
After fooling around for a while I got it working, but the problem is that its dead slow. I currently get 8 fps (140fps with a blank screen) when I try to rotate a texture.

My problem is that I loop trough the data to many times, but im not sure how to make it faster. Assembly is not an alternative for me :P

Here is the current Code


// Create bounding box
// Rotate the bounding box
// Move the bounding box
// Create a axis aligned bounding box
// Transform the bounding box so that one of the vertex are at 0,0

// For each pixel in the aliignedBox go back to the texture and see if there is a pixel there.
// if it is, copy the color of it
for(int y = lowestY; y < higestY; y++)
{
for(int x = lowestX; x < highestX; x++)
{
// Check if the pixel is inside the texture
//---------------------------------------------

// Move the point from screen space to texture space
float newX = x - moveX;
float newY = y - moveY;

// See if the point is inside the texture
Vector3D c = Vector3D(boundingBox[1].x,boundingBox[1].y, 0);
Vector3D p = Vector3D(newX, newY, 0);

Vector3D v = p - c;
Vector3D v1 = Vector3D(boundingBox[0].x,boundingBox[0].y, 0);
Vector3D v2 = Vector3D(boundingBox[3].x,boundingBox[3].y, 0);

if( ( 0 <= Dot(v,v1) && Dot(v,v1) <= Dot(v1,v1) ) &&
( 0 <= Dot(v,v2) && Dot(v,v2) <= Dot(v2,v2) ) )
{
// Find the closest texture pixel
// ----------------------------------

// Rotate the point back, to find the correct pixel
float newXtemp = newX;
float newYtemp = newY;

newX = abs(newXtemp * cos(-r) - newY * sin(-r));
newY = abs(newY * cos(-r) + newXtemp * sin(-r));

// Loop through the pixelList and find the pixel with the same position value
for(int i = 0; i < curSprite.pixelList.size(); i++)
{
if( ((int)newX == (int)curSprite.pixelList.xPos) && ((int)newY == (int)curSprite.pixelList.yPos) )
{
// Copy the colors of the pixel into the screenPointer
int offset = 4 * (((int)y * screenRec.getWidth()) + (int)x);

screenPnt[offset+0] = curSprite.pixelList.b;
screenPnt[offset+1] = curSprite.pixelList.g;
screenPnt[offset+2] = curSprite.pixelList.r;
}
}
}
}
}



Thanks,

Share this post


Link to post
Share on other sites
I think you're doing unnecessary work there.
All you need to do is perform the opposite of the rotation for every pixel in the bounding box, then use that coordinate to get the colour from the texture. You certainly shouldn't have to loop through the texture pixels. Unless they are in a random order, surely you can just use (y * texwidth + x)

I made a fairly decent 2D engine myself, but I quit before I finished rotation. :P

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.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!