News:

Printed Amstrad Addict magazine announced, check it out here!

Main Menu
avatar_ervin

Chunky Pixel Collision

Started by ervin, 15:35, 15 December 10

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

ervin

Hi all.

I'm several weeks into the development of a new game, which I have named "Chunky Pixel Collision" (see what I did there?)

I've been spending pretty much all the dev time thus far on writing the engine.
It features big fat chunky pixels, being thrown around pretty fast on a full-screen mode 0 display.
Also, sprites displayed in this system are clipped to all four screen edges correctly.

The pixels are twice the width of a mode 0 pixel, and 4 times as high.
A chunky square, in other words.
So effectively a full-screen resolution of 80x50 "pixels".

There are two reasons I went down the path of big fat pixels.
1) Performance. I've written a routine that fills 8 mode 0 pixels really quickly (ie. one of my fat pixels).
2) It looks really cool (if you like that sort of thing).

I don't want to announce the style of game I'm hoping to create just yet... in case I fall flat on my face.

Anyway, I wanted to put together a little demo for anyone that is interested.
I tried to think of the biggest, chunkiest cpc sprite around.
Who would you think of?

Well, I thought of the man himself, Savage.

I've been itching to show this to you all, so please download the dsk and have a go!
He can be moved around the screen using the cursor keys.
He clips correctly on all four sides, and he is completely redrawn every frame.
I'm getting around 10 frames per second at the moment, but there are some major optimisations I plan to incorporate (once I figure out how to do them!).

Can someone please try this on a real cpc?
I'm not sure if it will work on a 464, though.
Thanks.

redbox

Hey Ervin, I gave you a greeting in my new demo about your programming, so you've replied quickly!

Looks interesting and works on my 6128 Plus.

What optimisations are you working on?  I see lots of IX registers in your code which are useful but slooooooow in a loop.

fano

#2
Run perfectly on a 6128 type 1 and 6128+  ;)
It is an interesting concept , i am keen to see how you'll use it.
"NOP" is the perfect program : short , fast and (known) bug free

Follow Easter Egg products on Facebook !

Phi2x

#3
.

ervin

#4
Quote from: redbox on 16:09, 15 December 10
Hey Ervin, I gave you a greeting in my new demo about your programming, so you've replied quickly!

Looks interesting and works on my 6128 Plus.

What optimisations are you working on?  I see lots of IX registers in your code which are useful but slooooooow in a loop.

Thanks for the greeting in your demo! That's the first time I've ever been referenced in a cpc production! Very nice demo too.

The optimisations involve figuring out how to only draw the bits of the screen that change between frames. As you will no doubt remember  ;) , I spent a fair bit of time researching that concept during the 3d-maze development. I'll try to use those ideas in chunky pixel. That should make it run much faster.

Did you disassemble the code?  :)
IX and IY are used as extra registers during the part of the program that draws the screen.
I do 8 pops (to retrieve the sprite data), and then 4 sets of 8 pushes. 4 rows of 16 fat pixels are taken care of this way.

The code looks a bit like this:


pop af
pop de
pop bc
pop ix
pop iy
exx
pop hl
pop de
pop bc
exx

ld sp,hl
exx
push bc
push de
push hl
exx
push iy
push ix
push bc
push de
push af


SET and RES (thanks to Axelay for the SET 3,H idea) are used to move to the 2nd, 3rd and 4th raster lines for each "pixel".

ervin

Quote from: fano on 21:01, 15 December 10
Run perfectly on a 6128 type 1 and 6128+  ;)
It is an interesting concept , i am keen to see how you'll use it.

Cool, thanks for testing on real machines.
I wish I could do the same.    :(

ervin

Quote from: phi2x on 21:23, 15 December 10
I think I know what you're about to do. 8)

I watched your demo on CPCBox, runs great on it! It immediately bringed back some memories of a certain Amiga game that was deemed impossible to do. The name starts with Gl.... ;)

:-\  I probably shouldn't have hyped this up like I did (I was just so excited to have created something kinda cool).
Having a cpc version of Gloom would be amazing (that was a GREAT game, by the way), but my skills and mathematical knowledge just aren't up to it.

My game concept is indeed 3D, but not raycasting 3D. More along the lines of space harrier, without the shooty bits.

Now I'm off to optimise it, before getting to work on the 3D stuff itself!

redbox

Quote from: ervin on 23:58, 15 December 10
Thanks for the greeting in your demo! That's the first time I've ever been referenced in a cpc production! Very nice demo too.

Thanks, glad you enjoyed it!

Quote from: ervin on 23:58, 15 December 10
The optimisations involve figuring out how to only draw the bits of the screen that change between frames. As you will no doubt remember  ;) , I spent a fair bit of time researching that concept during the 3d-maze development. I'll try to use those ideas in chunky pixel. That should make it run much faster.

This is what I thought of as I remember discussing it before and you said that you draw the whole sprite each time.  I guess only drawing the bits that change largely depends on how much it needs to move each frame - if you are moving it by one whole fat pixel (infact I think I saw it moved more than that when I pressed a key) you might not have as much overlap...?  Testing would be the only way to find out!

Quote from: ervin on 23:58, 15 December 10
Did you disassemble the code?  :)
IX and IY are used as extra registers during the part of the program that draws the screen.
I do 8 pops (to retrieve the sprite data), and then 4 sets of 8 pushes. 4 rows of 16 fat pixels are taken care of this way.
SET and RES (thanks to Axelay for the SET 3,H idea) are used to move to the 2nd, 3rd and 4th raster lines for each "pixel".

Yes, I had a quick look and looking again now I see you've got some cool stuff in there - use of the stack, alternate registers, the SET and RES trick - great stuff.  I guess your optimisation will largely depend on the draw/not draw routines above then  :)

ervin

Yes, the code I uploaded moves Savage 2 "pixels" at a time, by referencing a moveAmount variable.

Yeah the optimisation and algorithms I've used so far have been based on a lot of trial and error, and a heck of a lot of help from stuff I've learned here on these forums.
What an amazing resource.

Just imagine what the devs 20+ years ago could have come up with if they had such a great knowledgebase at their fingertips...

Axelay

Nice effect!  :)  Will be interesting to see how it develops further into a game.


I tried it on my unexpanded CPC464 and it seems to work just fine.


Also, sorry to pry into your code (but you mentioned using set 3,h and I couldnt help myself but have a little look) but I noticed you have done the lines in 'numerical' order, 1,2,3,4,5,6,7,8 - which sometimes requires multiple sets/resets.  I didnt look into the code enough to see the wider view of how it all works, but could you not do the lines in the order that only requires a single set or reset to get to each new line and save a little time?


like this say:


do line 1
set 3,h
do line 2
set 4,h
do line 4
res 3,h
do line 3
set 5,h
do line 7
set 3,h
do line 8
res 4,h
do line 6
res 3,h
do line 5

fano

Quote from: Axelay on 12:29, 16 December 10
do line 1
set 3,h
do line 2
set 4,h
do line 4
res 3,h
do line 3
set 5,h
do line 7
set 3,h
do line 8
res 4,h
do line 6
res 3,h
do line 5
This one is great , if you agree , i am going to borrow it to get a little further optimisation  ;D (crap ! i'll have to rewrite some tools code)
"NOP" is the perfect program : short , fast and (known) bug free

Follow Easter Egg products on Facebook !

arnoldemu

Quote from: fano on 12:43, 16 December 10
This one is great , if you agree , i am going to borrow it to get a little further optimisation  ;D (crap ! i'll have to rewrite some tools code)
I agree. this is great.
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

redbox

Quote from: arnoldemu on 12:44, 16 December 10
I agree. this is great.

Me too.

For this to work, the first line still has to be locked to an even address line though (assuming y=0 to start)...?

But for compiled sprites, it's quite an optimisation.


ervin

#13
Quote from: Axelay on 12:29, 16 December 10
do line 1
set 3,h
do line 2
set 4,h
do line 4
res 3,h
do line 3
set 5,h
do line 7
set 3,h
do line 8
res 4,h
do line 6
res 3,h
do line 5

Thanks Axelay.
Glad to hear that it works on a 464 - although that may not be the case in a little while, as there will hopefully be many, many sprites in this game, and for that I'll need to learn how to use the extra memory banks of the 6128.

With the set/res stuff, I originally did have it like that, and only had one set or res per line change.
The problem was the there was the very occasional venetian blind effect appearing and making the screen tearing far more obvious (I've accepted the screen tearing as I won't have enough memory to do double buffering).
So I changed it to go from the top line to the bottom within each section. The speed penalty was small enough to be excusable.

Now I'm gonna try and figure out a way to store the huge Savage sprite in half the number of vertical columns, thereby halving the memory to store him. Sounds easy... except that catering for clipping on the left and right complicates matters... oh the joys of brain exercise!

Phi2x

#14
.

ervin

Quote from: phi2x on 14:17, 16 December 10
It is also possible to do the rasterline height stretching by hardware instead of using the z80. That would give you tremendous speedup.
You should check the CPC demo called "Overflow's Backtro". The technique used there is based on the following CRTC trick: if R1 has a higher value than R0 then the CRTC video repeats the same line again and again.

Don't know how practical it would be for a game though. That technique needs precise synchronizing of your code with the CRTC, switching R1 value every four rasterlines.

Now that does sound interesting!
Unfortunately it may be beyond the scope/intent of this project, and certainly beyond my skill!
I'm still pretty new to z80 coding, so I'll probably have trouble figuring that sort of thing out.

Axelay

Quote from: ervin on 13:49, 16 December 10

With the set/res stuff, I originally did have it like that, and only had one set or res per line change.
The problem was the there was the very occasional venetian blind effect appearing and making the screen tearing far more obvious (I've accepted the screen tearing as I won't have enough memory to do double buffering).
So I changed it to go from the top line to the bottom within each section. The speed penalty was small enough to be excusable.



Ah, that makes sense.  I thought I was seeing tearing so that it wasnt double buffered, but I didnt twig to the implications of that for a process that takes longer than a frame.  Bummer.  You really going for 128k only and still not enough ram for two screens though?  Yikes!


Quote from: redbox on 12:53, 16 December 10
Me too.

For this to work, the first line still has to be locked to an even address line though (assuming y=0 to start)...?

But for compiled sprites, it's quite an optimisation.




Yes, in Dead on Time, the sprites were either locked to every second or fourth address line depending on the need for the sprite, so they would be y val 0,2,4,6 etc, or 0,4,8,12 etc.  I think fonts are the only things I've locked to whole character lines though.

ervin

Quote from: Axelay on 14:53, 16 December 10
Ah, that makes sense.  I thought I was seeing tearing so that it wasnt double buffered, but I didnt twig to the implications of that for a process that takes longer than a frame.  Bummer.  You really going for 128k only and still not enough ram for two screens though?  Yikes!

Yeah, I'm going for a crazy number of sprites in this one, and I want to do it without post-loading disk access.
All part of the fun!  :)

redbox

Quote from: Axelay on 14:53, 16 December 10
You really going for 128k only and still not enough ram for two screens though?

So if you use 128kb then you page in the last 16k of the extra 64k to &C000 for double buffering...?

And this would mean all your routines could be hardcoded to &C000...  If so, I never thought of this (for some reason).  Drawback is of course it's 128kb only.

Phi2x

#19
.

ervin

Quote from: redbox on 15:05, 16 December 10
So if you use 128kb then you page in the last 16k of the extra 64k to &C000 for double buffering...?

And this would mean all your routines could be hardcoded to &C000...  If so, I never thought of this (for some reason).  Drawback is of course it's 128kb only.

I'm planning on storing the sprite data in the extra banks, and paging that in as required.
I have no idea how to do this... but I'll do my best to figure it out!

redbox

Quote from: phi2x on 15:22, 16 December 10
That won't work, the gate array doesn't have access to mapped RAM! It can only use the plain unmapped first 64KB of RAM.

Oh well, nice idea.  Thanks for letting me know  :)

ervin

#22
Okay, some progress has been made.

I had to change the data structure that stores the sprite info, to make it flexible enough for what the sprites will need to do.

This meant also rewriting the sprite manipulation+positioning+clipping code as well.
That was fun.  ???

Anyway, it seems to work perfectly now.
I hope.

The only drawback is that it is very slow. Slower than a snail pulling a caravan, in fact.
It's running at around 3.6 fps at the moment.
Luckily it is completely unoptimised C-like code (using the brilliant ccz80 compiler), which was done in order to figure out some really efficient algorithms.

Now it's time to convert it to machine code, and make those z80 registers work hard!

AMSDOS

When you're referring to using a crazy number of sprites in this game, you're not talking about having many sprites onscreen at once? Having many on the screen at once (even when using Assembly), will ultimately slow down the program! :( This mightn't be a problem on the Plus if that's what your using - personally though I'm not sure.
* Using the old Amstrad Languages :D   * with the Firmware :P
* I also like to problem solve code in BASIC :)   * And type-in Type-Ins! :D

Home Computing Weekly Programs
Popular Computing Weekly Programs
Your Computer Programs
Updated Other Program Links on Profile Page (Update April 16/15 phew!)
Programs for Turbo Pascal 3

ervin

Quote from: CP/M User on 06:12, 21 December 10
When you're referring to using a crazy number of sprites in this game, you're not talking about having many sprites onscreen at once? Having many on the screen at once (even when using Assembly), will ultimately slow down the program! :( This mightn't be a problem on the Plus if that's what your using - personally though I'm not sure.

The version I was working on before I put Savage in contained 12 Miner Willy sprites, that were 64 pixels tall (that's 64 normal pixels, as opposed to the chunky pixels I'm creating).
They were moving around the screen at around 11-12 fps.
That didn't contain the final big optimisation I plan to make.

Having lots of large-ish sprites on the screen at once is looking possible.  :)

Powered by SMFPacks Menu Editor Mod