Ralf wrote: ↑Wed Nov 15, 2017 9:48 am
The problem with beatemups is that they require a fast engine and a lot of memory for sprites. Sprites needs to be big and each actions requires a lot of frames to look nice. Needless to say it requires a good artist to draw them. I'm 90% programmer, 10% artist and I really struggled with these frames
Yet I wanted it to work on 48kB model. So I decided for empty background and lack of masks for sprites to save memory. Try just walking into enemy and you'll see that they are ORed one onto another. I don't know for sure how it would work in final game. Now we have Sword of Ianna, it uses OR method without masks and looks great so maybe there is hope for this approach.
I strongly recommend you to check out the following
masked sprite technique by
Jerri:
Code: Select all
;table-driven shift routine core (c) Jerri
;2 byte wide sprite example
;de = screen address
;h = shift table MSB
;sp = sprite
ld a,(de)
;left byte
pop bc
ld l,c
or (hl)
ld l,b
xor (hl)
ld (de),a
inc h
inc e
ld a,(de)
ld l,c
or (hl)
ld l,b
xor (hl)
dec h
;right byte
pop bc
ld l,c
or (hl)
ld l,b
xor (hl)
ld (de),a
inc h
inc e
;remainder of the right byte
ld a,(de)
ld l,c
or (hl)
ld l,b
xor (hl)
ld (de),a
dec h
;step down a line here as usual (INC D: LD A,D: AND #07 ...) and/or loop the routine (JP NZ ...), and so on
In more details, it works like this. You have a number of 256-aligned tables, each using two consecutive 256 byte segments per a single 'shift'. For instance if your sprites move in steps of 2 pixels, as is often the case, you would need 4 tables for shifts 0, 2, 4, 6. Or, depending which is more economical in terms of memory usage, you can discard the tables for shift 0 and treat this case as a less-wide sprite, drawn as-is.
Assuming HL is set to the first of the two tables, they are generated as such:
L = source byte
(HL) = 'left half' of the source byte, shifted as needed
(HL+256) = 'right half' of the source byte, shifted as needed
So for example if we're using a table of the 2 pixel shift, and the source byte is #C9 = %11001001, we have:
L = #C9
(HL) = %00 110010
(HL+256) = %01 000000
So basically in addition to the usual SpriteAddress, ScreenAddress, you now have the third input argument, Shift. From this, you calculate the required table, and set H to its MSB. Then proceed with the actual drawing the sprite, as in the code example above.
Tbh, I think this might just be the future of sprite drawing methods, at least for a number of applications. Not only you aren't required to store shifted copies of sprites anymore, you can also mirror them this way without any sort of extra speed penalty whatsoever (even though you'd need two versions of a sprite routine for each width, and 2x the amount of tables). It also lends itself very nicely for unrolling it the way it's usually done, as well as zigzag-drawing and such.
It is somewhat slower than the regular methods of course, but if you compare it with other options such as shifting in registers etc, the overhead is comparatively small.