Forum
Mirror a sprite - Printable Version

+- Forum (https://www.boriel.com/forum)
+-- Forum: Compilers and Computer Languages (https://www.boriel.com/forum/forumdisplay.php?fid=12)
+--- Forum: ZX Basic Compiler (https://www.boriel.com/forum/forumdisplay.php?fid=11)
+---- Forum: Help & Support (https://www.boriel.com/forum/forumdisplay.php?fid=16)
+---- Thread: Mirror a sprite (/showthread.php?tid=861)



Mirror a sprite - oblo - 11-14-2018

Hi all

Trying to save some UDGs, I'm looking for a way to mirror an existing sprite/UDG, so I only have to define them one way (i.e. facing sprites left) and, with a function, use those sprites to print them facing right.
I was toying with the hmirror function (<!-- m --><a class="postlink" href="http://www.boriel.com/wiki/en/index.php/ZX_BASIC:HMirror.bas">http://www.boriel.com/wiki/en/index.php ... Mirror.bas</a><!-- m -->) but I can't get it to work Undecided

Thanks and cheers.


Re: Mirror a sprite - britlion - 11-14-2018

What was the problem Oblo?

Read: <!-- l --><a class="postlink-local" href="http://www.boriel.com/forum/how-to-tutorials/tutorial-how-to-put-inline-assembly-functions-into-zx-basic-t729.html?hilit=mirror">how-to-tutorials/tutorial-how-to-put-inline-assembly-functions-into-zx-basic-t729.html?hilit=mirror</a><!-- l -->

This is the discussion where that came about. The fastest mirror solution is the one at the bottom of the page you linked to - faster and shorter by far than any other solution I've seen, though the maths are a bit brain aching if you try to understand how it does it.

If you want to vertically mirror, it's a matter of swapping the byte order - so instead of first byte to last, you read it last byte to first. Easier if you just peek then poke to your sprite buffer in forward or reverse order when switching the up/down direction.

Left to right you read the bytes into your live sprite buffer poke sprite1, peek (data1) Right to left, you do poke sprite1, hmirror(peek data1)


Re: Mirror a sprite - oblo - 11-14-2018

britlion Wrote:What was the problem Oblo?

Read: <!-- l --><a class="postlink-local" href="http://www.boriel.com/forum/how-to-tutorials/tutorial-how-to-put-inline-assembly-functions-into-zx-basic-t729.html?hilit=mirror">how-to-tutorials/tutorial-how-to-put-inline-assembly-functions-into-zx-basic-t729.html?hilit=mirror</a><!-- l -->

This is the discussion where that came about. The fastest mirror solution is the one at the bottom of the page you linked to - faster and shorter by far than any other solution I've seen, though the maths are a bit brain aching if you try to understand how it does it.

If you want to vertically mirror, it's a matter of swapping the byte order - so instead of first byte to last, you read it last byte to first. Easier if you just peek then poke to your sprite buffer in forward or reverse order when switching the up/down direction.

Left to right you read the bytes into your live sprite buffer poke sprite1, peek (data1) Right to left, you do poke sprite1, hmirror(peek data1)

Thanks for your rapid response, britlion. The syntax, what's the correct one? For instance, if I want to use the UDG \A, hmirror(\A), hmirror("\A") or hmirror(peek 23675) fails.

EDIT: I've just got to understand it. The function mirrors something it's already printed on the screen, but don't mirror sprites "on the go" (that's what's I was looking for Sad )

Cheers.


Re: Mirror a sprite - britlion - 11-14-2018

Yes - it doesn't mirror a sprite. It returns the input number with the bits reversed.

So hmirror (1) = 128 or in binary hmirror (%00000001) = %10000000
And hmirror (64) =2 or in binary hmirror (%01000000) = %00000010

And so on.

You have to run it over the sprite's data to retrieve each byte the other way around. This means you have a couple of choices - you can reverse each byte of the sprite using hmirror and write it back, so the sprite graphic changes direction in memory (either in a buffer, or where it's stored). You'll have to print multiple square sprites in reverse order too - so a 16 pixel wide sprite tha't's AB becomes mirrored B followed by Mirrored A.

Alrternatively your routine to put it on the screen can choose to poke up reversed bytes if you are doing more direct screen manipulation.

But if you had a standard UDG you could left right reverse it by doing

for i = USR "A" to USR "A" +7
poke i, hmirror (peek i)
next i

For example. This would iterate over the UDG and mirror it left/right - you'd presumably run this when changing directions.


Re: Mirror a sprite - britlion - 11-14-2018

oblo Wrote:EDIT: I've just got to understand it. The function mirrors something it's already printed on the screen, but don't mirror sprites "on the go" (that's what's I was looking for Sad )

Cheers.

I don't think you can write a function to mirror a sprite that's generic. A function returns one number. Sprites are always made of multiple bytes (sometimes quite a lot of bytes). This is the core of a routine that can be used to mirror sprites; but since there's no way to know how you are ordering your data for the sprites (size of sprite, order from left to right or columns, masking data, colour data?) there's no way to write a simple piece of code that works for your game. What you have here is the core function that reverses the pixels. You'd have to build a sprite flip routine that works for your sprite shape and size and features using this as the key bit.


Re: Mirror a sprite - oblo - 11-15-2018

Understood, I was simply asking too much Sad
Nevertheless, thanks for the clarification and for the USR code Smile I'll run some tests to check if its OK with the speed of the game or I'll need to accommodate more room to extras UDGs.

Cheers


Re: Mirror a sprite - britlion - 11-16-2018

Another way of doing it is to have (maybe compressed?) sprite data in storage, and unpack the sprites you need for this particular screen or part of the game to a buffer or workspace. You could then write out the reverse versions of these from one part of the workspace to another using the mirroring function.

Note that the fastest way to mirror a byte is a lookup table - so the first entry in the table is the mirror of "1" (128) and the second entry is the mirror of "2" (64), the third entry is the mirror of "3" (192) and so on.

The mirror code is pretty small and tight, though - and especially if you are using this to buffer out sprites in a screen by screen scenario, probably not too bad.


Re: Mirror a sprite - boriel - 11-28-2018

Another (memory expensive) faster way to reverse the bit in a byte is to have a table:
[0] -> [0]
[1] -> [BIN 10000000]
[2] -> [BIN 01000000]
.. and so on
but yet again you still have to reverse the byte order (this can be done in the routine if it reads the bytes in reverse order in memory)


Re: Mirror a sprite - britlion - 11-30-2018

boriel Wrote:Another (memory expensive) faster way to reverse the bit in a byte is to have a table:
[0] -> [0]
[1] -> [BIN 10000000]
[2] -> [BIN 01000000]
.. and so on
but yet again you still have to reverse the byte order (this can be done in the routine if it reads the bytes in reverse order in memory)

As I said in the last post Wink

Big Grin


Re: Mirror a sprite - boriel - 11-30-2018

britlion Wrote:
boriel Wrote:Another (memory expensive) faster way to reverse the bit in a byte is to have a table:
[0] -> [0]
[1] -> [BIN 10000000]
[2] -> [BIN 01000000]
.. and so on
but yet again you still have to reverse the byte order (this can be done in the routine if it reads the bytes in reverse order in memory)

As I said in the last post Wink

Big Grin
Certainly! sorry, I overlooked it.
BTW glad to see you alive and kicking. I'm working *very* hard in the new ZX Basic version, unfortunately I won't reach tomorrows deadline Sad
I have some improvements pending to include your libraries and some Fast floating point one.