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.
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.
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.
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.
Not too much to say here other than this is our version of the SurfaceView class used by Android.
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.
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.
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".
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.