09-08-2022, 05:08 AM
Over the past week I've been on a trigonometry quest to better understand the math needed for degree, radian, and vector math for my tutorial. The previous tutorial was lacking in this area and I'm changing that.
I've been using a routine written by Galleon back in 2009 to rotate a sprite using trig and _MAPTRIANGLE. I thought I would see if I could rewrite it using new commands that have come out since then like _HYPOT, _ATAN2, _D2R, etc..
The code below is my attempt at this, and it works. But still not nearly as efficient as Galleon's. I have marked Galleon's lines of code and my lines of code with REM statements, ' ******* RITCHIE and ' ******* GALLEON.
I've stared and stared at his lines 59, 60, 70, and 71 (Galleon's calculations) and I'll be damned if I can make sense of them. Could someone please explain to me how his lines of code achieve the same thing I'm doing? What am I missing here?
I've been using a routine written by Galleon back in 2009 to rotate a sprite using trig and _MAPTRIANGLE. I thought I would see if I could rewrite it using new commands that have come out since then like _HYPOT, _ATAN2, _D2R, etc..
The code below is my attempt at this, and it works. But still not nearly as efficient as Galleon's. I have marked Galleon's lines of code and my lines of code with REM statements, ' ******* RITCHIE and ' ******* GALLEON.
I've stared and stared at his lines 59, 60, 70, and 71 (Galleon's calculations) and I'll be damned if I can make sense of them. Could someone please explain to me how his lines of code achieve the same thing I'm doing? What am I missing here?
Code: (Select All)
'** SPRITE ROTATION
DIM Img AS LONG
DIM RotImg AS LONG
Img = _NEWIMAGE(50, 100, 32)
_DEST Img
CLS
LINE (0, 0)-(49, 99), , BF
_DEST 0
SCREEN _NEWIMAGE(640, 480, 32)
CLS
_PUTIMAGE (100, 100), Img ' original image
RotateImage 30, Img, RotImg
_PUTIMAGE (200, 100), RotImg ' rotated image
SUB RotateImage (Degree AS SINGLE, InImg AS LONG, OutImg AS LONG)
DIM px(3) AS INTEGER
DIM py(3) AS INTEGER
DIM Left AS INTEGER
DIM Right AS INTEGER
DIM Top AS INTEGER
DIM Bottom AS INTEGER
DIM v AS INTEGER
DIM RotWidth AS INTEGER
DIM RotHeight AS INTEGER
DIM Xoffset AS INTEGER
DIM Yoffset AS INTEGER
DIM Rotate AS SINGLE ' ******* RITCHIE
DIM NewRadian AS SINGLE ' ******* RITCHIE
DIM Distance AS SINGLE ' ******* RITCHIE
DIM COSr AS SINGLE ' ******* GALLEON
DIM SINr AS SINGLE ' ******* GALLEON
DIM x AS SINGLE ' ******* GALLEON
DIM y AS SINGLE ' ******* GALLEON
IF OutImg THEN _FREEIMAGE OutImg
px(0) = -_WIDTH(InImg) / 2 ' -x,-y ------------------- x,-y
py(0) = -_HEIGHT(InImg) / 2 ' Create points around (0,0) p(0) | | p(3)
px(1) = px(0) ' that macth the size of the | |
py(1) = _HEIGHT(InImg) / 2 ' original image. This creates | . |
px(2) = _WIDTH(InImg) / 2 ' four vector quantities to | 0,0 |
py(2) = py(1) ' work with. | |
px(3) = px(2) ' p(1) | | p(2)
py(3) = py(0) ' -x,y ------------------- x,y
'Rotate = _D2R(Degree) ' ******* RITCHIE convert to radian rotation
SINr = SIN(-Degree / 57.2957795131) ' ******* GALLEON
COSr = COS(-Degree / 57.2957795131) ' ******* GALLEON
DO ' cycle through vectors
'Distance = _HYPOT(px(v), py(v)) ' ******* RITCHIE get distance to vector
'NewRadian = _ATAN2(py(v), px(v)) + Rotate ' ******* RITCHIE convert vector to radian then add rotation
'px(v) = COS(NewRadian) * Distance ' ******* RITCHIE convert radian to vector with correct distance
'py(v) = SIN(NewRadian) * Distance ' ******* RITCHIE
x = px(v) * COSr + SINr * py(v) ' ******* GALLEON
y = py(v) * COSr - px(v) * SINr ' ******* GALLEON
px(v) = x ' ******* GALLEON
py(v) = y ' ******* GALLEON
IF px(v) < Left THEN Left = px(v) ' keep track of new image size
IF px(v) > Right THEN Right = px(v)
IF py(v) < Top THEN Top = py(v)
IF py(v) > Bottom THEN Bottom = py(v)
v = v + 1 ' increment vector counter
LOOP UNTIL v = 4 ' leave when all vectors processed
RotWidth = Right - Left + 1 ' calculate width of rotated image
RotHeight = Bottom - Top + 1 ' calculate height of rotated image
Xoffset = RotWidth / 2 ' place (0,0) in upper left corner of rotated image
Yoffset = RotHeight / 2
v = 0 ' reset corner counter
DO ' cycle through rotated image coordinates
px(v) = px(v) + Xoffset ' move image coordinates so (0,0) in upper left corner
py(v) = py(v) + Yoffset
v = v + 1 ' increment corner counter
LOOP UNTIL v = 4 ' leave when all four corners of image moved
OutImg = _NEWIMAGE(RotWidth, RotHeight, 32) ' create rotated image canvas
_MAPTRIANGLE (0, 0)-(0, _HEIGHT(InImg) - 1)-(_WIDTH(InImg) - 1, _HEIGHT(InImg) - 1), InImg TO(px(0), py(0))-(px(1), py(1))-(px(2), py(2)), OutImg
_MAPTRIANGLE (0, 0)-(_WIDTH(InImg) - 1, 0)-(_WIDTH(InImg) - 1, _HEIGHT(InImg) - 1), InImg TO(px(0), py(0))-(px(3), py(3))-(px(2), py(2)), OutImg
END SUB