Tuesday, September 23, 2014

No, I was wrong

The morning after I posted that last post, I realized my "simple solution" was wrong. Because I can't determine if an enemy is showing on a frame until after I've moved all the enemies for that frame. So I really do need to save 3 sets of previous X/Y coordinates. That's 6 whole bytes of my 24 remaining.

I don't like it. But I'm not sure I have any options.

2 comments:

Bryan R said...

This is an intriguing puzzle. I don't really know how you are moving and tracking your enemies, but a couple of ideas come to mind. These may not actually apply to your situation.

To move your enemies, I imagine you must keep track of their direction/velocity somehow. If you're already storing that somewhere, could you use those numbers to undo the move which caused the collision?

Also, since you placed the enemies and you placed the walls, maybe you don't need to use sprite collision detection between those two things. Maybe you can know beforehand when the enemy will hit the wall, and turn at that time.

Nathan Tolbert said...

I appreciate your comments! (particularly giving me suggestions, any ideas are welcome!)

So I've actually considered both of those possibilities, at least in passing.

As far as knowing the enemy's direction/velocity -- I'm actually only storing their position, and one byte for each enemy's current "state", which gets feds into a finite state machine-ish procedure that updates their new position and state. I could probably write the code to be able to revert one frame back for an enemy based on the FSM. But sometimes the procedure uses the results of a random number to determine how the enemy moves, so I'd probably have to store that random number. And writing the extra code to back up one step in the machine (for each type of enemy) doesn't sound fun at all.

The wall collision might theoretically be a better option (that's how I had to do it on the Gameboy Advance version of the game, which didn't have hardware-based collision detection*). The difficulties with that:

1. The atari background/wall/playfield methodology is weird. It works at a different horizontal pixel scale from sprites, and the bits representing walls aren't arranged in a simple linear order. Meaning I'd have to do some non-trivial computation which might be an issue because...

2. I'm already using a pretty hefty percentage of my computation time for each frame. The processor on this thing is just so stinkin slow. With some smart coding and clever optimizations, I could probably figure out how to make it work within my processor time constraints, so it's worth considering further. The more I think about it, this MIGHT be doable. I'd have to work out the math to see how quickly I could compute and look up which background elements an enemy might collide with.

(Hmmm, this method also has slight complications if I have to use bankswitching. The atari can only address 4K of ROM at a time, so cartridges bigger than that use a special chip that toggles between memory banks for different parts of the code. I'm at about 2.5K right now, so I'm guessing I'll have to end up using bankswitching to handle the space taken up by various graphics and room definitions. Using this technique discussed above, I'd have to make sure that the collision detection code is in the same rom bank as the background definition, which also need to be accessible from the display kernel.)

Anyway, I appreciate the suggestions. I'll have to think some more about the 2nd one to see if it's feasible.


* - The hardware on the Gameboy Advance handled the background as individual tiles which were stored in a fairly linear array, so you could relatively cheaply determine which few tiles a sprite overlapped with, look up which they were, and know if it was a collision. Oh, and the processor was plenty fast.

Metatile Designer

For the NES game, I'm building my levels out of 32x32 pixel metatiles.  What is a metatile?  The NES background tiles are 8x8 pixels, bu...