Thursday, March 24, 2016

Asymmetrical rooms

One of the weird quirks of the Atari is that, while there are some registers to control the playfield layout (so you don't have to "chase the beam" to draw the entire background/playfield), there's only enough registers for half the screen, so it repeats the same graphics on both halves of the screen. There's another register that lets you determine whether it should be mirrored or duplicated.

Some games get around this by updating that register in the middle of the screen (which I also do when I'm drawing the subscreen map), but with the other stuff I'm trying to display (multi-colored main character, multiple enemies, missiles, etc), I don't really have time to do that. (as a counter-point, see the game Super Cobra, where they manage to cram that all in along with updating the background, although they have some clever limitations on movement to simplify things very slightly)

I've read bad reviews about this game, but I'm convinced the programmers are geniuses.

ANYWAY, my solution in Anguna is just to force every screen to be symmetrical (other than doors/walls on the far edges, which I fake with the Ball object). This makes for slightly less interesting room layouts, but makes my life a lot easier.  Except that my overall world design called for (at least) 2 rooms that broke that rule, and needed to be asymmetrical.  I had punted thinking through the design of how I was going to make these rooms work, assuming I'd come up with something eventually.

And so I did.

The 2 rooms are mirror images of each other, but not symmetrical themselves. It was a place where the river turned a corner:

How did I accomplish this, you may be asking? (If you are crazy enough to still be reading this)  I cheated.  The first half of the cheating is what you don't see, a grass-colored rectangle "enemy" that's just sitting on the left-hand side, hiding the river from view. Here's a similar picture of the room while I was working on it, and had the enemy colored red for debugging:

That accomplished half of what I needed -- making it look asymmetrical. But the hardware-based collision mechanism still knew I was walking into the playfield when I tried to walk through it. So I had to add a special exception in my general collision-processing code, so that playfield collisions in this particular region of these two particular rooms just didn't get counted.

The biggest drawback of cheating this way is that I can't have other enemies in this room -- I only allow one type of enemy per room, and the grassy overlay is using up the enemy for these two rooms. But that's ok -- I don't mind a few rooms here and there with no enemies in them. And I managed to get my asymmetrical rooms working.

And now, partially because it visually shows off my progress, but mostly because I'm obsessed with maps, here's the world map so far. It's about 1/4 to 1/3 of the total world that I have planned out.

Thursday, March 10, 2016

Compact it, Compress it, Recycle, Make Less of it!

My mission this week was to compress things. To compact it. Make less of it.  I was running out of space, and I needed more.

First pass was to go through my code looking for macros that I could convert to proper subroutines. I found a couple, which freed up a little space, maybe a couple hundred bytes total.

Next pass was to do with enemies what I had previously done with room layouts:  In my room definitions, I had a pointer to the enemy type that would be in that room. Pointers in 6502 are 2 bytes. I have less than 256 enemies, so it made sense to, instead of storing a pointer in each room definition, just use an index.  It took a tiny bit more code, but quite a bit less total space. That saved another couple hundred bytes.

The biggest savings, though, was redoing my room layouts.  Because of how the atari playfield registers work, and 6502 indexing works, it's easiest to store 3 chunks of data for each room layout -- one for the outside edge, one for the middle of each half-screen, and one for the middle of the screen.  So I stored 23 bytes of layout data for each of those chunks, for each room.

Well, it turns out that a lot of room layouts share similar chunks. For example, either they have completely blank outside edges, or nice square doors on the outside, etc. I had quite a few chunks that were repeated throughout my graphics data. So instead of clustering the 3 chunks together, I added yet another lookup table, where for each room layout, I store the indices of the 3 different chunks that make up that room.   That freed up about 400 bytes.

The bonus of this is that now I can make different permutations of my existing chunks, for nearly free. This gives me a lot more options for making different room layouts and keeping the game at least slightly interesting.

So, that's done.  Now back to content.

(Although some of the nice folks on AtariAge have convinced me that I should try to support the SaveKey, a hardware doodad that someone made, which plugs into the player 2 joystick port, and has some flash memory to allow game saves.  I guess it takes between 100 and 200 bytes of code to use it. Now that I've freed this up space, I may try to do it. We'll see)

I'll leave you with this nice picture of things being broken as I tried debugging my new room layout code.

Sunday, March 6, 2016

Darkness, and running out of space

This weekend's work was to add dark rooms. (at least, dark until you have the lantern) Which has been tough. I've given it a ton of thought, and have never been completely happy with what I've come up with. But with a good bit of trial, error, and wasted code, I've got something that works:

Dark rooms are limited to a single enemy. What I do is a trick that dates back to the catacombs from Adventure: I use an enemy sprite (set to 4x width) in yellow as a glowy area around the player. Then I change the background and walls to the same color, but change the rendering priority flag to put the playfield (walls) on top, the sprites 2nd, then the background last. Which means that everything looks black unless the glowy light is there, which gets rendered underneath the walls, showing where the walls are.

Thank you, Warren Robinett, for this awesome idea.

Now because I have other enemies that I want to render as well, I have to have some flicker going, and render the light and the enemies in alternating frames. (I just don't have the code space to do the more complex alternation if I have more enemies).

The one thing I have left with the darkness is that I want to hide the enemies until they get close to you. Which actually should be pretty easy, i believe.

Now the problem that I'm having is that I'm running drastically low on ROM space. I've got about 1K left of my 16K. In that space, I need to add a bunch of room layouts and color schemes, code for the dynamite, a bunch more enemies, and a sequence for winning the game. I also wanted to add support for the SaveKey, a cool doodad that someone made that plugs into the 2nd player controller port, and allows persistent storage for game saves. Adding the code for that takes about 100 bytes, which is about a tenth of what I have left. Ugh.

Thursday, March 3, 2016

Password Entry

It's late. I'm tired.

But by golly, I got the password entry UI working. With 133 bytes to spare. WHEW.

Of course, it doesn't actually let you start the resumed game from here yet, so maybe that's what I'll do with those leftover bytes.....

Wednesday, March 2, 2016


Tonight I started working on what happens when you die, and where you respawn, which ended up getting me excited about trying to make the password system work.  So tonight's project was building a reusable bit of code to both display the current password, as well as display the password UI while the user is entering a password.

I don't really have the UI part of it working yet, but after a couple of hours tonight, displaying the current password is working fine, including a checksum to keep people honest:

As I stare at it, I think the password logic might be a little too obvious, so I may end up obfuscating it just slightly by rearranging some of the graphics for the numbers/letters in the password. We'll see.