Thursday, August 28, 2014

Levels, levels, and more levels

The past couple weeks I've been focusing on making new maps.  At this point, I'm done with the temple zone, and almost done with the industry zone. 

I think I mentioned that I've added a couple of new items -- the "wall slip" and the laser that Robo-Ninja can shoot out of his eye-holes. I thought that might give me a fun programming break from designing maps. But fortunately, it turns out that I actually designed properly for these things, so they were really easy to add. The wall slip, in particular, only took about 15 minutes, by reusing what I had from the wall cling. The laser took a little while longer -- not because the laser itself was difficult, but I had to add functionality to the enemies that lets them die when hit. Either way, it was all straightforward based on the code design.

So back to editing maps. Robo-Ninja's world is starting to grow out a bit, although there's still a good way to go.  I think it's time to stop for awhile, so I don't get burned out and starting making stupid levels, and instead start writing the code for the opening story sequence. That will be interesting to write. 

I hope.
 

Sunday, August 24, 2014

Atari kernel vs Android

So tonight I split some time between writing code for a couple of new items in Robo-Ninja (the laser gun, and the "wall slip", where you can cling to and slowly slide down a wall), and working on trying to jam pack everything into my Atari "kernel" (the name they call the core display loop on atari games).

The contrast between the two was hilarious. I'm going slightly over my cycle count on my Atari kernel -- once I added code for displaying missiles and background, I'm taking too much time per scanline.  But I don't really want to cut any functionality out, so I've been tweaking and optimizing, trying to pare down an instruction here, an instruction there. My brain is now tired. I managed to squeeze it down to ALMOST small enough. Squeezing the rest is going to be pretty difficult.

Then back to Robo-Ninja. Writing in Java (instead of 6502 assembly!), not really worrying about performance unless I do something stupid. I can waste lines like crazy, and it doesn't really matter at all.

Weird.

Wednesday, August 20, 2014

Atari craziness

So between making more maps for Robo-Ninja (I finished the rest of the Temple zone yesterday!), I'm still playing with my side-SIDE project of learning Atari programming.

Let me just tell you, that machine is insane.

On most modern hardware, drawing game graphics is a matter of setting up a scene in openGL, (or  often, some framework that abstracts away the openGL and lets you tell it what stuff to draw where).

On the GBA, it was a little harder. You had magical memory registers for video ram, which you'd fill up with appropriate graphics, you'd poke palette data into a different register, then you'd have other  registers that told it how to build and display sprites or background tiles based on all that. You could, for example, fill in a register to say "put a 16x16 sprite, flipped horizontally, at position X,Y, based on graphic data at video ram location FOO" You still had to do a good bit of work figuring out how to swap data in and out of the limited video ram, how to update slices of the background tile data to make it look like the screen was scrolling, etc, but it wasn't too bad.

On the Atari, you have to hold the thing's hand THROUGH EVERY TV SCANLINE.  To position a sprite horizontally, you literally have to wait until the scanline is at the right place and say "DRAW IT NOW!" Which is tricky because the only way to track how far you are into the scanline is to count the processor cycles of every assembly command, and know that the scanline advances X amount for every cycle. You only get 76 clock cycles per scanline, which is only around 30 assembly instructions, so you're counting and squeezing to try to minimize every assembly command you send to it while drawing the screen.

Luckily it remembers the horizontal position of where you last said "DRAW IT NOW" so on other scanlines you can focus on doing such trivial tasks as loading each scanline's sprite data into the right register, hoping that you can load it into the register before the scanline passes the sprite's X position, because if you take too long, it will have drawn the sprite before you managed to load the new data.

Oh, and you only get 2 sprites and 120 bytes of ram to work with.

It's horrible and wonderful all at the same time. For some crazy reason, I'm loving it.  Tonight, for example, I was trying to figure out how to prevent the black bars from showing up on the left when you move a sprite mid-frame. Take a look at missile command and frogger:


Those are classic examples of games with positioning lines on the left -- the Atari hardware had a weird quirk where if you moved a sprite's horizontal position partway through the frame, it would draw a black line at the left. There didn't seem to much you could do about it. Quite a few games just gave up and had them. A lot of others (particularly Activision games, or so I've read), made the whole left bar of the screen be black, just to hide them.

But somewhere along the line, some smart person realized you could trick the Atari hardware into not showing them, if you wrote to the move register at EXACTLY the 74th clock cycle, at the end of the scanline. So I spent part of my evening counting clock cycles to try to write to that register at exactly the right time.

I ended up going with an easier but less elegant solution, which was to basically not put any enemies or background changes on that scanline, so I could spend an entire line just burning cycles to get to 74. It will work for what I'm going for, but prevents anything interesting from happening on that line.

Just for kicks, here's the code for managing that scanline:
      STA WSYNC   
        LDA #$80            ;2 prevent other things from moving on early hmove,
        STA HMP0     ;3  so clear out the movement registers 
        STA HMM0     ;3
        STA HMM1     ;3
        STA HMBL     ;3 
        LDY #7              ;2 (16 so far) ... 58 cycles left

BurnScanlineLoop
        NOP                  ;2  (7 cycles through each iteration of  
                             ;     the burn loop, 8 the last time through,
        DEY                  ;2    because the BNE only takes 2 cycles 
                             ;     if the branch isn't followed)

        BNE BurnScanlineLoop ;3 (2) (burns 48 during loop) ... 10 left


        LDA Temp             ;3  (basically a NOP, but needed to burn
                             ;3 cycles instead of 2)
        NOP                  ;2
        DEX                  ;2  Reduce the line counter since 
                             ;   skipping the regular WSYNC
        STA HMOVE            ;3  Do the MOVE!
        JMP ScanLoopSkipWsync ; Skip the Wsync since we used the whole scanline

And there we have it, folks. Clearly I've descended into unbridled insanity.




Wednesday, August 13, 2014

2600 and the teleporter

The thing that most causes me to give up and stop working on a hobby project is my tendency to decide on a new "ooh, shiny" programming project. I can't tell you how many times I've started something, but gotten distracted by something else along the way.

As I was working on Anguna, there were numerous times where I had to promise myself that I'd work on that "new shiny" project just as soon as I finished Anguna -- that was the only way I could keep myself motivated to finish instead of just giving up and starting the next project. Once I finished, I forgot what all of those other distracting projects were, so it no longer really mattered.

Well, suddenly I've discovered a new shiny. It's not really that new -- ever since about 2005 or so, I've had it in the back of my brain that eventually I wanted to try making an atari 2600 homebrew game. But somehow recently I got interested enough to spend some time reading up on how it worked. AND NOW I REALLY WANT TO MAKE ONE.

Ok, calm down, Nathan. You have another project, Robo-Ninja.

So right now, that's my biggest motivation for working on Robo-Ninja. The fact that when I finish, I can work on making an Atari game. Nevermind the fact that I'll probably have moved on to a new shiny thing by the time I finish.

Until then, I gave myself permission to mess around with 2600 programming at lunch, during the last few minutes at the office before coming home, etc. (And really, so far, that's been enough to be satisfying. I can't get anything done very quickly, but it gives me a chance to figure out how it works. Expect another blog post soon talking about my thoughts comparing it to GBA and Android programming)



Anyway, that said, I've been quiet about Robo-Ninja.

I recently decided I needed a teleporter.  One of my testers (thanks, Elijah!) suggested that it was really frustrating having to backtrack through levels, but I somewhat blew him off, since that is one of the main aspects of a metroidvania-style adventure game. But then two things happened:

1.  In my own playtesting, I discovered he was right. It was hard to backtrack.
2.  In one of my levels, I needed a new cool thing to discover, but not one of the main powerups.

So I decided it would be a teleporter. There'd be a few of them scattered around the world, and you could teleport between them once you discovered them.

So this involved quite a bit of new code -- I had to create the in-game "character" for the teleporter, to define the sprite and what happens when you collide with it, and a cool animation for making you teleport away.

Then I needed to track which teleporters you discovered, and link them to points on the minimap.

Then I had to build the UI for selecting where you want to go once you go into a teleporter.

This is just after I got whisked away by the teleporter


So that's what I've been working on for the past month or so. (If I worked on the game for more than an hour or so per week, it would probably help matters!) I think the teleporter is finally finished (other than tweaking the graphics on the UI screen), so tonight it's back to level design. Which I'm sure will make me think of some new crazy thing that I want to add into the game.

I'm never going to get to that 2600 game, am I?

Sunday, August 3, 2014

Android keyboard for Civilization 1

So I've recently purchased DosBox Turbo, the best (as far as I can find) implementation of DosBox for Android, and have been playing through old DOS games on my phone. It's been pretty awesome -- I've been currently playing Civilization 1, which is one of the best games ever, in my opinion.

The only problem is that for Civ, you need a keyboard with arrows and diagonals, as well as a number of regular keyboard commands. I've used the awesome Hacker's Keyboard for other games, but for Civ, I end up having to toggle back and forth between the "normal" and "alternate characters" modes repeatedly. And I'm using PgUp, PgDn, Home, and End keys for the diagonals, which aren't arranged intuitively on that keyboard. So it's a bit of a hassle.

So the other day, I thought, "how hard can it be to write a new keyboard layout to make this game easier to play?" Turns out the answer is "not very hard."  The android sdk distribution contains sample code for a simple keyboard, and it didn't take much beyond changing an xml layout file, and removing a bunch of unneeded code, to make my Civ 1 keyboard.

It's still not quite perfect -- there's still a bunch of unneeded code (left over from the sample code) that I haven't pruned out, and a few tweaks I'd like to make. But it sure makes playing civ easier.  If I ever get around to cleaning it up, I'll post the source and possibly put it up on the Play Store. Until then, feel free to download the apk file from me and try it out. I won't make any promises about the quality or anything at this point. But let me know if you happen to try it.



(and yes, I'm still slogging away slowly at Robo-Ninja)

NES Anguna

Well, I had a little bit of time still, while Frankengraphics is finishing up her game Project Blue, to have a little downtime on Halcyon, s...