Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you rotate a sprite around its center by calculating a new x and y position?

Tags:

c++

I'm using Dark GDK and C++ to create a simple 2d game. I'm rotating an object but it rotates from the top left corner of the sprite.

I have the following variables available:

  • PlayerX
  • PlayerY
  • PlayerWidth
  • PlayerHeight
  • RotateAngle (360 > x > 0)

Is there an algorithm that will modify the pivot point of the sprite, preferable to the center?

Here is a small code sample:

void Player::Move( void )
{

    if ( checkLeft() )
    {
        PlayerX -= PlayerSpeed;
        if ( PlayerX < 0 )
            PlayerX = 0;
    }

    if ( checkRight() )
    {
        PlayerX += PlayerSpeed ;
        if ( PlayerX > 800 - PlayerWidth )
            PlayerX = 800 - PlayerWidth;
    }

    if ( checkUp())
    {
        PlayerY -= PlayerSpeed;
        if ( PlayerY < 0 )
            PlayerY = 0;
    }

    if ( checkDown())
    {
        PlayerY += PlayerSpeed;
        if ( PlayerY > 600 -  PlayerHeight)
            PlayerY = 600 - PlayerHeight;
    }

    RotateAngle += 5;
    if(RotateAngle > 360)
        RotateAngle -=360;

    dbRotateSprite(Handle,RotateAngle);
    dbSprite ( 1 , PlayerX , PlayerY , Handle );
}

Edit

I'm considering opening up some reputation for this question, I have yet to be provided with an answer that works for me. If someone can provide an actual code sample that does the job, I'd be very happy.

The problem with Blindy's answer is that no matter how much I simply translate it back or forth, the spirte still rotates around the top left hand corner and moving it somewhere rotating around the top left corner, then moving it back to the same position accomplishes nothing. Here is what I believe to be going on:

alt text http://img248.imageshack.us/img248/6717/36512474.png

Just so there is no confusion I have created a an image of what is going on. The left shows what is actually happening and the right shows what I need to happen.

alt text http://img101.imageshack.us/img101/1593/36679446.png

like image 975
Sam152 Avatar asked Oct 17 '09 09:10

Sam152


People also ask

How do you make a sprite rotate in scratch?

Select "left-right" from the drop-down menu to make the sprite only rotate horizontally. Select "all around" from the drop-down menu to make the sprite flip vertically. Select "don't rotate" from the drop-down menu to make the sprite face only one direction.

What does sprite rotation do?

Sprite rotation is clockwise rotation of the sprite, in degrees. The sprite image will be rotated about its image's (anchor_x, anchor_y) position.


2 Answers

You'd need to do something like:

  • translate by (-playerx-playerwidth/2, -playery-playerheight/2)
  • rotate by rotateangle
  • translate by (playerx+playerwidth/2, playery+playerheight/2)

The idea is to center your sprite on the origin then rotate around the origin (glRotate) and after you get the rotated sprite you translate it back in its place.

NB: If your sprite is initially "centered" around the origin, but with a corner not the actual center of the sprite, you first translate the object to center the sprite's center with the origin. So like if your sprite had the top-left corner in the origin, you'd translate by (-playerwidth/2, -playerheight/2), then rotate then translate by (playerx,playery).

like image 200
Blindy Avatar answered Nov 02 '22 23:11

Blindy


The answers so far are correct in telling you how it should be done but I fear that the Dark GDK API seems to be too primitive to be able to do it that simple way.

Unfortunately dbRotateSprite rotates the sprite about the top left regardless of the sprite's transform which is why you're having no luck with the other suggestions. To simulate rotation about the centre you must manually correct the position of the sprite i.e. you simply have to rotate the sprite and then move it as a two-step process.

I'm not familiar with the API and I don't know if y is measured up or down and which way the angle is measured so I'm going to make some assumptions. If y is measured down like many other 2D graphics systems, and the angle is measured from the x-axis increasing as it goes from the positive x-axis to the positive y-axis, then I believe the correct psuedo-code would look like

// PlayerX and PlayerY denote the sprite centre
// RotateAngle is an absolute rotation i.e. not a relative, incremental rotation

RotateAngle += 5;
RotateAngle %= 360;
RadiansRotate = (RotateAngle * PI) / 180;

dbRotateSprite( Handle, RotateAngle );

HalfSpriteWidth = dbSpriteWidth( Handle ) / 2;
HalfSpriteHeight = dbSpriteHeight( Handle ) / 2;

SpriteX = PlayerX
        - HalfSpriteWidth * cos(RadiansRotate)
        + HalfSpriteHeight * sin(RadiansRotate);
SpriteY = PlayerY
        - HalfSpriteHeight * cos(RadiansRotate)
        - HalfSpriteWidth * sin(RadiansRotate);

// Position the top left of the sprite at ( SpriteX, SpriteY )
dbSprite ( 1 , SpriteX , SpriteY , Handle );
like image 38
Troubadour Avatar answered Nov 03 '22 01:11

Troubadour