Showing posts with label Technical Logs. Show all posts
Showing posts with label Technical Logs. Show all posts

Monday, November 03, 2008

XNA & EXTENSION METHODS 2

Continuing with the topic of how to use the handy functionality provided by "Extension Methods" with our XNA-based creations, for this article we are going to need the "FuelCell" tutorial (remember that you shall find this tuto -along with the "TopDownShooter" one- in the help file under the "What's New In This Release" section).

Ok. In the chapter called "Finishing Touches" of the FuelCell' s tutorial, you'll find the following method at the very end of the "FuelCellGame.cs" file:

private Rectangle GetTitleSafeArea(Viewport viewport)
{
Rectangle retval = new Rectangle(viewport.X, viewport.Y, viewport.Width, viewport.Height);

#if XBOX
retval = viewport.TitleSafeArea;
#endif

return retval;
}

If you remember my last article on the subject, you'll be anticipating by now that the Viewport struct could be "extended" so as to retrieve its "unsafe" area with one method call.

If so, you guessed it right! We can use Extension Methods to declare an operation called, say "GetFullArea", and give it the proper implementation.

Not only can we pass again a parameter by reference (using the "out" reserved word) -like we did in Part 1 of this series- but also in this particular case, since we're dealing with a struct, we can afford to implement an overloaded method that locally declares, creates and returns an instance of a Rectangle (I know what you're thinking, but unfortunately, there are no "Extension Properties" in C#, so we need to get the rectangle from a method call).

Using Extension Methods, our solution should look like the following:

using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace MyNamespace.Math
{
public static class MathExtensions
{
public static void GetFullArea(this Viewport viewport, out Rectangle area)
{
area = new Rectangle(viewport.X, viewport.Y, viewport.Width, viewport.Height);
}

public static Rectangle GetFullArea(this Viewport viewport)
{
return new Rectangle(viewport.X, viewport.Y, viewport.Width, viewport.Height);
}
}
}


Now, the GetTitleSafeArea(...) method could be re-implemented like this:

private Rectangle GetTitleSafeArea(Viewport viewport)
{
Rectangle retval;

#if
XBOX
retval = viewport.TitleSafeArea;
#else
viewport.GetFullArea(out retval);
#endif

return retval;
}

Or also like this:

private Rectangle GetTitleSafeArea(Viewport viewport)
{
#if XBOX
return viewport.TitleSafeArea;
#else
return viewport.GetFullArea();
#endif
}


Remember two important things:

  • You'll have to add the proper "Using" statement in the file that will use the extension method (in my example: "MyNamespace.Math"), and
  • You'll have to manually add a reference to the "System.Core" assembly in your project.

This technique can be used to get, say -among other things, a Vector2 containing the width and height of the Viewport (as well as for the display and the client area). I leave it as an exercise for you to try (you'll see it's actually quite easy to implement).

I hope you find this article useful.

'till next time,
~Pete

XNA & EXTENSION METHODS 1

With the release of XNA GS 3, two new tutorials were included into the "What's New In This Release" section in the help file: "TopDownShooter" and "FuelCell" games. For what follows, we'll be referring to the first tutorial game: TopDownShooter.

Sometimes we need to get an instance of a sound effect without playing it. The good news is that it can be done. The bad news is that there's no built-in method provided yet to get that instance in one step.

So, what's next then? Open the AudioManager.cs file provided in the TopDownShooter example. You should find the following code on the LoadContent() method:

// We call Play silently to retrieve a specific instance we can
// use for subsequent Pause and Play calls
SeekerInstance = Seeker.Play(0, 0.75f, 0, true);
SeekerInstance.Stop();
SeekerInstance.Volume = FXVolume; // set the real volume

As you can see, the above-mentioned code gives an idea of what you should use to get the instance of a sound effect "without playing it".

But, what if we want to get that functionality in one method (as if it were provided built-in) without extending the SoundEffect class? Well, in that case since we are targeting the .NET Framework 3.5 we can use the magic of "Extension Methods".

I'm not going to explain what Extension Methods are (to get a first read on the subject, please refer to this page), but how we can take advantage of them for this particular case.

Our goal is to extend the SoundEffect class in a way that:

  1. We do not create a specification of that class,
  2. We get a new SoundEffectInstance without playing it,
  3. We do not generate unnecessary garbage when getting a new instance, and
  4. Our method runs efficiently in the .NET Compact Framework.

Thus, our solution should be the following:

  1. We'll use Extension Methods technique,
  2. We'll mimic the code of the "TopDownShooter" tutorial,
  3. We cannot declare a local reference of type SoundEffectInstance within our method, and
  4. We should pass a parameter by reference of type SoundEffectInstance that can be null.

Therefore, our final implementation should be something like this:

using System;
using Microsoft.Xna.Framework.Audio;

namespace MyNamespace.Audio
{
public static class AudioExtensions
{
private static float VolumeLevelByDefault = .5f;

public static void GetCue(this SoundEffect soundEffect, out SoundEffectInstance soundEffectInstance)
{
GetCue(soundEffect, out soundEffectInstance, VolumeLevelByDefault, 0f, 0f, false);
}

public static void GetCue(this SoundEffect soundEffect, out SoundEffectInstance soundEffectInstance, float volume, bool loop)
{
GetCue(soundEffect, out soundEffectInstance, volume, 0f, 0f, loop);
}

public static void GetCue(this SoundEffect soundEffect, out SoundEffectInstance soundEffectInstance, float volume, float pitch, float pan, bool loop)

{
// Play the sound silently and stop it immediately.
soundEffectInstance = soundEffect.Play(0f, pitch, pan, loop);
soundEffectInstance.Stop();

// Set the passed volume level.
soundEffectInstance.Volume = volume;
}
}
}

As you can see, I'm naming the static method "GetCue" but you can call it, say, "GetInstance" if you prefer. Also, since we cannot yet use optional parameters -we'll have to wait for C# 4.0 for that- you will have to create as many overloaded methods as you need.

Now, in the LoadContent() method of the AudioManager.cs file, all we should use instead is:

// Get the new instance of the seeker sound effect.
Seeker.GetCue(out SeekerInstance, FXVolume, 0.75f, 0, true);

Don't forget to add the proper "Using" statement on the AudioManager.cs, linking to the namespace where the extension method was declared and implemented (in my example "MyNamespace.Audio"), or your code won't compile.

Also, you will need to manually add a reference in your project to the "System.Core" assembly -in case it is not already referenced.


Well, this is it. Now you know how to extend the SoundEffect class to get a new instance of a sound effect in just one method call, virtually speaking ;)

One final note: by using "Extension Methods" we are not breaking any design principles, since we have no direct access to private members of the "extended" type (being the latter, in this example, the SoundEffect class).

Enjoy!
~Pete


Wednesday, October 15, 2008

CONTENT MANAGERS 101

If you have been using XNA GS for some time now, then you will know by heart the benefits of the content pipeline. If not, just to mention a few, here is a brief list for you to check before reading on this post:

  • Improves the process of importing assets to your own XNA games,
  • Faster loading times for pre-built assets (in binary format), and
  • Easy to extend for importing custom content to our XNA-based creations.

Ok, let us go on, now.

I. THE BASICS

On the process of creating your game, having built all your assets at compile time with GS you will have to use a Content Manager to load them at runtime. Fortunately, as you all may know by now, XNA already provides one for you. What is more, the game project template defines a reference and creates and instance of it on the game class.

This CM will take care of both, the loading and unloading process of pre-built assets. This means that behind the scenes, not only will it handle the instantiation of the assets being loaded but also, when properly requested, it will dispose for you the ones that can be disposed.

For loading, you will have to use a sentence like "this.Content.Load<...>(...);" or "this.Game.Content.Load<...>(...);" and the usual place to put them is inside the overriden LoadContent method of your game class and or drawable game components.

And for unloading, all you have to do is call your CM's Unload() method. Again, being a usual place to include this sentence inside the overriden UnloadContent method of your game class and or drawable game component.

II. BEHIND THE SCENES

Now, If you have been reading carefully you will notice that you can load assets individually but there is no way to unload them individually. At first you may think that this is an unpleasant restriction, but as you may conclude after reading this post -or at least, as I expect you will, this is not. In fact, it helps you manage your assets on a very tidy manner.

Generally, for the sake of performance, efficient memory allocation and best user experience, you design your game so that all the needed assets are loaded at "one time", say, at the begining of each level. So, even if you load the assets individually, that behavior from the perspective of "one-shared time bucket" -to call it some way- shows that you programmed the logic of your game to treat all these loaded assets as a cluster.

The above-mentioned rationale can be then extended to the process of unloading assets. There is no need to assume a priori that each asset will be unloaded individually at different times during gameplay. And therefore, they will be treated as a cluster, in this case during the respective level, and unloaded altogether, again, in "one-shared time bucket", when requested.

You may wonder: "Ok, but what if I want to dispose certain assets during runtime and, at the same time, to keep others in memory?". The answer to that is quite simple actually: just create more than one content manager.

We will get back to this topic in a moment, but first let us consider another important aspect of the Content Manager.

III. THINGS NOT TO DO

Avoid to manually dispose your assets!!! The CM does not like that you handle the destruction of assets by using sentences like "this.myAsset.Dispose();". In fact, the CM does NOT monitor if you do, and thus, it could and will get confused when that happens.

Let us see an example. Say you have a Screen1 and Screen2 classes and:

  1. Both share the game's CM,
  2. Both load the same pre-built texture on their respective local Texture2D fields,
  3. Screen1 is created and shown first, and
  4. Screen2 is only created and shown after Screen1 is manually disposed.

If Screen1 manually disposes the texture (either using the Dispose Pattern or by calling Dispose within the UnloadContent method) without calling "this.Game.Content.Unload();" first, when Screen2 tries to draw the texture on screen you will get an exception stating that the texture has being disposed, even if Screen2 loaded that texture. As I told you before, the CM gets confused with situations like this.


Therefore, avoid these implementations:


protected override void
Dispose(bool disposing)
{
if (disposing)
{
if (this._myTexture != null)
{
this._myTexture.Dispose();
this._myTexture = null;
}
}

base.Dispose(disposing);
}


... and ...


protected override void
UnloadContent()
{
if (this._myTexture != null)
{
this._myTexture.Dispose();
this._myTexture = null;
}

base.UnloadContent();
}


Being the proper way to unload assets:


protected override void
UnloadContent()
{
this.Game.Content.Unload(); // Or the CM you use.

base.UnloadContent();
}


Please notice that this is also allowed by the CM:


protected override void
Dispose(bool disposing)
{
base.Dispose(disposing);

if (disposing)
{
if (this._myTexture != null)
{
this._myTexture.Dispose();
this._myTexture = null;
}
}
}

protected override void UnloadContent()
{
this.Game.Content.Unload(); // Or the CM you use.

base.UnloadContent();
}


Comply with the above, and you will do good.

IV. THINGS TO DO

Getting back to the question of how to unload assets at different times at runtime, there is one practice that will help us understand why it is sound and thus, advisable, to have more than one CM in our XNA-based games.

When you create a program you declare global variables and local variables. This common practice incorporated to our daily programming tasks is the key that will then leads us to think of global and local assets.

You may consider an asset "global" if its lifetime lasts across all the game, or at least, most of it. In this sense, assets should be deem as "local" instead if it is expected and intended to unload them once a stage in the game has finished but the game has not and will not, at least for a while more.

Thus, when creating your game, use:
1) A Content Manager for "global" assets: the one instantiated by default within the Game class (which you can access using the Content property), and
2) One (or more) Content Manager(s) for "local" assets: say one content manager per level, per screen, or per whatever category that fits your game's design.

Again, group your assets in clusters based on lifetime, and you will know which one is global and which ones are locals. If all your screens will use one spritefont in common, then there is no reason to load and unload it for every screen; just load it once and hold it in the collection of global assets. If a ship model will be used in only one level, handle it locally to that level.

As you can see, using more than one Content Manager is a sound practice: easier to apply, easier to debug, easier to mantain and easier to extend.

Sometimes there is no need to have more than one CM for all the game, depending on the game of course, but still it is a good practice to know and get accustomed to, since in the end it helps us manage our assets at runtime in a more tidy and convenient manner.

So, my recommendation is: get used to it. The sooner, the better.

V. CONCLUSION

The Content Pipeline is a great tool to import assets to our XNA-based games which is complemented with the proper manager to handle that content at runtime: the ContentManager class.

By using instances of this class wise and properly, we could get (more) efficience in the fields of implementation, debugging, mantainability and extensibility.

In order to achieve this goal certain practices must be applied:

  1. Use one instance of the ContentManager class for global assets,
  2. Use at least one instance of the ContentManager class for local assets, and
  3. Do not manually dispose assets; instead, call the Unload() method of the CM.

I hope you find this post useful. Comments and suggestions are welcome.

Cheers!
~Pete

Thursday, October 02, 2008

XNA GS CONNECT UPDATE

In preparation to the extreme makeover that the 360's Dashboard will experience later this year, Michael Klucher has announced a new version of XNA Game Studio Connect.

This version will allow us to also run XNA Framework 3.0 games. So, this is a perfect time to start porting our projects to XNA 3.0, don't you think?

Head over Michael's site to know how to get the upgrade, which is a manual process.

'till next time,
~Pete

Tuesday, May 13, 2008

VS 2008 & .NET 3.5 SP 1 BETA RELEASES

I was reading Scott Guthried's blog this morning so I found a great surprise: the first Service Pack beta release for both, Visual Studio 2008 and .NET Framework 3.5 is out.

One of the things that amazed me while reading through the new features we'll find in the final release has the following title: "WPF Interoperability with Direct3D".

But why does this means a lot to me -or should mean a lot to us XNA-based game developers?

If you ever attempted to integrate a D3D-based game/application into a WPF-based project, you may know that one of the hard burdens to surpass to get that job done is called "Airspace", a strict rule that prevents both type of applications to co-exist in the same region of the screen, at least without a simple solution.

And I say simple here because to "bend" this rule a little bit to make the user believe that a real integration exists -meaning, as if there was not Airspace at all in the first place- either you had to use a decorator-pattern-based implementation or a solution where you intercept all windows messages in order to "bake" all pixels rendered by D3D into an image that can be later used by any WPF control ... if you want to know more about this rule and or get one of these solutions or both of them just do a simple Internet search with the words "DirectX WPF Airspace" :)

Well, as this is becoming a built-in feature now, it means that we can stop worrying about finding or choosing the optimum way to integrate D3D and WPF, what in turn means that we don't have to constraint our D3D-based projects to WinForms controls anymore and thus we can let our imagination fly to create a rock-solid kicking @$$ game-level editor using WPF and XNA -specially now that GS 3 integrates into VS2008.

Really great news ... although we have to wait a bit more to get our hands on this feature until the final SP is released ... :)

Cheers!
Pete

Sunday, December 16, 2007

XNA & BEYOND: THE PATH TO VS 2008

I have uploaded my first article to "The Code Project" site, which shows how to integrate an XNA-based application into VS 2008 (an implementation for WPF is included) ... read it here.

Also in the article I present -what I think is- a simple solution for embedding your XNA games within a WinForms control; a topic that has been heavily discussed in the (XNA Creators) forums these days.

I hope you find it useful.

Cheers!

Thursday, December 13, 2007

PROBLEMS INSTALLING "NET RUMBLE" STARTER KIT

Well, having installed XNA GS 2.0, I then downloaded and install the Net Rumble Starter Kit. The process ended without problems so everything looked ok so far.

For my surprise, when I opened VS 2005 Express and attempted to create a new project based on that kit, I found the kit wasn't shown in the IDE's projects browser.

The template was installed under this folder:

(myOSDriveLetter)/Users/(myUserName)/Documents/Visual Studio 2005/Templates/ProjectTemplates/Visual C#

... but still the IDE didn't notice it at all.

At first I thought it had something to do with the fact that I'm using a non-english version of the IDE and a non-english version of Vista 32-Bit (something similar to what it's commented here: see section 1.2.2), but I cannot set the "International Settings" to "English" since, in my case, everything is in Spanish.

So, what to do? After locating the "SpaceWar" Stater Kit template file, I found that both, PC and 360 versions, where installed under a folder named "XNA Game Studio 2.0".

So, I created a new folder under ".../ProjectsTemplates/Visual C#", then renamed it to "XNA Game Studio 2.0", finally moved the "Net Rumble" template file to that folder, and presto!

Cheers!

Wednesday, May 16, 2007

QUATERNION CAMERA IN XNA

Scot Boyd, author of the upcoming book "Expert One on One: XNA Game Programming for Xbox 360 and Windows", has provided the source code of the "QuaternionCamera" class which will help you avoid that nasty Gimbal Lock problem that you may face when working with yaw, pitch and roll at a time.

From the post: "... XNA unfortunately does not provide a QuaternionCamera class in it's Framework. Nowhere on the Internet could I find a camera class that provides six degrees of freedom without requiring additional coding from the reader ... In the process of attacking this problem in my book, I've made a few camera classes. I'm posting the simplest class here - good for beginners. The final camera class in the book will be more complicated. This class should provide a good jumping-off point for anybody interested, or a simple helper class for those who just want a camera without hassles. In the camera, GetViewMatrix and CreateYawPitchRoll are where the money is ...".

Read on!

Tuesday, May 15, 2007

TRANSITIONS - PART 2

Shawn has published the second installment on his series of articles regarding "trabsitions", this time focusing on the physics part.

From the post: "... you may not know exactly when you want things to start or stop moving. When the factors controlling your transitions get more complicated, it can be easier to switch to a physics based approach ...".

Read on!

Sunday, May 13, 2007

GAME DESIGN PROBLEM

After conquering "deferred shading", Jason Maskell is crying loud for help ... Ok, maybe I'm exagerating ... :)

As Jason approaches the phase of implementing a physics handler, he encounters a design crossroad. So he would like to hear what others with experience in the field have to add so as to help him decide what to do.

From the post: "... I’ve got to come up with some elegant system to retain my 2d movement vector on the flat grid, but also have an equivalent 3d worldspace vector at the same time. It’s an interesting problem but I think I’ve got it. It’s starting to feel grossly complicated though ...".

Have ideas? Post them here.

Friday, May 11, 2007

CONQUERING DEFERRED SHADING

Jason Maskell comments about his experiences with deferred shading techniques.

From Jason's post: "... I’ve thought that I’ll probably have to write a material editor sort of thing where my artist can play around with the materials settings until he finds out the right settings to stick in the lookup texture. For instance, he will be putting an index value in the alpha of the texture, which will then lookup into another texture to get 4 values instead of one ...".

Do I see some soft lighting in that screenshot?

GETTING STARTED WITH XNA: PRIMITIVES

Brecht Kets has published a series of articles about primitives with XNA.

From the articles: "... A triangle is defined by 3 points, which is defined by a Vector3, containing the X, Y and Z coordinate (3D space), and maybe some additional information, such as color. Such a point is called a vertex. XNA has some vertex structures embedded, and one of them is perfect for this example: VertexPositionColor. So let us add this to our class ...".

You can find part I and part II on his blog.

Thursday, May 10, 2007

CRIMSON UPDATE: VASCULITIS

NekoCake's engine has been updated and a demo is included.

From the post: "... for anyone who is interested, heres a short demo. It only works with an xbox controler at the moment. left stick moves you around, B jumps and A kills you. If anyone can run it and tell me how it runs on there pc id be gratefull! ...".

So, let's tell this guy how it runs ...

Wednesday, May 09, 2007

BLUEPRINTEDITOR'S DOCKING NIGHTMARES

Mike comments on the experiences he is facing along the process of building a UI for his XNA-based world editor: "Blueprint".

From Mike's post: "... As XNA runs using a DirectX graphics device its very picky about loosing its rendering state. So if a user undocks the window and moves it about and then redocks it, it doesnt like it due to the loss of rendering state. For now the XNA window has been fixed so that it cant be undocked ...".

Later.

Tuesday, May 08, 2007

UPDATE ON CRIMSON ENGINE

Codenamed "Vasculities", there's a new update of NekoCake's engine: "Crimson".

From the post: "... So far, ive completely rebuilt the screen system. Ive looked through Microsoft’s game state management sample and i loved the way they implemented some things (especially the transitions!). After playing with it a bit, it was clear id have to do a bit of retooling on my screen system, which ended up with me ripping out the whole screen system and starting from scratch ...".



Stay tuned!

Friday, May 04, 2007

"TRANSITIONS PART ONE: THE IMPORTANCE OF CURVES"

As promised, Shawn is starting to blog on transitions with "... The Importance of Curves".

From the post: "... Whenever you are dealing with transitions that take some fixed amount of time to complete, it can be useful to normalize their position along this timeline into a control value in the range 0 to 1. This makes the transition state easier to manipulate ... More importantly, you can apply curves to make the animation speed up or slow down in interesting ways. Normalized control values are useful for this because it is easy to apply curves that will affect their shape without changing the overall range of the motion ...".

Read on!

Tuesday, May 01, 2007

MCCODER'S "LITTLE COLLISION MANAGER"

MCCoder has published the source code for his "Stand alone little collision manager".

From the post: "... I had previously been doing all my collision stuff during my physics steps, which led to pretty fantasic failure cases. I was checking to make sure the objects were heading in the same direction before I’d say there was a collision, but this often led to objects coming to a rest while penetrating another object (say two objects interpenetrated and bounced off each other, but not with enough force to actually seperate them) ...".

Read on.

JONAS FOLLES' FIRST XNA GAME: "XPONG"

Jonas Folles is sharing his first game created with the XNA Framework to the community.

From Jonas' post: "... So as I mentioned in the beginning I just completed my implementation of PONG written using the XNA framework. I wanted my PONG game to be more "complete" than some of the XNA PONG samples available online. There are some nice tutorials you might check out. One of them is a video tutorial over at LearnXNA that walks you through an implementation of Pong. Two other implementations worth checking out are Rob Loachs' XNA Pong and Tiny Tennis up on Coding4Fun ...".

Welcome, Jonas!

"SINGLETONS"

There's a new post at XNAtutorial which brings some light on the Farseer singleton.

From the post: "... In other words: When starting the game, the static Farseer is not created. If a piece of code tries to access the Physics property, then the static part of Farseer is created. Or, if someone tries to instantiate Farseer, it is not instantiated, but the static part is activated ...".

More after the break!

Monday, April 30, 2007

"EXTENDING THE BITMAP FONT MAKER UTILITY"

There's an interesting article available at Ziggyware -"Extending the Bitmap Font Maker Utility", which explains how to add more image extensions to the tool recently released by the XNA Team for the creation of bitmap fonts.

From Ziggy's article: "... Extending the Bitmap Font Maker Utility to support multiple file formats is a very easy task since the .NET System.Drawing.Bitmap class wich the font utility uses to write its output with already supports several file formats via the System.Drawing.Image base class ... I have chosen to implement bmp, jpg, png and tiff ...".

Read on!