Evolution of Levels
07/01/14 04:51 PM Filed in: iOS | Development
During my extended absence from blogging, I have been hard at work (well, mostly hard at work!) on a new iOS app. It started off as a fun exercise, and has turned into a game. One of the areas of the game I’ve reworked multiple times is the method of providing game level data. The game didn’t even really have levels, but as I played it and tested it, and played other iOS games, adding progressive levels felt like the right way to go. At first, the levels were completely hardcoded into an array of C structures. This worked to get things started. Then, I decided that being completely generated was the way to go. I wrote and entire level generator, although it had rules and parameters so each level wasn’t completely random. It worked nicely, but didn’t seem all that great for challenges between players, or replaying to improve your score. So, jumping onto the JSON train, I next specified the each level format in a JSON-based file, which I loaded at startup. This was a very pleasant format to write (much better than plists)(you can only click on those little tiny + and - icons in Xcode’s plist editor so many times before going crazy), and gave me a certain amount of flexibility. However, it just felt so heavy... all those arrays of strings. I don’t think it was a huge performance problem, but I just felt like it was heavier than I needed. So, back to C structures. But this time, just a small change in how I formatted the default entries in the header file (comments and putting each field on its own line ) made it feel like JSON, but I got back my beloved bitfields and integer-based efficiencies. One area that had pushed me toward JSON was the need to specify some help text per level. Putting ObjC strings into C structures is not really doable, but I came up with a workaround. The strings I needed for each level were written with each structure, but commented out and included an easily grep-able tag. One quick build phase where I ran some grep/sed magic over my header file and generated a .strings file, and I was in business. A great bonus is that some day I could localize the app more easily. Plus, one quick memcpy of the pre-initialized structure into heap-allocated memory meant I could have the best of both worlds -- some values computed at runtime and most values set up ahead of time in a easy-to-read and modify header file. Having things in C also makes it possible to do some debug-only startup validation of the data that would be more difficult to do in a JSON/Dictionary based solution.
Something that seemed like it should be straightforward has certainly taken me a while to figure out. This might not even be the final iteration. But, I’ve coded up the first 10 levels of the game using the new structure (and due to some good factoring in my code, the changes to support an entirely new level format were mostly hidden in one class), and it feels pretty good. One of the reasons I hadn’t finished specifying all of the levels in the game (I’d like to release with 50 levels to start), had been partly due to the cumbersome nature of adding new levels. I’m hoping that the next 40 levels go as easily as the first 10 went.
Good luck designing your own apps! Don’t be afraid to iterate and throw out something that doesn’t feel like it’s working for you. It might have cost me a few hours to rework this code, but if it means I am able to move forward in completing a part of the app that had been annoying me, then it was most definitely time well spent.
Something that seemed like it should be straightforward has certainly taken me a while to figure out. This might not even be the final iteration. But, I’ve coded up the first 10 levels of the game using the new structure (and due to some good factoring in my code, the changes to support an entirely new level format were mostly hidden in one class), and it feels pretty good. One of the reasons I hadn’t finished specifying all of the levels in the game (I’d like to release with 50 levels to start), had been partly due to the cumbersome nature of adding new levels. I’m hoping that the next 40 levels go as easily as the first 10 went.
Good luck designing your own apps! Don’t be afraid to iterate and throw out something that doesn’t feel like it’s working for you. It might have cost me a few hours to rework this code, but if it means I am able to move forward in completing a part of the app that had been annoying me, then it was most definitely time well spent.