Page 1 of 1
Sprite transparent pixels issue
Posted: Mon Nov 18, 2019 1:10 pm
by Kitsune Mifune
Been getting on rather well (albeit slowly) with my game, but I've run into a small issue with the sprites.
I thieved a piece of code from the CPC forums to use in the draw routine. It checks for transparent pixels in the sprite frame and doesn't draw them. It works really well, and I actually know what's going on in the code (in theory), but there are still some blue pixels around the edge of the sprite that it seems to have missed and they are still showing. The picture below shows what's happening:
It seems to be skipping over a horizontal pixel byte, because it looks like it's every second byte that is being checked when it reaches the actual player pixels. I'm sure that one Mode 0 pixel is one byte, but it looks like it's taking it as two per byte.
This is the code I'm using. As always, many thanks in advance!
Code: Select all
DRAW2SCREEN:
ld a,(SPRITE_HEIGHT) ; Load sprite height value to 'a'
ld b,a ; Height (LINES)
Spritenextline:
push hl
ld a,(SPRITE_WIDTH) ; Width (BYTES)
ld c,a ; Bytes per line
SpriteNextByte:
ld a,(de) ; Read sprite pixels
inc de ; Update sprite pixel pointer
or a ; Zero (i.e. fully transparent?)
jr z,NO_MASK ; If yes, then skip
ld (hl),a ; If no, then write byte to screen
NO_MASK:
inc hl ; Increase destination (Screen) Address
dec c ; Repeat for next byte
jr nz,SpriteNextByte
pop hl
call GetNextLine ; Scr Next Line (Alter HL to move down a line)
djnz SpriteNextLine ; Repeat for next line
RET
Re: Sprite transparent pixels issue
Posted: Wed Nov 20, 2019 11:19 pm
by akuyou
Yes, this is to be expected - a mode 0 pixel is one NIBBLE (4 bits... 0-15) - so there are TWO Mode 0 pixels per byte - if both aren't zero then you'll get the blue outline you're seeing.
This is the same transparency method ChibiAkumas used by the way! the black borders around the characters worked well in that case, as it made them look 'cartooney'
I think you have two options
1. Redraw the sprites so the effect is less noticable (maybe make color 0 black?)
2. Change the code and use a different transparency routine... a 'Look up table' is a commonly used method - you can create a 256 byte table of 'Masks' to remove the background (via AND command) - looking up the byte value from your sprite to work out the correct mask to remove the non zero bytes, then OR in your sprite over the top... It's not something I've used, but games like Operation Wolf can be seen doing it in disassembly.
Re: Sprite transparent pixels issue
Posted: Thu Nov 21, 2019 9:15 am
by Kitsune Mifune
Thank Keith.
I tried setting the background colour to black, and it was definitely an improvement, but it's a bit too blocky for my eyes. I'll look in to another way of removing the transparency. I've not used LUTs much, so maybe this will be a good exercise.
Re: Sprite transparent pixels issue
Posted: Fri Nov 22, 2019 10:29 pm
by akuyou
You've probably figured it out by now, but I though I'd cover this in my tutorials at some point so...
I've added a new file to the Z80 sources.7z on my webiste 'CPC_Bitmap_Transparent.asm'
This will show a sprite 3 times, once with no transparency, once with 'zero byte' as above... and the final with the lookuptable

- screencap.jpg (9.22 KiB) Viewed 12709 times
Here's the code I used to build the LUT:
Code: Select all
ld hl,TranspLUT
ld (hl),%11111111 ;Both pixels kept
BuildLutAgain:
inc l
jr z,LUTdone ;Done all 256
ld a,l
and %01010101 ;Right Pixel Mask
jr nz,BuildLut2
ld (hl),%01010101
jr BuildLutAgain
BuildLut2
ld a,l
and %10101010 ;Left Pixel Mask
jr nz,BuildLutAgain
ld (hl),%10101010
jr BuildLutAgain
LUTdone:
And to show the sprite:
Code: Select all
DrawSpriteT:
ld de,TestSprite ;Sprite Source
ld ixh,64 ;Lines (Height)
ld bc,TranspLUT
SpriteNextLineT:
push hl
ld ixl,8 ;Bytes per line (Width)
SpriteNextByteT:
ld a,(de) ;Get Sprite Byte
ld c,a ;Change Low Byte of LUT
ld a,(bc) ;Get Mask for Sprite Byte
and (hl) ;Mask current pixel out of back
or c ;Or in new pixel
ld (hl),a ;Save to screen
inc de ;INC Source (Sprite) Address
inc hl ;INC Dest (Screen) Address
dec ixl ;Repeat for next byte
jr nz,SpriteNextByteT
pop hl
call &BC26 ;Scr Next Line (Alter HL to move down a line)
dec ixh
jr nz,SpriteNextLineT ;Repeat for next line
ret
Re: Sprite transparent pixels issue
Posted: Sun Nov 24, 2019 9:40 am
by Kitsune Mifune
This is great! It works beautifully. Thank you.
I had made some ham-fisted attempt at another transparency method, but I wasn't really getting anywhere.
Would this work with a flipped image? I only ask because I'm literally just about to try and attempt a sprite flipping routine, so may as well try and work it into that too, and I assume some tweaking will be needed for the reversed bits.
Excellent stuff though. I understand LUTs a little better now just seeing how this works.

Re: Sprite transparent pixels issue
Posted: Sun Nov 24, 2019 11:12 am
by akuyou
There's no reason this wouldn't work combined with the 'flip image' lookup table..
This code will work with any sprite that's got color 0 as transparent.... you'd just need to 'chain' this lookup code with the 'flipping' lookup code you have
*** Update! - Example attached! ***
You may be a bit short of registers at that point!... By the way, are you familiar with the 'stack misuse' trick, using the stack pointer for fast data reading, rather than just temporary storage... I only mention it because your game looks to be using pretty big sprites, and all fast CPC games will probably use it (OPWolf and my ChibiAkumas both did)
I covered it to some extent in my Z80 tutorials... it's tricky, so it's not something you need to worry about now, but you'll probably want to use it in your final game...
https://www.chibiakumas.com/z80/index.php#Lesson8
You'll also want to lookup unwrapped loops, if you've not come across them yet when you're looking for 'super speedy sprites'.
Re: Sprite transparent pixels issue
Posted: Sun Nov 24, 2019 12:44 pm
by Kitsune Mifune
Excellent! I'll have a look at that Stack trick.
I've pretty much resigned myself to the fact that the game is going to be slow, but as long as it's comparable to the original Amstrad Final Fight conversion in terms of speed then I'll be happy, and any little tricks to boost speed will be great. The original was actually fairly decent in terms of speed, it was just the jumping which was slow. I know it was a rush job, and it's actually running Richard Aplin's Double Dragon II code underneath, and I think that saved on some CPU load by slicing the sprites horizontally so that there's less transparent pixels to check (or something).
Anyway, I'll report back once I've figured out how to actually flip the sprites. I've got a 30 byte piece of code off of a French website that I'm trying out, so fingers crossed it works and I can incorporate the masking code.
Thanks again for the help!
If I can remember my YouTube password I'll try to jump on one of the Saturday live streams at some point when I'm not in the studio recording rubbish bands.