Sunday, November 29, 2009

Indifference Engine Ready for Development Use.

Finally, all features are implemented, all known issues are fixed, and all game modes run at an acceptable speed even with the engine running at full tilt. I hereby declare the first version of the Indifference Engine complete. Now the fun part can begin: Actually making games!

Of course, it's probably more accurate to say that the Indifference Engine is 98-99% done. That's because, although I've tested all the features in isolation, and I've tested how they interact as much as I could within a reasonable amount of time, a full-fledged game is going to put a greater strain on the engine than my test data, and might well expose some subtle bugs that the initial tests missed. But that's not too big a deal -- the entire engine is fundamentally sound and any remaining mistakes could only be in the form of minor logic errors, which are generally pretty easy to find and fix. So from here on, it's mostly a matter of designing and creating game content. Pretty exciting.

- Satellite Observatory (James)

Thursday, November 26, 2009

Indifference Engine Almost Done...

Since finishing battle mode, I've added the victory screen, random encounter tables, the settings screen, saving and loading, and an autosave so if the application quits in the middle of the game (for example, if you're playing it on an iPhone and you get a phone call) it will preserve your data and reload it the next time you start your app. All that's left is to make a title screen and then add sound. Though the real test, of course, will be how smoothly it runs once all of these features are implemented. My biggest fear is that battle mode will slow down again once I add audio -- but if that happens, I'll just figure out even more ways to optimize it.

The autosave feature was a bit of a pain to implement. As best as I can tell, the only place where you can add autosave functionality is in the applicationWillTerminate method of the AppDelegate. But the problem there is that my main View class, where I keep all my data, is invisible to the AppDelegate class. (Huh? MVC? Screw that.) And it's kind of hard to save data that's invisible to you.

My solution was to create a singleton class and import it in both the AppDelegate and the View. That's still just a one-way communication though -- the AppDelegate and View can talk to the singleton class, but not the other way around. That was good enough, though. The View class periodically compiles autosave data within the singleton and then when the application terminates, the AppDelegate checks in with the singleton to see if it needs to autosave -- and if so, it does. Then when you start the game back up, if autosave data exists, the InitWithCoder fires it up and you can continue on your merry way. It was a bit trickier than that, though, because the game needs to track a ton of state data and sometimes my timing on compiling the autosave data was a bit off, resulting in the data getting out of sync -- for example, it saves a bunch of Event data but then tries to load it in Map mode, which causes it to get really confused and then die horribly, thus making it impossible to ever start the game again since it immediately crashes. That obviously isn't very acceptable behavior, so I spent a few hours tracking all those bugs down and making sure the autosave data stays synced no matter what combination of loads, saves, and mode changes the user goes through. It seems to be working now.

Just a couple finishing touches to go. Gonna be glad when the programming phase is behind me and I can start actually making a game with this engine that I've spent forever designing and implementing.

- Satellite Observatory (James)

Saturday, November 21, 2009

Some progress...

My battle system is complete. When I tested it out on my actual iPod with everything running at the highest possible capacity, the performance slowed down; but by cutting out some non-critical animations, I got it to run really smoothly even with the enemy and player groups at full size and both sides' attack intensity turned up really high. The battle system looks /slightly/ less cool, but it's a minor downgrade and well worth it to get it running at a smooth 30fps. So I can put a big green checkmark next to that item on my to-do list... as long, of course, as it doesn't slow down again when I go back and add sound to it after enabling the victory, settings, and title screens (all of which is gonna be pretty boring, but needs to be done). It better not...

Monday, November 16, 2009

Fun moments in programming

I've been really productive lately. Over the past 3 days, I've written over 2000 lines of code and gotten a huge amount of functionality in my game engine in place. Mostly it's been lots and lots of string and array manipulation, and calculating graphical coordinates. But just now I came across an interesting problem:

I was coding changing equipment on your character. Because I store equipment data as structs, it seemed straightforward enough: Create a "swap placeholder" equipment variable and then do this:

Swap placeholder = player's current equipment
Player's current equipment = new equipment
New equipment's slot (the equipment inventory is stored as an array) = swap placeholder

However, this did not work and I quickly realized why: My structs contain strings, and when I use the "=" operator to copy structs, it just copies the pointers of the strings over. I thought of 2 possible solutions:

(1) Write a crapton of tedious, repetitive code to manually copy all the data, accounting for all possible combinations of new and old equipment; or
(2) Write a function that takes 2 equipment structs as parameters and copies the old into the new, and just call this function a few times.

Option (2) is better than option (1) from pretty much any standpoint, but I soon realized another problem. Since my equipment is structs and not objects, by default, they get passed into a function by value and not by reference. This means they become local variables and any changes made to them don't affect the original structs, thus defeating the whole purpose of the exercise. The solution, obviously, is to pass in the addresses of the structs and dereference them in the function, but I had no idea how to pass structs by reference in Objective-C and couldn't really figure it out.

...Then I remembered that Objective-C is a proper superset of C.

So I went back into my raw-C DataTypes header file and added my copyEquipment method signature to that in C format, then wrote the function definition in my Objective-C source file (which looks weird packed in between my Objective-C functions because the signature syntax is completely different), and used the "->" dereference operator to assign values to the struct members while retaining the memory address of the original struct. But, since the string members are still Objective-C objects, I had to combine the C dereference with the Objective-C signals. Then I went back and replaced my original copying code with calls to the copyEquipment function using the "&" address-of operator (after fetching the relevant equipment out of the inventory array).

...Then it worked.

It's very rare that I actually have reason to use the -> and & C operators, so that was actually kinda fun.

Whee.

- Satellite Observatory (James)

Thursday, November 12, 2009

Mwahahaha.

I just set the following as the desktop background on my Mac:


I love it!

Wednesday, November 11, 2009

Tic-Tac-Awe Pro coming to iPhone

It has been a while since our companies last post, so I wanted to update everyone on what we are doing.

Our first game out of the game, Tic-Tac-Awe (which is free) has been downloaded going on 200 times in its first month. By publishing this game, and a paid version of it, Tic-Tac-Awe Pro, which implements difficulty levels, we have learned how to sell on the App Store. With all of our information set up, now all we have to do is complete the games we are working on, and publish them. The faster we publish our games, the more successful our company will be!

James and I have quickly been learning the in's and out's of the iPhone hardware and software, what it is capable of and what it is not. Lesson number 1 - it does NOT have the power of a full computer. You cannot throw dozens of graphics on the screen all at once without worrying about performance. This is important, because even the weakest laptops today are more powerful, hardware-wise, than the iPhone. This is not to bash the iPhone - it is a hand-held device. You have to program it as such.

And, as such, our flagship Windows game, Sorceror's Stripes, did not port so easily. It will be ported, make no mistake, but we may need to use the 3-D accelerated OpenGL ES for the graphics, rather than the much easier to use Quartz, which chocked on James' animation.

We have other games in the pipeline, however, that are not as graphics intensive. Specifically, adventure games, very fun and detailed, but that does not use the graphical power. As we finish these up, please support our company by buying a copy of Tic-Tac-Awe Pro (as soon as it clears the App Store, probably a week or so), or buying the fun and flashy Windows game Sorceror's Stripes!!!

More posts to come soon!