Jump to content
IGNORED

Sprite Routine Development (for Atari 8bit)


Recommended Posts

Emkay, can you please post a screenshot of g2f mockup screens just the antic 4 screen and just the pm data separate?

 

it makes it more visible how the pm data is handled in your example.

 

thanks.

 

The original game is done in Antic E, so the playfield graphics are built on 4 colors.

With charmode the screen can have some more "depth".

Link to comment
Share on other sites

  • 2 weeks later...

Okay here's my very first Smartfont Demo (v.0.0)

 

I made this yesterday. See screenshot, play the atr, look though the code (Xasm). More comments later.

 

It's all softwaresprites (still without PM underlays and playfield background and overlap handling) in Antic 4.

Link to comment
Share on other sites

  • 3 weeks later...
and the original rent...

 

http://www.student.oulu.fi/~loorni/covert/rants/sprite.htm

 

just to have all in one topic...

843782[/snapback]

 

I read this one some time ago, and got hold of a copy of "Green Beret" for the C64 to check it out. It's much better than the version for the A8, which is one of those games that you'd have been really unhappy to have paid for at the time.

Link to comment
Share on other sites

ok. here are my thoughts about sprite flickering & ring buffer:

 

assuming we have 8 virtual sprites no. 1-8 and our engine is trying to assign them to the 4 available hardware players per scanline... i am not going into the sorting issue (which makes life really easier...please read the other docs here...)

 

no... let's think about they are all have y-position f.e. 100... so they stay on one line...

 

1st frame:

 

1,2,3,4,[5],[6],[7],[8]

 

sprites 1-4 could be mapped on the 4 hardware sprites. the engine markes sprites 5-8 as "non-mapable"... now think on ms pacman and on joust. there the engine is "flickering" through the virtual sprites... now the ringbuffer used in MSX games by konami comes in place. the video chip can display 4 sprites max. per scanline as well... so let's see how this works in the 2nd frame... assuming that the sprites haven't moved...

 

so... the starting point in the virtual sprite list is incremented by 4 (the max. available hardware sprites...)

 

so... we start with sprites 5,6,7,8,1,2,3,4 now... the mapper rejects sprites 1,2,3,4

 

2nd frame

[1],[2],[3],[4],5,6,7,8

 

so... the other sprites are visible...

 

hope this makes it clear... here is another example with 6 sprites on one scanline...

 

1st frame

 

1,2,3,4,[5],[6]

 

2nd frame

 

1,2,[3],[4],5,6

 

3rd frame

 

[1],[2],3,4,5,6

 

4th frame

 

1,2,3,4,[5],[6]

 

...

 

hope you got it...so on weekend i try to implement this ringbuffer into my sprite engine...

Link to comment
Share on other sites

In the unneccesary comments dept., I feel compelled to mention that the sprite display strategy you are calling a 'ring buffer', technically is not a ring buffer. A ring buffer is a double ended queue that has a read pointer and a write pointer, usually implemented as an array and two indexes. It's used in communications and other 'producer/consumer' applications, especially when multiple threads could be reading and writing to the buffer at the same time. The pointers wrap around back to the start if they go off the end, so thats similar to what you are doing, but really thats the only similarity. What you are doing with the sprites is just a sorted list, with a windowing algorithm to control which ones and how many are 'active' at any one time. It's much more like a classical scheduling algorithm than it is a ring buffer.

Link to comment
Share on other sites

ok. played around with the code of multiplex. i found several bugs which are removed and tried to implement the ring buffer kind of concept but this does not work... my feeling tells me that there is a logical problem....

 

my question is... after sorting all sprites depending on their y-position how should i fill the buffer for flickering?

 

i mapp the first 4 sprites to the players and set a DLI for this zone... the next sprites from no. 5ff are tested if they overlap with sprite 4...if so they are rejected and the next possible sprite starts the next zone with 4 hardwaresprites and so on... in the demos you see the white scanlines which indicate a starting zone...

 

so in theory i would need a buffer for each zone??? containing all sprites which would be there even the rejected ones?

 

i am not sure if i can virtually flipp through the whole 16 sprites with the ring buffer concept?

Link to comment
Share on other sites

I am not really sure what you are trying to do....what do you mean by 'zone'? Are you trying to get more than four sprites on a scanline, or just more than 4 sprites to a screen, or both?

 

If I understand, for the case where you have more than 4 sprites on a scanline, you could just cycle through them 4 at a time, which is what that 'ring buffer' idea from the article is about. You have them sorted into an array, and you bump the start point by four each time, wrapping back around at the end.

 

But it still seems like you could have cases where a single sprite would overlap more than 1 'zone'....not sure what you could do there.

Link to comment
Share on other sites

i am splitting the sprites via DLI... of course in a "zone" you can set 4 sprites in 1 DLI... but you have to "reject" other sprites which could not be mapped to the 4 available hardwaresprites in a zone as they would overlap...

 

the ringbuffer from MSX is dealing with the available 32 hardwaresprites so no sorting etc needed here as the TI chip is capable of displaying 32 sprites but only restriction not more than 4 per scanline...

 

not sure how this logic can be implemented into "my" method which is based on sorting the 16 virtual sprites by y-position and then map them to the available hardware sprites.... the mapper is setting on determined positions DLIs where the engine thinks would be the optimal way...

(in general the place where no sprites are overlapping and a "new" zone could start).

 

the not capable sprites are moved off the screen and are not treated by any engine...

Link to comment
Share on other sites

Well...it would work a *lot* better if you had the sprites all being the same vertical size...and if you had the screen divided up into 'zones' that were as tall vertically as the sprites...and the sprites could only fit into zones, ie., no single scanline vertical motion. That way it would be very clear when something is overlapping something else. Otherwise you are going to have to do lots of compares. But thats pretty restricting, so how about :

 

One thing maybe is to not only have your regular ring buffer, but also have a special 4 slot array for holding the 'active' sprites info. As your scan line moves into the display zone for a sprite, you copy that sprites id number into the 'active' buffer in slot 1..keeping track of the start and end y scanlines...then as you move down the screen, keep inserting sprites as you run into them...until your 4 slots are full. If you run into any more while your slots are full, they don't get displayed. Also watch the ending scan lines, and as the scan line moves beyond the bottom of any sprite thats in the active buffer, you remove him and thus next time you run into a new sprite you want to start displaying you will have an empty slot. You'd also need to bump some kind of counter for each sprite, in order to remember which ones got displayed last pass...if you only paid attention to the sprites that are valid for the scan line and have the *lowest* usage count, that should swap in some of the ones that got left out last pass.

Edited by danwinslow
Link to comment
Share on other sites

thanks dan... some of your thoughts i had yesterday as well... (f.e. frame counter per sprite or cue). my sprites have all the same resolution 8x8 so you can compare which one are overlapping and which not...

 

i wanted to avoid too much DLIs as for my 16 sprites example you would need maximum of 4 zones e.g. DLIs to split them up (4x4 =16).

 

Raster, coder of RMT, mentioned last year that in an older demo of him he worked with this "slot" concept... so i have to rethink...

 

dan, but think of several conditions f.e.

 

all 16 sprites on different y-positions not overlapping

 

all 16 sprites on same y-position

 

etc... just to get an idea of a kind of "rule"...

Link to comment
Share on other sites

Well, the display slots idea would handle both of the boundary cases you mention, but it could possibly generate a lot of DLI's I guess...if all sprites were on the same y, then the 'first' four would get displayed, then the next four, so for 16 sprites, each one would get displayed every 4th scan...which would be pretty blinky I would imagine. If all sprites did not overlap ( which might be impossible, depending on how tall your sprites are ) then there would always be a free slot in the display slots array.

My feeling is that without special screen arrangements and limitations on movement it will just be too unwieldy and slow. Allowing for full and free motion of 16 sprites is just not going to be easy

Maybe you could prevent overlap in certain cases...ie., when you know that the proposed motion for a given sprite would move it into overlap, you could block that motion.

Link to comment
Share on other sites

  • 4 weeks later...
  • 1 month later...

i don't know if this is relevant but, there were a series of article on 'Atari Graphics' in the Database version if Atari User magazine, they even had a listing for displaying multiple sprites (PMG) on a single screen, the article claimed at least 80 sprites (PMG), the series of Articles were by Richard Vanner i thinkx.. i don't know though, if the sprites used were software or hardware generated

Link to comment
Share on other sites

  • 1 month later...

A nice description of the method of ring buffering used on the TMS chipset (CV, TI99, MSX etc):

 

There can be 32 monochrome sprites of either 8x8 or 16x16 pixels on screen, each of which can have its own color. However sprite bandwidth is limited to max. 4 sprites per scanline. I.e. if there are more than 4 sprites next to each other horizontally, then the rest will disappear. In that case only the sprites with the highest priority (lowest position in the spritelist) are shown. If necessary, games often attack this problem by rotating sprite priorities. This way, every video frame a different set of sprites disappears in areas where there are more than 4 per scanline. Instead of disappearing entirely, the sprites will flicker (sprite multiplexing). This is a common technique, for example the Atari 2600 had max. 2 sprites per scanline and still the Pac-Man faced 4 ghosts (which would start to flicker as soon as more than one was on the same scanline. One hardware sprite was used for the ghosts, the other for the Player, which didn't flicker).

 

There is a status bit "5th sprite" that tells that one or more sprites disappeared due to bandwidth overload. By checking this bit, software can determine whether it needs to enable the abovementioned technique.

 

There also is a sprite collision flag, which becomes set when two sprites overlap. This is useful for triggering more advanced collision detection routines inside the software which can then determine the exact location and act upon it (for instance show 'Game Over' because Pac-Man got eaten by a ghost).

 

Konami games such as Nemesis had the priority rotation always active (as can be seen when getting an "option", flying into it (with no further sprites positioned in the affected scanlines), and then pressing F1 for Pause). Method: A sprite position ring buffer is held in main memory. Up to 32 of the leading entries are copied to TMS9918 memory. Next video frame, the start position of the ringbuffer is incremented by 4 entries (this value leads to minimum flicker on a chip that can do 4 sprites per scanline). If the ringbuffer got more than 32 entries, then even without 5th sprite condition (more than 4 sprites per scanline), sprites start to flicker. But even more than 32 sprites are visible, i.e. the max 32 sprites onscreen limit is broken the same way as the max 4 sprites per scanline limit. It can happen that rotation of the list is nessesary even when no 5th sprite condition occurred (when there are more than 32 enemies), and it can happen that objects collide without the videochip noting it (because the sprite multiplexer displayed them in distinct video frames), which is why an advanced game engine does not use those hardware flags.

Edited by Jetboot Jack
Link to comment
Share on other sites

/*
 "Engine #4" dla spritow programowych na grafice v1.3 by Tebe/Madteam
 
 W porownaniu do "Engine #3" uzywa szybszej metody sprawdzania kolizji, sprawdza odleglosci od srodka duchow.
 Metoda ta niezaleznie od wielkosci ducha zajmuje zawsze tyle samo czasu CPU, nalezy tylko odpowiednio
 wykalibrowac "czulosc" testu kolizji (procedura PRG_DUCHY).

 Wersja najszybsza (bez maski andowania podobnie jak "Mario Bros"), dziala w dwoch krokach:
 1. oddanie starej zawartosci ekranu na podstawie "bufora tla"
 2. postawienie ducha na nowej pozycji X,Y

 Uzyte sa 3 bufory, 2 bufory ekranu i 1 "bufor tla".
 "Bufor tla" umozliwia przywrocenie domyslnej zawartosci buforom ekranow.
 
 Duchy rozpisane sa na 4 klatki, co 1 piksel w prawo.


 Duchy okreslaja:
 - wspolrzedne X,Y lewego gornego naroznika sprita
 - identyfikator ducha (np. na jego podstawie mozna okreslic czy duch jest smiertelny dla innych duchow)
 - wskaznik widzialnosci
 - wskaznik kolizji z innym duchem
 - tablica z fazami animacji ducha
 - program obslugi ducha (tam ustalamy pozycje X,Y ducha, reakcje na kolizje itp)
 
 last changes: 31.08.2005
*/

 

Engine #4 for program sprites on graphics v1.3 by TeBe/Madteam

 

In comparison to ENGINE #3, it uses faster method to check collisions, it checks out distances from the middle of sprites.

 

This method always takes the same CPU time regardless of sprite size.

 

But keep in mind you should suitably calibrate "sensitivity" of the collisions' test ("PRG_DUCHY" procedure)

 

The fastest version (without AND-ing mask similar to "MARIO BROS" ingame) works in two steps:

 

1. giving back old screen data (based on "background buffer")

2. putting sprite on the new position X,Y

 

There are used 3 buffers: two screen buffers and one "background buffer".

 

"Background buffer" enables to restore default contents for screen buffers.

 

Sprites are grouped on 4 frames, every 1 pixel on right.

 

Sprites are defined by:

 

- X,Y coordinates of left upper sprite's corner

- sprite identification (e.g. based on this, you can check whether the sprite is "deadly" for other ones or not)

- visibility indicator

- collisions (with other sprite) indicator

- table with animation frames of sprite

- program for using sprite (you can set there X,Y position of sprite, reaction on collisions, etc.)

 

 

 ini_duch  : inicjalizacja ducha
 restore   : zwraca stary wyglad grafiki ekranu dla duchow
 put_duchy : umieszcza na ekranie ducha
 prg_duchy : wywoluje programy obslugi duchow oraz sprawdza kolizje

 

ini_duch  : sprite init

restore   : restores old screen's look for sprites

put_duchy : puts sprite on screen

prg_duchy : call program for using sprites and checks out collisions

Link to comment
Share on other sites

  • 8 years later...

In the unneccesary comments dept., I feel compelled to mention that the sprite display strategy you are calling a 'ring buffer', technically is not a ring buffer. A ring buffer is a double ended queue that has a read pointer and a write pointer, usually implemented as an array and two indexes. It's used in communications and other 'producer/consumer' applications, especially when multiple threads could be reading and writing to the buffer at the same time. The pointers wrap around back to the start if they go off the end, so thats similar to what you are doing, but really thats the only similarity. What you are doing with the sprites is just a sorted list, with a windowing algorithm to control which ones and how many are 'active' at any one time. It's much more like a classical scheduling algorithm than it is a ring buffer.

The above description is universally known as the ring buffer technique when it does apply to game development approach on those ancient beasts. So do not hurt people by entering in this forum only to let us know your ample knowledge of definitions in computer science. ;-)

Link to comment
Share on other sites

The above description is universally known as the ring buffer technique when it does apply to game development approach on those ancient beasts. So do not hurt people by entering in this forum only to let us know your ample knowledge of definitions in computer science. ;-)

This thread is from eight years ago. Some of the above posters haven't been on Atariage in years. Just letting you know in case you didn't realize it.

 

Allan

 

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...