Login
Search
Categories
Vote!
Loading ...Twitter
Archives
- July 2012 (1)
- September 2011 (1)
- August 2011 (2)
- July 2011 (7)
- June 2011 (6)
- May 2011 (4)
- April 2011 (8)
- March 2011 (7)
- February 2011 (4)
- January 2011 (5)
- December 2010 (5)
- November 2010 (3)
- October 2010 (6)
- September 2010 (9)
- August 2010 (3)
- July 2010 (2)
- May 2010 (1)
- April 2010 (4)
- February 2010 (1)
- November 2009 (1)
- October 2009 (2)
- August 2009 (3)
- July 2009 (4)
- June 2009 (1)
- March 2009 (1)
- January 2009 (1)
- December 2008 (1)
- November 2008 (1)
- October 2008 (1)
- September 2008 (1)
- August 2008 (1)
- July 2008 (1)
- June 2008 (1)
- April 2008 (1)
- March 2008 (1)
- February 2008 (1)
- January 2008 (2)
- December 2007 (1)
- November 2007 (2)
- October 2007 (1)
- September 2007 (4)
- August 2007 (4)
- July 2007 (4)
- June 2007 (5)
- May 2007 (4)
- October 1982 (1)
Category Archive: DevLog
Subcategories: No categories
AS3 Memory Fail
I’ve been too busy to update the devlog recently but I have in fact posted new content to Bowmaster Winter Storm every Friday for the past few weeks. Go check it out if you haven’t taken a look lately.
www.lostvectors.com/winterstormbeta
I’ve had some recent major triumphs, some mini defeats and mini triumphs lately. In the not so distant past I had some issues with a memory leak in Winter Storm. After much investigation and some thrashing I decided it was time to do some much needed refactoring. At this time I still had no real idea where the cause of the leak was.
My first step was to create a more formal process for handling event listeners. In AS3 I take issue with the lack of management functions that exist for working with events. The event model is much improved over AS2, but a few things caused some issues for me.
Function “removeEventListener” does not provide feedback on whether the operation was successful.
Ideally you would always call this function with the correct parameters to remove an event listener. However if you mistakenly give just a single incorrect parameter then the removeEventListener function call fails silently. The event listener that you though you removed remains in memory along with all of its attached references thus causing a memory leak.
for example:
1 | myHugeObject.addEventListener("destroy", handleDestroy); |
… later in the process, somewhere else in the code…
1 | myHugeObject.removeListener("destroyed", handleDestroy); |
Note: The event string parameter is the incorrect string. Syntactically there is no error. The program will compile. Not only that, but there is also no runtime error as well. Even though no such listener exists with the signature of event string “destroyed” and “handleDestroy” the function will not throw an error.
Even if you now do this:
1 | myHugeObject = null; |
The object remains in memory, now with no way to reference it, hence memory leak.
I was certain that I used removeEventListener responsibly and everywhere I added a listener I made sure to include a removeEventListener in a destroy function that was called when the object is no longer used. The problem was that I had made the mistake I described above. I found this out with the help of a custom event management class I created called EventManager.
Essentially I created a class to handle all event listener adds and removes so that all such operations could be audited for validity.
My syntax changed from:
1 2 | myDispatcher.addEventListener("event", listenerFunc); myDispatcher.removeEventListener("event", listenerFunc); |
to:
1 2 | EventManager.addListener(myDispatcher, "event", listenerFunc); EventManager.removeListener(myDispatcher, "event", listenerFunc); |
By funneling all event listener add and remove calls through this static class I was able to provide extra debugging feedback. For example, whereas before with removeEventListener if you attempted to remove an event listener that does not exist Flash would not care to inform you. With EventManager, if you call removeListener and it cannot find the listener you’re looking for a runtime error will be thrown.
EventManager essentially maintains a global registry of all event listeners that is now visible to the developer. I had to convert hundreds of calls to add/removeEventListner to use EventManager but it was worth it. With the added visibility and error checking of my EventManager class I was able to see when and if the registry was continually growing instead of staying within a certain size. And upon initially testing the fully converted code I immediately discovered a few listeners that were lingering and occasionally had runtime errors indicating that I was attempting to remove events listeners that did not exists.
So this was a major triumph in my battle against those evil pesky memory leaks. After fixing all the issues with event listeners I thought I was sure to see no more memory problems. While I did notice fewer memory issues, I still noticed some instances where memory usage would continue to creep up. It was then that I decided to revisit the method of disposing of application objects.
For all of my objects I have some form of “destroy” function that is called when the object is no longer needed and this function primarily just removed event listeners. I didn’t attempt to nullify references to other objects stored as member data within this object because I figured as long as my application didn’t refer to this object (i.e. store a reference to it) then garbage collection would eventually take care of everything.
For example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | class ObjectA { public var m_objB:ObjectB; public var m_objC:ObjectC; public function destroy():void { // remove listeners } } class MainApp { public var m_objA:ObjectA; ... public function startNewLevel():void { m_objA = new ObjectA(); } public function showUpgradesMenu():void { // show upgrades } public function endLevel():void { m_objA.destroy(); } } |
With this design, the ObjectA’s destroy function would only remove listeners. Also, in MainApp, the reference to m_objA is only overridden when startNewLevel() is called. Therefore even though endLevel() was called, if the next step is to call showUpgradesMenu() the user may be looking at new upgrades to purchase for a while before startNewLevel() is called. In the meantime the reference to m_objA still exists even though it’s destroy function was called, and within it exist references to instances of ObjectB and ObjectC.
I decided to take a more aggressive and proactive approach to freeing memory. I made the design decision to nullify all member data object references whenever an object is destroyed and then also nullify the current reference to the destroyed object.
The new way:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | class ObjectA { public var m_objB:ObjectB; public var m_objC:ObjectC; public function destroy():void { // remove listeners nullifyReferences(); } public function nullifyReferences():void { m_objB = null; m_objC = null; } } class MainApp { public var m_objA:ObjectA; ... public function startNewLevel():void { m_objA = new ObjectA(); } public function showUpgradesMenu():void { // show upgrades } public function endLevel():void { m_objA.destroy(); m_objA = null; } } |
You may think that just setting m_objA to null after the destroy() call should be enough, and for what you can see in this example it definitely would be, but in the context of a larger application there may exist other references to m_objA so simply nullifying it in MainApp will not guarantee that it is a candidate for garbage collection.
So I applied this design strategy to my game application. It was a bit tedious but worth it because a useful side effect of nullifying member references after destroying an object is that any other objects that may have been incorrectly using an object after destruction can no longer access public member data in the destroyed object. What happened in my game after I implemented this design was that the game application started to show runtime null reference errors everywhere in application was using a destroyed object when it wasn’t supposed to.
As part of a “design by contract” approach the game application is not supposed to use destroyed objects. This means that instead of checking “isDestroyed?” every time I want to use an object’s data, I make sure that the code doesn’t try to use destroyed objects in the first place. For instance, game unit AI is not supposed to target units that are destroyed, so when the application returns a list of all the closest enemies it makes sure to not return any “destroyed” enemies. The AI can assume the list of enemies it received consists of only “alive” enemies (a precondition for using the list). For the most part, I did a good job of ensuring that destroyed objects were not used. However, just like the event listener issues mentioned above, there were a few instances where I made mistakes.
So with a little bit of debugging and redesign I was able to not only improve memory usage efficiency but I was able to locate erroneous areas of my code. Since this design overhaul the game is running much more smoothly and previous failed memory tests are now passing and I now have a good infrastructure in place to prevent further memory issues. Now I can focus my efforts on more of the fun stuff like creating new content and game balancing.
Rest
Yeah, so I’ve been working a lot and have been writing several devlogs but haven’t had a chance to post them until now. In short, I’ve been so busy working that I tend to use every last minute of the night performing "just one more test." I’m taking this short break to post these updates. I recommend starting with Tell Me Where It Hurts Part Part 1 and then moving on up. I hope this squelches any concerns that maybe I was slacking off this month. Time for a break.
Tell Me Where It Hurts Part 3: Security Checkpoints
This memory testing is quite the bug hunt. I’ve been testing between two computers and two browsers. I’ve been patting down every game object for illegal memory stashes. Offending code blocks are stripped and searched and sometimes even completely exterminated. Progress is being made little by little as I debug and optimize while innocent code is made to suffer inconvenient slow performing test operations.
It has been a tedious process but still productive. All this debugging has reacquainted me with some old code. Some of which I haven’t seen in months. It’s been nice getting back in touch.
I still haven’t found that magic one-line-of-code that if fixed would solve all my problems…
1 2 3 4 5 6 7 8 | //////////////////////////////////////////////////////// /////////////////////// PAIN IN BEHIND BEGIN /////////// // set to false before testing public static var GAME_BUGGED:Boolean = true; // set to 0 before posting public static var MEMORY_LEAK_RATE_KBS:int = 1024; /////////////////////// PAIN IN BEHIND END ///////////// //////////////////////////////////////////////////////// |
9:45 PST – I finished coloring and formatting this series of devlog posts. That part about me "taking a break" mentioned above turned out to be an hour of devlog mayhem. The real break starts now.
9:46 PST – Okay, I’ll break for reals in a second but I think I just plugged another memory leak…

I’ve been having trouble with the pikemen so I have them fight to the death for my amusement. Actually, I don’t even watch the battle. I just work on other stuff and wait for my computer to come to a screeching halt due to flash consuming all of my resources. At the end of this night I looked over and saw that they were still duking it out AND my ram was still not completely ravaged. As you can see, there has been 323 level changes (levels last just a few seconds) and still no problems! Yay. I’ve decided to tell you this because I want to completely jinx my code. Or do I? Take that Karma. Or don’t not take it not. See if I do not don’t care not so much so not… Everyone stay real quiet… … … okay I think the it’s safe now. I need food.
10:00 PST (-8 GMT) Posting…devlog
Tell Me Where It Hurts Part 2: Not (All) My Fault
So after doing some further tests I was able to pinpoint code that would result in memory leaks. The code itself looked harmless and functionally it worked.
I narrowed a leak to a “doSomething” function in my Util class. I knew it caused an error because when I turned the function into a no-op the leak went way. So I knew that something in that code was causing the leak. But just looking at it, it made no sense whatsoever why there was a leak.
Example original code:
public static function doSomething(clip:MovieClip):void
{
var mc:MovieClip;
do some sort of gotoFrame logic on clip
for all children in clip {
if child is MovieClip {
mc = MovieClip(child);
doSomething(mc);
}
}
}
This code recursively does something on a movieclip and all of its children that are also movieclips.
public static function doSomething(clip:MovieClip):void
{
do some sort of gotoFrame logic on clip
for all children in clip {
if child is MovieClip {
doSomething(MovieClip(child)); // cast child and send
}
}
}
Notice that I removed the local variable “mc” and just passed a MovieClip casted version of child as the parameter. There was NO functional reason for this change. I really had doubts that this would have any affect. After all, “var mc:MovieClip” is a local variable and should be marked for garbage collection at the end of the recursive function call. The function does in fact end so don’t think it’s runaway recursion. We’re dealing with clips that are just 3 subclips deep at most and I use this function several times a second on many clips without any hanging.
When I tested the second version of the code there was no leak to be found. Undeniably the code change had some effect. Why?!? My theory was that since I was calling this static function from inside a non-static instance of an object that maybe Flash had some obscure rule about local variables inside static functions and it caused the program to hold on to all references to MovieClips thus preventing them from ever being garbage collected.
I don’t pretend to know everything there is about Flash or how it works. But something about this seemed real fishy. I often like to blame flash for its bugs but I do this mostly to complain about the IDE. I like to trust that the flash player is solid and without error… yeah, so naive. It’s not a good practice to blame the flash player because then you may write off real issues as “flash bugs” when in fact they are your fault. I try hard to give flash the benefit of the doubt. I’ve done so for this entire week. I’ve torn apart my code to pinpoint the causes for memory leaks. I’ve been rebooting my game practically one feature at a time just to find issues. This is how I found the issue mentioned above.
Even though I felt a little relieved that I’ve finally “fixed” one of the leaks, something didn’t feel right about that fix. I didn’t feel it was my fault. It felt like a hack solution and what bugged me the most was that I had no real understanding of the issue. There was no white-paper or release-notes that I was aware of that explained the issue I uncovered. I’m not sure I can even recreate the leak using anything but the complex environment of my game code. I’d love to make a lean code example of the issue without my entire game attached and submit it to Adobe and ask “why?”. I felt run down. A little defeated…
AND THEN… On a whim, I decided to test the code on a different machine. I should have done in the first place. It’s good practice to test the application in different environments with different browsers. I don’t know why I assumed my environment was error free. I was wrong.
I took the same exact game that had the leaky code and ran it in IE on a Windows XP 32 bit system. I was originally running on Windows 7 64bit using IE 32 bit. Using the same problematic version of my game but using the XP machine with latest flash installed the game had NO MEMORY LEAK. At that point I was mad. All this time I thought it was my fault. All this time I spent turning code on and off and locating obscure areas of code that my flash player decided it just didn’t like willy-nilly.
So now I go back and test variations of my game using past tests that failed before to see if they would pass this time on the different computer. Unluckily only some of the previous failed tests passed this time so I still had memory leaks that were my fault somewhere. OR the flash player on this other PC had a different kind of criteria for giving me faulty memory management. Either way I had to fix something because chances are I’m not the only one with the issue. However now I’m left second guessing whether or not the leaks are my fault or the player’s.
All I can do now is do further tests and isolate the areas of code that cause the game to break. Even if it’s a dumb flash bug and not my fault I still have to adapt since no amount of yelling at Adobe is going to fix this issue right this second.
The plus side to all of this testing is that it’s giving me a good understanding of how much memory certain features use. This will help me determine where I need to optimize the game to make it run smoother.
UPDATE: The saga continues… Read Part 3.
Tell Me Where It Hurts Part 1: For the Horde
I’m oh-so-close to posting a new update to Bowmaster Winter Storm (Alpha 0.0.1.9). I was so ready to start preparing the files for post and I blocked out an entire day to work on it. As I started working I discovered, much to my dismay, a memory leak! Dun dun dunnnnn! Well, I noticed that after performing some overnight tests using never ending battles that the game would use up all available memory and then crash the web browser… err…maybe I shouldn’t be telling you this.
To those of you who don’t know what a memory leak is it’s when a computer application starts using up memory but doesn’t free it up after it’s done using it. This is most often the developer’s fault due to a programming bug or just poor design. A simple flash example of how this might occur with poor design is that let’s say every time you killed a unit or closed a window that instead of removing it from memory the programmer coded it to just turn invisible by setting alpha = 0. Essentially this would cause the data to continue to exist in memory instead of being freed for use for new enemies and new windows. Unfortunately my memory leak was caused by something way more difficult to locate.
Anyway, it’s quite demoralizing when you set aside an entire day to work on play-testing and game balancing (the fun stuff) to then discover that you first need to fix a major issue instead. Not a great way to start out the day. Looking at the faded out crashed internet explorer window with a frozen image of bowmaster carnage in the background, I was not looking forward to hacking up my code to find the cause behind the memory leak. Image having an apartment that you just cleaned and organized and then getting a knock at the door – It’s the FBI and they have a warrant to search the place. Sure it has to be done but in so doing they’re likely going to trash the place. That’s what debugging memory leaks can be like. I just got done working on my unit-skinning system and re-integrating old units and adding new ones. Now I need to go into the code and start turning off stuff, add hard coded test functions to inspect output, and otherwise break the game in order to try to fix it.
Not knowing how long this was going to take or even where to start for sure, I did my best to divide and conquer. Unfortunately it’s not easy just turning off half the code without adding new bugs, but in theory if you could turn off areas of the program in half increments you can potentially narrow down the source of the problem fairly quickly. For example, if I suspected that some of the new unit skins may have been causing the problem, I could just not load those units and only load the ones that I know have worked in the past.
Not only is it difficult to find a memory leak, it may be difficult to replicate one in a short period of time because it may take a while before the impacts are noticeable. I needed a way to accelerate the process of replicating the issue. I hacked my game to load tons of units in random areas of the map so they would instantly engage in battle. With more data being loaded and unloaded more frequently I could now inspect the memory usage using the Windows system processes inspector to see the memory increase quicker. I was also able to get the web browser to crash in a matter of minutes instead of hours. Yay!
It may sound odd to be happy to cause the game to crash, but when debugging it’s essential to be able to recreate the issue. With this step complete I was ready to start turning off sections of my code to see if doing so would remove the issue. The usual suspects for potential memory leakage were the new units, the elaborate special death animations (slice in two, electrocute etc.), and certain custom units like pikemen and dragons that have special ways in which they attack.
Technically speaking, there are few known best-practices that will prevent memory leaks from occurring. If you’re not a programmer or you do not care about these tips then feel free to skip down to where I talk about how dumb I am.
Tips:
1. Use weak references when adding event listeners.
addEventListener(“eventString”, listenerFunc); // wrong way
addEventListener(“eventString”, listenerFunc, false, 0, true); // correct way. The last three parameters are optional but the default useWeakReference parameter is set to false so you need to set it to true.
2. Even if you use weak references, call removeEventListener to explicitly remove event listeners when you know they aren’t being used.
3. Adding code to clips embedded in a timeline may cause memory issues. For example if you add a listener to a clip on the timeline and then that clip is replaced by a blank keyframe you may have memory problems. Another example is if you give a clip on the timeline an instance name and then move that clip to a different layer with the same instance name you may have memory problems.
4. Remove or nullify references to unused objects. An object will continue to stay in memory if there are references to it. In Bowmaster for example, I keep a singleton reference to the LevelManager class instance for easy global access in other classes. However, this instance is only relevant when the player is in-game and is not relevant when viewing the main menu screen. Therefore I need to make sure to set the global static singleton variable to null when the game window is closed otherwise all objects still referenced by the LevelManager will not be freed.
So despite how smart I may sound listing all those tips above, I felt like a total flash noob spending the entire day trying to locate the problem. I kept turning on and off code and checking the results but every time I wasn’t able to specifically pinpoint the issue. I thrashed for hours, 12 full hours, trying different things and documenting the results. At some point you just need to call it a day, and I probably wasn’t very productive or efficient for those last four hours I worked, but it’s hard to stop when you think to yourself, maybe if I try just one more thing…
The next couple of days I was forced to only work in short increments, but I was making progress. I eventually turned off all the units except the grunt and started testing one skin at a time. I discovered that just one of the five unique grunt skin sets was causing a memory leak. Guess which one… It was the orc. Yep, I created a new grunt unit that used the same basic animation as the skeleton foot soldiers but changed the graphics to look like an orc. And then for some reason, in an act of defiance, the orc decided to crash my game. I give him life and this is how he repays me? By hording all the memory and never giving it back? Bad orc! Bad! (::scrohboo::) So it wasn’t just the fact that he looked like an orc — that would just be silly. Specifically I narrowed it down to some embedded code that I used to animate the shine on the orc’s sword. What was unsettling was that I used this embedded code approach before in other animations. I’m thinking that the new skin redesign may have made this code incompatible, or maybe it was always broken and I just never noticed the memory leak until now.
Luckly, after some tweaking I was able to get the shine animation to work AND not crash the web browser (i.e. no memory leak), but I’ll need to inspect other areas of the game that use similar embedded code and fix those as well.
It was one of those traumatic software development experiences where there’s no hope and you wonder if you’re going to have to redesign the entire application… Yeah, maybe I blamed flash a little too. I was quite vexed about this issue. I did not want to crash people’s web browsers. I care about the user. Yeah, maybe the issue will only affect those that play for hours straight without refreshing the browser, but I’m not going to deny them that opportunity just because I didn’t want to fix a bug.
On one hand it looks as if it took several hours just to find and fix one bug. On the other hand, I just spent several hours towards the goal of ensuring that the user has an error free experience. And in the process of doing so I’ve implemented several useful debugging systems that will allow me to test the game much easier in the future.
Yeah, so maybe it’s not so easy to skin an orc. But in the end it will be worth it. Stay tuned. You’ll see.
UPDATE: Not so fast jase… don’t think this is over. Read Part 2.
Frackin Skin Job
Here’s just a simple example of the skinning stuff I’ve been working on (click on the buttons at the top right to change the image).
Originally I was redesigning the character animation models to allow me to replace the entire set of body parts with any different set of body parts so that … it would make my life easier. But then I started to see the potential for changing just certain parts of the character such as their helmet or weapon. I kind of got carried away a little and needed to take some steps back to determine all the impacts that my redesign had on other game systems such as collision detection and damage calculations. I kept running into chicken-egg conundrums regarding game unit initialization. Like… "do I skin the unit first, then reinitialize the bounding boxes? What if I want to add a weapon after the unit has already been initialized. But I already initialized all his weapon stats! Oh crap, now he’s not doing any damage for some reason. Why are my arrows passing right through him!?!?… ::quits and goes to play Mass Effect::" So as you can see, even if none of that makes any sense to you, I had to re-think some of my initial design. This is why the frackin skin job has been so hard to kill. Gladly I think the hard part is over. I’ve developed a flexible approach that allows me to skin, reskin, change weapons, remove weapons, change armor, remove armor for the Pikeman game unit. After a little more testing, I will adopt this same approach for the rest of the game’s less complex units.
In other news…
Snowboarding:
I stopped (for now) due to injured elbow (it was worse than I thought… physical therapy here I come!). I’m hoping to get back on the slopes soon enough. At least I didn’t break an arm like my friend did on the slopes. He just recently got his cast off right before his 30th birthday. I asked him, "how’s it feel to be 30?" he says, "It’s great… I just started physical therapy."
Gaming:
I’ve just beat Mass Effect 1 since I love living in the past. I missed out on that game… rather I tried it but didn’t really give it a fair chance and it just fell by the way side. After finishing a play through of Dragon Age I decided to give BioWare’s space epic another try. My original mistake the first time I tried Mass Effect 1 was to judge it on its underwhelming 3rd person shooting mechanic. I didn’t give it a chance to hook me in with the story and biotics (spells). So with all the news and podcast coverage on Mass Effect 2, I was dodging ME1 spoiler bullets all matrix style so figured it was time to give ME1 another shot considering how apparently awesome ME2 is. As soon as I beat ME1 I bought ME2 from Steam. I couldn’t wait. It’s cool how ME2 uses your personal character’s save file from ME1. I’m not very far into it but so far I’m really liking it. And they improved the shooting mechanic! Yay. And did away with all that pesky inventory management…yay?
Skinning an Orc
Winter approaches. This year seemed to fly by. It’s almost Christmas! Lately I’ve been working on programming for my yet to be released Bowmaster Winter Storm Beta. I have been working on some cool stuff that will help me optimize file size and increase productivity in the long run. Specifically I’ve been working on character skinning. In the past I used unique movie clips for each character even if they used the same animation. So for example when I wanted to create new units I would just copy and paste the same animation and rename and manually re-skin the graphics. The problem is that each copy has its own set of hundreds of animation key frames. This was the design approach that I carried over from Prelude and with the amount of content planned for BM2 this is just not going to work out anymore. Flash tends to choke and crash when I open the animation library because there’s just so much there (and I plan on adding lots more!). Hence, it was time for me to take action.
I’ve redesigned the beta build of BMWS so that I only have one animation clip per character type that I can then dynamically change the body parts to. So imagine a stick figure that has all the basic animations such as walk, attack, die… Then I just attach whatever parts I want to the stick figure and make the stick parts invisible. Since there’s less duplication in the Flash library, the export .swf file size is reduced which means the game loads faster and can be easily be uploaded to other sites that have file size restrictions. It also means I can cram more content into the game without using as much space and without crashing Flash as often (not a hard thing to do by the way).
This new approach will also increase productivity. In the past, if I wanted to change the animation of the walk sequence I would have to manually fix the animation in all the characters that used the same walk method. Now I can just make the fix to the main animation clip and all characters that use that animation model are automatically updated.
And lastly, aside from increased productivity and reduced file size, this redesign opens up the possibility for increased variety in character models. For example, in the past if I wanted to make two skeleton grunts with the same animation to have two different weapons (one a sword and one an axe let’s say) then I would have to create two different movie clips (or do some other tricky sub-clip key frame magic). Now I can swap any body part at any time, including the weapon. Now that everything is skinable, all body parts are targetable through Action Script. I can load anything from armor, weapons, clothes, monkeys, ham sandwiches, anything. Imagine instead of seeing the same ninja graphics for every rank, you see the color of his belt change. Higher level orc grunts could have spikier armor and meaner looking helms than the low level initiates. Maybe you could even upgrade the weapons or armor of your own troops and see this reflected in the character models. These are still just examples of what is possible – I won’t give away any specific new details just yet.
My (Windows7) LAN Party … The Invention of Awesome
So my friend signed up for the Windows7 party pack with free copy of Windows7. I guess you had to give a story about how you’d have some sort of Windows7 party and if they picked you they would give you a box of party supplies (balloons, streamers, party favors … all Windows7 themed) along with a free copy of Windows7. My friend applied for the free copy and gave some story about how he was going to have a boat party and sail around the harbor… he did it just for the free copy of course… but since I was having a LAN party he offered to donate the decorations. So I kind of had a Windows7 party… But I’m a little bitter because had I known about the free windows deal I would have signed up because my LAN party was no typical frag-fest and it would have most certainly awarded me my own copy had I applied.
Okay so here’s what I did: I combined a typical LAN party (Call of Duty 2, Soldat, Left 4 Dead, Demigod) but added Live-Action-Roleplaying elements to it. Of course my guests were completely unaware of this feature until I “rescued” them from “real-life” wearing a mad-hatter hat, some Ozzy Osbourne sun-glasses, and wielding a kick ass (plastic) crusader sword. I escorted guests from outside my apartment and opened the gate to my parking garage using none other than my totally legitimate Game Master magical powers (electronic key fob) and escorted the refugees of reality to the safe room… the Realm of Anti-Reality (aka my apartment).
Bare in mind my friends aren’t huge Live-Action-Roleplayers (neither am I really, though I’m totally for it
and also bare in mind that not everyone showed up at the same time… so I’m running back and forth from my apartment, in and out of the safe room, up and down elevators, being stared at by several NPC characters (my neighbors) while looking like a crazy mad man holding a plastic sword and pretending to open the automatic gate with his “force powers”. At least it’s kind of near Halloween time, but mind you my LAN started in the middle of the day so there was lots of daylight and little chance at going stealth.
Anyway… so at the safe room I started the character creation process. My friends were like, “you’re are nuts” and I’m like “just bare with me here, if you want to opt out then you can be an NPC and you won’t be affected by any spells…” and they’re like, “Spells… oh god, what are you up to Jason.”
Naysayers! But I was determined to convert them and they were all willing to give it a shot.
So the first part was the character creation process… First they had to give themselves a new Name. Then they had to choose their character class… Thief, Assassin, Peace Keeper, or Wizard. Then they had to pick a side: The Green Berets (allies of the Pirates) or The Red Army (allies of the Ninjas). All of this info went onto their sticker name tag. Then I gave them 5 gold coins and their XP score card (note card) and gave them a single bronze mardi gras bead necklace (to indicate they were level one).
As we played games throughout the night I would award XP and gold for winning matches. People would keep their own score (we used the honor system) and as people leveled up they would get more beads and higher ranked colors (such as silver, gold, and then purple).
Gold coins would be used to buy items such as nerf guns, ammo, snacks and drinks (honor system again… 1 coin for all you can eat/drink per trip, unless you were a thief then you might just steal the food and hope a peace keeper didn’t catch you).
Yeah so early on in the night my fiancée, as a thief, chose to steal all of the “good” food from the counter and set up shop with all of her stolen goods charging high prices per item. She also stole the pizza from me when I was paying the delivery guy and then extorted 25 XP from me (the Game Master) before letting anyone have a piece. She played her part well… perhaps too well.
So later on in the evening I introduced spells and gave out class specific quests. For the spells, I created a few basic ones to give people ideas and then asked everyone to take a note card and write their own spell idea down. You had to write down the spell name, what it did, and your name (author of the spell). Spells were things you could cast on yourself or on another person and were semi-game related… stuff like, “Spell of Melee Weapons Only” where you could only use melee weapons, or “Call of the Wild” where the person had to yell out a roar or give a battle cry whenever they were about to attack someone. Someone got both of these spells cast on them during free-for-all Call of Duty and it was pretty funny to watch. Another spell I liked was, “Spell of Questioning” the person had to form everything they said into a question (even if it was a statement)… the guy was like, “Who just killed you!? Was it me? How ya like me now? … Do I have the enemy flag!?!? Shouldn’t I be protected right now!?!?!” I’d hand these spells out randomly to people, everyone got one to cast sometime during a match and they got recycled and more were added as the night went on.
Yeah so the spells were pretty wacky and highly un-balanced and ad-hoc but it added to the craziness and people really got into it.
Then there were the class-specific quests. There was an over population of assassins, so the few peace-keepers there were had their hands full. One of them even got corrupt and started selling nerf guns and ammo to the villains. So I created a quest for the other two peace-keepers to grief that person for the rest of the night. I gave a quest to some of the assassins to stealth kill execution style to the back of the head certain targets (with nerf guns or in game… whichever was possible). They couldn’t be caught by the peacekeepers or else it wouldn’t count. At this point there was just one Thief and it wasn’t my fiancée. She must have eaten a poison apple because she was a sleeping beauty for the rest of the night
So I gave this thief a quest to steal all of the peacekeeper’s nerf guns without them looking and then hide them somewhere. He also had a separate quest to steal their peace-keeper hats (which ironically were mobster hats) and throw them across the room.
There was only one Wizard. I gave him the quest to create five new spells and hand them out to random people… He took it upon himself to create way more than five and instead of giving them to people he sold the spells. He then would create immunity spells to cancel those spells and sold them to other people. Yeah so he kind of got super rich with gold and I had to eventually “patch” the game and nullified any immunity spells that were out there and I made all previous nullified spells re-activated.
I even had Wii Sports Resort going, and a little Air-Soft shooting gallery with little plastic ninja and pirate “army men” in which you had to shoot only enemy targets and avoid hitting your allies. Of course it was completely safe and eye protection was required. I kept a global scoreboard of Pirates vs Ninjas… I think Pirates won… though there was lots of friendly fire and collateral damage so it’s hard to tell if this was intentional.
Yeah so I don’t know if anyone has ever done something like this. If not, I just invented something awesome.
the sleepy giant… (is not very reponconsive*)
2009-10-08 the sleepy giant… (is not very reponconsive*)
So I’ve been trying to cram as much summer activities into every last shred of daylight left nowadays so game development has been simmering on the back burner lately. However since my last post I’ve been incrementally working on new game modes for Bowmaster winter storm (yet to be released). The design is highly interchangeable so I’ve been having fun creating some interesting victory and defeat conditions… for example (hypothetical):
Mission: Fire Dragons Invade the Town!
You are victorious if you accomplish any of the following:
1. Kill All Fire Dragons
2. Destroy the Enemy Castle
You will be defeated if any of the following occur:
1. Your hero dies.
2. Three of the five escaping villagers are killed.
3. The refugee shelter is destroyed.
Here’s an example of how crazy and modular these conditions are…
Mission: Beat the Clock Jumpy Happy Land
You are victorious if you accomplish any of the following:
1. You jump 99 times.
You will be defeated if:
1. The game timer expires.
2. You die.
3. You use any weapon.
Disclaimer: This is just a hypothetical example and this exact level scenario will probably not be in the game (maybe in a separate challenge mode… oh cool idea jase).
So hopefully I’ll have more chances to work on game development in the near future. For now I have to make room in my apartment for the Epic Rocktober Birthday LAN Party that’s about to go down. Time to get rid of boxes and boxes of childhood memories in the form of old schoolwork papers, soccer and little league trophies, old PC Gamer magazines, empty N64 boxes etc… it’s so hard to say goodbye. I feel like I’m defragging my life… what sucks is that it doesn’t happen automatically overnight while I’m sleeping…. like a sleepy giant… (you thought Bowmaster WS was the giant… nope. it was me all along. How’s that for a plot twist?)
*responsive – a “happy word” according to that little “I’m a PC” girl that is a on the new windows7 commercials. Rockin’ slideshow. My favorite is the kitten in the sea of marshmallows. If you dvr’d the season premiere of House then look for that commercial. It’s hilarious. I watched that thing like five times.
Bowmaster Winter Storm Status Update
I still working on balancing units but I’ve finished implementing the unit rank system for all of the current units in the game. The rank system (unit level system) allows me to set unit stats and abilities based on a single rank number. So for example I have a function that sets all sorts of stats and AI code based on the rank number for that unit. This makes it easier for me because I can call a single function (e.g. trebuchet.setRank(4)) and all the stats that are relevant for that unit are updated (e.g. hit points, movement speed). The unit AI code also may use this rank number to determine how the unit will think. A low level dragon may fly low and not move around as much as a higher level dragon. A high level shield grunt will block more often than a lower one. A ninja may use more advanced melee attacks at higher ranks.
So for these past weeks I’ve been integrating the setRank function and identifying variables and AI code that could be scalable according to the rank. This will provide the player with new experiences when encountering the same types of enemy units later in levels. Aside from unit rank icons I’m thinking about maybe tweaking the look of the player skins slightly to reflect rank, like changing the color of the ninja’s headband, or the number of spikes on a grunt’s helmet. This is a nice-to-have feature at this point though and I’m focusing on gameplay and functional stability at the moment.
I have a rough plan of the level progression as it relates to unit types and ranks. I’ll be refining this plan as I continue development. My next major tasks are updating and balancing the upgrade system and developing new game level objectives.
Upgrade System Development
The current alpha version (0.0.1.8.3) has a demo set of skills and skill mod combinations with some random costs and skill requirements associated with them. These skills, the mods that are available, and costs may not reflect what the game will be like at launch. Specifically, I plan on revamping the ally unit upgrade system. The unit pre-requisites will be made clearer and you’ll be able to upgrade the unit ranks to match or overpower the ranks of enemies you encounter. Also, the current version does not have player rank requirements but in the future certain skill may not be available until your character reaches a certain rank.
Game Level Objectives
The current alpha version (0.0.1.8.3) has only one objective. It is the same for every level. Just kill every enemy and don’t get killed yourself. I plan on having a few new types of game objectives. I have been planning on doing this for a while now so this isn’t late breaking news, but until now I haven’t been able to start development this aspect of the game.
Here’s just a few ideas for game objectives:
Capture the flag: Classic Bowmaster Prelude level objective where you can either win by capturing the flag or destroying all of the enemy units.
Defend your base: Win by successfully defeating all of the enemies. You lose if your base is destroyed.
Attack enemy base: Win by destroying the base against a never ending horde of enemies. You lose if you die. Perhaps you have a limited number of troops at your disposal (ouch that sounds harsh… at your “disposal”)
Escort/Protect: Protect a slow moving caravan or injured unit as it is transported from one area of the map to another.
These are just a few ideas for game level objectives. I also plan on generalizing the design of these objectives to allow for interesting variations. So even if the objective is familiar the situation may be a lot different. Instead of escorting a single unit from one place to another, you may have to protect an exodus of refugees escaping from a raided town and they’re coming from the same direction as the enemies.
I’m in the early development process for these features so I haven’t completed a whole lot of code for the other modes, but I have been toying with some variations on the current game mode. Since I’ve been working a lot with the unit AI code I’ve been trying to refactor the code to anticipate these new game modes and mode variations. One very important design change was the concept of which way is “forward”. Right now I have the good guys always come from the left and bad guys from the right. They each move “forward” toward the other team. I used to have functions in the unit AI code called advance() and retreat() but this was always relative and became very confusing. I also locked myself into the idea that good or bad units will _always_ come from the same side. Well I’ve finally generalized this code and now I can place a unit anywhere on the screen and it will move to a target spot of interest. No more confusing functions and no more “forward” variable or hard-coded start position point.
This redesign means that I can now create some interesting new variations on the current “kill all enemies and don’t die” objective. I tested two new ideas variations. The first thing I did was switch the starting positions, just to see if the AI still worked. Success! Both armies marched towards each other as expected. It was just a little weird because it was so different to be shooting in the other direction (especially if you’re using the pull string method). I then tried something a little more interesting. I place the starting spot for the good guys in the middle of the screen next to a stonekeep and created spawn points at both the left and right edges of the screen. It was very exciting being completely surrounded with almost no safe place to retreat too. Maybe I’ll create a zombie level
So I’ll continue to provide devlog entries as I work on the BETA but it may still be a while before I post the BETA to play. However, I’ll continue to support the ALPHA that’s currently up so if there’s any major bugs found then I’ll try to fix it and re-post.