Page 1 of 1
Rotate Sprite around another's midpoint [SOLVED]
Posted: Fri Mar 08, 2024 9:18 pm
by tikidays
Hi, I have a spinning ship sprite (source) that has a light set at an offset, with Purebasic there appears to be no way to set the spin origin, so my routine below only rotates lights on the upper left XY of the ship's sprite and not the centre of the sprite.
Ive tried many ways to add XY offsets for the light to move it to the correct origin with DisplayTransparentSprite but nothing works. Im hoping I have missed something obvious.
Code: Select all
Procedure lights(*source.sprite)
updateXY(*source\lights()\offsetX,*source\lights()\offsetY, *source\rotate)
DisplayTransparentSprite(*source\lights()\image, source\x + tempX , source\y + tempY ,255,*source\lights()\colour)
EndProcedure
Procedure updateXY(offsetX.f, offsetY.f, direction.f)
directionRadian.f = Radian(direction) ; convert angle from degree to radian
tempX = ((offsetX)*Cos(directionRadian))-((offsetY)*Sin(directionRadian))
tempY = ((offsetY)*Cos(directionRadian))+((offsetX)*Sin(directionRadian))
EndProcedure
I think its a math problem, but one I cant seem to get my head around. As you can see I couldn't see an easy way to return the updated XY from the procedure as Purebasic only supports one variable to be returned?
Re: Rotate Sprite around another's midpoint
Posted: Fri Mar 08, 2024 10:15 pm
by STARGĂ…TE
The math of the rotation looks fine.
To return multiple values from a procedure you can use Pointers and additional parameters:
Code: Select all
Procedure lights(*source.sprite)
Protected tempX.f, tempY.f
updateXY(*source\lights()\offsetX,*source\lights()\offsetY, *source\rotate, @tempX, @tempY) ; pass pointer of tempX and tempY
DisplayTransparentSprite(*source\lights()\image, source\x + tempX , source\y + tempY ,255,*source\lights()\colour)
EndProcedure
Procedure updateXY(offsetX.f, offsetY.f, direction.f, *tempX.Float, *tempY.Float)
directionRadian.f = Radian(direction) ; convert angle from degree to radian
*tempX\f = ((offsetX)*Cos(directionRadian))-((offsetY)*Sin(directionRadian)) ; Store the values at the passed pointer
*tempY\f = ((offsetY)*Cos(directionRadian))+((offsetX)*Sin(directionRadian))
EndProcedure
You can also try my
HyperTransformSprite().
It has two additional parameter for the rotation origin.
Re: Rotate Sprite around another's midpoint
Posted: Sat Mar 09, 2024 2:48 pm
by marc_256
@tikidays,
Hi, for my 2D applications I use my way to calculate some stuff ...
If I understand your problem well ...
You want to rotate a light around the center of a sprite (ship) in an 2D space.
Your solution
Code: Select all
Procedure lights(*source.sprite)
updateXY(*source\lights()\offsetX,*source\lights()\offsetY, *source\rotate)
DisplayTransparentSprite(*source\lights()\image, source\x + tempX , source\y + tempY ,255,*source\lights()\colour)
EndProcedure
Procedure updateXY(offsetX.f, offsetY.f, direction.f)
directionRadian.f = Radian(direction) ; convert angle from degree to radian
tempX = ((offsetX)*Cos(directionRadian))-((offsetY)*Sin(directionRadian))
tempY = ((offsetY)*Cos(directionRadian))+((offsetX)*Sin(directionRadian))
EndProcedure
I work with longer variable names, sorry but for an old guy and very complex 2D/3D drawing programs it is better for me.
Please adapt for your needs ...
Code: Select all
;- GLOBAL ZONE
Global ShipSprite_PosX.w
Global ShipSprite_PosY.w
Global ShipSprite_Width.w
Global ShipSprite_Height.w
Global ShipSprite_CenterX.w
Global ShipSprite_CenterY.w
Global Light_PosX.w
Global Light_PosY.w
Global Light_OffsetX.w
Global Light_OffsetY.w
Global Light_Distance.w
Global Light_Angle.f
;- INIT ZONE
ShipSprite_PosX = 400
ShipSprite_PosY = 300
ShipSprite_Width = 101
ShipSprite_Height = 101
ShipSprite_CenterX = ShipSprite_PosX + Round (ShipSprite_Width/2, #PB_Round_Up)
ShipSprite_CenterY = ShipSprite_PosY + Round (ShipSprite_Height/2, #PB_Round_Up)
Light_Distance = 200 ; this is the distance in px between center of sprite and the light
Light_Angle = Radian (90.0) ; this is an example angle use for next loop for 0...360 deg
Light_OffsetX = Cos (Light_Angle) * Light_Distance
Light_OffsetY = Sin (Light_Angle) * Light_Distance
Light_PosX = ShipSprite_CenterX + Light_OffsetX
Light_PosY = ShipSprite_CenterY + Light_OffsetY
Marc,
Re: Rotate Sprite around another's midpoint
Posted: Sun Mar 10, 2024 4:26 am
by tikidays
@Stargate
Thanks so much for your feedback, cleared up my understanding around pointers, most appreciated.
@marc_256
Awesome example, rotating around the ship will come in handy later on!
But these lights I want to stay in a fixed position as the ship rotates. My code appears to keep the lights in the right position, but appear to be rotating around some other point than the midpoint.
Re: Rotate Sprite around another's midpoint [SOLVED]
Posted: Fri Mar 15, 2024 6:51 pm
by tikidays
Discovered the issue, when I was setting up the lights I was placing them from the upper left x,y of the sprite, not from the mid point, I then pass the mid point of the main ship sprite to the DRAW command and this resolved the issue. I also had to take into account the mid points of the lights. Hope this helps someone else.
