20 Jun 2015 @ 12:07 AM 

More babbling about BASeBlock. It’s actually rather sad in a way because I would actually prefer to work on my work projects than on my own, simply because there is so much code involved in the changes I want to make to BASeBlock.

My biggest mistake when originally writing BASeBlock was in using the built-in .NET Serialization capabilities. The biggest problem with doing so is that the data stream is not very accessible, data errors are difficult to localize, and it is basically a huge nightmare- not to mention that there is no guarantee of data being portable from one build to the next. This was actually why I created my XML Serialization library a few months ago, “Elementizer”. The aim of Elementizer is to provide XML save/load functionality and have it implementable in a very similar fashion to ISerializable. This is in contrast to the existing XML Serialization solutions I found which tend to rely on saving and restoring public properties, and I do not want to change my object heirarchy and how values are exposed simply so they can be saved/loaded by a XML library. Right now my task is quite monumental- I need to go through and add support for my IXmlPersistable interface to every serializable class in the project. I’m trying to do it peacemeal and do a bit of testing as I go (so I don’t have to just press F5 later and hope it all works!) and while I’ve only got a rather basic amount working it works alright- I’m able to save and load a few block types to and from XML. The real question is going to be what it looks like with an entire LevelSet, which naturally requires quite a lot of other classes to support the feature. The biggest issue was adding support for some less-than-standard data types to Elementizer, such as Bitmaps and certain data types like DateTime and TimeSpans, which themselves implement ISerializable but for obvious reasons can’t implement IXmlPersistable. My solution consisted of using Elementizer’s ability to add deserializers and serializers for specific data types and I just slapped those into the Standard Helper.

It’s a daunting task but it is very sad seeing something that I used to take so much pride it be sort of abandoned in an unfinished state. And I think it is the Serialization that really keeps me from getting motivated- if I can fix that to use XML, I might be more inclined to fix other issues with the program, much like how I started to fix the GameState implementation. And, it will serve as a great example for Elementizer, since the serialization that BASeBlock needs is quite complicated- it needs to save an EditorSet which has lists of sounds and images that are added on and optional music, as well as a LevelSet which has sets of Levels which in addition to their own properties such as music and themes also have a set of various blocks and block types as well as Balls that the level starts with- so I won’t be able to really test saving very well until later.

The one great advantage of the ISerializable Interface implementation is how I was able to utilize it for the Copy-Paste feature of the Level Editor. I actually think the level editor is probably my favourite part of the program, actually.

Posted By: BC_Programming
Last Edit: 20 Jun 2015 @ 12:07 AM

EmailPermalinkComments (0)
Tags
 24 Apr 2015 @ 7:21 PM 

BASeBlock was one of my first projects that I wrote in C#. I wrote a program that sort of worked like HijackThis and a INI file reader class- which I Discussed 5 years ago (That long? Amazing), But BASeBlock was my first attempt at creating a project using a language that wasn’t horribly lobotomized. (I refer to Visual Basic 6).

I’ve found myself avoiding it somewhat for quite a long time. It is using code that I have since extracted, repurposed, and improved (such as my update library) for other projects. Another problem is that there are some glaring architecture issues in it’s design (when isn’t there) which were because I was unfamiliar with certain design patterns. For example, my game state management is a switch in the drawing and game tick routines on a game state enumeration, whereas a better design is to use a gamestate interface of some sort and have your different game states compartmentalized better.

However I’ve more recently come to rather like one aspect of BASeBlock. I designed it. I wrote it. While I imagine there are some helper classes and such which I may have acquired elsewhere, the bulk of the implementation is me. There is an aspect of that that I find particularly tantalizing, especially compared to my work. Don’t get me wrong I do love what I do and I have a lot of input in engineering decisions that affect my work, but like any software it is designed to a certain requirement, and with a certain timeline, and a lot of that simply isn’t mutable.

This brought my personal projects into new light for me somewhat when I think of it this way. For some time I’ve only thought of them in the back of my mind as a burden- after working 10 hours dealing with invoice printing considerations, I’ll remember my personal projects and feel bad that they have fallen so far by the wayside they’re stuck in the radiator. But I also forget that, unlike my work- my personal projects have no external director. I can add, change, remove, refactor, and redesign anything I want, and I have to answer to nobody- I’m “in charge” of what they become and how they get there.

Which that in mind I’ve taken it upon myself to actually start progress on making BASeBlock more palatable for me to actually work on. The GameState oddity is like an unsightly mole or other minor annoyance- you don’t notice until you have it pointed out to you (or in my case, until I learned of the pattern, and used it successfully in my poorly named Prehender and BCDodger). It is a major change/refactoring that I wasn’t really keen on doing even when I was working on the game almost daily and had a fairly good understanding of it’s architecture and design, so trying it now is perhaps putting too much faith in not only my abilities but also in my abilities when I was writing it, but if I want to improve it, I need to eliminate that unsightly implementation or I’ll just avoid it until I do.

What is this “GameState” implementation?

In my haste, I did rather forget to explain the particulars of what I was talking about when I talk about “Game States”. Game states are basically what state a game is in and are rather commonplace. A Game will have a different “state” for being paused, showing a menu, showing an introduction sequence, etc. an “Enumeration-based” approach like the one I described might implement things like so (halfpsuedocode)

The basic architecture is to have a switch or similar style of conditional processing within any of the routines which will act differently based on the games current state. This does the task and works as intended, but it tends to lead to long rambly routines, and then all your different states get mixed up in one function. The interface-based approach creates an interface and then each State will be a class that implements that interface. This can be implemented in a number of ways, but the effect is to separate the information and implementation required for each state to a separate class. This allows you to add new features to a state without affecting the “namespace” of other states or interfering with it’s variables, which is sort of the entire point of having separate scope abilities to begin with. It also allows some interesting Chaining abilities. If the Running State stores all the information about game objects, for example, and knows how to draw or tick those objects, a “Slow Motion” state could simply delegate to a provided standard State but only call the tick once for every two calls; a Pause screen could not call the Tick function of a provided composite class, and instead call the draw method and then render a 25% shaded box atop it, or apply a color transformation to wash out the result, or a pause logo of some sort on top to provide the “Pause” effect. An “introductionImage” type state may have a single purpose- you give it an image and a GameState, and it will fade the image in, wait a few seconds, fade it out, and then set the current state to the provided state. Games often show various startup logos, and this can be used to easily fade in and fade out through numerous images and then go to the main menu (presumably a Menu state), and so on and so forth. This can all be implemented, of course, with the enumeration method but it requires a lot of plumbing which also tends to get in the way of everyday development and iterative design.

Posted By: BC_Programming
Last Edit: 24 Apr 2015 @ 07:21 PM

EmailPermalinkComments (0)
Tags
Tags: , ,
Categories: Programming
 29 Oct 2014 @ 3:04 AM 

It is a rather basic concept. The idea of saving some state within your program to disk, and restoring it later. Particularly when you are dealing with an object graph in memory and want to restore it. Unfortunately, the easiest way isn’t always the best way.

BinaryFormatter

Interestingly, .NET actually contains built-in serialization capabilities. The basic premise is that your class implement ISerializable and also implement a constructor and a specific constructor, as seen here:

This method does work, really- it’s not super hard to use and setup though it can be a bit of a pain in the butt to maintain. Of interest is that you can GetValue() and AddValue() arbitrary objects, as long as they are also ISerializable. You can use particular Formatters to take your Serialization Information and save it. BinaryFormatter is in particular the one I found most reliable.

There are however some rather significant issues. The first is that you really don’t have a lot of options when it goes to actually serializing data. There is BinaryFormatter and a few JSON converters which don’t work particularly well. The main issue is not so much the underlying interfaces and requirements, but really it’s two-fold; there are few reliable IFormatter implementations that you can rely on from launch to launch (BinaryFormatter fails very easily, and the errors are rather generic) and additionally when dealing with deep object heirarchies small mistakes such as forgetting to mark a method as virtual or forgetting to implement a constructor can cause hard-to-trace bugs in the program.

I speak mostly from my experience writing the logic in BASeBlock to save and load Levelsets. It has been some time, but the serialization nightmares still pester me. Additionally, it bothers me that the Binary format that the files end up as are not very transparent; I cannot easily look inside them without deserializing them in the game editor and if it fails- well, delete it and try again. This rather dampens my attempts to create a “standard” levelset that shows off it’s capabilities.

Recently I set to the task of switching to a new Serialization scheme. I quickly gave up when I realized how much work it would be and just how much code I had written and how many classes needed changed and so on. For that moment I rather gave up. Ideally, however, I would be able to save to XML, ideally with the XDocument/XElement logic. Then save load from XML in much the same way as now. Originally I thought “simple, I’ll just make something like what I already have but create methods that serialize to a XElement and constructors that accept and read from an XElement. This framework would work, but the thing that bothered me is that it was duplication; I had two completely separate but similar save methods strewn about. I gave up on it at the time.

I did attempt previously to create a way to serialize and deserialize from XML via the Formatter method, but this has some rather troubling issues. The main one is that you cannot access the property bag of the object (the SerializationInfo); otherwise it would be relatively straightforward; just take the propertybag of t =he main object and save it and it’s descendants to nodes and attributes and values and such. But this does not appear to be the case. Instead, you serialize in place to a stream, serializing each object directly to the stream. It might be possible nonetheless but it will certainly require that I rethink my approach. At any rate for the “long-term” goal, BASeBlock would be greatly serviced by simply having it use XML files rather than binary files, if only for compatibility.

In looking over BASeBlock while writing this, I’ve come to find a lot of older code that I thought was quite robust which, in the process of my work I have copy-pasted into classes for our products which have subsequently morphed in form, function, and in generall been extended vastly in capability. Some of these I even discussed previously on this blog, such as my DebugLogger. I’m uncertain of how “safe” it would be to copy them BACK to BASeBlock, so I’ve not done so; I’d rather keep my personal projects and work projects as far away from each other to prevent “code ownership” issues. If I copy code from my personal projects to my work projects than from that point on I like to consider them “forked”. But this has the additional issue- If I improve the work version, would writing the same improvements to my personal version still cause it to count as belonging to my employer? It’s a tricky question which I’ve pretty much avoided altogether by taking the rather unsavoury approach of avoiding my personal projects (though to be fair the real reason I’ve not gotten back to them is simply due to time constraints). At any rate it is interesting to think that at any one point a programmer/developer might have code or programs they are proud of, but a few years down the line they look back on that program in disgust. BASeBlock doesn’t quite fit that criteria, but parts of it do. Components and classes that I used to consider excellent, robust, and awesome have ended up getting improved and now that old version feels like getting into a go-kart after driving a Pagani. I like to think this is a good thing. At the same time, I do wonder if perhaps I should try to create personal projects in another programming language just to “top up” on that language. Continuous self-improvement is particularly important I feel but I’ve also not exactly followed my own advice on that front for a while. I’ve got less time to work on this blog than I used to and in some ways that bothers me. Additionally I feel severely outclassed by the C# expertise I see in the insiders mailing list as well as C# community that I’m almost skeptical I belong there. Then I think about how that might fall into Scott Hanselman’s “imposter syndrome”… then I think that only somebody subject to the Dunning-Kruger effect would say that. Then I think that only a person with imposter syndrome would think they were subject ot the Dunning Kruger effect for thinking they had imposter syndrome, then I think….

Posted By: BC_Programming
Last Edit: 29 Oct 2014 @ 03:04 AM

EmailPermalinkComments (0)
Tags
Tags: ,
Categories: Programming
 19 Jan 2013 @ 6:25 AM 

Though I do tend to try to write my samples and test applications, as well as any new programs, using Visual Studio 2012, I haven’t yet migrated most of my other applications to it. For BASeBlock and BCJobClock, for example, they started off in Visual Studio 2008. More recently, I migrated them to Visual Studio 2010. BCJobClock had it’s project upgraded to Visual Studio 2012, (but for some reason the admin applet doesn’t work on Windows 8, which is something that certainly bears further investigation). Anyway, I’ve been strongly considering it the more I think about it. In particular, I’ve found Visual Studio 2010 to actually be a lot slower. Originally, I thought this was because my 201 install had several add-ins installed, such as ReSharper, but now that I also have a version of ReSharper that works with Visual Studio 2012, I still find 2012 to be far more responsive.

Now VS2012 has gotten some flak from certain users for adopting the Windows 8 UI style into it’s icons, as well as using Caps in it’s menus. I really have no strong preference here at all, and I personally don’t see what the fuss is about. I’ve heard people say that the capitals “hurt their eyes” but I can honestly say that I don’t understand how that could be the case.

Anyway: I’ve been considering switching BASeBlock over the Visual Studio 2012. If I do I won’t be upgrading the project to use the 4.5 framework, though. At least not yet.

Posted By: BC_Programming
Last Edit: 19 Jan 2013 @ 06:25 AM

EmailPermalinkComments (0)
Tags
Tags: , , ,
Categories: Programming
 28 Jun 2012 @ 8:29 AM 

That’s right. The latest version of BASeBlock now adds a working Polygon block. There was a lot of reengineering to be done, but it works realistically; which is to say, a ball will bounce at the proper angle.

Some boring technical stuff

Having Support for arbitrary polygons is something of a pipe dream I had. Every attempt failed. What made it possible was in fact me adding ellipse blocks, in which I unwittingly added support for polygon collisions, since the Ellipse Block was in fact just a polygon and used euclidean geometry to determine if and make adjustments to ball collisions. After getting that working, I realized it would make sense for EllipseBlock (and possibly other kinds of blocks) to simply derive from an Abstract PolygonBlock that did the work of dealing with the details of the polygon itself, while the derived class pretty much just handles it’s own fields and creates the Polygon to be used. The math itself actually uses some of the same code that was being used for ball collisions, which takes two polygons, a speed (for the initial polygon) and returns a result structure that determines if they currently intersect, if they will intersect, and how to adjust the latter to be no longer touch the former. I use that last item to create a collision normal, and reflect the speed vector of the ball across a vector perpendicular to it.

A lot of other code needed to be changed to streamline the support of it. iEditorBlockExtensions, a interface used for adding editor-oriented support, had to add a method to allow for the overriding of the selection “pulse” drawing, which at the time only drew the rect. A lot of other code that assumed that the BlockRectangle was the definitive source of the block’s shape had to be changed. This actually ended up in the addition of another virtual method to the base Block class, “GetPoly()” which of course in default implementations returns the polygon of the rectangle, but PolygonBlock not surprisingly overrides this and returns it’s own poly. The base implementation of EditorDraw() fills the polygon dictated by “FillPoly” so this works out just fine; The Editor now allows selection of polygon-shaped blocks by actually clicking on them (rather then in their rectangle) as well as highlighting only the poly (again, as opposed to their rectangle).

Currently it only supports convex polygons, but that is not planned to change, since a concave polygon can easily be simulated with convex polies anyway. (And I haven’t actually tested it with non-convex poly’s so I’m really just assuming for the moment it doesn’t work for them).

It will still need some touching up, and I’ve been making a few other minor cosmetic and UI changes (allowing drag-drop of files on the editor, better dirty-file prompts (for unsaved documents) and so forth). The only area that needs significant work and/or rework is probably the path editing.

In summary, the Next Version of BASeBlock is going to be a significant upgrade, with a completely new domain of blocks to use and explore. I still need to make some sort of “standard” LevelSet that isn’t the crappy LevelBuilders included with the game.

Posted By: BC_Programming
Last Edit: 28 Jun 2012 @ 08:29 AM

EmailPermalinkComments (0)
Tags
 04 Jun 2012 @ 12:16 AM 

The currently released version of BASeBlock is 2.3.0. I have made a lot of changes to the game, added a few blocks, abilities, and other fun stuff, and refactored various parts of the code to make things work better since then. One of the biggest new features is “framerate independence”. 2.3.0 and earlier versions basically did velocity like this for every game tick:

However, the faster the game loop ran, the more times this would run, and typically the higher the fps the more the game loop would run too. This meant that the speed of objects could be the same internally but visibly the objects seemed to move at wildly different speeds. The “fix” to this is relatively simple- instead of simply adding the velocity to the location, we need to take into account some other factors. First, we analyze the problem. What do we want to achieve? The quick answer is “we want the movement of objects to remain equal regardless of how fast the game ticks go”. The best way I’ve found is to choose a given framerate as the “ideal” framerate; if the game runs at this fps, than the result would be that the velocity is added verbatim; If the framerate is less, than we add “more” to compensate; for example, a framerate of 30 in this case would double all speed additions that are performed; and a framerate of 120 would half them.

BASeBlock already tracks the FPS, so the solution was three-fold; first, create a routine that would retrieve the appropriate multiplier based on the framerate and the desired framerate, next, create a routine to simplify the incrementing of a location with a velocity that would take into account the current multiplier that was derived from the framerate, and also to change all the code that simply adds them to use the new routine.

Implementing this in BASeBlock was something I was wont to do for quite some time; it seemed a lot more involved than it really was. Eventually I just decided to try; if things went sour I could always roll back to a previous SVN commit anyway.is has

First, I added the routine for getting the game Multiplier. This required the current FPS of the game. Since that seems like something best dealt with in the presentation layer (and also since the main game form was already tracking FPS for the FPS counter) I simply added a property to the IClientObject interface, which is designed to allow for a way for the form and the game logic to communicate without explicitly requiring knowledge on what it is communicating with. With that property in place, I simply implemented the multiplier routine as a basic division- the DesiredFPS divided by the current FPS. (There is an exception for the case where the retrieved FPS is 0 where it will return 1 for the multiplier). One very interesting side effect of this is that I could, if I wanted, “fake” slow motion by munging around with the CurrentFPS as returned by the clientObject, though that is probably not a good use of this design.

I then implemented a simple routine for incrementing the location, not surprisingly I called this “IncrementLocation”. It adds the velocity, but multiplies it by the multiplier as derived from the currentFPS and desired FPS.

This worked rather well, once I found and replaced all the old direct-addition code with a call to this routine. However there were still some odd behaviours; mostly related to velocity decay. Some objects- particles, the gamecharacter’s jumping, some items falling, and whatnot would reduce or increase their speed by multiplying components of that speed by a set factor. For example, a particle might “slow down” after it spawned by multiplying it’s X and Y speed by 0.98 each frame. I needed to make similar adjustments to the multiplications factors there in much the same manner as for the additions.

I still encounter minor issues that are a direct result of the changes to a “managed” framerate concept; a nice benefit compared to 2.3.0 is that I was able to remove the silly Thread.Sleep() call that slept for 5 or 50 milliseconds (I forget specifically) so the framerate is typically higher; on the “Spartan” Level set builder, the framerate is usually close to 200, which is pretty good for GDI+, and that’s the debug build, too, which is slower than release.

After this, I tried to improve the platforming elements of the game a bit more. I added some new powers, fixed a few minor issues with some of the powerup management code, and added a new interface for the editor to allow blocks to draw something “special” when being shown in the editor; this is used by the powerup block to show the contents of itself as well as modify the tooltip shown. Another change was “block tracking” at the level of the PlatformObject. This also sounded a lot more complex than it was. The idea was simple- when the character, or anything, is on a block, we want them to move with it. This was done by having the platform object track any block it is on, then, each frame, adding the distance the block moved, if any, to it’s own location as well.This has worked spectacularly. I also added an interface for blocks so they can receive notifications from a platformobject when they are stood on.

There is a bit of a downside to this idea, though, based on how I implemented some other “moving” block features for performance reasons. I have a few blocks that give the illusion of moving when hit, but in fact destroy themselves and spawn another object in their place that looks the same. These blocks include BlockShotBlock, BallDirectShotBlock, and the “magnetAttractor” block; the first one gives the appearance of shooting upwards when hit, breaking all blocks in it’s path; the second goes in the direction the ball that hit it was going, and the third works in tandem with another instance of a magnetAttractor block to create the illusion of the two blocks flying towards each other and exploding, or flying apart. These rely on GameObjects to control their behaviours after they are hit, allowing themselves to be destroyed and allowing the rest of their “action” to be governed by those objects. Most specifically, the “BoxDestructor” which is used to create a block-shaped projectile that can destroy other blocks. The magnetAttractor creates two such blocks when necessary, and controls them with yet another gameobject that handles their velocity change, and detects when they meet, creating the requisite explosion. I did it this way because my animatedBlock “architecture” is terrible and annoying to work with, or, at least it was at the time. This means that a gamecharacter cannot stand on such a block and be “fired” along with it, which would have been an awesome gameplay principle for level design. I did create a movingplatform block that opens up some neat possibilities too, though. And causes some really goofy gameplay when I replace all the blocks in a level with them.

My next endeavour was related to the editor; With the new platforming component, I had made it possible to create a Platform-oriented level, with or without a paddle, by adding the appropriate triggers and components to a level. I forgot to add some of these more than once; in fact the second level of the “testplatforming5.blf” levelset included with 2.6 forgot to set the autorespawn field of one of the spawner blocks, meaning that once you die, you cannot beat the level, since only the paddle respawns, not the character. To help alleviate this, I decided to create “templates”. This means that when adding a new level, as well as being able to just add a blank level, one can create a new level copied from a template. This really added a richness to the editor. Templates are loaded from the templates directory, and can be shown either in a categorized drop-down or in a categorized dialog; the “category” design derives from the template concept used with tools such as Visual Studio itself or VB6, which separates the templates into separate categories. This should make the creation of custom levels, particularly platforming levels, far easier. Templates can also add sounds or images to the loaded Set. (possible revisions might be to warn when a template object conflicts with an existing resource, rather than replacing it).

I also fixed a myriad of other bugs and UI issues that I encountered while working on other features. The newer version is really shaping up to be a great update.

Posted By: BC_Programming
Last Edit: 04 Jun 2012 @ 12:16 AM

EmailPermalinkComments (0)
Tags
 12 Apr 2012 @ 7:52 PM 

BASeBlock – Music Manipulation Lessons

As with most games, BASeBlock has music. Originally, I implemented a naive approach to have “Multiple music” playing; a simple stack. The multiple music idea is sort of like
how games might change the music to a boss music when a boss appears, and change it back when they die, or how a certain powerup might change the music while you have it.

This implementation sat for a while. it used a stack based approach- the Sound manager had PushMusic and PopMusic methods.

However, several critical flaws in this approach became clear after I added an invulnerability powerup. Everything seemed to work fine, (get the powerup, you’re invulnerable and while you are there is different music) however, the problem became clear when I, while still invulnerable, released a boss. The boss music would start playing; however, while the boss was alive, the invincible power would run out; it would “PopMusic” which would revert the music from the boss music to the starman music, and then only when the boss died would it go back to normal. This is obviously not intended. The ideal case would be:

  1. Player starts level. Level Music is playing.
  2. Player gets invulnerability powerup; invincible powerup music plays.
  3. While invincible, the player, or something causes a boss to spawn.
  4. when the boss is spawned, the invulnerable music can continue until the power runs out; at which point it plays the boss music, or, the boss music can replace the invincible music. The former is probably overall a better idea.
  5. Either way: the music must fit. Invincible music should only play while the player has said powerup; and boss music should only play when there is a boss.

Obviously, my approach failed miserably; it worked fine, but I had only had a single “active” piece of music at a time; how do you manage multiples?

After some thought, I considered the idea of “reference counting” or keeping track of how many times a given piece of music was requested to play. a boss spawning would increment the boss music by one, a second one with the same music would make it two; each time this happens, the sound manager could re-evaluate which piece of music to play based on finding the maximum reference count.

With this idea, I rearchitected some of the code within the SoundManager. The SoundManager (technically cNewSoundManager, since it was a rewrite of a strongly coupled version I had before) is essentially a class that, well, manages sound and music. I have a interface class that allows for different actual implementations of the details of playing sound (“Driver” classes, of you will) The Manager class itself merely deals with the details based on that basic functionality, which exposes a few critical events, such as music stopping and whatnot. The original “PushMusic” and “PopMusic” stack based approach used a small data class, shown here:

A minor explanation may be necessary; iActiveSoundObject is an interface class that is implemented by the “driver”; same for iSoundSourceObject; the details of how they work isn’t important, just that their interface methods do what the interface definition says. A Active Sound object is something that is “active” usually, this means it is playing, but it could also be paused. A Sound Source object can be used to “spawn” Active Sound Objects; in order to actually play music or sound, a iActiveSoundSource object is required. Rather than discard this class I extended from it. Arguably, I could have simply changed the actual class itself but that could always be done later:

Again, another private class. The Implementation of IComparable is vestigial from when I was flailing around trying to shoehorn the old stack-based approach into the new reference counted method using a SortedDictionary. Then I realized it was stupid and just made the data structure a normal dictionary.

Dictionary<String,TemporaryMusicData> to be precise; This indexes the TemporaryMusicData instances by Name (Key); the Name/Key is used by the sound Manager to index Sound sources, so getting the appropriate source is easy given a name, and it’s guaranteed to be unique since the listing is taken from the file system itself, and the loading routine has other considerations to prevent duplicate entries (and error handling for duplicate key Exceptions if they do occur). The Occurences field is basically the entire purpose here; when “Temporary” music is told to play, it merely increments the field for the appropriate entry at the Named Index; then both the Stop and Play routines will call another routine that Ensures that the item with the maximum occurences is playing. The implementation for the relevant routines:

So far, this has worked well.

However, more recently I found that I also need the same sort of “reference count” management for other things related to powerups, such as the “DrawAttributes” of various objects. But it would be foolish to clutter up that code with this sort of thing. Surely there is some way that I can add the feature with little to no changes to existing code? Turns out, that leveraging a few C# features, this is relatively easily accomplished.

Consider the Nullable<T> class. Any struct or value type can be made “Nullable” using it; there is even a shortcut in the language syntax for type definitions to use it, by appending a question mark, (Nullable is equivalent to int?). What we want is a way to- generically- make a class “reference counted” so that only the value that has the highest reference count “is” the value. The Nullable<T> type can be implicitly cast to type T in most contexts; so you can change a T to a Nullable<T> type with few code changes, which is what we are after.

Enter ReferenceCounted<T>

ReferenceCounted<T> is the name of the class that I created (or, as I write this, am creating) for this purpose. My original idea was to use implicit cast operators to make it a simple type change; assignments to the object of the “old type” (type T) would “automatically” be added to the reference list; going the other way, the ReferenceCounted<T> Type would be implicitly cast to T by way of taking the T value it currently has with the highest reference Count. This hit a snag, however; the second cast, thankfully, would work fine, but the first would not have the proper information; the cast operator is a static routine and wouldn’t have access to the ReferenceCounted<T> Object that is being assigned.

somewhat miffed but not surprised (it would be silly to provide for overloading of the assignment operator, but in this case I wish there was an exception), I didn’t give up; I just thought about it a little. And it hit me- I don’t need to overload the assignment operator to overload assignment; I could overload the addition operator and implement the “assignment” code there; this is what the Event classes do for event hooking; and I could use -= to remove “references”. Arguably, this would take more code and wouldn’t be quite as clean as I was hoping, but for the most part the actual reference counting logic would be out of the way, handled mostly by the implicit cast to T.

After some effort… it was made. Here is the source code:

Aftermath

Pleased I had created a nice implementation, I set about creating the Comparison routine. Unfortunately, to my horror and surprise, the class which I wanted to use in conjunction with this class in one instance, ImageAttributes, had no way of getting it’s ColorMatrix. This presented an issue since I didn’t want added ColorMatrix values to mess about with the image, and the results could be less than extraordinary unless I cached each ImageAttributes.

And that was the entire purpose. However I decided to consider how else to acheive my goal; the goal here was to prevent powerups from changing the state of GameObject’s appearance in a manner that prevented them from undoing it. So, for example, powerups might have a limited duration, and the results from a overlap of two powerups could result in a confusing ending state for the object. The idea was to replace the GameObject class’s “DrawAttributes” field with a ReferenceCounted; then in it’s draw routine, it would assign use that in the appropriate method which would implicitly cast it to the maximum referenced item in the list. All I needed was a way to compare DrawAttributes aside from as references; but the ImageAttributes class, sadly, does not provide this functionality.

So how do I address this?

I considered possibilities, and the problem, a bit more thoughtfully. Evidently, the ReferenceCounted<T> class would be very useful for it, but what would I use it for.

I’ve decided- though not yet attempted to implement- that I would use the ReferenceCounted class to keep track of The powerups themselves rather than a few fields of the gameobject. Since the powerup classes are what would result in the unwanted behaviour, it makes sense. So how does it work? Well, the framework basically allows a GameCharacter to have a list of GameCharacterAbilities; the GameCharacter calls the draw function of each when it draws, and it calls a frame function when it’s own frame function is called. My idea is to change that to a ReferenceCounted<GameCharacterAbility>. The code could then be changed to only call PerformFrame and Draw for the one with the highest reference count, or something similar.

The other possibility is to change the GameObject’s DrawAttributes field to a read-only property that is created “on the fly” from another new ColorMatrix field; the ColorMatrix item could be a ReferenceCounted object and therefore the use of that object in the property would use the implicit conversion operator. I’m trying to avoid this, even though I cannot foresee a circumstance where the ImageAttributes class provides something that I can’t do with a ColorMatrix (oh it does, but nothing I know how to do) I prefer to keep all my roads open, so to speak. If there was a way to compare the innards of the ImageAttributes, I could just change the DrawAttributes field to a ReferenceCounted object and make a new comparer, but it’s unfortunately not that simple.

Posted By: BC_Programming
Last Edit: 12 Apr 2012 @ 07:52 PM

EmailPermalinkComments (0)
Tags

 Last 50 Posts
 Back
Change Theme...
  • Users » 45017
  • Posts/Pages » 369
  • Comments » 105
Change Theme...
  • VoidVoid « Default
  • LifeLife
  • EarthEarth
  • WindWind
  • WaterWater
  • FireFire
  • LightLight

PP



    No Child Pages.

Windows optimization tips



    No Child Pages.

Software Picks



    No Child Pages.