Page 1 of 1

My projects

Posted: Mon Nov 13, 2017 9:23 pm
by Ralf
In an attempt to make this forum alive ;) I'll be showing here in this thread some my unfinished game projects.

There was a time a few years ago when I was coding like crazy, doing several games at once.

Now it's unfortunately less time, motivation and stamina but I hope to finish at least some of them one day.

I was going to keep it all secret until release but as there may be not any release it doesn't matter now.

There is also good news, for 99% I'll be realising a new platform game, quite big as for me in December this year.

Please visit this thread from time to time. Screenshots and downloads to follow soon :)

Re: My projects

Posted: Tue Nov 14, 2017 10:08 am
by Ivanzx
I remember the old thread from WoS with a lot of screenshots from your projects, some of them looked excellent ;)

Looking forward to seeing them here, maybe you get an extra motivation over here and are able to finish some!


By the way do not forget the ZX Dev Conversions! We are waiting for you!! :P

Re: My projects

Posted: Tue Nov 14, 2017 9:37 pm
by Ralf
Hi Ivan, nice to see you here!

Yes, I made once some post on WOS about my unfinished projects but now i'm going to show more :)

As for Zx Dev Conversions my game that I'm going to finish in December is more an inspiration than faithful conversion. I'll see if you accept it at all ;)

Okay, let's start with my old, unfinished projects.

I have always been a fan of fighting games and wanted to make one. But unfortunately it's a rather hard genre for programming, much harder than platformer, maze or puzzle

I have 3 (!) unfinished projects (2 at rather early stage) involving fighting. Today I'm showing first of them, called Swordmaster.

I wanted to do one on one fighting game but was some kind of realistic that something like Street Fighter or Mortal Kombat could be too hard. So I searched an easier inspiration and found - arcade game from 80s called Hippodrome:

http://www.mobygames.com/game/arcade/hippodrome

Image

I don't remember why I changed name from Hippodrome to Swordmaster. Maybe it was something about copyrights or maybe there isn't actually any hippodrome in my version.

It's done in about 25%. You can't have a real fight but you can kill 1st enemy ;)

Image
Image

Early demo download:
https://www.sendspace.com/file/bz31k2

Re: My projects

Posted: Tue Nov 14, 2017 10:17 pm
by R-Tape
Like it Ralf.

Was going to say "you never see fighting games or big sprites these days", but Sword of IANNA keeps spoiling it every time I want to say something like that!

Is there a lot more to do on the player's moves? Unless you're sticking faithfully to Hippodrome I'd like to see a Speccy fighting game with key combos for special moves, e.g. back, back, forward+fire for something extra powerful.

Re: My projects

Posted: Wed Nov 15, 2017 9:48 am
by Ralf
It was supposed to be quite fathful to Hippodrome so no combos unfortunately.

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.

Another problem for me was building sprites from smaller parts. A standing hero is 4 bytes wide, when he makes a sword attack he suddenly becomes 7 bytes wide. You must have procedures for sprites of different width - I discovered that one general procedure was too slow for me so I heavily optimized, unrolled the loops and so on.

So every sprite is actually a table of sprites like body, sword and tail for the snakeman.

I didn't touched this particular project for 3 years or so and now would like to finish other stuff first. But who knows, maybe one day I'll return to it :)

Re: My projects

Posted: Wed Nov 15, 2017 10:55 am
by Hikaru
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.

Re: My projects

Posted: Thu Nov 16, 2017 6:58 pm
by Ralf
Thanks Hikaru for this code.

I'm already using in some my later games tables of shifted bytes + table of mirrored bytes. Of course not all my games, but for example in Janosik and my new game to appear in December. I actually started from very lame code and improved with each game.

Just tell me as I'm lazy and it's late ;) Does this code do some masking? Is it using some autogenerated on the fly masks?

Re: My projects

Posted: Thu Nov 16, 2017 7:18 pm
by Hikaru
Ralf wrote: Thu Nov 16, 2017 6:58 pm Thanks Hikaru for this code.

I'm already using in some my later games tables of shifted bytes + table of mirrored bytes. Of course not all my games, but for example in Janosik and my new game to appear in December. I actually started from very lame code and improved with each game.

Just tell me as I'm lazy and it's late ;) Does this code do some masking? Is it using some autogenerated on the fly masks?
Well, it displays masked sprites on the screen as I said. :) As for the sprite masks, they are just regular sprite masks, stored together with sprite data as usual (byte 0: mask, byte 1: sprite, and so on). This algorithm shifts both the mask and sprite data as needed on the fly while it is drawing the sprite.

Re: My projects

Posted: Thu Nov 16, 2017 7:34 pm
by Ralf
Okay, I was fooled by these XOR. I use first AND for mask and later OR for sprite.

In Janosik I also used 8 versions of sprite routine: for sprites with Y position at 0,8,16,24... another version for Y at 1,9,17,25... and so on.

The source of serious delay in sprite drawing is going one line down. In universal code you would probably do:

Code: Select all

INC H
LD A,H
AND 7
JR NZ,End

LD A,L
ADD A,32
LD L,A
JR C,End

LD A,H
SUB 8
LD H,A

End:
When you do 8 versions, then you just do in each version INC H and nothing more in 7 cases and full check always in 1 case.

Re: My projects

Posted: Thu Nov 16, 2017 7:58 pm
by Hikaru
Ralf wrote: Thu Nov 16, 2017 7:34 pm Okay, I was fooled by these XOR. I use first AND for mask and later OR for sprite.

Yes, this is needed in order to use the same tables for both the sprite/mask data. Here, the masks aren't stored in an 'inverted' format, as is usually the norm, but instead have the same 'polarity' as the sprite data (so they look kinda like black shadows, or outlines).

Ralf wrote: Thu Nov 16, 2017 7:34 pm In Janosik I also used 8 versions of sprite routine: for sprites with Y position at 0,8,16,24... another version for Y at 1,9,17,25... and so on.

The source of serious delay in sprite drawing is going one line down. In universal code you would probably do:

Code: Select all

INC H
LD A,H
AND 7
JR NZ,End

LD A,L
ADD A,32
LD L,A
JR C,End

LD A,H
SUB 8
LD H,A

End:
When you do 8 versions, then you just do in each version INC H and nothing more in 7 cases and full check always in 1 case.

There's a way to avoid using 8 Y-unrolled versions of sprite routines, with only a single routine and a block of JP's. Like this:

Code: Select all

	ld a,h			;somewhere close to the sprite routine entry point...
	and #07
	ld e,a
	add a
	add e
	ld (.LOC_Jmp),a
.LOC_Jmp=$+1
	jr $+2
	jp .line0
	jp .line1
	;...
	jp .line7
.line0
	pop de
	ld a,(hl)
	and e
	or d
	ld (hl),a
	inc l
	;...
	inc h
.line1
	;...
;.line2, 3, 4 ... 7
Actually, you need to have two blocks of JP's, the second one for drawing the last few lines, but that's more or less the idea. I've used this in the demo of CATS Faith.