Nycterent: Outpost

A couple of months back I started a new project, and this time it’s not using XNA. I decided that the very limited audience for an XBLIG project would be so limited that my somewhat ambitious goals for quality, content and player experience were simply going to be wasted effort.

I decided to refocus my efforts on a much wider potential audience and a much more ambitious project. Enter: Nycterent: Outpost. It’s a space-based exploration and construction game. The word Nycterent roughly means “Night Hunter” which seems to fit the game given the eternal blackness of space.

More information can be found at the Nycterent project website http://www.nycterent.com


Tags:
Categories: General | Gaming

0 Comments
Actions: E-mail | Permalink | Comment RSSRSS comment feed

Where did these go…

Couple of months ago I posted some pics of the most “recent” state of the atmospheric work I’d implemented as of Jan 2010, but that blog post seems to have disappeared into the void.

So this is basically a repost..

atmo3atmo1atmo2

It’s using a modified variant of the popular atmospheric scattering shaders floating around the web, though still with bugs as is probably evident in the above pics. The terrain looks so flat because I turned off alot of the extras (normal maps, height variances etc) when working on getting the shaders right.

Also, the pics would look alot better if they used HDR, at the moment they’re just using a crude exposure function in the pixel shader.

I might revisit this sometime, maybe for Galactic Ranger, or the PC-only project I’m prototyping which uses a voxel-based planetary landscape. Who knows


Tags:
Categories:

0 Comments
Actions: E-mail | Permalink | Comment RSSRSS comment feed

Stick City – A game in a week

Recently I blogged that I undertook a challenge set by myself, to create a game in one week.

The result of that one week’s work was Stick City:

Since others are undertaking the XNA One Week Challenge as well, I thought I’d structure this post as more of an interview/post-mortem style post that others can re-use the format of if they like.

What is the name of your game and how did you choose it?
My game is called Stick City. It came about very quickly after deciding to use Stick Figure animation for the main character, and since he’s running across rooftops, Stick City was born.

Where did the game play concept come from?
I had been thinking about a 2d side-scrolling platformer on and off for the last couple of months whilst I work on Galactic Ranger. I had something quite involved in mind, but the core element was run and gun. When I decided to write a game in a week, I just took the primary element from those thoughts I’d been having and ran with it.

What is the primary game play element?
You move your character across rooftops of a city as quickly as possible. Buildings may have gaps in between them and be different heights. There are also obstacles such as varying height Smoke Stacks which you have to negotiate as well, either by jumping or by shooting and destroying them.

What did you plan to include but ended up excluding? Why?
I had originally planned to have Stick-man enemies on the rooftops shooting at the player, which was the primary reason for him having a gun. Around day 3 I decided to for-go enemies because of the cost of implementation in terms of AI as well as placement within the procedurally generated levels. I also planned to include more vertical movement (about two screens high) but scrapped it early on also because of the implementation cost.

What were the tricky technical parts that you ended up including?
The arm control for the main character in itself was easy, but integrating the arms with the animation sets for the body required that I keep a separate arm offset position for each animation state. When the character hits the ground after a big jump/fall and performs a roll, the arms are not drawn and the player cannot fire his gun.
Also, tweaking the physics to get a nice feel for a man running across rooftops parkour style took some time. If I had more time I would have added more animations for various scenarios to improve the experience.

What art content did you create and what did you use to do it?
I created the main character animations in a program called “Styx” which does frame-by-frame stick figure animation using a jointed figure. I exported as a set of transparent-background PNG’s and used a freeware tool to convert those PNG’s into a transparent-background sprite-sheet, ready for loading.
The building texture I created in Photoshop, just applying some basic shapes and adjusting colour to get a somewhat city building effect.
For the pigeon I traced the silhouette of a pigeon from a free photograph and then animated each frame manually in Photoshop.
The background was a photo of a storm cloud modified in Photoshop overlayed onto a city skyline silhouette.
The smoke-stack image and smoke were created in Photoshop.

What about the sounds?
Sound is tricky for me, I have no experience creating audio content and as such I always find it challenging to find/create good sounding effects and music.
The character vocal effects (jumping, puffing when running, landing hard etc) were done by me, recorded using Audacity and just exported into XACT.
The city ambience background track to the levels was sourced from a site that I have royalty-free downloads from. Same for the bird effects, footsteps and gunshot.

Did you use any ready-made code?
I based it on the engine I’ve created for Galactic Ranger, my main project. Though heavily modified this version to be geared toward 2D instead of 3D. This provided game state management, contextual content loading, input handling etc.
I also ended up using the Particle2D sample, modified, for the smoke stacks.

How were your 7 days structured?
Basically went like this:

Day 1: ~7 hours. Setup project, modified a copy of my Galactic Ranger engine, made draft title screen and menus. Generated some stick figure animation for primary character, created crap building texture in Photoshop. Setup a layer2D object to handle the parallax layers in the background. Created a basic “GenerateLevel” method which would generate randomly positioned “buildings” in a level. Made the position of the character change based on controller input.

Day 2: ~5 hours. Started to implement character physics (gravity) as well as crap collision detection system. Extended “GenerateLevel” procedure to be more configurable in terms of building placement. Added “clutter” elements (pigeons) to the levels for some atmosphere. Also added gun and arms to character, added bullet management.

Day 3: No Work performed

Day 4: ~3 hours. Finalised collision detection and response. Added basis of block-based obstacles. Made pigeons react to player proximity and fly away. Also made pigeons react to being shot (SQUAWK).

Day 5: No work performed

Day 6: ~3 hours: Changed up art style for the title and load screens to be in-line with what evolved from the game play art direction. Made all visible pigeons flee when they heard a gunshot which can be problematic if they get between you and your target when you’re moving fast..

Day 7: ~6 hours: Finalised “GenerateLevels”, setup level generation system into 5 difficulty using procedural method configuration. Decided 50 levels was enough, 4 second code change could make well beyond 1 million levels over 5 difficulty levels possible. Decided that obstacle stacks were in fact smoke stacks and added particle systems to each one. Created Box art, logo, FRAPS’d game play video and uploaded to YouTube. And finally, put into playtest.

What next?
At the moment Stick City is in playtest to get peoples feedback on how I actually did with creating a game in a week. It will most likely go through some polishing iterations to get ready for review, maybe add a new mechanic to make it more fun, and release on XBLIG.

Would you ever undertake the XNA One Week Challenge again?
Probably. Using the experience from this game means I’ll know what to expect next time and use my time better. Of course, It will be a difference genre next time.


Tags:
Categories:

12 Comments
Actions: E-mail | Permalink | Comment RSSRSS comment feed

XNA One Week Challenge

CAUTION: The start of this blog post is a bit ranty. Feel free to jump down to the good stuff if you’re offended by people stating their opinion on other people’s work.

image

Take some time and really digest the image above.

Really ingest it.

This is what someone thinks constitutes a game. By any developer worth anything, the above screenshot could be developed in XNA in about 5 minutes. Apparently some people think that a day or even a week is too much time to spend on a game and appear to be delusional enough to expect people to pay good money for their game.

When viewing this game when it had been put into review on Sunday 26th September, after I got mad and failed it for using a prohibited word (“Leaderboard”), I started to wonder how long he’d actually spent on making it..

[Ending Rant]

Enter the XNA ONE DAY CHALLENGE

Yes, one DAY. I started my game on pure impulse intending to show what could be created in a day. But as it turns out, even I have standards and even though I could move my character and blow stuff up, there’s no way I was going to call it a game worth of mentioning to anyone.

Enter the XNA ONE WEEK CHALLENGE

So I decided to change it to a week instead. It’s a short enough time span that the desired effect of showing what could be accomplished in a short enough amount of time was still possible. So on that, here are my original goals for the challenge I set myself:

  1. It must not be a genre that I’m working on for my main project (A 3D space shooter), so as gameplay elements must be created from scratch.
  2. It must be of sufficient quality that it can pass review without issue. That basically means basically not adding potential fail-prone code (online high scores, network play etc).
  3. Do not re-use art assets from my other projects. Avoid purchasing assets where possible, but if unavoidable, maximum budget for entire game is AUD$50.
  4. Must demonstrate gameplay which is fun and which is not a direct clone of another game.
  5. Re-using utility code or engines from my other projects was allowable.

The intention with these goals was basically to force the creation of code, rather than repurposing of existing code and to force me to keep scope small enough that I could complete a new codebase within a week.

I addressed the above goals with my project like so:

  1. I chose to make a 2D side-scrolling twin-stick platformer.
  2. Keeping the concept simple (traverse a level as quick as possible, destroying objects in your way) kept scope small and as such, gives me more time to get stuff right.
  3. I decided to base my game around a character made from a Stick Figure to keep art assets simple and also meant that I could create them myself.
  4. I like the idea of moving through a level as quick as possible whilst having to navigate or destroy obstacles. I added some more natural/parkour style movement to the main character so that it feels “right” as he runs and jumps around. Also the ability to shoot obstacles changes the game from basic obstacle avoidance to a “run and gun” style.
  5. I re-used the engine base from my main game, Galactic Ranger, but since it’s 3D I tore it to shreds and changed to be oriented more for 2D. No graphics or gameplay elements survived this process. 

My Challenge Game

Name: Stick City
Started: Sunday 26th September 3pm AEST
Due: Sunday 3rd October 3pm AEST

Genre: Side-scrolling twin-stick platformer
Premise:
You’re a guy traversing the roofs of your city, trying to get home in time to watch your favourite TV show, Sticks and the City.
Gameplay:
You navigate across the rooftops of buildings, jumping spans and avoiding obstacles. If in doubt, use your trusty hand-cannon to clear the path!
Art style:
Basic 2D graphics using Photoshop. Main character animated in “Styx”.
Sound: Voiceovers by yours truly. Music from a library that I had previously purchased.

I’m currently on day 3/7 and the only thing I’m willing to show at this point is the 10 minute title screen:

PressStart

Shortly after posting a comment on twitter about it, fellow XNA developer @DustinTigner picked up on the idea and started planning his own XNA One Week Challenge. You can read about Dustin’s progress over here

If you decide that you’d like to see what you can accomplish in a week and show those lazy cash-grabbing massage-app-using zombie-loving honourless XNA developers what some effort in a short amount of time can produce, feel free to let me know and I’ll keep a registry of XNA One Week Challenge games and they’re progress and sale results.

Also feel free to use #xnaoneweekchallenge on twitter so fellow one-weeker’s can see what you’re up to.


Tags:
Categories:

1 Comments
Actions: E-mail | Permalink | Comment RSSRSS comment feed

Garbage safe number to string conversion

Typically when optimising XNA XBOX 360 games garbage collection usually comes to the top of the pile. I posted earlier about how to use CLR Profiler to locate code which is generating garbage, and this post will demonstrate one method that I use to eliminate garbage generation on a frame-by-frame basis.

First off, when using ToString() to get a string representation of a number (float, int etc) it generates garbage. Usually when you are converting numbers to strings you are then passing that string to some mechanism which will show it on the screen. This could be a score, ammo remaining, players level etc.

One method to avoid this is to store a string instance alongside your number, and only when the number changes, you ToString() it into the string. This works great for slow-moving numbers such as player level, but not great for score or ammo since it’s very likely that it will change almost every frame anyway.

The method I prefer is to store a lookup table of a certain range of numbers, and use the provided number to fetch the appropriate string from the array when required. This has a downside, which is up-front memory allocation (couple of meg for 200,000 numbers) and you’re limited by the size of the table you allocate initially. However the upside is that you don’t need to clutter your classes with a string instance for each number you want to show and you also have no penalty if you show a constantly changing number every frame.

Since I’ve wrapped it up in a nice little extension method called ToStringSafe() I’ll just post a shortened version of the static Extension class:

    public static class Extensions
    {
        private static string[] _numbers = new string[60000];

        static Extensions()
        {
            for (int i = 0; i < _numbers.Length; i++)
            {
                _numbers[i] = i.ToString();
            }
        }

        private const string Negative = "-";
        private const string NaN = "NaN";
        private const string Inf = "Inf";
        private const string K = "K";
        public static string ToStringSafe(this float value)
        {
            if (float.IsNaN(value)) return NaN;

            if (value > _numbers.Length - 1)
            {
                return string.Concat(_numbers[(int)( value / 1000 )], K);
            }

            return value >= 0 
                ? value > _numbers.Length - 1 
                    ? Inf 
                    : _numbers[(int)value] 
                : string.Concat(Negative, _numbers[(int)value * -1]);
        }

        public static string ToStringSafe(this int value)
        {
            return value > _numbers.Length - 1 
                ? string.Concat(_numbers[value / 1000], K) 
                : _numbers[value];
        }

        public static string ToStringSafe(this long value)
        {
            return value > _numbers.Length - 1 
                ? string.Concat(_numbers[value / 1000], K) 
                : _numbers[value];
        }
    }
 

And also a sample usage:

_spriteBatch.DrawString(_font, (GC.GetTotalMemory(false) / 1024).ToStringSafe(), new Vector2(0,20f), Color.White);

Which generates zero garbage every frame. It’s a very crude method but very effective!

The only case that will generate a small amount of garbage is when ToStringSafe()’ing negative numbers, as the ‘-‘ character is concatenated.

Also, you might notice my ToStringSafe methods are aware of the lookup table boundary and return a default value for those cases. The overload for float is a bit of a special case, which is why there’s a bit more to it. First of all, it doesn’t show the fractional component but that has never been an issue for displaying floats to the user, since generally the user doesn’t care about 4.53234 for my scenarios.

I’m sure if you really wanted to support the fractional components I’m sure there’s a way of isolating that part of the number and ToStringSafe()’ing that in itself. Maybe :)

 


Tags: , , , ,
Categories: Samples | XNA

2 Comments
Actions: E-mail | Permalink | Comment RSSRSS comment feed

September Progress Video

Just a small update with a video to show the recent progress on Galactic Ranger. The video mainly shows space combat including music and sound effects. All the sound you can hear in the video is in-game, nothing was added after it was recorded. There is also some static objects (asteroids, space station) which use the same rendering method as the ships (diffuse/specular/normal/glow mapped). The asteroids use a single sphere for their collision volume and the space station uses multiple Object Oriented Bounding Boxes (OOBB’s) so that the player can actually fly through hollow parts of the station.

So here’s the video, more soon!


Tags: , , ,
Categories: Gaming | XNA | General

19 Comments
Actions: E-mail | Permalink | Comment RSSRSS comment feed

August Gameplay Update

It’s been just over a month since my last game play update, so I figured it’s time to do another one. No video this time however, just a few screenshots.

First off, the change list over the last month:

  • Replaced ship rendering technique. Now renders ships with Diffuse/Normal/Glow/Specular maps and they look great in-game. Nick Gravelyn’s ShaderToy was fantastic for letting me quickly write and debug the shader without having to kick into my game each time I change my shader.
  • Designed the mission/level structure. Each story mission will be accompanied by one challenge mission and one Survival mission (to be confirmed/renamed later). A second challenge mission is unlocked when the first is completed. Each story mission and it’s sibling challenge/survival missions are unlocked when the previous story mission is completed.
  • Designed a 3-tree upgrade system. Players will be able to distribute points accumulated on levelling-up into 3 areas of ship improvement. The player will need to decide how they distribute those points, they will not be able to upgrade to all items. Final items in the trees shown in the screenshot below have not been finalised. The trees are:
    • ‘Destruction’ – Improve the damage-dealing capabilities of your ship by increasing weapon capacity, fire rate and increasing damage. Also unlocks higher-end weapons.
    • ‘Mitigation’ – Survival by mitigating a lot of damage through hull strength and regeneration, also reduces chances that enemy EMP missiles will have an effect.
    • ‘Evasion’ – Survivability through the evading of enemies all together. Gives scanner jamming, missile decoys, better flares, faster ship etc.
  • Added ability for player to be awarded experience points for kills which vary per level.
  • Added ability for player to ‘level up’. Each level has a different experience point requirement
  • Added Pilots. Basically a character of sorts that you progress with. All experience, levels, awardments and statistics are added to the Pilot you selected to play with. This allows you to continue to work on a specific pilot and have a separate pilot for your friends/family if they wanted to play.
  • Added Awardments (achievements) attainable by individual pilots. There are currently about 36 awardments in the game, of which some are:
    • Missile Command’ – Kill 100 enemies with missiles
    • Frankly Flanking Failed’ – Kill an enemy while flying backward
    • Skills Like OJ’ - Be the target of 10 or more enemies at the same time and survive for 20 seconds
  • Worked on enemy AI a little bit, improved their handling of the scenario where they are about to fly straight into their target.
  • Created a template level for my survival mode, which contains 15 waves of various numbers of enemies.
  • Added EasyStorage 2.0 to handle save device selection for saving Pilots.
  • Started to add a few things which are aware of if the game is running in trial mode (such as level selection)
  • Purchased assets for the small fighter ships, which are shown in the screenshots below.
  • Worked on pieces of the interface such as level select, pilot create/edit/selection.
  • Implemented dual 1080p / 720p paths. UI elements are designed for 1080p and automatically rescaled if 720p is used (if the display is not capable or if the Xbox is not set to 1080p / 1080i)

And now some screens..

shiptypesmovement movement2 ship1 ship2 ship3 20100807_015859 20100806_144139 upgradetree 

To wrap up, You can find me via:

Twitter: twitter.com/jasedeacon
Youtube: youtube.com/user/vereoraus
IndieFreaks: indiefreaks.com/community/jasedeacon/profile

Next update will focus on the various level types and probably some effect improvements as well. Plus video!


Tags: ,
Categories: XNA | Gaming

72 Comments
Actions: E-mail | Permalink | Comment RSSRSS comment feed

Gameplay system updates

Over the past fortnight I’ve been working on various gameplay systems in order to progress to making the first level.

Some of these are:

- FTL system working for all ships. FTL must first be charged to full, then can be used to make a jump. FTL charge is reset to zero on jump completion. Currently AI ships FTL to a specific location if they are following waypoints and they are tracking a “JumpTo” waypoint type. The player’s ship currently just jumps 25km forward. Targetting to come at a later stage when I add all the targetting subsystems.
- Naïve missile tracking. Missiles take a very basic approach to tracking which can often lead to "orbiting" moving targets instead of hitting them. Basically, they determine where the target is going to be in X seconds in the future based on the target’s current velocity, where X is the time in seconds that it will take the missile to reach the target at it’s current location. It’s not great, and it needs work.
- Basic sound testing. Just guns, FTL jump and missile sounds at the moment. Gun sound needs to be more friendly for faster firing guns, it isn't at the moment. Missile sound is too "hissy". But they serve as decent indicators anyway.
- I’ve also started experimenting with Voice Acting, since the Single player campaign will feature quite alot of it. I’m hoping to get volunteers down the track for certain roles of yet-to-be-created characters, but for now it’s just me.
- Basic smooth menu interface. Uses GSM but heavily modified to provide a bit better experience in my opinion.
- Added a waypoint system. This is different to the objective system because Objectives are goals for the player, whereas waypoint sequences are for AI units to follow. There are currently 3 types of waypoints, Move (ignores all units and just moves to the waypoint), JumpTo (same as Move, except the ship Charges FTL and jumps there) and AttackTo ( moves to the waypoint but engages any valid targets on the way). Will be the basis of scripted events for all AI ships, friendly and enemy.
- Flexible UI messaging system. Text can be added to one of 4 predefined regions of the screen (easily changed) and behave a certain way. The left, top and right seconds all float the text up and then fade it out. The bottom text area just shows it and then hides it after a short duration.
- The actual enemy spawning is done by triggering a Sequence stored in the level XML file. The SequenceElement is “SpawnEnemy” and it automatically knows that it should appear as the ship is FTL jumping in. Positions are defined with a relative scope which can be Player, World or Node.
- Also added very basic impact effects for bullets and missiles. Same effect used for ships being killed.
- Uses broad-phase sphere/sphere collision tests then narrow-phase OOBB/OOBB and OOBB/Ray testing. Collision point tests aren’t being calculated correctly for OOBB/Ray collisions which is why the bullet impacts appear to be penetrating ship hulls when they aren’t.
- Motion Star field is working but gets messed up a bit when the player jumps.

As it stands I’m probably about 2 weeks away from getting a playable first level. There’s alot of interface work to get done, mainly around targetting and direction finding.

I’ve uploaded a video showing some of these elements.. embedded below. Make sure you watch it in 720p or you might not see some of the smaller ships flying around :) Direct Link Here


Tags: , , ,
Categories: XNA | Gaming

16 Comments
Actions: E-mail | Permalink | Comment RSSRSS comment feed

How to eliminate frame-by-frame Garbage Generation using CLR Profiler

When working with XNA on the XBOX 360, managing your Garbage generation and collections is extremely important for performance. I’ve already blogged on some code-level optimisations which help with reducing garbage generated, but I’m going to show how to identify and fix using the fantastically free CLR Profiler.

The way I see it, there are 4 steps.

1. Verify            2. Profile            3. Locate            4. Fix

1. Verify
First off, you need to verify that you are generating garbage each frame. You can do this easily by displaying the value of the GC’s total memory using something like SpriteBatch.Draw(). To get the total memory allocated, use:

GC.GetTotalMemory(false) / 1024

This will return the number of Kilobytes of allocated memory. So if you have 11 megabytes allocated it will return a value of 11264.

Now when you run your XNA app, this number will increase (either fast or slow, or not at all) and then jump back down a couple of megabytes (if on windows). When it does that jump, a Garbage Collection just occurred. If GC memory is increasing very slowly (4-10 bytes/second) then that’s a fairly good place to be. Ideally you don’t want that number to change after your level has started. In some cases, especially on new, un-optimised projects, the number may tick over so fast you can’t even read it.

2. Profile
Now, go and get CLR Profiler, free, from Microsoft and extract it somewhere locally. I usually run the 32-bit version of CLR Profiler even though I’m running on 64-bit windows. I figure the XNA process is 32-bit, so it makes sense. I’ve never had any issues in the past, but your mileage may vary. If you have problems, try running the 64-bit version or as administrator if you’re using Vista or Windows 7.

image

Once you start it, select your XNA application executable and it will launch your app. Depending on how fast your allocations are occurring you may only need to play for a couple of seconds or a couple of minutes. Generally I like to profile around 3-4 collections before exiting.

When you exit, CLR Profiler will analyse the data collected from your app and then display a summary window.

image

From there, the first thing I look at is the Time Line. This will show me my allocations over time and GC’s will appear as spikes made up of the types that were allocated.

image

You can safely ignore the initial section of the graph, as allocations are expected when you load resources (textures, models, allocate initial strings etc) and GC’s during this period are not really an issue. You will need to identify the point in time of the section you want to profile, typically this will be the section that you added the GC.GetTotalMemory() to show up. In the above graph, it starts at approximately 13 seconds into the run.

You can use the Radio buttons at the top of the window to get more detail. Usually 20 or even 10 on both groups is a decent detail level. Use the scrollbars to slide right and down a bit to view one of the spikes at the top of the graph. In the below example, because I had so many collections the spikes were very narrow at horizontal setting 20, so I went down to 5 to make them wider and see more detail.

image

Now select and drag a section in which you can clearly see a 'step' or 'jump' up in the spike. This ‘step’ up represents a new object allocated. In the above picture I’ve selected a section between 15.183 seconds and 15.225 seconds, represented by the vertical bars.

On the right hand side, you will see a list of types and allocated sizes. When you select a small section of the graph (the 'step up' bit) it will only show allocations that occur within that selection. So in the above graph we can clearly see that over 42 milliseconds 94208 bytes of System.Single[] was allocated. That’s 2.1MB of garbage per SECOND, which is why there are so many collections occurring in my sample.

So, lets find out where it’s being allocated, and fix it.

3. Locate

Right click on the highest allocated type line on the right, and choose “Show who allocated”. In the above picture, it’s the System.Single[] line. You should see something similar to:

image

Scroll all the way to the right and you’ll see your hotly allocated type:

image

Start to follow the chain to the immediate left and you’ll see the method hierarchy that ends up allocating that type. In the case above, it’s OrientedBoundingBox.Intersects. Armed with the method, and the type (System.Single[] aka float[]) we can take a quick look at the method and..

        public bool Intersects(OrientedBoundingBox oobb1, Matrix oobb1Matrix, Oriented…
        {
seperating
= Vector3.Zero;

worldAMin
= Vector3.Transform(oobb1.Min, oobb1Matrix);
worldAMax
= Vector3.Transform(oobb1.Max, oobb1Matrix);

worldBMin
= Vector3.Transform(oobb2.Min, oobb2Matrix);
worldBMax
= Vector3.Transform(oobb2.Max, oobb2Matrix);

centerA
= (worldAMax + worldAMin) * 0.5f;
centerB
= (worldBMax + worldBMin) * 0.5f;

halfExtentA
= (worldAMax - worldAMin) * 0.5f; //centerA - oobb1.Min
halfExtentB = (worldBMax - worldBMin) * 0.5f;

float[] overlappingExtents = new float[15];

Vector3 centerAtoB = centerB - centerA;

It’s quickly evident that declaring a new array of 15 floats each time this method is called is the culprit, especially since this method is called potentially thousands of times per frame depending on how many active objects there are.

4. Fix

In this case it’s quite easily fixed, simply by moving the overlappingExtents declaration from within the method body to outside (so it’s a private field on the OrientedBoundingBox class) means it’s only ever allocated once when the class is created.

We can tell from logic further down in the method that all 15 values are replaced before the values are used, so we don’t have any issue with data hanging around between calls to Intersects. Running another profiling session after moving that one line of code results in a much happier graph:

image

This scenario was one that I identified and fixed during a long GC optimisation session which resulted in the current version of my game only allocating around 3-5 bytes per second which made my  Xbox very happy. There were a lot of results from that big GC optimisation session, one of which was my previously blogged ResourcePool class.

However, there are more involved scenarios relating to string usage especially that need more creative approaches to fixing, but hopefully this has explained enough to help you find where your collections are occurring and some steps to resolve them.


Tags: , ,
Categories: General | XNA

98 Comments
Actions: E-mail | Permalink | Comment RSSRSS comment feed

Generic Resource Pool

I've decided to release a number of isolated components of the game I'm working on to anyone who can benifit from them. They will be small components with a specific, targetted purpose.

The first component is a generic ResourcePool for maintaining pools of reusable object instances. This is very useful for things like bullets or enemies which are created, perform some function for some amount of time, and then die.

To use, setup your resource to implement IPooledResource like so:

    /// <summary>
    /// Sample enemy resource implementation. This could contain
    /// update and drawing methods as well as any extra data/logic.
    /// </summary>
    public class SampleEnemy : IPooledResource
    {
        /// <summary>
        /// Position of our enemy
        /// </summary>
        public Vector3 Position;

        /// <summary>
        /// The change in the enemies position over time
        /// </summary>
        public Vector3 Velocity;

        /// <summary>
        /// Our enemy texture
        /// </summary>
        public Texture2D EnemyTexture;

        #region IPooledResource Implementation
        
        /// <summary>
        /// PoolId of this resource.
        /// </summary>
        public int PoolId
        {
            get;
            set;
        }

        /// <summary>
        /// Initialise the very first time.
        /// You would do things like load resources for the very first time here.
        /// </summary>
        public void Initialise()
        {
            EnemyTexture = Engine.ContentManager.Load<Texture2D>("Content/Textures/Enemy");
        }

        /// <summary>
        /// Called each time this resource is allocated
        /// </summary>
        public void Reset()
        {
            Position = Vector3.Zero;
            Velocity = Vector3.Zero;
        }

        /// <summary>
        /// Called to unload any XNA resources loaded
        /// </summary>
        public void Unload()
        {
            EnemyTexture.Dispose();
        } 

        #endregion
    }

Then you can setup a pool class:

   /// <summary>
    /// <![CDATA[
    ///     The idea behind this class is that it contains the pool and manages
    ///     updates to our active SampleEnemies. An alternative approach would be to 
    ///     inherit ResourcePool<SampleEnemy> directly
    /// ]]>
    /// </summary>
    public class SampleEnemyPool
    {
        public ResourcePool<SampleEnemy> Pool;

        /// <summary>
        /// Default constructor
        /// </summary>
        public SampleEnemyPool()
        {
            // Initialise our pool of 1500 enemies.
            Pool = new ResourcePool<SampleEnemy>(1500);
        }

        /// <summary>
        /// Would be called every update to process enemy movements etc.
        /// </summary>
        public void UpdateEnemies()
        {
            // Walk backward through our ActivePool list because Enemies may be reclaimed
            // during this loop, therefore shortening the ActivePool list.
            // If no resources could be reclaimed inside this loop, we could walk forward
            // instead.
            for (int enemyIndex = Pool.ActivePool.Count; enemyIndex >= 0 ; enemyIndex--)
            {
                // Get the index of the enemy within the resource pool
                int poolIndex = Pool.ActivePool[enemyIndex];

                // Get the resource from the pool
                SampleEnemy enemy = Pool.Pool[poolIndex];

                // Update the resource however we like
                enemy.Position += enemy.Velocity;

                // Arbitrary condition to "kill" an enemy. Can be anything.
                if (enemy.Position.X > 800f)
                {
                    // The pool reclaims this resource, removing it from the active list.
                    Pool.Reclaim(enemy);
                }
            }
        }

        /// <summary>
        /// Can be called by anything to create a new enemy.
        /// This does not have to be here, as Pool.AllocateNew can be called from anywhere
        /// </summary>
        /// <param name="position">Position of the new enemy</param>
        /// <param name="velocity">Veclocity of the new enemy</param>
        /// <returns></returns>
        public SampleEnemy SpawnEnemy(Vector3 position, Vector3 velocity)
        {
            // Get our new resource
            SampleEnemy enemy = Pool.AllocateNew();

            // assign some basic parameters
            enemy.Position = position;
            enemy.Velocity = velocity;

            // Return the instance to our caller.
            return enemy;
        }
    }

And then you can just call SpawnEnemy or integrate with the pool class however you like. It provides enough to be useful but doesn’t pigenhole you into a specific implementation method except for implementing IPooledResource.

Feel free to use however you like. If you modify it, don’t redistribute it saying you got it from me. You can credit me if you use it in your project if you wish, but not required :)

You can download direct via SkyDrive here:

 


Tags: ,
Categories: XNA

33 Comments
Actions: E-mail | Permalink | Comment RSSRSS comment feed