Mirror sprites
Mirror sprites
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
Thanks in advance
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.
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.
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.
help please?
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.

help please?
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.
* 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.
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?
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?
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.
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.
- netmaestro
- PureBasic Bullfrog
- Posts: 8451
- Joined: Wed Jul 06, 2005 5:42 am
- Location: Fort Nelson, BC, Canada
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
- Fou-Lu
- Enthusiast
- Posts: 201
- Joined: Tue Jul 12, 2005 8:30 am
- Location: I'm pretty sure this is all a nightmare
- Contact:
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:
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,
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.
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.
- Fou-Lu
- Enthusiast
- Posts: 201
- Joined: Tue Jul 12, 2005 8:30 am
- Location: I'm pretty sure this is all a nightmare
- Contact:
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.fweil wrote:@Fou-Lu,
DisplaySprite() is just a copy of a memory area to the video buffer.