The flying monkey! This character will act like the insect from Mario Bros. that hops from place to place. I'm halfway happy with how the sprites turned out, but probably will make some changes to it tomorrow. For example, the flying monkey seems a bit too static because his legs and arms are completely stiff.
The big change over the last two days have been the new high-scores! For local high scores, I use a simple SQLite database (which is super easy to do in Android). For online high scores, I use MySQL and a little hash function to make sure only the game client can send scores. Scores are seperated by 'local,' '24h,' and 'global.'
That's all. Was a more relaxed weekend, but will get back to a rigorous schedule tomorrow!
I'm incredibly embarrassed by this. Early on, I made the really lazy, stupid decision to make it so enemies wouldn't collide. Of course, I had my reasons-- originally the game was going to include mobs of zombies (200+ on the screen at a time) and with my silly brute force physics engine, that would scale terribly. However, with an arcade style game, the maximum number of enemies will probably be under a dozen.
But really, it was just laziness. Anyway, I decided it just wouldn't fly. Enemies changing directions when running into each other is absolutely vital to this game style. Before, different types of enemies never affected each other. The variety added by having two different types of enemies on the screen was the sum of its parts. However, if the enemies can interact with each other, then the variety is multiplied-- because each enemies unique differences then effect each other. The strategies the player has to use to defeat each enemy must be altered to deal with the circumstances.
For example, without the ability for enemies to collide with each other, if I hit a werewolf (or crab from Mario Bros), I can simply wait at the other side of the level (because the world loops) for the werewolf to come around. However, given enemy-enemy physics, if that werewolf runs into something else, it will turn around and I will miss it. Before, I only needed a single strategy to defeat the werewolf. Now, I need more.
Ghosts. Ghosts are classic. I based mine off of the Super Mario Bros ghosts. Originally, I tried making them boids, but ghosts aren't boids. Ghosts are soulless individuals who never use teamwork. So, no matter how fun boids are, I had to scrap it. I'm thinking of maybe making a skeleton fish enemy so that it can be a boid (and swim around in little schools of fish). I think that's about all there is to say about that.
Faster yeti code (now it draws ice in strips instead of in blocks)
The mystical Yeti. Definitely my favorite enemy so far. The Yeti can raise his arms to the sky and magically turn the ground into ice! He's a vague copy of Freezie. This was a slightly interesting challenge because to turn the ground to ice, somehow the ground object has to be updated and be able to have normal parts and icey parts at the same time. I think the fact that this was an easy challenge is a testament that our code system isn't *completely* terrible :)
Because I didn't have the "uses-sdk" and "supports-screens" tags in my AndroidManifest.xml, the screen wasn't scaling correctly-- meaning opengl was drawing to a surface half the size of my phone's actual screen and then scaling it afterwards. With this fixed, the game now correctly renders to the entire screen... which caused a 10 frames per second performance hit. The game was now running at 35 frames per second.
So, instead of making my bear run around and attack the player, I frantically optimized.
Get rid of getters and setters. Changing entity.getX() to entity.x improved performance by a solid 5 fps.
Use local variables whenever possible especially in "for (... i < array.size() ...)".
Hidden, annoying optimizations:
Apparently, the game was making a single Integer object every time a sound was played. That single object caused garbage collection every 30 seconds, making the game stutter.
(Intentionally) rendering to a smaller resolution, then scaling up the result. This led to unreasonably *huge* gains. I'm surprised I haven't seen this in other games as the jump in performance is enormous.
with 75% resolution (~55 fps)
full resolution (~35 fps)
Allow the user to disable parallax layers (-5fps)
Don't load new textures, change texture crop, etc if you're still working with the same texture. This is obvious, but saves a lot of time, especially when rendering bumped platforms (because those are a series of the same sprite, over and over)
Working with re-sizing the resolution manually forced me to actually fix how the game renders on different sized screens. I haven't tested it on a tablet, but I'm fairly certain it now renders sanely on all devices, and that regardless of DPI, the game should appear to be similarly scaled.
Added more gfx options.
Screen resolution scaling.
Fixed looping world bugs.
Lots of optimization/testing.
Here are those sprites! I've worked on a ghost, a bear and a yeti.
Preventing camping is one of the biggest concerns when making any kind of action game. For gameplay to be interesting, it must be varied. Nothing kills variation like this:
Most of the changes I've made in the last couple days directly counter camping.
First, the world now loops on itself. This is the most significant change in the game from the last few weeks-- and it surprises me how long it took me to realize this change was needed. With a world that loops over itself, there is no need for walls. Without walls, there is no 'safe' ground. Before, you could put your back to a wall and only deal with zombies that came from the other side. Without walls, the level is 'open'-- an enemy can get you no matter where you are.
Second, enemies that have been knocked down will immediately get up if you hit the ground beneath them again. This change simply forces the player to attack from different (if only slightly different) locations. If the player continues to attack one spot, he will lose the enemies he's already knocked down.
Third, the addition of the werewolf (this is actually an old change). The first time you attack a werewolf, it doesn't get knocked down-- it gets faster, forcing the player to chase after it or anticipate it's movement. It is impossible to kill a werewolf by staying in one spot.
Fourth, the addition of the creepy twins. The creepy twins are two girls that mirror each other's movements. When one turns around, the other turns too. When one is knocked down, the other is knocked down too. However, if one is killed, it doesn't die permanently unless you also kill the other. This, like the werewolf, forces the player to significantly move after knocking down the enemy.