Wednesday, February 29, 2012

Design to Product - Software Design Pt 2 (13 / 17)

After coding for a bit, redesigning, testing, then coding some more, we ended up with the basic elaboration to our software design.  Please note that this is a live process.  In other words, when we found snags, re-analyzed what we were doing, and asked ourselves how we could go about doing it better, we scrapped some work "for the greater good" (whatever that means).

So, here is a breakdown of the major classes of the project and what they do on a conceptual level.  Normally a UML diagram or something here would be sufficient, but we're renegades like that.

Bubble
This class deals with every "bubble" in the game.  The gameplay is such that new bubbles are spawned at the top of the playing field and slowly descend towards the bottom of the screen.  This class handles the updating process (how much and how far does each bubble move), as well as drawing each bubble.  Each bubble also has a value which pertains to its assigned color  (which is randomly assigned in generation).

For some static functionality, this also handled loading all game resources associated with bubbles (like the bubble graphics themselves).  The most important point here is that all graphics should be loaded once and only once then drawn per instance of a bubble.

Gamedata
This is a convenience class that handles persistent data about the game itself.  Specifically, this remembers the player's options whether to have the sound on or off.  Originally, it was designed to also keep track of in game purchases with points, but as the design evolved, this feature was removed.  Because all of the "persistence layer" stuff was conveniently packaged in this one class, adding and removing new things is easy.

GameThread
The bulk of the higher level stuff is in this class.  Big questions are handled here, like "is the player in any menu", what to do when the player wants to pause/resume the game (this is the in game feature, not the activity pause/resume), high level resource initialization, the game loop itself, touch event propagation to support classes/objects, and things like this.

This class also handles the Android lifecycle events of pausing and resuming, which is completely different than the in-game feature.  We put this functionality here because it has high level access to basically everything in the actual game logic that needs to know about activity life cycle events such as these.

GameView
Not too much to say here other than this is our version of the SurfaceView class used by Android.

Marble
Like the bubble, this class handles everything that has to do with the player marbles.  These marbles need to be updated every game cycle so they have an update method, need to be drawn on the playing field, and need to be spawned based on player input.

There are some methods that let us query what kind of marble this is.  Specifically, is this a "normal" marble or is this a "special" marble.  In the gameplay, normal marbles are simple red, green, blue, yellow playing pieces, and special marbles are just that.  They do things that normal ones don't.  The game design had changed over development - originally, we had rainbow marbles, rocks, purple marbles, and heart marbles.  This changed to only have rocks and purple marbles (more on this in the post-production article later).

At any rate, this class is very similar to bubbles and share the same design, but different code from each other.


MarbleSlot
This class is "part of" the playing field.  This handles the player's desire to launch marbles from it.  Each slot contains a marble value and when it comes time, the playing field spawns a new marble based on which slot the player initially touched.

Logically, these slots are just defined zones in the playing field that define whether or not the player touched a specific area and don't do much else other than that.  Based on the assigned marble value, it also draws a colored marble to represent what marble will spawn when interaction occurs.

PlayingField
This is the over-arching class one step down from the game thread itself.  This "contains" every intractable aspect of the game, all marbles, all bubbles, and even the GUI while playing.  This large class handles all the essential gameplay logic to include setting up a new game, actually creating new marbles from the slots, propagating update method calls, propagating draw method calls, increasing player marble stock, harming the player, resource management, and lots of supporting methods - including collision detection/response.

From the game thread, a playing field instance is created and basically sticks around until the program is considered "finished".


PlayingPiece
This class is a parent class to Marbles and Bubbles and defines what exactly makes them playing pieces.  The class defines a collision flag (used for collision detecting), a velocity vector, a RectF object used to define piece positions (and drawing boundaries), a method to calculate the distance to another playing piece (used again for collision detection between marbles and bubbles), and some convenience methods shared by marbles and bubbles.

Almost anytime there is overlapping features or methods used by more than one class, it is almost always a good idea to create a parent class.  Essentially, this is like saying "ok, so, we have this cool new game, it involves some playing pieces that collide with each other"... what does that mean?  Well, those pieces are either marbles or bubbles and their interaction with each other.  Excellent candidate for a parent with two children sort of situation.

Wednesday, February 22, 2012

Design to Product - Software Design (12 / 17)

Finally, let's talk about how the code should be set up.

We mentioned earlier that we took the game design, analyzed it, and figured that nouns become classes and verbs become methods.  This sounds good on paper, and there are even tools available to help this process.  We could sit around and chart UML all day, every day in regards to the design, but is it necessary?  That depends.

Because our product isn't an enterprise solution, our team is small, and one guy is basically doing everything, a massive UML chart isn't really necessary.  Of course, we could never discount the idea that someday in the future these things could become useful (like if we sold our products off to another company, as an example).

Regardless, the best way forward for us is to pick apart the major components of the design and start designing what logic should go where and what it should be called.

Honestly, because of our development methodology (or lack there of, depending on who you ask), we take more of an extreme programming measure in this regard.  We make classes as we need them.  We start with a basic skeleton framework, then start adding new classes as they are needed in the code itself as we program the meat and bones of the product.

We start with the largest classes in the skeleton.  Specifically, for Android programming, we start with the GameActivity class.  This class acts, more or less, as the "starting point" for the program and interfaces with the OS.  Because of how Android itself is designed, we must make a GameThread class that contains the top level logic for the flow of the game itself.  We also will need an extension of a View class so that we can interact with the screen and display stuff.

Right away we have:
GameActivity
GameThread
GameView

Without really even going further, based on the game design, we know we already have 2 major components to the product, a Marble, and a Bubble.  These playing pieces are what are the basic, interactable things in the game itself.  Because both things follow the same physics, we decided that it is best they share a common parent class; PlayingPiece.  This parent class defines movement vectors, collision information, the abstract methods of how the pieces are updated and that each child class should know how to draw itself to the screen.

At the same time, we can't really play the game without some sort of logical thing to interact with and where the playing pieces do their magic.  Enter the PlayingField, a logical container that contains everything the player can interact with and see.

The game design indicates the need for persistent data over game launches, so we made another class Gamedata that is our "middle man" that handles data saved and loaded between game sessions.

We also ended up needing a class called MarbleSlot, a place where players can touch and interact with the playing field in which marbles can be spawned from.

All that said we now have:
Bubble
Gamedata
GameThread
GameView
Marble
MarbleSlot
PlayingField
PlayingPiece

There are one or two utility classes that are used to assist in the passing of data and messages between classes, but those are fairly technical and don't have anything to do with the direct design of the content of the game.  Suffice to say, those can take a while to design and program as well.  Just because a game design is "simple" doesn't mean the work behind it will take a set number of hours based on the relative ease of that design.  Lots of "stuff" can go on behind the scenes that can take days or even weeks to implement that have no actual, obvious visual effect on the product itself.

For example, a programmer could spend a month just drawing some graphics on a display.  They are very proud of this accomplishment, but to non-programmers they usually have the attitude of "you spent a month on this, and only have this to show for it?!".  Get used to scenarios like this because it happens more often than not.

Anyways, now that we have our basic classes determined, the essentials are fleshed out.

Tune in next time for elaboration of the class designs and the overall flow of the logic for some of them.

Tuesday, February 21, 2012

Design to Product - Requirements Creep (11 / 17)

While designing, programming, and testing, we came up with some new ideas of how to make the game better.

The dreaded phrase "ya know, this would be cool if...".  Yes that.  What just happened is something called requirements creep, or rather, features and things that were not part of the original design document, but have become desired enough to "add in" some extra things or at least change a couple of things that we had already designed.

This sneaky way of adding new things in to the product forces us to change code, update documentation, and start our testing all over again with the new things put in to the product.  Long and sad story short, it simply means more time is required before the product can be released.  WARNING: If this gets out of hand, your product will be delayed indefinitely as more and more new things keep getting piled on!

Fortunately, some of these sneaky new features that were drafted up can wait until after the game is released and we can put the new content in with a content patch later.  If you've been reading along, during an earlier blog article I mentioned separating things that we need versus what we want.  Requirements creep operate the same way.  What must we absolutely have to have in the initial product release versus what can wait.  There is a risk involved with this.  The more we "must" have before initial release, the longer the product will take to get out the door... but if those new features really enhance the product and make it more appealing or playable, we certainly should include it.

For example, during our play testing, we saw that most the gameplay levels were "too easy".  The player could easily fly through the game levels without much of a challenge.  According to the design, this was basically as the product was designed.  Well, unhappy with it, we decided that different sized bubbles should play a part of making the game more difficult as the game levels were increased.  This new "feature" wasn't part of the original design - nor was the existing code ready to make such a new leap in to catering to differing size bubbles.

Because we felt that this sort of thing should be required to make the game more challenging and offered in the initial product, we accepted the new feature, and the recoding of the necessary systems began.

Since our code was relatively easily adapted to the change, it took about 4 hours to modify the existing code and test it to approve that the game now has incorporated the changed feature.  If your software person/team is inexperienced, or the code you've inherited is "bad", even a simple change like this could take days to implement.  You may scoff at this idea, but I will reiterate my earlier warning, even the smallest things can take a dreadful amount of time to incorporate.  Even something as so much as changing the color of something can take a very long time - it all depends on how the software was designed, their existing features, and how well things were programmed, and of course there could be other unforeseen technical problems further complicating the desired changes.

During our testing and development, we also found it necessary to upgrade our core code reuse library to incorporate more graphics utility functions because of the demands on this product.  This took a couple extra hours to research, code, and test.  The tradeoff is such that now projects in the future can reuse this code, saving the time and headache later of having to redevelop it again.

While programming a game, or really any software, the programmer should always be aware of what they are making could be generalized in to useful and reusable modules for other projects.  There is, again, a tradeoff to "just make this feature" and "generalize" it for generic use.  It usually is quicker just making the solution once while specifically tailoring it for the one active project, but if another project needs that functionality, it takes more time later to surgically remove that code from the project and alter it later for the newer product.  The experience of the programmer here will help them dictate when and what they should generalize.

A specific example of this - one of our products that hasn't been released yet uses a feature to flash the screen red when the player takes damage.  During the development of the new product, it was mentioned "hey, it would be nice to have a visual indicator for when the player takes damage".  It was quite apparent that the code from the older, unreleased project should be recycled in to this new project.  Of course, this functionality wasn't generalized in to a code library; however, the existing feature was found to rely on almost no external variables in the older product, and the code was easily extracted from the 3 different functions that it was hooked in to.  There were a couple of dangling variables that was required for the code to work as well, so there was some time needed to track those down and copy those over as well.  These variables had to do with the time involved with "how long to flash the screen" as well as "how much red is flashed at a given time".

If the older code was sloppy, or had I not been intimately familiar with the code, a job like this - tracking down code/features to extract - can take a while.  This is something that shouldn't be taken lightly when planning how long a product will take to develop.  Code reuse is good and saves time, but if you have to attack another product with a scalpel to find all the code to reuse, it can be a nightmare in itself.

Ok, so, we had a requirements creep with the flashing feature.  It took about 30 minutes to track down our existing code to make this happen and we integrated it in to the new product -- in theory.  Remember, we need to test the new code to make sure it wasn't rejected by the new product!  Sure enough, we attempted to test it; and nothing happened when it was suppose to.

A quick "oh duh" moment later, and we realized we forgot to call our new flashing code when the condition warranted it.  We integrated the code, but forgot to actually use it.

We decided to call the new flash code from inside the method where players take damage and decided to test it again.  Huzzah, it worked!  Not only did it work, but it worked as expected!

Long entry, but take away from this that new things, small things, and even big things can, and will, come up during coding and testing.  Some of these things fall in to the "need to have" category and can add substantial time involved in to the development of your product.

Next time we'll get in to the software design aspect of the product, I hope!



Sunday, February 19, 2012

Design to Product on Android - Delays (10 / 17)

During our software design and programming of the app, various delays have already been cropping up.  Specifically with the business side of the house.  We've been meeting with people and potential contractors for other projects we're working on.  While ultimately this is a good thing, it does take a toll on the direct development of the project.

Truth be told, these were fairly predictable delays and were taken in to account during earlier phases of planning.

In other good news, we acquired a music track that will be placed in one of our products.  In addition, we have been created more artwork and content for this new product.

Er, instead of going in to software design next, we'll be talking more about a prevalent issue with software development - the requirements creep.  A dreaded topic in all software shops and definitely something of prominence in the games industry.

Wednesday, February 15, 2012

Design to Product on Android - OMG Code, well almost! (9 / 17)

Ok, finally, we're talking about the core of app development, the coding!

First, I must emphasize that it is probably in your best interest to consider using an app library, or writing your own.  This will substantially cut down on the time needed to make a game (or probably any app for that matter).  Of course the trade off is learning the external library, figuring out its limitations, and making new products with it, which translates to more initial time involvement, but could pay out in the end.

As for us, we developed a small game library that has some very basic code all wrapped up in to a tiny, neat package.  It mostly allows us to mangle with time functions, "button" code, random numbers, and some other graphical utility functions (like getting the current display orientation, the density of the screen, the screen dimensions, etc).

If you make your own library, like we did, I highly recommend putting any and all code that you think is generic enough that *all* projects of yours in the future could want.

If you didn't already know, you will have to have some way of writing code.  We recommend using Eclipse with the Android SDK, it's free, works, and packs various useful conveniences while developing.  You will also need someone versed in Java and able to use the Android SDK.

If your person doing the development is new to Android, Java, or both, we highly recommend making some test projects first, before attempting to make your dream game/app.

It is our intention for this to not be a tutorial on how to make an app in detail, but rather talk about designs and coding specifics instead, more or less from a management perspective/process.

Ok, so once we have our IDE all set up, we can look over our game design and start plotting how we want to design the software itself.

Different software process methodologies deviate greatly in this area, our studio essentially identifies major topics/nouns used in the design of the product and USUALLY makes an assumption that those will be Java classes.  I mentioned *usually* because this isn't always the case and we also do not use any automated tools or UML or anything goofy like that.

Instead, we look at the major concepts of the design and turn those in to classes first.  Specifically, we know that we will need a PlayingField where by all "game playing" will take place.  That becomes a class (and a very useful one at that).

Because of how Android works, we must have an Activity class.  From there, we also must have our own SurfaceView class (we implement a GameView class that inherits from SurfaceView), and a class which encapsulates the main processing of the game.  We make a GameThread class that inherits from Thread so that all our game processing can take place on its own.

So, without really getting in to picking apart our design, we know we have the following classes already:

GameActivity
GameView
GameThread
PlayingField

While we pick apart our design and start coding, the blog will be inactive for the next couple of days.