Mirror sprites

Just starting out? Need help? Post your questions and find answers here.
AJirenius
User
User
Posts: 29
Joined: Sun Aug 21, 2005 12:51 pm

Mirror sprites

Post by AJirenius »

Is there any fast and easy way to mirror sprites? I am very new at this but Ive searched the helpfiles and the forum as well and cannot find a good solution (as Im mostly are tiling backgrounds with sprites right now I am using oldfashioned 2dsprites).

Thanks in advance
AJirenius
User
User
Posts: 29
Joined: Sun Aug 21, 2005 12:51 pm

Post by AJirenius »

If you could help me with just flipping an image as well it would be as great. Otherwise I need to just mirror the images in a Photoshop and that would pretty much suck :P and double the filesize of the project :roll:
fweil
Enthusiast
Enthusiast
Posts: 725
Joined: Thu Apr 22, 2004 5:56 pm
Location: France
Contact:

Post by fweil »

AJirenius,

Here is a sample code that allow to H/V flip an image.

The main part manages the H/V flip by pushing H and V keyboard keys.

It uses API image structures for a fast memory dump of theprocefore image bessing pixels in memory instead of using Point() and Plot() commands.

This is easy to use with any image, gadget image or sprite.

Code: Select all

Enumeration
  #Window_Main
  #Gadget_Image
  #Image
EndEnumeration

Procedure Create_Image(ImageWidth, ImageHeight)
  ImageID = CreateImage(#Image, ImageWidth, ImageHeight)
  StartDrawing(ImageOutput())
    Box(0, 0, ImageWidth, ImageHeight, #Black)
    For i = 0 To 10000
      Plot(Random(ImageWidth), Random(ImageHeight), Random($FFFFFF))
    Next
    DrawingMode(1)
    BackColor(0, 0, 0)
    FrontColor(255, 255, 255)
    Locate(20, 20)
    DrawText("Image sample")
  StopDrawing()
  ProcedureReturn ImageID
EndProcedure

Procedure Image_To_Memory(Image, ImageWIdth, ImageHeight, ImageDepth, Address)
  hBmp = UseImage(Image)
  hDC = StartDrawing(ImageOutput())
    bmi.BITMAPINFO
    bmi\bmiHeader\biSize = SizeOf(BITMAPINFOHEADER)
    bmi\bmiheader\biWidth = ImageWidth
    bmi\bmiheader\biHeight = ImageHeight
    bmi\bmiheader\biPlanes = 1
    bmi\bmiheader\biBitCount = ImageDepth
    bmi\bmiheader\biCompression = #BI_RGB
    GetDIBits_(hDC, hBmp, 1, ImageHeight, Address, bmi, #DIB_RGB_COLORS)
    Dim Undo(ImageWidth, ImageHeight)
    CopyMemory(Address, @Undo(), (ImageWidth * ImageHeight - 1) * 4)
  StopDrawing()
EndProcedure

Procedure Memory_To_Image(Address, Image, ImageWIdth, ImageHeight, ImageDepth)
  hBmp = CreateImage(Image, ImageWidth, ImageHeight)
  hDC = StartDrawing(ImageOutput())
    bmi.BITMAPINFO
    bmi\bmiHeader\biSize = SizeOf(BITMAPINFOHEADER)
    bmi\bmiheader\biWidth = ImageWidth
    bmi\bmiheader\biHeight = ImageHeight
    bmi\bmiheader\biPlanes = 1
    bmi\bmiheader\biBitCount = ImageDepth
    bmi\bmiheader\biCompression = #BI_RGB
    SetDIBits_(hDC, hBmp, 1, ImageHeight, Address, bmi, #DIB_RGB_COLORS)
  StopDrawing()
  ProcedureReturn hBmp
EndProcedure

;
; An horizontal flip consists in flipping the array
; For a fast rendering and a short source code, I prefer to use a set of two arrays
;
Procedure Image_Horizontal_Flip(Image.l)
  UseImage(Image)
  ImageWidth = ImageWidth()
  ImageHeight = ImageHeight()
  ImageDepth = ImageDepth()
  Dim Pixels1(ImageHeight - 1, ImageWidth - 1)
  Dim Pixels2(ImageHeight - 1, ImageWidth - 1)
  Image_To_Memory(Image, ImageWidth, ImageHeight, ImageDepth, @Pixels1())
  For x = 0 To ImageWidth - 1
    For y = 0 To ImageHeight - 1
      Pixels2(y, x) = Pixels1(y, ImageWidth - 1 - x)
    Next
  Next
  ProcedureReturn Memory_To_Image(@Pixels2(), Image, ImageWidth, ImageHeight, ImageDepth)
EndProcedure

;
; A vertical flip consists in flipping the array
; As for horizontal flip, for a fast rendering and a short source code, I prefer to use a set of two arrays
;
Procedure Image_Vertical_Flip(Image.l)
  UseImage(Image)
  ImageWidth = ImageWidth()
  ImageHeight = ImageHeight()
  ImageDepth = ImageDepth()
  Dim Pixels1(ImageHeight - 1, ImageWidth - 1)
  Dim Pixels2(ImageHeight - 1, ImageWidth - 1)
  Image_To_Memory(Image, ImageWidth, ImageHeight, ImageDepth, @Pixels1())
  For x = 0 To ImageWidth - 1
    For y = 0 To ImageHeight - 1
      Pixels2(y, x) = Pixels1(ImageHeight - 1 - y, x)
    Next
  Next
  ProcedureReturn Memory_To_Image(@Pixels2(), Image, ImageWidth, ImageHeight, ImageDepth)
EndProcedure


  WindowWidth = 640
  WindowHeight = 480
  ImageWidth = WindowWidth - 20
  ImageHeight = WindowHeight - 20
  If OpenWindow(#Window_Main, 0, 0, WindowWidth, WindowHeight, #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget | #PB_Window_SizeGadget | #PB_Window_TitleBar | #PB_Window_ScreenCentered, "MyWindow")
      AddKeyboardShortcut(#Window_Main, #PB_Shortcut_Escape, #PB_Shortcut_Escape)
      AddKeyboardShortcut(#Window_Main, #PB_Shortcut_H, #PB_Shortcut_H)
      AddKeyboardShortcut(#Window_Main, #PB_Shortcut_V, #PB_Shortcut_V)
      If CreateGadgetList(WindowID(#Window_Main))
          ImageGadget(#Gadget_Image, 10, 10, ImageWidth, ImageHeight, Create_Image(ImageWidth, ImageHeight))
      EndIf
      Quit = #False
      Repeat
        Select WaitWindowEvent()
          Case #PB_Event_CloseWindow
            Quit = #True
          Case #PB_Event_Menu
            Select EventMenuID()
              Case #PB_Shortcut_Escape
                Quit = #True
              Case #PB_Shortcut_H
                SetGadgetState(#Gadget_Image, Image_Horizontal_Flip(#Image))
              Case #PB_Shortcut_V
                SetGadgetState(#Gadget_Image, Image_Vertical_Flip(#Image))
            EndSelect
        EndSelect
      Until Quit
  EndIf
  
  CallDebugger
End
My avatar is a small copy of the 4x1.8m image I created and exposed at 'Le salon international du meuble à Paris' january 2004 in Matt Sindall's 'Shades' designers exhibition. The original laminated print was designed using a 150 dpi printout.
AJirenius
User
User
Posts: 29
Joined: Sun Aug 21, 2005 12:51 pm

Post by AJirenius »

Wonderful!

I just cant believe you guys are spending time helping guys like me out in here. Definitely gets me stuck to this language.

thanks again, will try as soon as I get back from work. My little Dungeon Master is on its way :D
AJirenius
User
User
Posts: 29
Joined: Sun Aug 21, 2005 12:51 pm

Post by AJirenius »

Ok..
I need to swallow my pride here cause Im totally stuck.

I tried several ways to convert this into using it at sprites in a fullscreen environment. As Im not familiar with the gadgets nor handling data at adress and bit level I just cant figure the code out and how to do this on a sprite.

:cry:

help please?
AJirenius
User
User
Posts: 29
Joined: Sun Aug 21, 2005 12:51 pm

Post by AJirenius »

Noone got a code exampel on how you flip your sprites horizontally? I thought this would be a common thing.

:shock:
MadMax
Enthusiast
Enthusiast
Posts: 237
Joined: Mon Oct 06, 2003 11:56 am

Post by MadMax »

Well, you have various options

* Use something similar to fweil's code. I use something similar sometimes.

* You could write an ASM routine. Haven't used ASM since the good old Z80 days but shouldn't be too difficult.

* I've seen a few Sprite libs around, maybe some of them will do exactly what you want.

* Use Sprite3D instead of normal Sprite. Only trouble with Sprite3D is that collisions aren't easy with Sprite3D. Of course you could use Sprite3D to flip your Sprites onto normal Sprites before the main loop starts.

* Or believe me, it's simpler to have your sprites already flipped before. Usualy not all sprites need to flip, depends on game of course. If you use PNG they won't use up too much memory.
AJirenius
User
User
Posts: 29
Joined: Sun Aug 21, 2005 12:51 pm

Post by AJirenius »

Well MadMax this is the thing:

Im making a Dungeon Master Clone here using sprites as tiles building up the visual world (and therefor I need the transparency effects).

Flipping all sprites would almost double the size of graphics as everything is flipped to create movement feeling and .. yeah half the graphics.

Ive been around on all big sites around and seen some libs but not ONE had a spriteflip function (screenflip was there though).

I know nothing about ASM so there is no way for me to go there.

I tried to use something similar to fweils code as I stated at an earlier post but I just couldnt get it to work as I wasnt sure about how the memoryadresses was handled.

Transforming to 3d flipping and go back to 2d would probably cause a lot of graphic distorts and filtering issues but Im not sure.

So... this is my situation... ...help?
fweil
Enthusiast
Enthusiast
Posts: 725
Joined: Thu Apr 22, 2004 5:56 pm
Location: France
Contact:

Post by fweil »

Here is a code for flipping sprites, the first one (horizontal flip) a bit optimized using some ASM code, and the second one (vertical flip) using simple PureBasic instructions.

It provides an easy way to flip sprites on the fly, not too much consuming neither CPU nor memory.

Tell me if this solves more or less your issue.

Code: Select all

Procedure HFlipSprite(SpriteNumber.l)
  SpriteAddress.l
  ArrayAddress.l
  StartDrawing(SpriteOutput(SpriteNumber))
    DrawingBuffer = DrawingBuffer()
    DrawingBufferPitch = DrawingBufferPitch()
    SpriteHeight = SpriteHeight(SpriteNumber)
    SpriteWidth = SpriteWidth(SpriteNumber)
    Dim Array.l(SpriteHeight - 1, SpriteWidth - 1)
    MemoryLength = SpriteHeight * SpriteWidth * 4 - 4
    ArrayAddress = @Array()
    For i = 0 To SpriteHeight - 1
      SpriteAddress = DrawingBuffer + DrawingBufferPitch * i
      For j = 0 To SpriteWidth - 1
        !  MOV     eax, dword [esp+4] ; PokeL(ArrayAddress, PeekL(SpriteAddress))
        !  MOV     ebx, [eax]
        !  MOV     eax, dword [esp+8]
        !  MOV     [eax], ebx
        ArrayAddress + 4
        SpriteAddress + 4
      Next
    Next
    For i = 0 To SpriteHeight - 1
      For j = 0 To (SpriteWidth - 1) / 2
        x = Array(i, j)
        Array(i, j) = Array(i, SpriteWidth - 1 - j)
        Array(i, SpriteWidth - 1 - j) = x
      Next
    Next
    ArrayAddress = @Array()
    For i = 0 To SpriteHeight - 1
      SpriteAddress = DrawingBuffer + DrawingBufferPitch * i
      For j = 0 To SpriteWidth - 1
        !  MOV     eax, dword [esp+8] ; PokeL(SpriteAddress, PeekL(ArrayAddress))
        !  MOV     ebx, [eax]
        !  MOV     eax, dword [esp+4]
        !  MOV     [eax], ebx
        ArrayAddress + 4
        SpriteAddress + 4
      Next
    Next
  StopDrawing()
EndProcedure

Procedure VFlipSprite(SpriteNumber.l)
  StartDrawing(SpriteOutput(SpriteNumber))
    SpriteHeight = SpriteHeight(SpriteNumber)
    SpriteWidth = SpriteWidth(SpriteNumber)
    Dim Array.l(SpriteHeight, SpriteWidth)
    For i = 0 To SpriteHeight - 1
      For j = 0 To SpriteWidth - 1
        Array(i, j) = Point(j, SpriteHeight - 1 - i)
      Next
    Next
    For i = 0 To SpriteHeight - 1
      For j = 0 To SpriteWidth - 1
        Plot(j, i, Array(i, j))
      Next
    Next
  StopDrawing()
EndProcedure
My avatar is a small copy of the 4x1.8m image I created and exposed at 'Le salon international du meuble à Paris' january 2004 in Matt Sindall's 'Shades' designers exhibition. The original laminated print was designed using a 150 dpi printout.
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

Don't forget that almost anything you do with images can be converted to sprites using GrabSprite(). Just manipulate your images, draw them to screen output and grab them to sprites from there. If you don't flipbuffers the user will never see the operation taking place and it is very fast.
BERESHEIT
User avatar
Fou-Lu
Enthusiast
Enthusiast
Posts: 201
Joined: Tue Jul 12, 2005 8:30 am
Location: I'm pretty sure this is all a nightmare
Contact:

Post by Fou-Lu »

I think this would be a good time to ask something I've been wondering about sprites (although I could have started a new topic about that before).

Does anybody know how the "DisplaySprite()" command would look in ASM? I think that it would be better not to change the sprite itself, just draw it backwards. There could be something like: "DisplayMirroredSprite()" or an optional parameter... :roll:

~Fou-Lu (aka Lørd Cinneris (actually Elias Sant'Ana))

Image Image
fweil
Enthusiast
Enthusiast
Posts: 725
Joined: Thu Apr 22, 2004 5:56 pm
Location: France
Contact:

Post by fweil »

@Fou-Lu,

DisplaySprite() is just a copy of a memory area to the video buffer.

The code I suggested here demonstrates you can manage updates and copy to the sprite's memory, but you could also just apply changes to the video buffer as well.

But using sprites functions helps in easy coding.
My avatar is a small copy of the 4x1.8m image I created and exposed at 'Le salon international du meuble à Paris' january 2004 in Matt Sindall's 'Shades' designers exhibition. The original laminated print was designed using a 150 dpi printout.
AJirenius
User
User
Posts: 29
Joined: Sun Aug 21, 2005 12:51 pm

Post by AJirenius »

fweil: the code (both of the examples) works perfectly and does exactly what i need/want.. Ill put up a small demonstration of my work soon to show exactly how it works! Thanks again!

"Many thanks high power, keep em coming please /Shepherd, Black&White"
fweil
Enthusiast
Enthusiast
Posts: 725
Joined: Thu Apr 22, 2004 5:56 pm
Location: France
Contact:

Post by fweil »

As Droopy says : you know what ? I'm happy !
My avatar is a small copy of the 4x1.8m image I created and exposed at 'Le salon international du meuble à Paris' january 2004 in Matt Sindall's 'Shades' designers exhibition. The original laminated print was designed using a 150 dpi printout.
User avatar
Fou-Lu
Enthusiast
Enthusiast
Posts: 201
Joined: Tue Jul 12, 2005 8:30 am
Location: I'm pretty sure this is all a nightmare
Contact:

Post by Fou-Lu »

fweil wrote:@Fou-Lu,

DisplaySprite() is just a copy of a memory area to the video buffer.
Isn't it possible to copy the memory backwards? I'm asking that because you can't copy all the memory at once. You need to copy the bytes to the registry at some point so, instead of placing them where they should be you could change their position... :roll: It would be just a matter of moving the pointer in a different way.

~Fou-Lu (aka Lørd Cinneris (actually Elias Sant'Ana))

Image Image
Post Reply