Page 1 of 2

Rotate image fast? (wheel of fortune like)

Posted: Thu Jul 02, 2009 11:13 pm
by ricardo
hello

I want to rotate a simple image (something like the wheel of fortune):

Image

Its just for a small game i want to code for my kids (wheel of fortune with very simple phrases, all downloable games in spanish have phrases very complicated for them)

I do not nothing about sprites, dont know if its possible or using bmp, jpg.

Any help are welcome :)

Re: Rotate image fast? (wheel of fortune like)

Posted: Thu Jul 02, 2009 11:30 pm
by ricardo
ricardo wrote:hello

I want to rotate a simple image (something like the wheel of fortune):

Image

Its just for a small game i want to code for my kids (wheel of fortune with very simple phrases, all downloable games in spanish have phrases very complicated for them)

I do not nothing about sprites, dont know if its possible or using bmp, jpg. avoiding sprites, because i want the rest of the app to be a simple interface since i dont want to spend much time coding it. Just want something fast to code.

Any help are welcome :)

Posted: Thu Jul 02, 2009 11:40 pm
by ricardo
Maybe drawing it to make it rotate?

Posted: Thu Jul 02, 2009 11:56 pm
by Kaeru Gaman
513x513 is just 1 pix too big. make it 512x512.

then load it as a sprite, create a Sprite3D from it, and use RotateSprite3D.
http://www.purebasic.com/documentation/ ... prite.html
http://www.purebasic.com/documentation/ ... ite3d.html
http://www.purebasic.com/documentation/ ... ite3d.html

using sprite and screen is the easiest approach.

you can create buttons etc. on the screen itself, using sprites for fancy skinned look.

or you use a WindowedScreen in the middle for the wheel only, and create the rest of the GUI in boring standard buttons.


... doing the same with Images surely is possible, but you would need ASM routines to rotate the Image, there is nothing native for this in PB.

Posted: Fri Jul 03, 2009 12:24 am
by netmaestro
...but you would need ASM routines to rotate the Image...
No, lots of options. Here's one:

Code: Select all

;================================================== 
;  Program:     GDIPlus Rotation Demo 
;  Author:      netmaestro 
;  Date:        July 2, 2009
;================================================== 

CompilerIf Defined(GdiplusStartupInput, #PB_Structure) = 0 
  Structure GdiplusStartupInput 
    GdiPlusVersion.l 
    *DebugEventCallback.Debug_Event 
    SuppressBackgroundThread.l 
    SuppressExternalCodecs.l 
  EndStructure 
CompilerEndIf  

#background = 0 ; image# for background 

Prototype GdiplusStartup( *token, *input, mode ) 
Prototype GdipCreateBitmapFromFile(filename.p-bstr, *image)
Prototype GdipCreateFromHDC( hdc, *gfx) 
Prototype GdipRotateWorldTransform( *gfx, angle.f, mode)
Prototype GdipResetWorldTransform( *gfx)
Prototype GdipTranslateWorldTransform( *gfx, wmidf.f, hmidf.f, mode)
Prototype GdipDrawImageRectI( *gfx, *image, x, y, Width, Height ) 
Prototype GdipDeleteGraphics( *gfx ) 
Prototype GdipDisposeImage( *image ) 
Prototype GdiplusShutdown( *token ) 

OpenLibrary(0, "gdiplus.dll") 
  
Global GdiplusStartup.GdiplusStartup                           = GetFunction( 0, "GdiplusStartup" )          
Global GdipCreateBitmapFromFile.GdipCreateBitmapFromFile       = GetFunction( 0, "GdipCreateBitmapFromFile")
Global GdipCreateFromHDC.GdipCreateFromHDC                     = GetFunction( 0, "GdipCreateFromHDC" )      
Global GdipDrawImageRectI.GdipDrawImageRectI                   = GetFunction( 0, "GdipDrawImageRectI" )      
Global GdipRotateWorldTransform.GdipRotateWorldTransform       = GetFunction( 0, "GdipRotateWorldTransform" )      
Global GdipTranslateWorldTransform.GdipTranslateWorldTransform = GetFunction( 0, "GdipTranslateWorldTransform" )      
Global GdipResetWorldTransform.GdipResetWorldTransform         = GetFunction( 0, "GdipResetWorldTransform" ) 
Global GdipDeleteGraphics.GdipDeleteGraphics                   = GetFunction( 0, "GdipDeleteGraphics" )      
Global GdipDisposeImage.GdipDisposeImage                       = GetFunction( 0, "GdipDisposeImage" )        
Global GdiplusShutdown.GdiplusShutdown                         = GetFunction( 0, "GdiplusShutdown" )  

Procedure InitGDIPlus() 
  input.GdiplusStartupInput 
  input\GdiPlusVersion = 1 
  GdiplusStartup( @*token, @input, #Null) 
  ProcedureReturn *token 
EndProcedure 

Procedure ShutDownGDIPlus(*token) 
  GdiplusShutdown(*token) 
  CloseLibrary(0) 
EndProcedure 

Procedure RotateImage(*image, bkgimage, angle.f) 
  width=ImageWidth(bkgimage) 
  height=ImageHeight(bkgimage) 
  wmidf.f = width/2 
  hmidf.f = height/2 
  wmid.l = height/2 
  hmid.l = height/2  
  hdc=StartDrawing(ImageOutput(bkgimage)) 
    GdipCreateFromHDC( hdc, @*surface) 
    GdipRotateWorldTransform( *surface, angle, 1) 
    GdipTranslateWorldTransform( *surface, wmidf, hmidf, 1) 
    GdipDrawImageRectI( *surface, *image, wmid, hmid, -width, -height) 
    GdipResetWorldTransform( *surface)                                      
  StopDrawing() 
  GdipDeleteGraphics( *surface)  
EndProcedure 

*token = InitGDIPlus() 

GdipCreateBitmapFromFile("513pxwheeloffortuneseas.png", @*wheeldisc) 
CreateImage(0,513,513,32) 

OpenWindow(0,0,0,540,570,"Rotation Demo",#PB_Window_ScreenCentered|#PB_Window_SystemMenu) 
SetWindowColor(0,0)
ImageGadget(0,15,15,0,0,0) 
ButtonGadget(1,220,540,100,20,"Spin!") 

RotateImage(*wheeldisc, #background, 0) 
SetGadgetState(0,ImageID(#background)) 
      
Repeat 
  EventID = WindowEvent() 
  Select EventID
    Case #PB_Event_Gadget
      Select EventGadget()
        Case 1
          inc.d = (500+Random(200))/100
      EndSelect
  EndSelect
        
  If inc
    inc - 0.01
    If inc<=0
      inc=0:spinning=0
      intangle=Int(angle.d) 
      offset=intangle%15
      If offset > 7 : angle+(15-offset) : Else : angle-offset : EndIf
    Else
      angle.d+inc.d:If angle >=360:angle=0:EndIf 
    EndIf
    RotateImage(*wheeldisc, #background, angle) 
    SetGadgetState(0,ImageID(#background)) 
  EndIf  
 
Until EventID = #WM_CLOSE 

ShutDownGDIPlus(*token)  

Posted: Fri Jul 03, 2009 12:44 am
by ricardo
Thanks for you answers!! :)

But now i found a problem i was not aware... how do i know which is the area pointing up when i stop the rotation? This is getting more complicated that what i was thinking about! :P

Best Regards

Posted: Fri Jul 03, 2009 1:05 am
by netmaestro
It isn't difficult. Make a Select/Case block with upper and lower limits (remember you're dealing with floats) where the result is decided by the finishing angle. 0=900, 15 (or better 14 to 16, floats remember) = 300, etc.

Posted: Fri Jul 03, 2009 1:13 am
by Kaeru Gaman
@netmaestro

ok, you're right... why write everything again when GDI+ already has all you need.

just would have taken weeks for me to import all the stuff and learn how to use it. :mrgreen:

with Sprite3D, would have been a one hour job for me.

Posted: Fri Jul 03, 2009 1:27 am
by netmaestro
Sprite3D may be smoother, not sure. It probably is.

Posted: Fri Jul 03, 2009 1:48 am
by netmaestro
Interesting, if you resize the .png to 512*512 it runs smoother. A nice multiple of 2 is probably a lot easier on the gdiplus algos.

Posted: Fri Jul 03, 2009 5:43 am
by IceSoft
Kaeru Gaman wrote: ... why write everything again when GDI+ already has all you need.
Why not?
GDI+ is only for Microsoft OSes.

Using the Sprite3D functions ... and your source works also on Linux and MACOS.

Posted: Fri Jul 03, 2009 7:23 am
by +18
why this occurred for me?

Image

Posted: Fri Jul 03, 2009 8:04 am
by Michael Vogel
+18 wrote:why this occurred for me?...
Is *wheeldisk already a pointer var? Then it is equal the reference address already, adding an additional "@" would be a little bit to much here :wink:

If you are not sure, just insert some debug lines like...

Code: Select all

Debug *wheeldisk
Debug @*wheeldisk
Michael

Posted: Fri Jul 03, 2009 9:02 am
by infratec
Hi,

since I like it crossplatform compatible:

I simply modified the example of the PureBASIC helpfile
(10 minutes work)


But than I needed to convert the picture to bmp.
UsePNG... was not working, don't know why.

PNG is working now

So I reduced the sice to 512x512 and set the cornercolour to 255,0,255.

Code: Select all

UsePNGImageDecoder()

If InitSprite() = 0 Or InitKeyboard() = 0
  MessageRequester("Error", "Sprite system can't be initialized", 0)
  End
EndIf

If InitSprite3D() = 0
  MessageRequester("Error", "Sprite3D system can't be initialized correctly", 0)
  End
EndIf


If OpenWindow(0, 0, 0, 800, 600, "Wheel V1.01", #PB_Window_ScreenCentered|#PB_Window_SystemMenu)

 If OpenWindowedScreen(WindowID(0), 0, 0, 800, 600, 0, 0, 0)

  ; Load our 16 bit sprite (which is a 24 bit picture in fact, as BMP doesn't support 16 bit format)
  ; 
  LoadSprite(0, "Wheel.png", #PB_Sprite_Texture)
  CreateSprite3D(0, 0)
  
  Sprite3DQuality(1)
  
  TransparentSpriteColor(0, RGB(255, 0, 255)) ; Our pink is transparent :)

  x = 0

  Repeat
    
    ; Inverse the buffers (the back become the front (visible)... And we can do the rendering on the back)
    
    FlipBuffers()
    
    ClearScreen(RGB(0,50,128))
    
    ; Draw our sprite
    ;
    If Start3D()
      DisplaySprite3D(0, 144, 44)
      RotateSprite3D(0, x, 0)
      Stop3D()
    EndIf
    
    Delay(10)  ; to reduce the cpu load from 100 to 10%  :)

    ExamineKeyboard()
    
    x + 1 ; to speed it up, increase this value
    If x > 359: x = 0 : EndIf
  Until KeyboardPushed(#PB_Key_Escape) Or WindowEvent() = #PB_Event_CloseWindow
  
 Else
   MessageRequester("Error", "Can't open windowed screen!", 0)
 EndIf
 
Else
 MessageRequester("Error", "Can't open window!", 0)
EndIf

End
Best regards,

Bernd

Posted: Fri Jul 03, 2009 9:06 am
by Psychophanta
@ricardo, can't help, as i am so anti-capitalist.
To me that wheel is like a latin cross to Count Dracula. :P

Sorry, if not help i should be just shuted up :oops: