It’s been a while since I’ve written here, but there hasn’t been much to say on the OA front. I’ve been working on a bit of client work, but also did some work on porting the Empire Casino suite from iOS to Android. Having been written in cocos2d-x, the engine makes it fairly easy, but there were a couple of iOS-only things I had to change to be cross-platform, and I ran into a few pitfalls that I’d like to mention here. As of this writing, cocos2d-x 3.0 is still in beta, so we’re using 2.2.2.
- To reiterate a little from a couple of posts ago, don’t use spaces in filenames. “make” doesn’t like them. Also, Android and Java are more strict about package naming than iOS, so the package name had to change on one of the projects.
- The Android toolchain doesn’t like incrementing enums. (And I’d prefer not to turn off warnings) To get around this you can do something like:
for (eMonth month = eMonth_March; month < eMonth_June; month = (eMonth)((int)month+1))
- By default, Android compiles chars as unsigned. To change this, add -fsigned-char to APP_CPPFLAGS in Application.mk. This wasn’t causing a problem for us to my knowledge, but I want to keep things as standard across platforms as possible.
- There’s a bug in cocos2d-x 2.2 Android’s Cocos2dxRenderer.cpp regarding starting an app when the screen is off. It shouldn’t affect many users, but it can be annoying for development. Just add
to the top of Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeOnPause.
- Remember you can
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
to ignore iOS specific code on Android. (Other platform defines: ANDROID, BLACKBERRY, WIN32, WINRT, WP8, MAC, LINUX, MARMALADE, NACL, EMSCRIPTEN, TIZEN)
- This one was a bizarre one, which I lost quite a bit of time figuring out. I kept getting the message “Failed to run aidl. Check workspace log for detail.” when building, after I added In-App Billing. (The workspace log just gave details about where in the code it crashed) Webpages about the issue that I could find gave vague “restart Eclipse” or “delete your project and recreate it” solutions. I finally narrowed it down to the seemingly unrelated fact that I had a <classpathentry> in .classpath that pointed to a directory that didn’t exist. (added when I erroneously followed an old tutorial)
- The In-App Billing flow seems to be a separate Activity, and when returning to the cocos2dx activity, text can appear as black boxes depending on when it’s rendered. Update your value/messagebox CCLabelTTFs using runAction(…callfunc…) as suggested in the link.
- Except for Subscriptions, all IAPs in Android IABv3 are “Managed”, and consumption is determined by code. To “undo” a nonconsumable purchase (ie: I bought an item, and now want to test not owning it again), I just changed the consumption code to operate on nonconsumables instead of consumables. I then exported to a separate (well-labeled) APK, and just run it to consume my purchase.
Finally, an APK is actually a zip file. You can unzip it to see exactly what’s included with the binary, and the file structure.
Link of the week: Jazzpunk – Being a fan of sci-fi (and absurdist humour), I enjoyed the trailer, which is rife with references to Johnny Mnemonic. Check out Giant Bomb’s Quick Look to get an idea of if you’d be interested in playing.
Git commit message of the week: “Updated all them there submodules y’all.”
Chat message of the week: “new tutorial: ‘f*** it. you’re on your own.’”
Glitch of the week: The buttons are positioned properly (although the background image is scaled too small) since they’re positioned as a percentage of the screen size, but the elements of the wheel were also being translated by percentages of the screen size. I changed them to percentages of the wheel background (circle image) size, and it looked better.
Note: Showdown went live today, as well as the Office Attacks update!
As the year comes to a close, the Empire will be shut down most of next week for Christmas, so there will be no blog post. I just wanted to do a quick rundown of what I did in 2013…
- Did a bunch of QA work on various apps
- Started this blog
- Made a 30-inch real-life tower from Office Attacks
- Made an Online Workshop Demo for Office Attacks
- Helped file a SRED claim for Office Attacks
- Went to the Calypso water park
- Got Showdown approved by Apple after several networking problems
- Released Office Attacks after redoing the tutorial a million times
- Went to a launch party for Office Attacks and edited a trailer video
- Helped my co-workers release a bunch of apps (testing, advice, etc)
- Started porting the Empire Casino suite to Android
Here are the apps we released this year, starting with Empire Casino:
- 3 Card Poker (iOS)
- Blackjack (iOS)
- Baccarat (iOS)
- Pai Gow Poker (iOS)
- Slots (iOS)
- Angry Janitors (iOS/Android) (Client work for ISSA)
- Showdown (iOS) (More client work)
- Critter Craze (iOS/Android)
- Office Attacks (iOS) (Canada-only at the moment)
So 2013 was a busy year, and 2014 will probably be busier. For now, though, I hope you all have a Merry Christmas and a Happy (and safe) New Year.Link of the week: Dungelot – I found this game in Mike Rose’s Best of 2013 article. It’s sort of a cross between Rogue and Minesweeper. An amusing time-waster. If you want something a little more involved, check out The Depths (Android) by a friend of mine.
Chat message of the week: “I’ll come in and bang some rocks together. ” (power was out at the office for part of the week)
Glitch of the week: When trying to get Office Attacks working on iPhone, we had an office that was zoomed out too far at one point.
Since the Office Attacks update was submitted to Apple this week (along with our new Empire Casino Slots), there’s not as much OA stuff to talk about, so I thought I’d share some random suggestions from my last year of work.
Learn keyboard shortcuts – Since programming involves a lot of typing, I try to avoid using the mouse whenever possible. So if I need to do any file operations, I’ll generally do them at a command line with cd, pushd & popd, mv, cp, rm, open, etc instead of mousing around. When I started using OSX, I thought it was cool that you could do Command-tab to switch windows like Alt-tab in Windows, but found it odd that windows of the same type were “grouped together”. I soon found that Command-` (backtick) could switch between windows of the same application. Command-shift-3 for taking a picture of the screen was weird, compared to “printscreen”, but oh well. (OSX keyboard shortcuts) Sometimes you can even create your own shortcuts. My old netbook doesn’t have PageUp/PageDown keys, so I used AutoHotkey to map them to Ctrl-Up and Ctrl-Down.
Don’t put spaces in filenames – This is arguably a matter of opinion (they really irritate me), but depending on your workflow they can be a major hindrance. At the command line, you have to either put the filename in quotes, or put a backslash before each space. (to distinguish a space in a filename from a space that separates arguments) Forbidding spaces can also save you headaches if you have to use certain tools like “make”. I’ve been given a cocos2d-x project that built fine for iOS, but the Android toolchain isn’t happy about the filename spaces. Similarly, be careful about naming. Project names like “example-project” and “com.company.2examples” were fine when compiling a cocos2d-x project on iOS, but not on Android.
Watch your data formats – You can end up with a lot of wasted space if you’re not careful. Going from >250MB to 10MB in animation data in the previous entry was an extreme example requiring a lot of work, but figure out what formats your platform supports and see how much you can compress your assets before they look or sound bad. Some things to look at include the following:
Graphics: Codec and settings, resolution, colourspace (e.g. RGBA8888 vs RGBA4444), frame rate
Audio: Codec and settings, KHz, number of channels (stereo vs mono)
Before I started on Office Attacks, the sound was being stored in DVD quality, or 48KHz stereo, since those were the default settings used in a sound tool. Sound effects really don’t need that high fidelity, so I converted them to 22KHz mono for large space savings. And although PNG is lossless compression, there are settings that affect the amount of compression, and it depends on the contents of the image, so no single one is “best”. There are tools like OptiPNG and pngcrush to help you. (PNG may not be appropriate for your project, but it’s just an example) To see what’s taking up space, I cd to the .app directory in the simulator folder and do “du -k | sort -n”.
When I needed to free up space on my iPad I found that a sudoku app was using 100MB. A hundred megabytes. I don’t know what caused it to take up that much space but now it’s been BALEETED. The bigger your app, the more likely it is to be on the chopping block when the user needs to delete something. (In comparison, Sudoku 7 by another local company uses <10MB) Also, try to remember to delete old or placeholder assets that are no longer used.
Keep notes – Although there are email histories and chat logs to remember things for us, I also have a text file to save random snippets that might help me later. Error messages, test results, helpful commands or settings I haven’t memorized, you name it. At my previous job we had an internal wiki, so I asked Steve to install Confluence, since we’re already running Jira for bug tracking.
Anyway, those are the tips that came to mind for now. Got any more?
Links of the week: GOG.com is offering Fallout 1/2/Tactics for free for a couple of days. Also, Ludum Dare is this weekend! Instead of playing games, make one! (where have I heard that before?) Admittedly, I’ve only made one Ludum Dare game… boing SMASH.
Git commit message of the week: “Doh. forgot to #build”
Chat message of the week: “heheh puddles are dead snowmen”
(We have a puddle graphic in the original Office Attacks release, and the Christmas update has a snow-nerd with a cardboard sword that was placed next to a couple of them)
Glitch of the week: Here’s a small issue where a particle system wasn’t being properly removed on the Critter Craze pause menu. Not overly notable… except my wife said it looked like blood.
Note: Yet another app! Our Critter Craze game is now on Google Play and is in the Apple submission queue!
No post last week, in part because it was American Thanksgiving, and I figured I didn’t want to disturb all of your food comas. I listened to the MST3K Turkey Day marathon in the background while working.
This week I thought I’d list some of the things that are going into the next update of Office Attacks!
- Auto-pick towers/powers when you have fewer items than slots
- Changed End Level screens to better match UI of other screens
- Added Christmas/Hanukkah decorations (icon sneak preview at right)
- Review stats during Supercharge
- Double-tap tower placement
- Double-tap tower selling (no more big dialog box over gameplay)
- Added sales, as mentioned in the previous entry
- Audio tweaks
- Added buying full towers
- Fixed piece of the day, added tower of the day
- Fixed graphics on older devices
- Fixed powers on iPhone (d’oh!)
- Fixed close upgrade dialog bug (sorry!)
And more! A big one is that for new players, we revamped the tutorial. (again) In our playtests, we found that people were having a lot of fun in the Workshop, so we put its tutorial first. We later realized that when people download the game, however, they’re expecting tower defence, so now we start the player in levels and introduce the Workshop later on. This update will be submitted to Apple soon.
This week, we presented a small postmortem of Office Attacks! at the local IGDA chapter. I went through our archives and calculated the space savings made via the SWF rendering system talked about in early entries.
- Old Steve spritesheets: 24MB
- Old Enemy spritesheets: 70MB
- Old Tower spritesheets: 150MB
The last value is actually a low estimate. Retina spritesheets were never generated for the towers, so I just multiplied the non-retina 75MB by two.
New “shapesheet” system:
- Steve data: 0.5MB
- Enemy data: 3.2MB
- Tower data: 6.2MB
So from over 250MB to 10MB. Not bad. But what causes the app to be around 100MB? Everything else. Code, sound, and stationary images for multiple chapters, UI, etc.
PS: I didn’t include an enemy scheduled for an update in the figures above. She has more animations, so the spritesheets for her alone were 30MB.
Link of the week: Starwhal – (online demo on their site) This is a fun, quirky, locally-made multiplayer game that’s been making the rounds in the indie scene. Their Kickstarter launched just over a week ago and is already over 40% funded! Check it out!
Also Windforge! I mentioned them here before but this is the last day of their Kickstarter! Go fund the fun!
Git commit message of the week: Nothing overly amusing in our repo lately, but a recent xkcd comic was rather relevant.
Glitch of the week: With an incorrect anchor point and/or position, it looks like Santa is sitting in Steve’s lap! “And I’d like a ‘Mr. Chills’ water cooler for Christmas! Ho ho ho!”
Note: Pictures from our launch party last weekend are now online.
Also, our Pai Gow Poker is now in the App Store!
Unfortunately, some bugs were introduced in the iPhone version update of Office Attacks (C’est la vie), but we’re working on them, and adding some holiday cheer to the game. A few new features will also make it in, but I wanted to talk about some design decisions first.Like many other tower defence games, we wanted to show the current health of the enemies. A standard “health bar” seemed very cliche, so I tried to think of something that wouldn’t be as obtrusive. After doing some research (read: Google image search) into health bars, I found an awesome concept by Adam Vian that you can see to the right. It looks cool, but isn’t appropriate for our game.
I stared at the enemies and thought about where we could display this information. After noticing that they all have a semitransparent oval shadow, I thought maybe we could display it there. So I made a green oval the same size as the shadow and placed it underneath, since it also had to go below the feet and legs. Then as the enemies take damage, the oval shrinks and changes colour in the standard green-yellow-red fashion. Some might find it a bit subtle, but I think it’s neat.
At first we had an “upgrade badge”, which can still be seen in the tower upgrade screen. We placed it to the upper left of the tower, so as not to obscure it, but it was difficult to see which badge went with which tower. When Steve originally created our OATowerViews, he placed a semitransparent square below the tower. I wasn’t sure what this was for, but it turned out to be useful, since I started changing its colour to show the tower’s upgrade level.
I was reading an article called Mastering Free2Play: The Titanic Effect by Ramin Shokrizade recently. Since technology now allows for payment in the middle of an experience, such as via in-app purchases, he proposes the scenario of asking the audience for money during the emotional moments near the end of Titanic. He talks about Distressed Monetization, where games put the player into distress, then offer to sell relief. Admittedly we have something like this, with the pay-to-skip tower building time, but I wanted to add something along the lines of his next point.
He also talked about Elated Monetization, where you basically make the player happy, then “pass the hat”. In the case of a movie, the viewer is happy at the end, but since it’s over, some may feel no incentive to pay. Given our design, however, we could put it in between levels, but which levels? After thinking about it, I decided to do it after the first time the player beats a level with a new enemy. (interns not included) In that case, the player’s happy about beating the level, but also about seeing something new. Also, rather than only driving people to the store, I made it so that an hour-long sale begins, for added incentive.
Another minor change I made this week was to the character bios screen. I figured that since I already have a shader that turns every pixel black, I could show silhouettes for characters you haven’t encountered instead of a question mark.
Finally, I’d like to give a shout out to the board game Castle Panic. The “Drive Him Back!” card is what inspired the “Paper Portal” power in Office Attacks. You can see Wil Wheaton and friends play Castle Panic in TableTop. (DHB card is at around 14:30)
Link of the week: The Trenches – This webcomic about game testers has been running for a couple of years now, but I think I prefer the “Tales From the Trenches” — reader-submitted stories about QA departments. (scroll down)
Git commit message of the week: “Fixed number of starting workshop slots. http://www.youtube.com/watch?v=8DdeLUA0Fms“
Chat message of the week: “An Office Attacks purchase has just gone through!” (Steve made it so this notification is posted to our chat. It’s neat)
Glitch of the week: Wow. After selling a tower, you could click on the empty space, then sell it again. D’oh!
Note: If you’re local to Ottawa, Canada, we’re having a Launch Party for Office Attacks tomorrow! Tickets still available! Meet Steve! He’s visiting Canada!
Edit: Office Attacks iPhone is now live! (in Canada)
We’re putting a few finishing touches on the iPhone version of Office Attacks, but I’m also helping out on a couple of other projects. I just wanted to do a small post on an issue that came up a while ago in OA concerning text quality.
For a while, text looked like this in the game. You can see dark “halos” around the letters, but the texture for the bitmap font looked fine. Note that we have a few general empty button graphics, and draw text on top of them. This is good if you change your mind about wording, or want to localize.
I’m sure most of you know about alpha, or the amount of transparency of a pixel. When using OpenGL, though, there’s another factor that comes into play when using alpha — the blend mode. They’re a bit like the blend modes for layers in Photoshop and GIMP, though those can be more complex.
After doing some tests, I found that even though we were using the default (“Normal”) setting for text in CocosBuilder (which we used for laying out our UIs), it was coming out with a different setting.
Then after some Googling, I found that there was a bug in CocosBuilder where the blend mode wasn’t being saved properly. We wanted the first mode below, but it was coming out as the second.
- glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
After updating CocosBuilder, the blend modes being saved were the right ones and it looked better. So all good, right? Wrong.
Although we don’t do much text fading in the game, we fade in and out the achievement dialog, and fade out the standard dialog. The standard dialog doesn’t fade in since it comes up more frequently than the achievements, but it fades out quickly to help distinguish one from another if another comes up.
At some point after fixing the text, I noticed the fade was looking odd. Since it’s a very quick fadeout and there were other issues to look at, I didn’t really get a chance to figure out what was happening until I had some time to slow down the fade and look at the issue. As you can see, after the dialog faded out, but just before it was removed, the text could still be seen.
It was a little bit of messing around, but the fix was to use the GL_SRC_ALPHA blend mode while fading, and the GL_ONE blend mode when displaying. So the text changes appearance a little, but a halo during the fade is better than not fading at all. To help illustrate the issue, below is a picture taken in the middle of the fade. The text on the left is using GL_SRC_ALPHA, while the text on the right is using GL_ONE.
Another issue at play here is premultiplied alpha. Premultiplied alpha seems to be standard when using PNGs in cocos2d to mimic the behaviour of UIImage, but is an option when using PVRs. For a font, though, we should be using a PNG (lossless) instead of a PVR. (lossy)
There are a lot of funky blend modes in OpenGL. Until next time, here are a couple of resources:
- Anders Riggelsen’s glBlendFunc Tool – An interactive testbed for blend functions.
- GL Blend Modes cheatsheet – This image is so old (from the days of Quake?), I’m not sure who made it, but it’s a handy guide.
Git commit message of the week: “Now this is a story all about how my screen got flipped turned upside down, and I’d like to take a minute just sit right there, I’ll tell you how I removed a function called preferredInterfaceOrientationForPresentation // be aware!”Chat message of the week: “Sounds like a new [Monday Morning Meeting] policy: ["Scotch makes meetings way better." -- tweet from Jenn during MIGS]“”
Glitch of the week: In the process of making Office Attacks work on iPhone, we ran into this problem on the iPhone 4. Unlike later devices, the maximum texture size on iPhone 4 is 2048×2048, not 4096×4096. Some changes were made to the max texture size sent to TexturePacker, and it was all fixed.
Note: Although Office Attacks! is out now on the Canadian App Store for iPad, an iPhone/iPod Touch version is coming soon!
As I promised last time, this week I’m going to talk about the special effect for the nerd… the lightning bolt! Who needs Thor to make lightning when you have code?
This effect is one of those things that didn’t make it in for the first release, but was something I wanted to work on. What happens is that when the nerd gets enough energy, he uses it to disable the player’s most expensive tower within range. Although he has a neat animation for the event, in the first release the tower simply turned semitransparent.
We needed something better. First I thought about creating an “X” out of lightning, which I would make with midpoint displacement. You basically keep subdividing a line, and displace the midpoint in the Y (in my case) axis by a random amount, reducing the random range each time. The first attempt is the first picture to the left, which didn’t look very good. I used a CCDrawNode like the tutorial circle. I wanted transparency, but it appears that you can’t change the alpha of a CCDrawNode, and if you draw multiple semitransparent line segments, you get ugly darker dots where the lines overlap.
While searching for how other people did lightning for inspiration, I came across a mention of CCMotionStreak, which I started looking into. CCMotionStreak is meant for the type of effect where you have something like a spaceship or a rocket, and you want a line tracing behind it as it moves. CCMS has code to handle the line fading out over time. Another nice thing about it is that you can specify a texture for the line, so you can easily have one with nice faded edges.
Although the cocos2d documentation is usually good enough to figure out what I want to do, I wasn’t sure how to use CCMS. After looking at some examples, and the code for CCMS itself (yay open source!), I found that the initial setPosition call places the CCMS, but then points are added with future setPosition calls. A little odd, but okay.
So I did this, and got… nothing. I took out my clear call, and got the straight line in the second image. After thinking about it and looking at the CCMS code some more, I realized I was trying to use CCMS in a way it wasn’t intended. To get a streak trailing a spaceship, you simply do setPosition, as I mentioned, but then the code is expecting update to be called, since you generally only want to add one streak segment per tick. I wanted to create the whole line every tick.
So I added an update call after each setPosition call, and got the third image. (I removed the clear call, remember?) I added back the clear to get the fourth image. For the fifth image, I changed the line texture, and put CCMS and CCDrawNode side by side to compare. In the fifth image you can also see a couple of sparks, which is basically a stripped down version of the welding effect.
At some point along the way, I decided that instead of having a “lightning X” on the tower, the lightning should shoot from the nerd to the tower, and the tower should start smoking and sparking. So I made a smoke particle system, and you can see it with the final lightning effect to the right. The lightning ended up being three copies of the same bolt, each one with points displaced slightly randomly from the others.
For the smoke, I originally made a particle effect with the simple circle graphic from the welding sparks. I soon remembered that we actually have a smoke effect in the game – the death animation for the crybaby and the interns – so I took the graphic from those animations and used it instead. Since it’s a larger image, it gave me more coverage and I could go from 200 particles to 50. I could also use the rotation parameters available in CCParticleSystemQuad – they’re usually useless with particle images that are symmetrical.
Links of the week: Kickstarter, Kickstarter, Kickstarter! A bunch of local indies have started Kickstarters recently, so I thought I’d list a few and see if any tickle your fancy.
- Windforge – “CONTRA meets MINECRAFT in a building-block RPG! Explore an ever-changing steampunk world featuring Airships & Sky Whales!”
- King Voxel – “King Voxel captures the magic of games like “The Legend of Zelda”, but adds a world generator and voxels!”
- RimWorld – “A sci-fi colony sim driven by an intelligent AI storyteller.” This one actually ended a week ago, and met its goal (and then some!), but you can still take a look.
Git commit message of the week:
“Strangest request ever – added analytics to animated rubble.”
(After having a small “emoticon war” on Hipchat. Hipchat has a lot of emoticons.)
Glitch of the week: It’s always the simple things that get you… When displacing midpoints I wanted a random range from, say, -10 to +10. So I did something like (arc4random()%21)-10, forgetting that arc4random() returns an unsigned int. (unsigned)0 – 10 = four billion and something = messed-up lightning.
Last week Steve wrote a great Office Attacks post-mortem, and at that time, the game was in the review queue at Apple. Well, last weekend it was approved and it’s now on the App Store! For now, though, it’s only available in Canada while we test the waters and see how people respond to it. Our analytics will tell us things like if a level is too hard, and we can do some tweaks before the worldwide release.
After submission, work still continues. We’ve had a teaser trailer of the comic up for several months now. Work on a gameplay trailer was waiting until some of the in-game level design was finalized. Now that it’s been submitted, I’ve had time to work on a gameplay trailer, and here it is! I used to do video editing as a hobby for years, so that’s why it fell to me to work on a trailer. It took a little bit of time to get back up to speed, but I’m fairly happy with the result. Since I’ve only done video editing on PCs (AviSynth is awesome!) and we only have Macs at the office, I worked from home for a few days. While I was gone, my co-workers made a replacement. I think he commits twice as much code as I do.
So the week before this one, I worked on a special effect for the nerd, which I think I’ll leave until next time. I wanted to spend a little time talking about the few days leading up to submission to Apple.
In the week before submission, a lot of decorations were being added to levels. Unfortunately when some objects were flipped, they were appearing differently in-game than the level builder, as you can see above. The fix for that was a small equation change, but the anchor points also needed help. In the case of the decorations, the anchor point allows the decoration image to be properly aligned with the squares below it. A relatively new addition, however, was subobjects. We used to have decorations like “table” and “tableWithVase” and “tableWithLamp”, but Steve made it so objects, like tables and desks, could accept subobjects. This, of course required more coordinate definitions, and so I had to adjust the subobject locations and anchor points of the subobjects. To the right you can see a test of putting one particular subobject on most of our tables and desks. Mixing and matching tables/desks and the objects on them allows us some more variety in the look of our levels.
We also had it so that we played a character’s sound for their attack, special, or death at the beginning of their animation. I changed it so that you can specify which frame of the animation the sound should play on. Previously, the musician would trigger a guitar twang while he pulled out his guitar. Now it happens while he strums the guitar.
Finally, I added some simple debugging code that I should have added long ago. Due in part to incorrect anchor points and equation problems mentioned above that caused things to look differently in the level builder and game, people were placing objects in squares occupied by other objects (screwing up the z-ordering code), or placed them so that they went out of bounds, overlapping a wall a little. An array and a few loops later, and the game now tells me where problems are in levels, instead of me staring at them looking for issues.
Link of the week: What’s the hardest bug you’ve debugged? – A very interesting story about looking for a bug in Crash Bandicoot for PS1.
Git commit message of the week:
“Dungeon front wall doors were swapped.” (d’oh!)
Chat message of the week:
Steve: I just RTed the OA tweet – do I get a promo code?
Jenn: hahaha sure – PROMO CODE: HAVENTYOUPLAYEDTHISENOUGH
For now, I leave you with the following:
The same way graduating from high school or college is called “commencement”, which can be defined as “a beginning or start”, I don’t see this as the end of a journey. I simply see it as the beginning to the world playing this fantastic game we’ve all spent so long on.
Office Attacks began over 2 years ago. I’ve spent the vast majority of my professional career here at Arctic Empire working on Office Attacks. In fact Friday marks my 3 year anniversary of my first contract here.
Office Attacks began as an idea a long time ago. While we’ve just submitted v1 due for soft launch in Canada mid-November, this is truly only the beginning. We have insane amounts of new features and improvements waiting in the queue. But this is a post-mortem, so I’m sure you’re looking for some juicy details on the development, as well as before and afters.
As you can see, we had very humble beginnings. That screenshot was simply showing off this level which was built using our way-old borrowed from Galaxy Express level builder. Nothing fancy, but a good start. By the way, that screenshot was taken on May 18th, 2011.
If we skip ahead a few weeks, we now have towers and enemies on stage. Aren’t they pretty?!
Would you believe that the entire time we were using this 2D view of Office Attacks we had that stupid placeholder “Steve”? In fact, our current protagonist Steve didn’t even exist back then; I know, right?! For those who may still be interested, here are a few more images of Office Attacks at this stage.
Now let’s skip ahead a few months.
As you can see, the game is progressing quite nicely – though it’s still quite far from what we have now. What’s that you say – does the aspect ratio appear a bit different than what you’re used to? In fact, Office Attacks started out as an iPhone game! But it became so big and beautiful, we realized it could only realistically be an iPad game – at least at that time. Who knows what the future holds!
Isometric! This change was decided upon sometime in October of 2011 – almost exactly 2 years ago. We realized that Office Attacks had huge potential, but our current downfall was the graphical quality of the game. So that’s when we really kicked it up a notch and started playing around with isometric.
Yeah, so that didn’t work. Back to the drawing board!
Whoa, that’s much better. Already seeing better stuff. Though, why is Kiki behind Steve’s desk? I’m fairly certain at this point Steve STILL has yet to exist. Seriously – looking back, I don’t know why we didn’t see this gaping hole in our story. Still, I digress.
Now that we’ve moved to being isometric, things start to take off. We have a level builder entering the picture, as well as the beginnings to a complete rewrite! That’s right – you saw the old non-isometric version above, but quite frankly, a rewrite was absolutely in order. So we started fresh – we designed our system robustly to handle development and got to it.
Ah, Steve has now entered the picture. We still have some tiny enemies, but we’re getting there! Obviously we’re still a fair ways off from where we are now, but the game is really starting to show its true colors.
It’s worth taking a quick break from screenshots to discuss what is going on at this point in development: we quickly realized that by bringing on these high quality fully animated enemies and towers, we were going to have memory/performance issues with using spritesheets. Displayed in this graphic you can see the level 5 water cooler’s body in its old spritesheet format – that’s just one tower piece – each tower can have up to 5 different pieces, and you can bring multiple different towers in. Yeah – problems indeed. Tim started work on a vector drawing system – taking our original art from their swfs and drawing that content in game. Not a full flash runtime, but just enough to take the graphical data out of the swf and draw it. In his previous posts he has talked about it a bunch, so you can read it there.
Once his work began, we quickly had Tyler jump on board and help move some of it over to OpenGL, so we could integrate it into the game. They worked on this system full-time for a few months. We’ve jumped back on the system a lot between then and now, finally coming to our final system – using shapesheets! At this point, the *entire* level 5 water cooler [all of its pieces] fit in this shapesheet - we use some crazy magic to turn those “sprites” into full pieces at runtime. Seriously, it’s magic – Tim did an amazing job with the vector system, and with the assistance of Tyler and Clement, full credit goes to him.
So now that those guys are working in parallel with our spritesheet system, I’m busy working on other features. I could literally go on for another 1,000 words about the game and our progress, but I think I’ll summarize the rest of our development with some before and afters.
Now the part we’ve all been waiting for – stats!
Office Attacks has actually moved its contents into 3 different repositories over its lifetime. The first repository called “Office Defense” was created on March 25, 2011 at 3:17 PM. Funnily enough, back then we weren’t really great when it came to source control. The initial commit was the only commit in that repository. There are still 10 unstaged/uncommited files.
We got a bit better when we moved to the “Office Attacks!” repository, which was created on October 11, 2011 at 1:34 PM. That repository contains 10 commits, with approximately 1 month between a few of them. Yes, not great.
Finally, we get to our modern repository, called “OfficeAttacks” where we have been living up to this day. The first commit was on December 5th, 2011 at 11:30AM. The repository contains 2,932 commits authored by 4 people: Steve Kanter [me], Tim Park, Clement Todd, and Tyler Vezina.
Office Attacks consists of 177,744 lines of code, not including 62,024 lines of comments and 51,411 blank lines, all contained in 1,988 files. None of that includes 3rd party libraries – pure Office Attacks code. The repository currently weighs in at 2.17GB. Our Dropbox contains a grand total of just under 5GB of source art.
Because of the fantastic gource, I present to you a high-speed look at the Office Attacks git repository over the course of its almost 2 year life-span.
Link of the week: OfficeAttacks.com - yes, some self promotion, but go ahead and get a sneak preview of the game and try your hand at building a tower! Gameplay trailer still to come – keep your eyes out for it!
Git commit message of the week: “Version 1.0, mutter trucker”
Chat of the week:
[Oct-17 5:12 PM] Josh Garellek: did we actually just submit
[Oct-17 5:12 PM] Avi Davies: yes
[Oct-17 5:12 PM] Steve Kanter: yes
[Oct-17 5:12 PM] Josh Garellek: lol
[Oct-17 5:12 PM] Josh Garellek: seems a little lack luster
[Oct-17 5:12 PM] Jennifer June: he means anticlimactic
[Oct-17 5:13 PM] Steve Kanter: yes, true
[Oct-17 5:13 PM] Josh Garellek: yeah
[Oct-17 5:13 PM] Clement Todd: Doesn’t seem real
[Oct-17 5:13 PM] Avi Davies: that’s just cause you’re neck deep in paperwork
Glitch of the week: Glitch? NO! We just submitted. Heh, funny jokes. So, the simple non-technical version is, when you submit release builds, the code gets compiled differently. So we had some odd behavior with things getting broken – specifically, placing a tower crashed the game. Whoops! Luckily, we all tested the release build before we submitted it, so things like that got fixed.
Note: The blue boxes surrounding items in the images are merely debugging info.
(Or should that be “Office Stretch”?)
So this is it. We’re aiming to submit Office Attacks to Apple next week. We’re still finding “why wasn’t that found before?” bugs, but that’s what (further) testing is for, right?
In Dev Diary #16, I talked about “grounding” towers, or rendering them in-game without their bases. (since bases are optional when you construct your towers) I figured this was the end of it. When rendering towers with bases, I simply used the bottom of the SWF file as the “ground”, and centered the SWF file into the render area.
Well, there are a couple of towers that invalidated my assumptions. To the left are before and after shots of the Super Pencil Turret and the Regal Cooler in-game. The Super Pencil Turret has a laser sight that, when pointed down (ie: the tower is facing forward), expands the bounds of the SWF below the tower’s shadow. And the Regal Cooler has a few sparkle effects on the right side that cause the tower to be asymmetrical, and thus not easily able to be centered.
This was fixed by adding yet another anchor point to denote the bottom of the tower’s base.
To the right is another example of the TowerPieceToolScene, previously seen in Dev Diary #3. The old version only had the anchor points that join the pieces together… Front, Top, Left, Right, and Base. The new points since then are the following:
- C: Center – Helps center the tower in the Workshop
- S: Shoot – Represents where to start the projectile
- G: Ground – Bottom point of body, when rendering in-game with no base
- X: (I ran out of letters ) Bottom point of base, when rendering in-game
Adding the four new points were a little easier than the original five. With the exception of Shoot, they’re all generally the same for all eight direction views. Hopefully this is the last of the alignment issues… as I wrote in the chat, “I never wanna see another anchor point again.” (Anchor points are also used for alignment of decorations in-game, but I was referring to tower anchor points)
The “Shoot” anchor point was an important one. Previously, projectiles were pretty much spawning in the middle of the tower. It was a little tricky getting it to work with our “OAProjectileController” class. It basically starts a projectile at a grid coordinate, then moves it over time to the enemy’s grid coordinate. (but with a Y offset so that the projectile isn’t travelling along the floor) How can the tower shooting anchor point factor into this?
The projectile is an “OAProjectileView”, which is basically an empty CCSprite, with a child CCSprite added to it with the actual projectile image. The OAProjectileView is moved by OAProjectileController from the startGridCoordinate to the endGridCoordinate like before, but the position of the sprite within this view is set to the shooting anchor point offset. Since this offset isn’t appropriate for when the projectile reaches the enemy (it would likely overshoot the target), this offset position is also interpolated over time from the shooting anchor point to something appropriate for the target, like (0, HALFENEMYHEIGHT). For splash damage projectiles (ie: a coffee cup that crashes on the floor, creating a spill that damages multiple enemies), the final resting place is (0, 0). For these projectiles, an extra factor (height * sin(dt)) is added during flight to give it an arc.
There’s something else I added long ago to help in debugging. Steve posted a picture of it in Dev Diary #14, but you can also see it below. Every entity can have debug information printed on top of it, so you can see some of the game’s internals. Here’s what’s printed:
- Damage / UpgradeLevel (red)
- ShotsPerSecond / TimeUntilShoot (green)
- Energy / EnergyMax / EnergyUse (blue)
- Armour / Speed / Evade (red)
- Health / MaxHealth (green)
- Energy / MaxEnergy (blue)
- Damage (red)
- BuffType (green)
- BuffTime (blue)
Buff types include fire (armour down), ice (speed down), and critical hits. Some towers simply have shots per second, and others require energy to shoot. (Towers and enemies gain 1 energy per second) Enemies use energy for their special abilities. For example, Flynn (the hipster) spawns new hipsters. This caused a few problems.
When checking for a wave being complete, we have to check that all its enemies are gone and any hipster-spawned enemies are gone. Previously, enemies could still gain energy during their death animation, and hipsters could spawn a new one while they died. Apart from not really being fair, this caused a situation where levels ended early. You killed the last hipster in a wave, and that wave was marked as complete. While dying, a new hipster could be spawned, and after he was killed, that wave was marked as complete again, incrementing a “waves complete” counter an extra time that caused levels to end early. So now enemies don’t gain energy while dying, and we have better end-of-level detection code in place.
Other things that happened recently…
- Steve made some awesome optimizations to the rendering and z-ordering code.
- Steve wrote some code to output a PNG for every level. Unfortunately it doesn’t currently work with the z-ordering, but it’s still a great way for us to get a quick overview of them.
- Tutorial finally complete to people’s satisfaction.
- Added a bunch of decorations.
If all goes well, Steve will be writing here next week with a post-mortem. See you then!
Link of the week: IKEA or Death – Test your knowledge of furniture and music.
Git commit message of the week: “Updated chatting formula as per Avi.”
(Was supposed to be “chaching”, our in-game currency. No computer-generated dialog, sorry. )
Chat message of the week: “we don’t see eye to eye on how armor buffs work”
Glitch of the week: Steve was sprucing up the credits screen and ran into this issue. For some reason, the last character of each line was overlapping the one before it. This was happening when the text was centered, but not when it was left-justified. The small trick of adding a space to the end of each line fixed it, but I’m not sure why this happened. We’re using this font in a centered fashion elsewhere in the game. Hmm.