Jump to content
IGNORED

Could someone tell me the logic of how to manage multiple objects in the game?


Dong

Recommended Posts

Dear all, 

 

I am confused of how to manage multiple objects in one games? Here we talk aboout Atari 2600. For game, space invader, it has 30 enemies, and one agent. I am very curious about how to manage those objects in Just 128 byte RAM. It seems each one should take two bytes to record the positions(X, Y). But I did't see many changes of ram in stella when the enemies are moving. How to implement that? Could anyone tell me the logic of that?

519935987_ScreenShot2020-05-19at2_03_43PM.thumb.png.66a5db8cba1c9bc271683c58d9dd122f.png

Thanks in advance.

  • Like 1
Link to comment
Share on other sites

Mind that not every object on the screen has to have a representation of its own in the code!

E.g., having a look at the Space Invaders screen in your example, there are 6 rows of 6 invaders each. Mind that the rows move in concordance as a single block. So, you actually only need the (x/y) offset of the block and a byte a row with bits set for an active invader. The rest can be done by simple math, using a few shifts and addition for comparing objects. (However, the TIA collision registers will do some of this for us already.) Of course, we'd need some additional code to handle an entire edge (to the left of right) of the invader block becoming free, meaning, the block wouldn't reverse when reaching x=0 zero on the left side, but at x=16, where the second invader is located, etc. So we'd need another byte for an offset to add to this on the left and another one to be subtracted on the right in order to handle the desired reversal of direction properly. Considering it all, we'd need 6 bytes to store 6 bit-vectors for each of the rows of invaders, 2 bytes for the block coordinates and another two bytes for the left and right offsets. Putting this a step further, we could also store the latter in a single byte using a bit vector indicating offset shifts to be applied to the block coordinates, which would give us a storage requirement of just 9 bytes to handle 36 objects.

Edited by NoLand
  • Like 1
  • Thanks 1
Link to comment
Share on other sites

Thanks a lot.  It's very helpful. And does atari 2600 have some space other than the 128 bytes for storing the shape data of the invaders?

And Could you give me more information about the TIA collision registers? I am not a game programmer. In my mind, I think the collision was detected by some conditions judgement, such as the location overlap.  

 

Thanks for your detailed reply.

 

Edited by Dong
Link to comment
Share on other sites

First, mind that this is a simplified example to illustrate the principle. In actuality, there are also explosions and maybe even explosion phases to take into account. So it will probably a byte for each invader to store an additional state and a counter.

 

Regarding TIA collision registers, the TIA registers any of the possible combination of a set bit of any of the sprites overlapping and stores them in a few read-only registers. In theory, this would provide already all we need to determine a collision. (E.g., does the missile of the player overlap with the enemy sprite? Read the according register and check for the collision bit representing this exact condition.) However, here, we're repurposing sprites multiple times, so all the TIA could tell us is whether there was a collision at all and we would have to figure out on our own, which invader was hit, etc.

  • Like 1
Link to comment
Share on other sites

3 minutes ago, NoLand said:

First, mind that this is a simplified example to illustrate the principle. In actuality, there are also explosions and maybe even explosion phases to take into account. So it will probably a byte for each invader to store an additional state and a counter.

So, there are some place to store the shape data of the invaders. Here the shape data means the pixels which record how the invader should look like in the screen.  

 

6 minutes ago, NoLand said:

Regarding TIA collision registers, the TIA registers any of the possible combination of a set bit of any of the sprites overlapping and stores them in a few read-only registers. In theory, this would provide already all we need to determine a collision. (E.g., does the missile of the player overlap with the enemy sprite? Read the according register and check for the collision bit representing this exact condition.) However, here, we're repurposing sprites multiple times, so all the TIA could tell us is whether there was a collision at all and we would have to figure out on our own, which invader was hit, etc.

Here, what your mean is that the TIA will have some registers to record the ovelap event between bullets and the invader. The programmer can get that infomation and then decide what to do to react to this ovelapping thing. 

 

Am I correct? 

 

Link to comment
Share on other sites

3 hours ago, Dong said:

So, there are some place to store the shape data of the invaders. Here the shape data means the pixels which record how the invader should look like in the screen.

The shape data would be normally stored in ROM, of which there's plenty, comparatively speaking.

 

For a bit of understanding of what the TIA does or doesn't: The TIA just assembles a horizontal line of TV image on the fly. For this, there are background graphics (20 bits of "wide" pixels, 4 times the size of a normal pixel, repeated or mirrored for 40 wide pixels in total), two player sprites, a missile (a single dot) for each player, and a ball (another pixel). Sprites may be scaled and player sprites may be also repeated at an offset, up to three times. You may see where this goes with Space Invaders, already, as there are 6 Invaders, which may be accomplished by using the two sprites with 3 copies for each of the two sprites. We just have to change the pattern for the sprites, just at the right time, which is the tricky portion. So, where does the pattern come from? You read it from ROM and put it in the respective register. And you have to do it for each line of the screen. Mind that the TIA does horizontal lines only and has no notion/concept of a vertical extent. If we do nothing on the next line, the image will be repeated over and over, resulting in vertical stripes or bands. So we have to provide for this in the program, in a section usually called "kernel" that controls the visual image. We'll have to count the rows, as we're passing over them, and we'll have to figure out, if a certain sprite is on for the given row/line of the TV image. This is done by keeping track by counters, which are also used to read the sprite data with an increasing (or much more often, decreasing offset, as we're usually counting down to zero from a set number of screen lines). Fortunately, the 6502 processor provides some handy instructions for this.

 

(Mind that all invader sprites are positioned at the same horizontal offsets, meaning, we haven't to change the horizontal positions of the sprites. They are either off or displaying a certain pattern. However, down the image, it becomes more tricky, as we'd have to reposition the sprites for the barriers and the player sprite. The TIA has a really as basic as possible approach to this, where you basically say "now" to the chip, when the beam is it at the right position. This is, because the TIA doesn't implement numeric counters for determining positions, but so called linear feedback shift registers, which count in unique, but non-sequential digits. Oops. But this lessens the transistor count and therefore costs dramatically. Also, the CPU runs slower than the TIA, therefore, us saying "now" is a bit too coarse in granularity and we'll have to figure out a correcting offset. Fun! The tell-tale sign of this procedure are the black "combs" seen frequently on the very left edge of the screen, which are artifacts of this fine positioning.)

 

BTW, the TIA, being the little box of wonders that it is, does sound, as well.

 

3 hours ago, Dong said:

Here, what your mean is that the TIA will have some registers to record the ovelap event between bullets and the invader. The programmer can get that infomation and then decide what to do to react to this ovelapping thing. 

 

Am I correct? 

 

 

Yes, this is actually quite simple. While the TIA is assembling the signal, which will be eventually sent to the TV, it's rather easy to determine, if another signal source is already set high/active. If this is the case, this will be stored in the respective collision register, of which there are 8 in total to represent any of the possible combinations.

 

To tap into the TIA's "stream of thought", this may be well like, "Now on to the next pixel, which is pixel 67 – or 123, as I call it internally, – let's see, background is off, nothing to do, get the player sprite #0, oh, its position is well out of scope, never mind, then sprite #1, oh, it's active and, as I'm shifting the bits along, as well, it's an active bit. — Let's look up the color, oh, it's a bright red, put this on the output. Then, let's move to the first missile, oh, it's active as well, let's put this one on the output. Oh, there's already an active signal from sprite 1, let's take note of this…" – As it happens, each of the "oh"s can be implemented by a simple logical gate.

 

(These registers share addresses with those registers used to set the state of the TIA. If you write to these addresses, you set the state, if you read from them, you get a readout of the registers storing collisions or the state of the controllers. Again, this is for cost reduction, since, this way, we can save some cents on additional pins on the chip. Which is the logic behind most of the VCS/Atari 2600: Why spend money on each of the millions consoles shipped to users, if a few extra hours on the programmer's side may do the same? Still, development and production of the VCS was that expensive that Atari had to be sold to Time Warner in order to survive. It was pretty much on the verge of what was commercially viable at the time.)

Edited by NoLand
Link to comment
Share on other sites

You can see the registers in the debugger in Stella.

Screenshot_20200519_201459.thumb.png.c9e2be34b02b4be161070e7ac9a9e2ed.png

 

Here, I've stopped the tracing partway through drawing the shields.  The contents of P0 are currently drawing that part of the shield.  The 15 collision registers are in the upper-right of the TIA tab.  There's a bunch of other stuff there too.  You'd need to read up on this to understand it all, and how the TIA works.

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