Saturday, December 19, 2015

Scene2d


Wow, the scene2d framework has come a long way since I first looked at it, in some pre-1.0 version of LibGDX. In the last hour since the kids have been in bed, I've got almost half of my game UI mocked out using it, and switching from the draft/mockup to the "real thing" should be as easy as modifying the skin file, and then slightly nudging/resizing things.
I'd show some code here, but it's all so plain simple, I'm not sure what to even say. It's all super simple layout stuff, along the lines of:
    private Window buildControlWindow() {
        float paddingLeft = 120;

        Window window = new Window("Signal", getSkin());
        window.setPosition(0, 0);
        window.setSize(LifeInSpaceGame.WIDTH, LifeInSpaceGame.HEIGHT / 3);
        window.setMovable(false);
        window.setResizable(false);
        Label label = new Label("Radio Filters", getSkin());
        window.add(label).padLeft(paddingLeft).colspan(3).expandX();
        window.row();

        Button filter1 = new TextButton("     Filter 1     ", getSkin(), "toggle");
        window.add(filter1).padLeft(paddingLeft).expandX().padTop(10);
        window.row();

        Button filter2 = new TextButton("     Filter 2     ", getSkin(), "toggle");
        window.add(filter2).padLeft(paddingLeft).expandX().padTop(10);
        window.row();

        Button filter3 = new TextButton("     Filter 3     ", getSkin(), "toggle");
        window.add(filter3).padLeft(paddingLeft).expandX().padTop(10);
        window.row();

        return window;
    }


This builds the panel in the bottom right that lets you apply different "radio filters" to the radio signal audio that's coming in from the selected star, to help you try to pick out whether there are any signs of intelligent life coming from that star.
The next task is going to be the first somewhat challenging one: to have a cool waveform image scrolling by on the bottom left side of the screen to match the radio sounds that you hear when you tap on a star. I have some ideas about how to make it work really easily, but it might take a little finagling. 



Here we have some rough instructions (which hopefully I'll have time fill out later)
And the addition of the radio filter toggle buttions. The waveform should appear in the space to the left of the buttons.

LibGDX Game Jam

So this week I'm tentatively starting a project for the LibGDX game jam, a month-long jam with the theme "Life in Space"

Part of the jam is the requirement to document your progress, which I'm doing on their website. I'll try to cross-post a lot of it here as well, but my jam project log page is at http://itch.io/jam/libgdxjam/topic/12031/gauauus-log

The idea of the game is a very short story-based game where you are a researcher here on earth searching through the stars looking for radio signals that would show evidence of extraterrestrial life in space.  Because of the non-action, story theme, it's very different than other games I've done. And because the goal is to crank something small out quickly, it's been fun (for the 2 hours I've worked on it so far) not worrying about good extensible/general design, but writing just enough code to get the job done.

I'll leave you with a very minimal draft screenshot. The top starfield is where you search for signals. The bottom will be a control panel that lets you analyze radio signals as they come in.

Can I do this in a month? I don't know, but it'll be fun trying.


Monday, December 7, 2015

Door work and more

Ok, enemy spawning finally works right. There were a couple of minor bugs in my spawning code that I last posted (c'mon, nobody spotted them? I thought with a million eyes, all bugs are shallow? I guess that means I have a few less than a million readers that are also 6502 assembly programmers!) But I got the bugs taken care of.

I decided the next step, to try to get my brain interested in this project again, was to go ahead and start actually making the first dungeon. Awhile ago I posted a survey to see if I should re-implement the maps from the original Anguna, or make a new adventure. Everyone voted for a new adventure. But it sounds really fun to try to reproduce the first dungeon, at least. So that's what I started on.

And immediately realized that although I had worked out proof-of-concepts for my door code, it wasn't finished. Doors on the top worked. I hadn't finished doors on the bottom. Which required going back and modifying my display kernel code, which meant I was back to counting cycles.

But I think I have that working, finally.

I also originally only allowed for a left-side or right-side to be closed (if I wanted them both to be closed, I had to draw the room map with a permanently closed wall, which reduced that room layout's flexibility for use in other rooms).  But after playing with that, I didn't like it much. So I had to re-think how this was going to work.

Originally, I used the Atari "ball" graphics object, (which is a 1,2, or 4 pixel blob) extended vertically across the whole screen, to block off a left-side or right-side door. But if I wanted to block both at once, this wasn't going to work. (there's only 1 ball!) So instead, I counted and realized I had time to squeeze in one additional instruction in my code that pushes the background data to the right registers, so I could pre-load a byte in ram with a mask to be applied to the walls, and, OR that with the actual room wall data before pushing it to the display registers. Because I'm using a mirrored background, that could close both the left and right doors at once.

Both the left and right doors are closed! Hooray!


The next step is another part that I realized I never implemented: if you have a secret door that only opens when all the enemies are dead....well, it never opens.  Not because my code to open it doesn't work. But more because it turns out I never wrote that code.

So that's next!




Thursday, November 19, 2015

Enemy Spawning

Still working on Crop Insurance. The one nice thing about it is that I'm tracking my hours, which lets me see a better estimate of how much time I spend on my side projects. The answer is about 5-6 hours per week.

No wonder it took 3 years to finish Robo-Ninja.

That being said, I'm feeling a bit stuck on Atari Anguna. I haven't been doing much, because when I do, I've been working on my semi-random enemy spawning routines. And I haven't been happy with it.

The issue is that I don't want enemies spawning stuck in walls, which means:

1. I can go completely random on spawns, but then if it's a collision, try again.
1b. To check for a collision, I either have to do the math to figure out if I've collided with a wall (which on the Atari is non-trivial due to the crazy arrangement of the playfield registers) or
1c. Draw the enemy once, check the collision registers, and then move (which means each try eats up a frame, which could be slow and look really tacky)

2. Instead, I could designate "safe spawn" areas in each room layout.
2b. Depending on how I do this, it could eat up quite a few bytes per room. (I potentially need at least 3 safe spots per room. This could be 6 bytes per room, more than I want to spend)
2c. I could cut down on rom usage by having a lookup table of safe spawns, the question is how this would work, and doing the randomization and lookup in a way that's fast and compact.


I spent WAY too long thinking through these, testing ideas, etc, and not being happy with the results. Which made me less interested in working on the game, and thus slower progress.

Finally I have a solution that I think I'm happy with, and seems to be mostly working.  I build a lookup table of 8 potential spawn points (16 bytes for the lookup table). Then each room has a byte to tell which of these potential spawns are allowed for each room layout -- a 1 means it's safe to spawn in.  Then I pick a random number between 1 and 8, check that bit. If it's not safe, try the next. Once I get a safe bit, spawn an enemy at the position that the bit refers to. Then if there are more enemies to spawn, I just check the next consecutive bits (instead of picking more random numbers, and risking enemies spawning in the same position as each other) until I've spawned them all.

It seems to work, doesn't require much storage, and is relatively fast.

For any 6502 assembly nerds, here's the code I used. You can probably spot all the places that I'm doing things really badly (I end up wasting a lot of cycles saving and loading values -- it seems I just don't have enough registers to track everything I need and still use X and Y for indexed loads (Why oh why didn't the 6502 have TXY and TYX opcodes to move values between X and Y directly?))

LoadPositionsFromSafeSpawnsImpl
    SUBROUTINE
    ;TempPF2 should be the number of enemies we want to spawn
    ;TempPF2 then holds the number of enemies we want to spawn - 1
    dec TempPF2

    ;load the room index
    ldy #0
    lda (RoomDef),Y
    tax
    ;x now has room index

    ;Store #1 in TempPF1 to bit against..
    lda #1
    sta TempPF1

    ;get random number between 0 and 7
    lda Rand
    and #%00000111
    tay
    iny

    ;a has safe spawns
    lda SafeSpawns,X

    ;rotate the safe spawn based on the random number
    sty Temp
    ldx Temp

.keepRotating
    cmp #$80
    rol
    dex
    bne .keepRotating

    ldx Temp
    ;now work our way through seeing if it's safe
.checkSpawnLoop

    ;if it's safe, go to useThisValue (of x)
    bit TempPF1
    bne .useThisValue

.beforeRotation
    ;if not, rotate again, increase X
    cmp #$80
    rol

    inx

    ; if X equals start, fail. What then?
    cpx Temp
    beq .useThisValue

    ; if X equals 8, set to 0
    cpx #8
    bne .checkSpawnLoop
    ldx #0
    jmp .checkSpawnLoop


.useThisValue
    pha
    ldy TempPF2

    ; otherwise, look up X and Y in table
    lda SpawnsX,X
    sta Enemy0X,Y

    lda SpawnsY,X
    sta Enemy0Y,Y
    pla

    dec TempPF2
    bmi .allDone

    jmp .beforeRotation
.allDone

Sunday, October 25, 2015

CivKeyboard to play store

I haven't said much on here recently. Mainly because most of my non-work time has been doing some paid consulting work, (a project involving converting a farm insurance calculator from excel spreadsheets to a web app).

I do have a few things to say, though:


  • Robo-Ninja is now on the Amazon app store (it's now free to publish there, and they had an offer of $100 in AWS credit if you publish your first app there before Nov 1, so I took advantage of that!)
  • Do you remember that custom keyboard I made for playing Civ in DOSBox? I decided to go ahead and publish it on the play store. Google onrejected it the first time for "spam" in the text (they didn't like the Civ and DOSBox in the title I guess), but I reworded it and got it listed. (It's still in beta test mode, so that link might not work for you yet....)
  • Robo-Ninja finally hit 1000 downloads this week. Not particularly amazing, but at least people are finding and playing it.
  • I'm still slowly advancing on the girly game for my daughter. But she hasn't seemed particularly interested in it recently, so maybe I'll go back to focusing a little more time on Atari Anguna. We'll see.

Sunday, September 20, 2015

Girly game (more about ramps?)

So I've got yet another detour in my hobby coding.  While my son and I were working on Robo-Ninja, my daughter kept asking if she could help me design a game.  She had drawn some rough pictures and had some ideas about what it could be like, but we hadn't really done anything with it.

She asked again recently, so I thought it was time to humor her. She decided it would be a cute little game where she could walk around a neighborhood (in a 2-d side scroller, despite me trying to convince her that it should be a top-down game) to visit friends, and collect items.  Eventually we settled on the idea that she's trying to make a leaf collection for school, so she has to collect leaves.

Well, being a 2-d side scroller, and wanting to see if I can churn this out pretty quickly, I decided to reuse a bunch of the codebase from Robo-Ninja.

So with a few hours work, I was able to pull in a bunch of the main classes from Robo-Ninja, clean up a good bit of stuff, and have something working for her.  The biggest difference is that you can actually control the main character of this game, so I had to re-work the main character a good bit. Which also gave me a chance to redo a bunch of the code that had turned to spaghetti in Robo-Ninja.



Using the knowledge of the mistakes I made from Robo-Ninja, and some tips from that page I referred to in my last post, getting the collisions and movement, particularly on ramps, was quite a bit cleaner. It makes me pretty embarrassed to compare with my Robo-Ninja ramp code, really.

Anyway, the game currently lets you run and jump around. Time to add a little bit of fluff (items, characters to talk to), and it will be half done already. (yeah right, these things always take WAY longer than I'd ever estimate!)

Stanguna is still in my brain, even though I haven't done much with it lately. Someday soon, hopefully....

Saturday, September 12, 2015

Collectibles

Well, turns out that was pretty easy. The new build with collectibles is now in the play store. With a new achievement if you collect all 16 of them.

(which means I had to play through the game yet again to test it. I'm getting pretty good at this silly game by now)


Thursday, September 10, 2015

Collectibles in Beginner Mode

Well, it's time to open back up the IDE.

My friend Geoff brought something to my attention, which he's completely right about: In beginner mode, there's a bunch of dead-end passageways, with a yellow dot on the map implying there's something there. But there's nothing there.

Beginner mode, being a bit of an afterthought, doesn't have any of the slow-mo or checkpoint items. There's nothing to replace them, they're just gone. Which is weird and confusing.

I decided that an easy answer is to make them into simple collectible items. You find them, it says something like "you found collectible #3 of 16!"  And maybe have an achievement if you collect them all.  This makes the weird passageways make more sense, and adds a simple extra goal for beginner mode.

It should be pretty straightforward to add, we'll see how it goes.

Wednesday, September 9, 2015

Ramps

Well, the release of Robo-Ninja went well. People are playing (and hopefully enjoying) it, so I'm happy as a clam!

I'm spending a little time now in my "free time" focusing on some outside consulting work, but hopefully I'll be back in gear to work hard on Anguna Atari soon!

Until then, I was recently thinking about how I ended up handling slopes/ramps in Robo-Ninja, and how my code ended up getting really messy after a few iterations. I decided (now that I'm finished) to do some research about how other people have implemented them, and ended up finding this awesome article that talks about the standard methods for handling the mechanics of platform games.

It's pretty awesome.

Thursday, August 27, 2015

Release!!!! (And beginner mode)

And....Robo-Ninja is released!  It's up on the Play Store (although might take a few hours to appear for everyone).   Thanks for your help, everyone who tested, contributed graphics, ideas, etc.


Or, if you want to donate $1.00 and get to play the "harder" mode, use this one:

  Android app on Google Play


And for all you of you that found the game too difficult, you can thank my friend Bryan who finally convinced me to add an easier "beginner mode."  If you start in beginner mode, the game is 10% slower, and, more importantly, you have unlimited uses of the slowmo and checkpoint items. Being able to set a checkpoint after each set of obstacles makes the game a lot more playable if you aren't into crazy frustrating challenges.

You still have to pick one mode or the other at the start, and if you pick beginner mode, you don't get any achievements or get to post to the leaderboards (big whoop, eh?).

Friday, August 21, 2015

Good enough? Beta Test time

Ok, I think I found a cheesy solution to the problem (which involves looping the laser sound continuously the entire time you're playing, but mostly at zero volume), although I still see an occasional stutter right as you start a map.

I don't think I'm going to let that hold me up though.

If anyone wants to take a stab at it, I've got a build up on Google's Play's beta test system that I'm thinking of pushing to release, that you can try out: https://play.google.com/apps/testing/net.tolberts.android.roboninja.android

Just follow that link, and give it a whirl. Feel free to email me any bugs, or leave comments here.

If nothing drastic appears, I'll probably release it in the next couple days!

So close...but so laggy

I'm so almost done. Most of the bugs are gone.

Except there's one thing that I just can't seem to resolve. There's some weird gotcha in libgdx's audio engine (on Android) where there will be a brief pause, or drop in framerate, whenever a sound effect stops playing. During most of the game, there's very few sounds, so it's not a huge issue, but the lasers that the blue guards shoot (and that Robo-Ninja shoots) are causing problems.

I've tried all sorts of things, but I just can't seem to work around it.

I've got a couple more things to try, and if those don't work, then I'm giving up and removing the laser sounds. Ugh.

Saturday, August 15, 2015

Testing and Fixing

I remember this point with Anguna. Every couple nights, I'd go to bed and say "I think I'm done," but the next day I'd find 5 more bugs. My wife would laugh at me each time I'd think I was done.

I've been playing a lot of Robo-Ninja, and finding a fair number of little bugs. I spent tonight figuring out what was going on, and fixing a bunch of them, but there's still a small handful left.

Then I get to do this again.

And again.

Someday, I'll play through the game, and won't find a single bug. Today is not that day.

Tuesday, August 11, 2015

Robo-Ninja first draft finished?

Tonight I finished the last few features of Robo-Ninja (at least for the Android version, I'd still like to make some tweaks for a Chrome version), finished changing things to use Chris's awesome graphics, and fixed the last couple of known bugs.

The first "maybe" build is currently building on my Jenkins server. Tomorrow I get to start intensive testing (otherwise known as "playing through the game over and over until I'm sick of it") to see how many more bugs I can find and squash before releasing it.

It sure feels nice to be almost finished.

For those of you that signed up to be actual testers on the play store, I'll try to get the test build posted tomorrow if there's no glaring immediate issues.  

If anyone wants to test and hasn't done so, let me know. (In the comments below, or you can email me)

Friday, August 7, 2015

Retrospex 32 Review

RetrospexInternational recently sent me a couple units of their new handheld device, the Retrospex 32, a new dedicated GameboyAdvance emulator handheld.  To make the unit playable out of the box, they pre-loaded a handful of homebrew games, including Anguna, which is why they were kind enough to send me 2 of the units to play with.  I was pretty excited to get my hands on the device and try it (I loved my old GBA micro with a good flash cart!), and see Anguna running on it. So here's my thoughts after playing with it.



Their website lists the Retrospex 32 for £59.99, which is around $100 USD. It seems like it's marketed toward people into retro-gaming (which makes sense for a dedicated GBA emulator device). At that price, with that target market, and such a limited set of functionality (why not make it a multi-machine emulator, and emulate all the old consoles?), it would hopefully do a really good job of it.

The short version of my review: it doesn't. It has one job (emulating GBA games), which it does fairly poorly. It's a mediocre device that you'd expect your grandma to buy for $15 at Big Lots next to those fake Wii consoles.  I'd maybe buy one as a novelty for that price, but anybody that spends $100 on this will be severely disappointed.

So let's get down to the actual review here.

Hardware

The console is a little bigger than I expected, almost 6 inches long (about the same length as my Nexus 5, but about twice as thick.) The plastic feels cheap and flimsy, and the various pieces give and shift a little if you apply pressure in the wrong places.  (On one of the two devices they sent me, there's a loose piece inside that rattles around if you shake it) The buttons and d-bad aren't particularly comfortable, but they work ok.  The charger uses mini USB instead of micro USB, which is just a minor annoyance that adds to the cheap feeling. It takes an SD card (not a micro SD card!) which is a bit weird these days, but not a real problem. It gave me a use for those SD cards I still have lying around with no purpose.

It does have an RCA TV-out port, and a cable to connect to your TV's RCA ports. I haven't yet tried that, but it is one of the nicer touches.

Overall, it feels a little cheap, which wouldn't be a big deal if rest of the package was there, or if the price was a bit lower.

Controls

Here's where it starts to fall apart. Any fan of the Gameboy Advance knows that it has two thumb-buttons (A and B), and 2 shoulder buttons (L and R).  The Retrospex adds an X an Y button, but has no shoulder buttons. So you have to use X and Y for L and R.  This is pretty awkward for quite a few games (particularly racing games where you use those to help steer, and have to keep your thumb on the accelerator).

Like I mentioned earlier, if this was a multiple machine emulator, I'd shrug it off. But for a device with one job, to emulate GBA games, you'd think they'd take the time to make sure it had at least somewhat of a similar button layout as the emulated controller.  Or if they couldn't rearrange the layout, at least label the buttons with L and R so non-gamers would understand what it meant. (Once again, I'm confused about the target market -- real gamers would be put off by the wrong layout, and casual folks would be confused when a game, including the bundled Anguna, tells you to push L or R and that button doesn't exist!)

The other big offense, at least to those of us that actually played older games, is that they reversed the positions of the A and B buttons. If you played many Nintendo games it's ingrained in your muscle memory that A is on the right and makes you jump, B is on the left and makes you attack.  Why would you build a handheld dedicated emulator and get this wrong?

The ENTIRE point of having a dedicated hardware emulator instead of just buying an older Android device for $50 would be to have decent hardware controls.  But you won't find those on the Retrospex32.

Emulation

Emulation itself on the Retrospex 32 is "not too bad". By that I mean, if you weren't particularly picky or demanding, you wouldn't notice any issues. Most of the games I played worked correctly.

That being said, it doesn't quite run at full speed. It's close -- maybe 90 or 95% of full speed?  I first noticed while playing Anguna -- it just felt slightly sluggish (and I've tested it enough that I ought to know!) I pulled out my real GBA to compare -- on both devices I'd clear the enemies out of a room, move the character to a wall, then simultaneously start walking on both devices. Out of about 10 tries, the character reached the opposite wall about 1/3 to 1/2 a second earlier on the real GBA than on the emulator.

I noticed this slowdown even more when I decided to get crazy and try running PocketNES (a nes emulator for GBA) on it. PocketNES isn't flawless, but did a surprisingly great job of running nes games on the GBA on actual hardware (I probably spent as much time playing NES games on my GBA as I ever did playing GBA games!) On the Retrospex32, PocketNES just couldn't keep up on most games, dropping the frame rates like crazy.

Once again, casual players probably wouldn't care, but hardcore retro-gamers wouldn't find the slightly slower performance to be acceptable on a $100 device.  Nobody would complain if a GBA emulator on their computer, phone, or other multi-purpose device ran 5-10% slower than the real thing. But if that's the device's entire job, you'd expect emulation to be pretty accurate.

The major show-stopping issue is that for most games, the built-in save functions don't work (and there's no save-state feature). Meaning you can't save your game at all. You can't even save on Anguna, one of the built-in games! (it acts like you can save, but if you turn the device off and back on, everything is erased). This pretty much ruins the device for me. There aren't that many GBA games that I'd want to play without being able save my progress.

UI and Misc

A few other comments about the device are worth mentioning. The roms on the SD card must be put into a folder called GAMES (case-sensitive). There's no folder browser or anything, it just finds the roms if they're in the right place, or gives up if not. Not a big deal, but not a simple task for the casual crowd.

The UI itself is mostly functional, but a little bit clunky and unpredictable. Many of the menu messages are mis-spelled or don't quite make sense. You can press Select+Y to exit the pre-loaded games and return to the root menu, but that doesn't seem to work reliably for other roms.

Conclusion

Really, I just don't understand this thing. It really wishes it was either a nice multi-console emulator device, or a cheap novelty. But at the current price, it's not really either one.

The broken control scheme and inability to save really are the main problems, but are critical ones. We took both of the Retrospex 32 handhelds on vacation, but they never got played. My son decided that, despite the touchscreen controls, he'd rather play the same emulated GBA games on the $40 android tablet, where he could, you know, save.

Monday, July 20, 2015

New UI, and terrible design

Well, now that the main game of Robo-Ninja is done, other than some testing, it's time to go back and rework some of the UI using the amazing graphics that Chris sent me.

With graphics like this, it starts to look like a Real Game
Well, in doing so, I've exposed all the bad design choices I made while doing the original UI. Things that should be pretty easy are harder than they should be, based on original assumptions. For example, in my original UI, the button width in a menu automatically changed based on the text width. In Chris's, it doesn't. But based on my "clever" menu code, changing that required a lot more work than it should have.

It doesn't help that, because I'm ready to be finished with the game, instead of going back and reworking the code with the new stuff, I'm just shoving it all together in the quickest way possible. So I've got a lot of dead code that doesn't do anything, layout functions that don't make sense in the new context, etc. 

Oh well. It's going to look a whole lot cooler, and I'm going to be done with it soon.

Although it will still take awhile to do this graphics rework.  I did some searching, and there's a lot more menus and buttons than I realized.

Monday, July 13, 2015

"Creative" is an adjective

Something that's bothered me recently is the term "Creative" as a noun, to describe certain types of artistic people.  Often graphic designers or marketing folks. (Wiktionary even has an entry for this usage of the word, specifically referring to marketing).  Our companies hire "creatives" to design our websites, marketing materials, flyers, etc.

Why does this bother me? Because this subtly implies that these types of people have some sort of monopoly or ownership of creativity. While we are becoming more an more of a "consumer culture" (fewer people are willing to sing, make art, or write poetry -- instead we leave these up to the "professionals"), terms like this tell the rest of us that we aren't creative. That creativity only belongs to a certain type of worker.

Instead, why aren't we appreciating the different types of creativity exhibited by all sorts of people, and encouraging everyone to create? (Or did we forget that the first definition of "creative" is "tending to create things"?)  So many people love to create, and be creative, although it looks very different than your typical artist/designer creativity.


My wife likes inventing homemade toys and projects with our kids. My office mate enjoys writing and blogging. I have friends that like to make up (create!) party games. I like designing video games. Another friend likes coming up with fun electronic gadgets. None of us are "creatives" but we love to create.

I also have a friend that is a well-respected electrical engineer at the university where I work.  He has loads of patents, and numerous inventions, some of which have the potential to positively impact huge numbers of people. Is he creative? I'd say so -- he created some amazing things. Does he do any sort of traditional art? Not that I know of.

Despite many of my examples being some sort of geeky creativity, this isn't about engineers vs artists. I just want to celebrate people creating. I don't care if it's dance or circuit design, poetry or carpentry. Most of us have the potential to be creative in some way, but reserving the "creative" label for a select few that are doing some sort of particular art or design doesn't reflect this.

Thursday, June 25, 2015

7-year old Anguna Bug

So Eli at Piko Interactive was testing Anguna, and kept running into a problem where the main boss would disappear halfway through the fight. Not that the dragon would really go away, but the sprite would disappear, but the collisions/bullets/etc would still continue.

Try as I would, I just couldn't reproduce it. He said it happened 100% of the time. But I couldn't see it happen. He sent me a save state and said that it should happen just right after loading from the save, but I still couldn't reproduce it. Finally, though, I just entered the cheat code to get tons of health, put the phone (emulator) down, and when I picked it up, he was gone.

So after quite a few more experiments, I somewhat sorted it out: It happened at 3ish minutes into the boss fight, every time, like clockwork. But the way I played, I never lasted 3 minutes in that fight. I always played it more aggressively, and was either dead or victorious in a minute or two. I never saw the bug, because I played the game differently (this is a good lesson to us programmers: sometimes people use our software differently, and expose completely different behavior than what we usually see! As a side note, the other day I had a problem at work, where a user said a field input NEVER worked. And it always worked for me in testing. Turned out, she always clicked the submit button, where I always pressed enter. The enter key worked. The submit button didn't. oops)

Anyway, once I figured out how to reproduce it, it didn't take long to find the problem. I opened up the code for the boss fight, and saw that the animation for the face (which only had one frame) was set up to display for 9999 game frames...then was supposed to start over (back to the one frame again!). 9999 game frames was about 3 minutes. Aha!  Turns out my code to start the animation over wasn't working right for these one-frame animations.

Which meant that there might be other issues with single-frame sprites. I dug around and looked -- most of them were set to some absurdly high number of game frames before they "repeated".  Turns out, if you put the game down for about 30 minutes without moving, a bunch of things (doors, items, locks, etc) timed out and disappeared. I guess nobody's ever tried doing that, that bug has been there from the beginning, but nobody has ever reported it!

It only took one line of code to fix it, and make the single-frame animations loop properly. Weird to find and fix a bug that serious and that old, with 1 simple line of code.

Assuming no other issues appear, manufacturing for the cartridges should start soon, according to Eli!

Saturday, June 20, 2015

Atari Green Toady

So the Green Toady in Anguna is the first somewhat difficult challenge the player faces. Unlike the simple slimes in the first few rooms, the Green Toady not only take a number of a hits to defeat, but also has a more difficult movement pattern:

He first wanders slowly and randomly, but as soon as he is lined up (or more accurately, close-to-lined up) with the player (on either the X or Y axis), he pauses, then charges quickly at the player, until he hits a wall.

Tonight's challenge was to get that working on Atari Anguna. This is the most complicated enemy so far on the Atari, and would require a bit more code than the other enemies. The trickiest part was something that should be simple for anyone with any real 6502 experience, but required some thought for me: figuring out a reasonably efficient way to determine if two numbers are within a certain range of each other. (ie I wanted to see if the enemy X position was within 5 (plus or minus) of the player X position).

What I ended up doing is below, although it's late, and I don't have the brain power to really figure out if there's any edge conditions that I'm missing involving overflowing between positive and negative numbers. (The X register contains the index of which enemy we're dealing with, as there can be more than 1 enemy onscreen at once):

    lda Enemy0X,X
    sbc PlayerX
    adc #5
    bmi .NotLinedUpX
    sbc #10
    bpl .NotLinedUpX
    ;chase main char only on Y axis


I'm loading the first value, subtracting the second. Then add 5. I check if the result is negative. If so, they're more than 5 apart in the one direction. Then subtract 10, and check if the result is positive. If so, it's more than 5 apart in the other direction. If neither is the case, then they're within 5 of each other.  It's only 16 cycles, so pretty efficient. I didn't bother to set or clear the carry flag, so it's not going to be exact (I could be off by 1, depending on the carry flag's state coming into this), but I'm not too worried -- for this case, "around 5" is all I need)



Anyway, the amazing part, is that after fixing a couple typos, the toady mostly worked on the first try. That NEVER happens.


I do have a couple minor tweaks to make him work better (I put the charge on a timer which is too short, and I didn't initialize him into any state, so he just sits there for awhile when he's first on the screen). But still, it was certainly an unexpected lucky outcome for a relatively complex enemy.

Monday, June 15, 2015

Moving from sourceforge

And along with this, I decided to move the DS version of Anguna (which was open-sourced awhile back, and sitting on sourceforge) away from sourceforge. Because if you haven't paid any attention to the news, Sourceforge has gone nasty.

So the source is up on bitbucket now. I still have some cleaning up I really need to do, but there it is.

Sunday, June 14, 2015

DS build (probably?) working again!

So again thanks to Sverx, I think I have the DS build of Anguna working again.

In response to one of my previous posts lamenting that I couldn't find a 2008 release of the devkitPro/libnds tools, he mentioned that he had a copy!  He sent me what he had, which turned out to be the windows version.

Although GBA anguna was developed on windows, I developed the DS version on linux. So everything I had was set up for linux, and I'm currently using (and running my builds on) linux.

My first attempt to get it working was to just use my current version of my gcc arm cross-compiler with the 2008 version of libnds, which as I suspected didn't work.  It compiled, but the linker complained about all sorts of things.

I didn't want to go all the way and set up everything in windows yet, so the next try was stupid: use all the windows toolchain compilers via wine. Has anyone EVER run windows versions of gcc on linux using wine before? A terrible idea.  But it seemed to work when I compiled it. (despite taking quite a while to compile!)  But when I ran the finished rom, it had all sorts of weird issues once you got into the game, past the splash screens.

But this seemed familiar, similar to the problems I had trying to compile the gba version on linux recently. So I went through and made sure to convert all the files' line endings to unix (not sure why that would be an issue, since they were originally done in linux), but then everything worked!

So despite the terrible idea of running all compilers in wine, I know have DS builds working again. (I think? I haven't tested it yet past the first couple of rooms)

Maybe that means the new dungeon will eventually get ported to the DS!

Friday, June 12, 2015

Corrected....

In my previous post about the volatile keyword, Sverx left an insightful comment, noting that because nothing is changing the SRAM data outside of my code, it shouldn't really need to be marked as volatile.  Which is true -- nothing really changes it at run-time.

So what was the actual problem and why did marking it as volatile correct it?

For one thing, as sverx mentions in the comment, SRAM can only be written 8 bits at a time. Which I'm doing (casting my data into 8-bit chars and looping through writing them one at a time). But now I'm wondering if the newer versions of gcc saw that, decided I was stupid, and optimized it into 16- or 32-bit writes. Which would make sense why adding debugging messages in the inner loop would change it.  Marking as volatile might also have been enough to scare the compiler off from over-optimization, and fixed it as well, although not quite as correctly.

Thanks sverx!

Wednesday, June 10, 2015

Updates

So here's where everything's at right now:

GBA Anguna: new content is finished, the rom is being playtested by folks at Piko Interactive (which they've already found (and I've fixed) one bug), hopefully soon will be sent off for production!

Robo-Ninja: The game is pretty close to finished. This week I've been working on the ending sequences and more google play services integration. I might skip the cloud saved games (it looks like a bit of a pain to convert my save game format to work with it, but we'll see).  The biggest change is that Chris (the guy that did the graphics for Anguna and the new awesome Robo-Ninja character graphic) has some great looking designs for improvements to other graphics in the game, including all the UI bits, so I'm planning to wait to see what he comes up with, and probably do a bit of reworking all the UI to use his designs.  (although there's still a little bit of work to do until then: tweaking some level designs, testing, and improved keyboard controls for non-touch screens (I plan to provide both a java desktop download, as well as a Google Chrome app)).

Atari Anguna: This poor guy has been getting neglected thanks to the work on GBA Anguna and trying to do a mad dash to finish Robo-Ninja. The core engine is in pretty good shape, and I need to build out a test dungeon to do some more in-depth testing. The next steps will be getting the header/hud thing working right, and then secondary items (bow & arrow, dynamite, etc).


Friday, June 5, 2015

Robo-Ninja Boss Fight

My office-mate Tim has been so kind as to play through Robo-Ninja, giving me great feedback along the way. A week or so ago, he finally got to the end -- at least so far. He got to the room right before the main boss. And has been patiently waiting for me to give him a boss to fight.

Well Tim, we're almost there.  I think the boss is done. Although once you kill him, I don't have any sort of victory sequence or anything. He dies and you're just stuck in his room. But hey, progress.

I ended up NOT giving him multiple forms after all. Partially because I'm ready to finish this thing, and partially because while testing it, he seems hard enough already. 

So now there's just a few things left to do:
  • A few map tweaks based on Tim's feedback
  • Fix a couple of bugs in my game engine (again, based on Tim's feedback) 
  • Add graphical icons on the teleporter UI (I've had blank placeholders sitting there for months now)
  • Finish the options and license/credits screen (I've used a ton of Creative-Commons licensed art and sounds, so I have a lot of credit that needs to be mentioned)
  • Finish the leaderboard and cloud save integrations
  • Add an ending sequence
  • Test, Test, and test again
  • Release the game, get rich, and retire

No DS re-release for now....

So today I download the source to the Nintendo DS version of the Anguna to see if I could easily get it to build, to push the new level to it as well.

Didn't turn out so well so far.

The development kit for GBA and NDS development (devkitPro) has both the compiler toolchains/build tools/etc for development, as well as some libraries for interacting with the various platforms. The libraries are mostly thin wrappers around the basic functionality (nice names for the various registers, utility functions to deal with them, etc), but there's a few other bigger bits, such as sound libraries, etc.

On the GBA, I didn't use any of the devkitPro libraries directly, and instead just managed my own, using just the simple register definitions.

On the NDS, I ended up using a lot more library calls from devkitPro. Which turned out to be the problem here. The NDS libraries on devkitPro have changes significantly in newer releases. And I'm having trouble coming up with a version of the library from 2008 that works properly.  Unless I can magically come up with a working version of libnds circa 2008, the only other solution is to rewrite quite a bit of code to work with the newer version of libnds. No thanks.


Thursday, June 4, 2015

Volatile

I spent about 2 hours last night pounding my head in a wall trying to figure out the solution to a new bug that I ran into: Anguna's save game function was no longer working.

In the GBA, the most common save method is to just write to a magical area of ram that happens to be battery-backed, so it retains its values. So when I save, I write the game state to that area, including a checksum.  On loading, I read the checksum to see if there's a valid game state in ram (as opposed to un-initialized garbage), and if it's valid, load it.

So last night, I was writing the data, but then when I read it back out, the checksums didn't match!

So I started debugging. I logged the first few bytes writing to save, and logged them again as I read them...everything looked right. So the first few bytes were working. I tried again with the last few bytes -- they matched also. Weird.

So I dumped ALL the data to a log upon saving and loading. And Lo And Behold, they matched, and it worked correctly.  Uh oh.

I removed the debugging, and it broke again.

This is normally an unhappy position to be, although this time it quickly led me to the solution. There were no actual side effects of my logging code (other than the logging itself), so clearly the compiler was optimizing something differently.

Then I checked to make sure that the save ram was marked as volatile. Nope. Oops.


In C, you can mark variables/memory/etc as volatile, which means that its value can be read or written outside of your current program. This lets the compiler know NOT to optimize away read/writes to it.

For example, in the gba, to get the state of the controller inputs, you read a particular memory location. If you don't mark it as volatile, the compiler will notice that you are reading it every frame, but never writing to it, and might optimize away your other reads. Which is not what you want.

In this case, I'm not sure exactly WHAT the compiler was thinking in optimizing away my reads/writes to the save data, but marking it as volatile did the trick. And I guess the compiler's optimization strategies have changed since I last worked on Anguna, as I never had it marked volatile before. Oh well.


Sunday, May 31, 2015

Anguna New Level

Ok, I promised I'd share, so here you go.

For the upcoming cartridge release of Anguna by Piko Interactive, we decided to add an additional dungeon level to Anguna, to sweeten the deal for anyone who might buy one. So the past couple weeks I've working like mad to try to add the new content before production of the physical carts starts.

Today, I finished the first draft of the Ice Dungeon, with slippery ice on the ground, a new Golem boss, and a new inventory item (a ring of teleportation):

Fighting the fearsome Ice Golem

For now, this dungeon is going to be exclusive to the physical carts you'll soon be able to purchase from Piko Interactive, to try to help them sell these things.

The process has been interesting -- first I had to just get the silly thing to build properly on a modern development environment, then I had to go through and fix a bunch of bugs that originally existed in the game, but somehow never manifested themselves on the older versions of the compiler/toolchain.  Once that was finished, it was a pretty straightforward process to start adding content. It definitely brought back memories of 10 years ago when I started this project!

In other Anguna news, if you have a windows phone, check out My Boy, a gba emulator that features and bundles Anguna.

Monday, May 18, 2015

Anguna Teaser

I've been quiet recently, but working hard. Working on some stuff related to the original Gameboy Advance version of Anguna.  I'll go into more detail later.

The fun part has been re-installing all the tools needed to build and edit Anguna, and realizing that there were a number of bugs that "worked by coincidence" with the older versions of devkitPro, but don't work anymore.  I spent longer than I anticipated just getting everything working again.  It brings back weird memories, looking at this old code. And geez, I don't know how I ever got this game finished, with how difficult it is to debug code on the GBA.  Fun times.

Ok, enough being mysterious for one night.

Friday, May 1, 2015

Playfield editor and Green Toady

Today was an Atari Anguna day.

First, I was working on some new room layouts, and got a little frustrated with the room editor I had been using (Kirk Israel has an incredible 2600 Sprite Editor on his website but his playfield editor leaves a bit to be desired. (mainly, that I couldn't drag to paint, instead had to click each cell, also that I couldn't paste my code into the tool to modify already-existing rooms).

So I decided to rewrite it. The end result isn't perfect, but seemed worth the time. (about an hour and a half). It fixes those issues and a few other minor niggles from Kirk's editor. It's posted at http://www.tolberts.net/pf.html and the code is fully contained in that one page, (other than pulling in dependencies from google) in case anyone wants to take it and improve upon it.

I also started on the next enemy, the Green Toady (the first difficult enemy from the first dungeon in GBA Anguna). I've got him working, but now realized that I don't have a mechanism for enemies sprites to flip horizontally depending on their direction. It didn't look too strange for the slimes, but it looks dumb for this guy to always face the same direction.

The 2600 has a register to flip sprites horizontally, but because I'm reusing the player-2 sprite for all the enemies on the screen, I have to update that register in the display kernel. In other words, it has to be fast, and fit somewhere in the kernel where I have unused cycles. So that's the next challenge waiting for me....

Those are supposed to be pillars, but I've been told it looks more like "The Illini Room"

Looking at that screenshot, I really need to go back and rework the top header bar. It's a mess of brokenness right now.

Monday, April 27, 2015

Boss Fight

I'm starting to make progress on the Boss Fight.

Like many games, this fight moves through a few phases, alternating between times where you just have to survive, and times when you actually try to attack back.

The first phase involves lots of jets of fire filling his room that you have to avoid. From the top, the sides, etc. It's tricky, but not too bad, really. I've just about got this phase finished. Next will be a part where you can fly up and try to get a shot off with your laser before he starts shooting fire at you again.
Geez, in this picture, you can't even SEE Dr. Squidbrain because of all the fire.


Friday, April 24, 2015

And 2 MORE bytes ram

And today, while the baby was napping, I managed to remove 2 more variables from ram (associated with enemy missiles, that I realized were no longer needed). That frees up TWO MORE ADDITIONAL BYTES.

I now have 14 unused bytes of ram.  That's awesome. I might even be able to support a 4th enemy per room, at this rate.

This post needs a subject

Been slowly chugging away, but not much to say.  Other than a big THANK YOU to Tim Dudek for doing some serious testing of Robo-Ninja. He's helped me fix a number of bugs, performance issues, and a few map issues.

Mostly, I've been setting up the overall structure of the game so that each build (android/desktop/etc) can specify more of the behavior specific to that build. That let me add the Google Play Games integration into the Android version but still have everything else work correctly. I'm also planning to add some help text to non-touchscreen versions (desktop, web, and my new plan to use Google's Arc Welder to make a Chrome App as well) to make it more obvious how to play with a keyboard.

Then, now that I started that, it made sense to finally break Aaron's mode out into a separate build, to remove it from the "real" build. (if you recall, he started making his own levels (Geesh, that was more than 2 years ago. That's an eternity in a kid's life))

I also need to actually finish the final boss fight. I made the story cutscene that shows when you enter his room. Now I need to actually script the fight itself. I've come up with the idea of how I want the fight to work, but it's going to take a bit of work.



I've mostly pushed Atari Anguna (and my Bot-Box tutorial for Chris) to the backburner for now, trying to get closer to finishing Robo-Ninja. But I did finally sit down with Atari Anguna today and give it at least a little love, getting the next major chunk of the game engine working: enemy missiles. Well, that should really be missile singular -- I'm only supporting one missile at a time. But it only took about an hour to get them in place, so my orange slime can now shoot blobs of goo. Well, you have to use your imagination. It looks more like a dot....


Thursday, April 9, 2015

Play Services

After a lot of work trying to figure out issues with Google and Android SDK libraries, I've got the Google Play Games API working! (by "a lot of work" I mean maybe 3 or 4 hours....I guess that's not so bad)

Based on the results of the votes, the answer sounds like I should go ahead and use the games services to their full potential. Here's a test run of unlocking the first achievement!



This tutorial was super helpful in figuring out how to get started. Although there were a few hiccups that I'll document here in case the answer is helpful to anyone (or myself next time!)

First, I got all sorts of errors with not being able to find the right libraries. As many forums have mentioned, the dependencies specified in the build.gradle file have to match the SDK version that you download using the Android SDK manager. The working combination that folks are recommending as of today (Apr 2015) is the following in build.gradle:

        compile 'com.android.support:appcompat-v7:21.0.3'
        compile 'com.google.android.gms:play-services:7.0.0'

With that, you need to download the v21 (Android 5.0.1) SDK in the Android SDK Manager. Also, you have to scroll ALL THE WAY TO THE BOTTOM of the SDK Manager, and find "Google Play Services" in the "Extras" folder:


Once that is done, I'd either need to recreate the IDEA project file (using the "idea" task in gradle), or manually add the jars for those files to the classpath in IDEA. (I'd recommend recreating the IDEA project file -- I tried adding them manually, which worked for development, but not for deploying to my phone, so I ended up having to build/deploy from the command line).

Also, the example code from the tutorial linked above is out of date for making calls to the games service. As this forum post discusses, instead of trying to use gamesHelper.getGamesClient(), you need to make static calls using the Games class:

   Games.Achievements.unlock(gameHelper.getApiClient(), "(your achievement id)");

Once I did that, I was almost there! The only other thing I had to do was go back and sign my apk with the same production key that I used to create and push the app on the play store. Once that was done, everything just worked!

Blaster MetroidVania

Well, I've been working on the next game, but not saying much.  Mostly because the majority of my free time involves working on fixing t...