Jump to content
IGNORED

In Development: Asteroids clone


Recommended Posts

I'm currently working on an Asteroids clone entitled Rasteroids. My goal is to make a clone that is closer to the arcade game that the versions I've seen (Asteroids, Meteorites, etc.) available on the 8-bit. There is much work to be done but basic asteroid and ship movement, firing, and some collision detection has been implemented. I'm curious to see if there is any interest in the community for such a game.

 

I've attached a couple of screenshots and a short AVI of the game running under Atari800Win Plus. Please bear in mind that the game is very much a work in progress at this point (i.e. Ship graphics need lots of work, Asteroids do not explode when hit, the player's ship cannot be destroyed, etc.).

 

-tjb

 

post-8855-1146624837_thumb.jpg

post-8855-1146624908_thumb.jpg

 

rastvideo.zip

Link to comment
Share on other sites

looks good so far

 

questions:

 

1) why artifacting turned on?

2) Antic F used? with 40 Byte scanlines?

3) sprite routines are based on EOR right?

4) how many objects will it possible to display?

5) double buffering?

 

i am just asking as i have played around years ago with a quick softsprite routine based on zoneranger by Activision.

Link to comment
Share on other sites

looks good so far

 

questions:

 

1) why artifacting turned on?

2) Antic F used? with 40 Byte scanlines?

3) sprite routines are based on EOR right?

4) how many objects will it possible to display?

5) double buffering?

 

i am just asking as i have played around years ago with a quick softsprite routine based on zoneranger by Activision.

 

I'd love to hear about these routines as well as the ones in ZoneRanger.

 

In regards to your questions:

 

1) why artifacting turned on?

 

I assume you are referring to having artifacting turned on in Atari800Win plus? I have it turned on to better approximate what the game will look like on real hardware. I've run it on a real Atari and the artifacting is actually not as bad.

 

2) Antic F used? with 40 Byte scanlines?

 

Yes, it uses Antic F.

 

3) sprite routines are based on EOR right?

 

Yes.

 

4) how many objects will it possible to display?

 

It really depends on the size of the objects. This is one area I realize I need to proceed with caution. Currently, the size of the largest asteroid is 32 x 32 pixels! Depending on how things work out I may have to shink it down somewhat.

 

5) double buffering?

 

At present I am not using double buffering but that is an interesting possibility. Are you referring to the use of page flipping?

 

I know you have alot of experience in sprite routines. Any suggestions/hints would be most appreciated.

 

-tjb

Link to comment
Share on other sites

Looks good. Are you implementing more ship angles than the original?

 

That was one of the big weaknesses of the original conversion.

 

I assume you're using a table lookup in the sprite routine to get the screen address based on the sprite's YPOS?

You can gain extra speed by creative table lookups.

 

I also would assume you are using pre-shifted sprite definitions?

 

A really nice feature would be tumbling/turning rocks but it might be rather expensive on memory - maybe do a 128K version?

Link to comment
Share on other sites

You could get turning rocks cheaply by having pre-shifted sprites with the animation dependant on the XPOS MOD 7 - slow moving rocks would turn slowly, fast moving rocks turn faster.

 

I would recommend using 2 sprite routines - the big rocks could be drawn faster with logic like:

 LDA ROCKDATA,X
 BEQ NOSTORE
 EOR (SCREEN),Y
 STA (SCREEN),Y
NOSTORE ...

 

2 extra cycles for a failed branch but several more saved for each blank byte in the sprite - the big ones would have a fair few.

 

Or, if double-buffer is used - just OR the data - no problems since only 1 bitplane is used... the "restore" routine would just store zeros where each sprite was.

 

Self-modifying code would be the way to go I think. Unrolled loops may or may not save time - the 6502 really needed postindexing modes like the 68000. The time you save with STA xxxx,Y vs STA (xx),Y can often be lost since you have to later do multiple updates to non-zero page locations rather than just having to update one or two z-page pointers.

It all comes down to the individual application.

 

I'm using SM code in Impossible Mission for the robot sprites - that allows me to merge and store a 8x24 pixel sprite (implemented in MC character mode) in well under 40 scanlines.

Edited by Rybags
Link to comment
Share on other sites

just an excerpt of the link i have posted

 

ok... another morning another info by heaven - the code spy... icon_wink.gif

 

the sprite engine is straight forward in zone ranger (s.a.)

 

0400-04bf

0500-057f lookuptables of scanline adresses

 

0e00 - 0ebf

0f00 - 0fbf lookuptables with 9er increment...

 

this was interesting... 9er? it seems so

unusual on 6502... but take a look again into

the code at $0600... how many bytes does it take to put one byte into vram?

 

lda ($fe),y ; 2

ora vram,x ; 3

sta vram,x ; 3

iny ;1

 

voila, 9 bytes.... this table is used

for self modifing code...

 

the core engine is located at $0260.

 

RTS ($60) is written directly via these look up tables into the code, with other lookup tables the engine knows how many scanlines has to be computed for each sprite and on which x-position...

 

at $02aa you find the entry JSR into the sprite copy routine at $0600 depending on y-position of the sprite...

 

the game itself does this at beginning:

 

1st init 5200 hardward

2nd generate lookup tables

3rd generate unrolled loops at $0600

4th unknown yet... icon_wink.gif

 

well... still some mysteries left... how are the sprites shifted? so they can be positioned on each pixel in x-direction?

and what are the lookuptables at $ae60,$ad40,$add0, $aef0 made for??? they

seem to contain the sizes of the sprites and other information... play around with these values and you see that the game will not crash but the sprites will differ & change...

 

more to come tomorrow morning...

Link to comment
Share on other sites

and the next one... more you might find in the old time pilot thread

 

another day...another try:

 

i had a closer look into the code at $0260 - the core sprite engine...

 

$ae60 - x-size of the sprites in bytes stored in $fc

$aef0 - y-size of the sprites in byts stored in $fd & y-register for the loop

 

$fa hold the byte which stands in the unrolled sprite copy routine and will be stored back when the sprite engine quits...

 

f.e. enter in the monitor "f $aef0 $af3f 2f" and all sprites turn into 32 pixel ones...

"f $ae60 $aeef 07" same in x direction...

 

now every sprite turned into 32x32 one... and you can continue the game with "cont" and see how fast zoneranger sprite engine really is... icon_smile.gif

 

$0260 combined with the unrolled copy code seems to be the core sprite engine... what i havent found yet is where are the preparations made so every sprite can be positioned on pixel bases... but when you make the above modifications in the table...it might be obvious that they are preshifted in ram...because while moving slowly the 32x32 sprites change there shape because the data is switched every pixel...

so they are definitly not preshifted in realtime... $fe contains the sprite data adress and is changed every next sprite (wow...what a trick... icon_wink.gif...

 

maybe tomorrow i have more informations...

 

the engine is quite tough... with EORing the stuff you get definitly rid off a clear screen routine...you jusr run twice through the sprite engine...

 

and you can have this lovely game logo staying there without the need to copy it there...

 

hve

 

ps. i will go for this engine for timepilot... seems quite usefull for that... and time pilot has same amount of sprites and sizes... so it could work really good...

Link to comment
Share on other sites

don't do

 

eor (screenvector),y

sta (screenvector),y

 

as your screen vram is fixed anyway... so you can have

 

lda (spritedata),y

eor vram,x

sta vram,x

iny

eor vram+1*40,x

sta vram+1*40,x

iny

lda (spritedata),y

eor vram+2*40,x

sta vram+2*40,x

...

iny

lda (spritedata),y

eor vram+31*40,x

sta vram+31*40,x

rts

 

so you can have a long runrolled loop f.e. 32 bytes vertical (as you said 32x32 = 4x32 bytes total). with a nice lookup table the sprite engine can put the RTS command directly into the sprite draw code draw a vertical stripe, increase X register (remember 4 collums do we need to draw for a 32x32 sprite) , draw next stripe until all 4 are drew. then restore the RTS with the old command in the sprite draw code.

 

with this you can update your spritedata pointer for animation etc...

 

how many different sprites will there be on screen?

Link to comment
Share on other sites

More potential time saving can be had by storing the sprites in a data structure similar to an actual screen. For a 32x32, have each group of 4 bytes on a 40 byte boundary.

 

Then, you can use the same index register for sprites and screen.

Plus, use a slightly unrolled loop - utilizing the index register to its full capability means you only go through the time-consuming process of updating the screen and sprite pointers for every 6th line.

 

 LDA #5
 STA VCOUNT; 5 iterations of the outer loop
DOSPTRITE1 ; outer loop starts here
 LDX #6; do 6 lines (6x40 = 240)
 LDY#0 
DOSPRITE2
 LDA (SPRITEPTR),Y ; get the sprite data (1st byte of line)
 EOR (SCREENPTR),Y ; EOR with existing
 STA (SCREENPTR),Y ; store it
 INY
 LDA (SPRITEDATA),Y ; get the sprite data (2nd byte of line)
 EOR (SCREENPTR),Y ; EOR with existing
 STA (SCREENPTR),Y ; store it
 INY
 LDA (SPRITEDATA),Y ; get the sprite data (3rd byte of line)
 EOR (SCREENPTR),Y ; EOR with existing
 STA (SCREENPTR),Y ; store it
 INY
 LDA (SPRITEDATA),Y ; get the sprite data (4th byte of line)
 EOR (SCREENPTR),Y ; EOR with existing
 STA (SCREENPTR),Y ; store it
 TYA
 CLC #37
 TAY
 DEX
 BNE DOSPRITE2
 DEC VCOUNT
 BEQ FINISHED; outer loop complete - now exit
 LDA SCREENPTR
 CLC
 ADC #240; 6 x 40
 STA SCREENPTR
 BCC NOINC1
 INC SCREENPTR+1
NOINC1
 LDA SPRITEPTR 
 CLC
 ADC #240
 BNE NOINC2
 INC SPRITEPTR+1
NOINC2
 JMP DOSPRITE1; back for outer loop
FINISHED 
 RTS; exit

Link to comment
Share on other sites

Looks good. Are you implementing more ship angles than the original?

 

That was one of the big weaknesses of the original conversion.

 

I assume you're using a table lookup in the sprite routine to get the screen address based on the sprite's YPOS?

You can gain extra speed by creative table lookups.

 

I also would assume you are using pre-shifted sprite definitions?

 

A really nice feature would be tumbling/turning rocks but it might be rather expensive on memory - maybe do a 128K version?

 

 

>>Looks good. Are you implementing more ship angles than the original?

 

Thanks. Currently the player's ship has 24 different positions. I believe Atari's has 16?

 

>>I assume you're using a table lookup in the sprite routine to get the screen address based on the sprite's YPOS?

>>You can gain extra speed by creative table lookups.

 

>>I also would assume you are using pre-shifted sprite definitions?

 

You're right on the money. I am using both a table lookup to find the screen address of the beginning of the row based on the sprite's Y position and pre-shifted sprite definitions.

 

>A really nice feature would be tumbling/turning rocks but it might be rather expensive on memory - maybe do a 128K version?

 

I had rotating rocks initially. It got pretty expensive as you mentioned in terms of memory - especially when you have several frames to make the animation smooth. I'd like to try adding them back at some point. Maybe there will be another version as you suggested - "Rasteroids Deluxe" :D

 

-tjb

Link to comment
Share on other sites

I really like the in-depth discussion on sprite engine techniques. If I would have known posting would have led to this I would have posted much sooner :)

 

Please, continue...

 

-tjb

Link to comment
Share on other sites

I think that unwound loop ZR method Heaven posted would be the way to go.

 

Probably split the big asteroids into 5 "strips"

 

ie - 1 strip for left/right columns and the 2nd column

2 strips for the 3rd column - looks like there are a lot of zeros in there. Although, circumstances change depending on the XPOS value I suppose.

 

Maybe reduce the size of the asteroids from 32 to 28 pixels wide? That way, you only do 4 columns instead of 5 of them 50% of the time.

 

Probably do some cycle counting exercises on the rendering of the smaller asteroids - might be quicker to render them a different way?

 

Investigate using page flip (double-buffer) - then you can just ORA the data, and store in zeros instead of the second call with EOR. Big extra memory cost, but a saving in cycles, plus any flickering issues will go away.

 

How will you be doing collision detection (ie shots to rocks)? Apparently, the arcade version uses "collision hexagons" where somehow objects are mapped into hexagon shapes.

Link to comment
Share on other sites

can you post or send me the sprites of the 3 rocks? thanks! i would like to make a test... ;)

 

I'm actually at work at the moment. I can send them later today. What format? Can I send you .bmp files?

 

-tjb

Link to comment
Share on other sites

I think that unwound loop ZR method Heaven posted would be the way to go.

 

Probably split the big asteroids into 5 "strips"

 

ie - 1 strip for left/right columns and the 2nd column

2 strips for the 3rd column - looks like there are a lot of zeros in there. Although, circumstances change depending on the XPOS value I suppose.

 

Maybe reduce the size of the asteroids from 32 to 28 pixels wide? That way, you only do 4 columns instead of 5 of them 50% of the time.

 

Probably do some cycle counting exercises on the rendering of the smaller asteroids - might be quicker to render them a different way?

 

Investigate using page flip (double-buffer) - then you can just ORA the data, and store in zeros instead of the second call with EOR. Big extra memory cost, but a saving in cycles, plus any flickering issues will go away.

 

How will you be doing collision detection (ie shots to rocks)? Apparently, the arcade version uses "collision hexagons" where somehow objects are mapped into hexagon shapes.

 

Thanks for all the ideas. I'll have to look into them. The only collision at present is checking to see if a bullet hits an asteroid. It uses the simple bounding-rectangle method. I'm open for suggestions.

 

-tjb

Link to comment
Share on other sites

Maybe have a two-level collision routine:

 

You should keep the screen X-index of the asteroids (0-39) in a buffer (for the restore operations).

 

Then, just convert the missile X to a 0-39 value.

 

Create a similar table for the Y values (0-23).

 

For each missile, subtract the Y value of the asteroid. Then CMP #4. Carry set=out of area.

 

Do the same for X value.

 

Both tests satisfied means the missile/asteroid are in the same viscinity - so go onto level 2 collision detect code:

 

Have a table for each Y value of the asteroid (e.g. 32 entries). Each entry has the actual offset of the start X and end X of the rock in relation to it's screen X value.

 

You then just have to do a range check on 1 or 2 Y entries comparing with the missile's position.

 

Probably better ways to do it. Maybe even have a 5 bytes (40 bits) x24 bitmap where you can represent the presence or absence of the asteroids.

Then for each missile, you have a single bit which has to be tested within that bitmap to see if it's a candidate for a collision.

 

The bitmap entries for big asteroids would have a 2x40 byte table, possible values would be (assuming here that x is the byte offset for the object within a screen line)

 

%11110000, %00000000 (x=0)

%01111000, %00000000 (x=1)

...

%00000001, %11111110 (x=7)

Link to comment
Share on other sites

a bmp is fine but i can do my own asteroids for testing in turbo basic xl...

 

the collision description looks interesting i have to think about it...

 

what about the following... who said that you need to use bitmap gfx for the shots as well?

 

what about using 7 player/missles for the "missles" and 1 remaining player for the ufo?

 

whould this destroy the highres look and feel as you can not define player/missles in antic F pixel size?

 

but you could then use the hardware collision checking which might quicker than the boundary box one... but this would mean that you have to sync the collision checking very carefully with the sprite engine otherwise the missles might get inside an asteroid... ;)

 

oh...how many shots can you fire at once in the arcade? as we need bullets for the ufo as well...

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...