Rotate Sprite around another's midpoint [SOLVED]

Just starting out? Need help? Post your questions and find answers here.
User avatar
tikidays
User
User
Posts: 46
Joined: Tue Oct 24, 2023 6:47 am
Location: New Zealand
Contact:

Rotate Sprite around another's midpoint [SOLVED]

Post 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?
Last edited by tikidays on Fri Mar 15, 2024 6:49 pm, edited 1 time in total.
User avatar
STARGÅTE
Addict
Addict
Posts: 2227
Joined: Thu Jan 10, 2008 1:30 pm
Location: Germany, Glienicke
Contact:

Re: Rotate Sprite around another's midpoint

Post 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.
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Lizard - Script language for symbolic calculations and moreTypeface - Sprite-based font include/module
marc_256
Addict
Addict
Posts: 835
Joined: Thu May 06, 2010 10:16 am
Location: Belgium
Contact:

Re: Rotate Sprite around another's midpoint

Post 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,
- every professional was once an amateur - greetings from Pajottenland - Belgium -
PS: sorry for my english I speak flemish ...
User avatar
tikidays
User
User
Posts: 46
Joined: Tue Oct 24, 2023 6:47 am
Location: New Zealand
Contact:

Re: Rotate Sprite around another's midpoint

Post 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.
User avatar
tikidays
User
User
Posts: 46
Joined: Tue Oct 24, 2023 6:47 am
Location: New Zealand
Contact:

Re: Rotate Sprite around another's midpoint [SOLVED]

Post 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. :D
Post Reply