Hi all
1st sorry for my bad english.
Is there anybody who can explain me with simple words how works the TransformSprite() function. What is the default parameters of this function, if i display a sprite, what are the default transformsprite parameters to display my sprite at his default aspect.
Please, give much samples as possible, and if in your examples, your used sin/cos funcs, tell me why.
Thanks by advance
kind regards
Request : TransformSprite() explanation for noob
- TazNormand
- User
- Posts: 27
- Joined: Tue May 26, 2009 3:17 pm
- Location: France
- TazNormand
- User
- Posts: 27
- Joined: Tue May 26, 2009 3:17 pm
- Location: France
Re: Request : TransformSprite() explanation for noob
46 read, no reply, does nobody knows how works TransformSprite(), even Fred nor Freak ?
Re: Request : TransformSprite() explanation for noob
A normal sprite is a box with a given width and height. When you draw a sprite to a x/y-cordinate on screen.
With Transform sprite you can deform the box in any kind, for example a trapezium. But you must give coordinates of every corner. You can even rotate a sprite with this function (and maybe because of this sin & cos are used).
Important - the order of the corner is importet or it will be empty.
A little code to play with:
With Transform sprite you can deform the box in any kind, for example a trapezium. But you must give coordinates of every corner. You can even rotate a sprite with this function (and maybe because of this sin & cos are used).
Important - the order of the corner is importet or it will be empty.
A little code to play with:
Code: Select all
If InitSprite() = 0 Or InitKeyboard() = 0
MessageRequester("Error", "Sprite system can't be initialized", 0)
End
EndIf
;
; Now, open windowed 800*600 screen
;
OpenWindow(0,0,0,800,600,"ESC=End",#PB_Window_ScreenCentered|#PB_Window_SystemMenu)
If OpenWindowedScreen(WindowID(0),0,0,800, 600)
; Load our 16 bit sprite (which is a 24 bit picture in fact, as BMP doesn't support 16 bit format)
;
LoadSprite(0, #PB_Compiler_Home + "examples/sources/Data/PureBasic.bmp")
LoadSprite(1, #PB_Compiler_Home +"examples/sources/Data/Background.bmp")
Dim x(3)
Dim y(3)
Dim dx(3)
Dim dy(3)
;set random corner
For i=0 To 3
x(i)=Random(700,100)
y(i)=Random(500,100)
dx(i)=Random(3,1)
dy(i)=Random(3,1)
Next
Repeat
; Inverse the buffers (the back become the front (visible)... And we can do the rendering on the back)
FlipBuffers()
ClearScreen(RGB(0,0,0))
;move corners randomly
For i=0 To 3
x(i)+dx(i)
y(i)+dy(i)
If x(i)<0
x(i)=0:dx(i)=Random(3,1)
EndIf
If y(i)<0
y(i)=0:dy(i)=Random(3,1)
EndIf
If x(i)>800
x(i)=800:dx(i)=-Random(3,1)
EndIf
If y(i)>600
y(i)=600:dy(i)=-Random(3,1)
EndIf
Debug " "+i+" "+x(i)+" "+y(i)
Next
;transform
TransformSprite(0,x(0),y(0),x(1),y(1),x(2),y(2),x(3),y(3))
;draw to 0,0 - because the coordinates are in the transformation!
DisplaySprite(0,0,0)
;transform Backside - uncommend this lines to see the diffrence
;TransformSprite(1,x(0),y(0),x(3),y(3),x(2),y(2),x(1),y(1))
;DisplaySprite(1,0,0)
StartDrawing(ScreenOutput())
For i=0 To 3
DrawText(x(i),y(i),Str(i))
Next
LineXY(x(0),y(0),x(1),y(1))
LineXY(x(1),y(1),x(2),y(2))
LineXY(x(2),y(2),x(3),y(3))
LineXY(x(3),y(3),x(0),y(0))
StopDrawing()
ExamineKeyboard()
Until KeyboardPushed(#PB_Key_Escape) Or WindowEvent()=#PB_Event_CloseWindow
Else
MessageRequester("Error", "Can't open a 800*600 - 32 bit screen !", 0)
EndIf
Re: Request : TransformSprite() explanation for noob
Here's something to play around with. I originally wrote it to demonstrate transforming a rectangular sprite for use in displaying isometric maps.
I updated it to show common transformations as well. I also added a feature to let you transform a sprite in real-time.
It does not deal with any 'Z' coordinates in the transformations.
I updated it to show common transformations as well. I also added a feature to let you transform a sprite in real-time.
It does not deal with any 'Z' coordinates in the transformations.
Code: Select all
;Program description: Sprite transformation effects
;Author: Demivec
;Written for: Originally for PB 4.61, with Windows OS, may not function correctly for other OS.
; It does not function correctly with the OpenGL subsystem.
;Date Written: 2 July 2012
;Last Updated: 4 October 2015 for PB 5.40b8 and added some additional features.
;
EnableExplicit
; Structure Point
; x.i
; y.i
; EndStructure
Structure Point_f
x.f
y.f
EndStructure
Enumeration sprites
#spr_pb
#spr_corner
#spr_text_1
#spr_text_2
#spr_text_3
#spr_text_4
#spr_mousePointer
EndEnumeration
Enumeration fonts
#font_large
#font_small
EndEnumeration
Enumeration windows
#win_main
EndEnumeration
Procedure handleError(value, text.s = "Unknown Error.")
If value = 0
MessageRequester("Error", text)
End
EndIf
EndProcedure
;Sprite info: (width, height) = original dimensions, (newWidth, newHeight) = zoom dimensions,
; degree = rotation amount, (cx,cy) = center point for rotation
Procedure MakeSpriteTransformation(spriteID, width, height, cx, cy, degree, newWidth, newHeight)
Protected.Point_f p1, p2, p3, p4
Protected.f wf = width / newWidth, hf = height / newHeight
If degree = 0
;simple transformation: no rotation, only zooming and translation movements possible
p1\x = (( -cx) / wf) - 0.5: p1\y = (( -cy) / hf) - 0.5
p2\x = ((width - cx) / wf) - 0.5: p2\y = (( -cy) / hf) - 0.5
p3\x = ((width - cx) / wf) - 0.5: p3\y = ((height - cy) / hf) - 0.5
p4\x = (( -cx) / wf) - 0.5: p4\y = ((height - cy) / hf) - 0.5
Else
;more complex transformation: rotation (around point cx,cy) and zooming possible
Protected.f angCos = Cos(Radian(degree)), angSin = Sin(Radian(degree))
Protected.f v1, v2, v3, v4, v5, v6, v7, v8
v1 = -cx * angCos: v3 = -cy * angSin
v2 = -cx * angSin: v4 = -cy * angCos
v6 = (width - cx) * angCos: v7 = (height - cy) * angSin
v5 = (width - cx) * angSin: v8 = (height - cy) * angCos
p1\x = ((v1 - v3) / wf) - 0.5: p1\y = ((v4 + v2) / hf) - 0.5
p2\x = ((v6 - v3) / wf) - 0.5: p2\y = ((v4 + v5) / hf) - 0.5
p3\x = ((v6 - v7) / wf) - 0.5: p3\y = ((v8 + v5) / hf) - 0.5
p4\x = ((v1 - v7) / wf) - 0.5: p4\y = ((v8 + v2) / hf) - 0.5
EndIf
TransformSprite(spriteID, p1\x, p1\y, p2\x, p2\y, p3\x, p3\y, p4\x, p4\y)
EndProcedure
;iso (squish) rotated clockwise degrees
Procedure MakeSpriteIsoClockwise(spriteID, width, height, cx, cy, degree, newWidth, newHeight)
MakeSpriteTransformation(spriteID, width, height, cx, cy, degree, newWidth, newHeight)
EndProcedure
;iso (squish) rotated counter-clockwise degrees
Procedure MakeSpriteIsoCounterClockwise(spriteID, width, height, cx, cy, degree, newWidth, newHeight)
MakeSpriteTransformation(spriteID, width, height, cx, cy, 360 - degree, newWidth, newHeight)
EndProcedure
Procedure MakeSpriteRotate(SpriteID, cx, cy, degree)
Protected width = SpriteWidth(SpriteID), height = SpriteHeight(SpriteID)
ZoomSprite(SpriteID, #PB_Default, #PB_Default)
MakeSpriteTransformation(spriteID, width, height, cx, cy, degree, width, height)
EndProcedure
Procedure MakeSpriteZoomHorizontal(SpriteID, cx, cy, newWidth)
Protected width = SpriteWidth(SpriteID), height = SpriteHeight(SpriteID)
ZoomSprite(SpriteID, #PB_Default, #PB_Default)
MakeSpriteTransformation(spriteID, width, height, cx, cy, 0, newWidth, height)
EndProcedure
Procedure MakeSpriteZoomVertical(SpriteID, cx, cy, newHeight)
Protected width = SpriteWidth(SpriteID), height = SpriteHeight(SpriteID)
ZoomSprite(SpriteID, #PB_Default, #PB_Default)
MakeSpriteTransformation(spriteID, width, height, cx, cy, 0, width, newHeight)
EndProcedure
Procedure MakeSpriteNormal(SpriteID, cx = 0, cy = 0)
Protected width = SpriteWidth(SpriteID), height = SpriteHeight(SpriteID)
ZoomSprite(SpriteID, #PB_Default, #PB_Default)
MakeSpriteTransformation(spriteID, width, height, cx, cy, 0, width, height)
EndProcedure
handleError(InitSprite(), "Can't open screen & sprite enviroment.")
handleError(InitMouse(), "Can't initialize mouse handler.")
handleError(InitKeyboard(), "Can't initialize keyboard handler.")
handleError(OpenWindow(#win_main, 0, 0, 800, 600, "Sprite Transformations, drag numbered corners to transform",
#PB_Window_SystemMenu | #PB_Window_ScreenCentered), "Can't open window.")
handleError(OpenWindowedScreen(WindowID(#win_main), 0, 0, 800, 600, 0, 0, 0), "Can't open windowed screen.")
handleError(LoadFont(#font_large, "Arial", 36), "Unable to load font.")
handleError(LoadFont(#font_small, "Arial", 8), "Unable to load font.")
handleError(CreateSprite(#spr_pb, 64, 64), "Sprite creation failed.")
handleError(StartDrawing(SpriteOutput(#spr_pb)), "Can't draw on sprite.")
Box(0,0,64,64,RGB($FF,$FF,$00))
DrawingMode(#PB_2DDrawing_Outlined)
DrawingFont(FontID(#font_large))
DrawText(0,0,"PB",RGB($FF,$00,$00))
Box(0,0,64,64,RGB($00,$00,$FF))
LineXY( 0,0,64,64,RGB($00,$00,$FF))
LineXY(64,0, 0,64,RGB($00,$00,$FF))
StopDrawing()
handleError(CreateSprite(#spr_mousePointer, 8, 8, #PB_Sprite_AlphaBlending), "Sprite creation failed.")
handleError(StartDrawing(SpriteOutput(#spr_mousePointer)), "Can't draw on sprite.")
FrontColor(RGB($00,$FF,$FF))
LineXY(0,0, OutputWidth() - 1,OutputHeight() - 1)
LineXY(0,0, 0,OutputHeight() - 3)
LineXY(0,0, OutputWidth() - 3,0)
StopDrawing()
TransparentSpriteColor(#spr_mousePointer, RGB($00,$00,$00))
handleError(CreateSprite(#spr_corner, 8, 8, #PB_Sprite_AlphaBlending), "Sprite creation failed.")
handleError(StartDrawing(SpriteOutput(#spr_corner)), "Can't draw on sprite.")
Box(0, 0, OutputWidth(), OutputHeight(), RGB($00, $FF, $00))
StopDrawing()
DataSection
cornerCoordinates:
Data.i 0,0, 64,0, 64,64, 0,64
EndDataSection
Dim corner.Point(3)
Define customSpritePosX = 400, customSpritePosY = 400, i
Restore cornerCoordinates
For i = 0 To 3
handleError(CreateSprite(#spr_text_1 + i, 8, 16, #PB_Sprite_AlphaBlending), "Sprite creation failed.")
handleError(StartDrawing(SpriteOutput(#spr_text_1 + i)), "Can't draw on sprite.")
DrawingMode(#PB_2DDrawing_Outlined)
DrawingFont(FontID(#font_small))
DrawText(0, 0, Str(i + 1),RGB($FF,$FF,$FF),RGB($00,$00,$00))
StopDrawing()
TransparentSpriteColor(#spr_text_1 + i, RGB($00,$00,$00))
Read.i corner(i)\x: corner(i)\x + customSpritePosX
Read.i corner(i)\y: corner(i)\y + customSpritePosY
Next
Define direction = 2
Define zoomX = 64
Define zoomY = 64
Define angle, newWidth, newHeight, displayRow, event, i
ReleaseMouse(1)
Define mouseIsReleased = #True, dragCorner = -1
Repeat
Repeat
event = WindowEvent()
Select event
Case #PB_Event_CloseWindow
End
EndSelect
Until event = 0
FlipBuffers()
ClearScreen(RGB($40, $40, $40))
displayRow = 70
MakeSpriteNormal(#spr_pb, 32, 32) ;normal appearance
DisplaySprite(#spr_pb, 100, displayRow) ;location is needed because display location was not part of transformation
MakeSpriteRotate(#spr_pb, 32, 32, angle) ;rotate around center
DisplaySprite(#spr_pb, 200, displayRow)
MakeSpriteRotate(#spr_pb, 16, 16, angle) ;rotate around non-center point
DisplaySprite(#spr_pb, 350, displayRow)
newWidth = zoomX: newHeight = zoomX
MakeSpriteZoomHorizontal(#spr_pb, 32, 32, newWidth) ;zoom horizontally
DisplaySprite(#spr_pb, 500, displayRow)
MakeSpriteZoomVertical(#spr_pb, 32, 32, newHeight) ;zoom vertically
DisplaySprite(#spr_pb, 600, displayRow)
displayRow = 280
MakeSpriteIsoCounterClockwise(#spr_pb, 64, 64, 32, 32, angle, 64, 32) ;squished vertically
DisplaySprite(#spr_pb, 200 - zoomX * 0.5, displayRow - zoomY * 0.5)
MakeSpriteIsoCounterClockwise(#spr_pb, 64, 64, 32, 32, angle, 32, 64) ;squished horizontally
DisplaySprite(#spr_pb, 300 - zoomX * 0.5, displayRow - zoomY * 0.5)
MakeSpriteIsoClockwise(#spr_pb, 64, 64, 32, 32, angle, 2 * zoomX, 1 * zoomX) ;squished vertically and zoomed
DisplaySprite(#spr_pb, 700 - zoomX * 0.5, displayRow - zoomY * 0.5)
MakeSpriteIsoClockwise(#spr_pb, 64, 64, 32, 32, angle, 1 * zoomX, 2 * zoomX) ;squished horizontally and zoomed
DisplaySprite(#spr_pb, 500 - zoomX * 0.5, displayRow - zoomY * 0.5)
displayRow = 400
MakeSpriteIsoCounterClockwise(#spr_pb, 64, 64, 32, 32, angle, 64, 20 + zoomX / 2) ;squishiness varying vertically
DisplaySprite(#spr_pb, 100, displayRow)
MakeSpriteIsoCounterClockwise(#spr_pb, 64, 64, 32, 32, angle, 20 + zoomX / 2, 64) ;squishiness varying horizontally
DisplaySprite(#spr_pb, 200, displayRow)
ExamineMouse()
;handle screen mouse activation/deactivation
If MouseX() < 2 Or MouseX() > ScreenWidth() - 3 Or MouseY() < 2 Or MouseY() > ScreenHeight() -3
ReleaseMouse(1): mouseIsReleased = #True
EndIf
If WindowMouseX(#win_main) >= 2 And
WindowMouseX(#win_main) < WindowWidth(#win_main, #PB_Window_InnerCoordinate) - 2 And
WindowMouseY(#win_main) >= 2 And
WindowMouseY(#win_main) < WindowHeight(#win_main, #PB_Window_InnerCoordinate) - 2
ReleaseMouse(0): mouseIsReleased = #False
MouseLocate(WindowMouseX(#win_main), WindowMouseY(#win_main))
EndIf
;handle corner dragging for deformable sprite
If Not mouseIsReleased
If MouseButton(#PB_MouseButton_Left)
If dragCorner = -1
For i = 0 To 3
If SpriteCollision(#spr_corner, corner(i)\x, corner(i)\y, #spr_mousePointer, MouseX(), MouseY())
dragCorner = i
MouseDeltaX(): MouseDeltaY() ;reset these values for further reads
Break
EndIf
Next
Else
corner(dragCorner)\x + MouseDeltaX(): corner(dragCorner)\y + MouseDeltaY()
EndIf
ElseIf dragCorner <> -1
corner(dragCorner)\x + MouseDeltaX(): corner(dragCorner)\y + MouseDeltaY()
dragCorner = -1 ;signal that no corner is being dragged
EndIf
EndIf
TransformSprite(#spr_pb, corner(0)\x,corner(0)\y, corner(1)\x,corner(1)\y, corner(2)\x,corner(2)\y, corner(3)\x,corner(3)\y)
DisplaySprite(#spr_pb, 0, 0) ;drawn at location 0,0 because sprite location is part of transformation
;display corners for dragging
For i = 0 To 3
DisplayTransparentSprite(#spr_corner, corner(i)\x, corner(i)\y, 128)
DisplayTransparentSprite(#spr_text_1 + i, corner(i)\x + 8, corner(i)\y)
Next
If Not mouseIsReleased: DisplayTransparentSprite(#spr_mousePointer, MouseX(), MouseY()): EndIf
;update animation attributes
angle + 1: If angle > 360: angle = 0: EndIf
zoomX + direction
If zoomX > 100 : direction = -2 : EndIf
If zoomX < 20 : direction = 2 : EndIf
ExamineKeyboard()
If KeyboardPushed(#PB_Key_Escape): Break: EndIf
Delay(1)
ForEver