dev in the making

game development, maya and code by brainzizi

Archive for the ‘xna’ Category

Things learned the hard way

with one comment

Decided to write a post. And possibly a helpful one! What a day!

I present – lessons learned the hard way in game programming:

Do not write your own physics for games.

Use http://farseerphysics.codeplex.com/ for 2D and http://physxdotnet.codeplex.com/ for 3D physics. Do not write you’re own just because you need a simple physics engine in your game – even if you do have the neccessary knowledge. It’s too big to finish in a reasonable time and there are far better engines out there.

Learn to use some paint software and a 3d modelling package

You will need art for your game. Lots and lots of art if you’re making anything bigger than puzzle games. Learn how to use Photoshop, Gimp or whatever to create basic game 2D game art. Also learn a 3D modelling package like Maya or Blender because – if you can handle the math – you will want to do something in 3 dimensions. Also learn Mudbox or some other free sculpting package if you don’t want to totally devote to 3D with learning how to uv map / texture. Also to touch UV mapping: Do not UV map a model manually using plane, sphere, … projections. Use something called LSCM mapping. Blender has it by default and most packages have a plugin that handles that (Maya has RoadKill)

Learn about view and projection transforms and object, view, world coordinate systems

Not knowing how to handle transformations between different coordinate systems turns out to be quite a bummer when trying to do anything a bit more complex with graphics. You need to know the maths so you can do a whole lot of cool stuff like shadow mapping and camera effects… Start with Vector math, and go on with Matrix math and View, Projection, Transformation matrices. It’s really practical math, ready-to-use math, not something abstract with a lot of theory behind.

Well, that’s it for now. What did you learn the hard way in game programming?

Advertisements

Written by brainzizizi

10.30.2010 at 15:56

Export Maya’s custom attributes to XNA

leave a comment »

If I only knew it was this easy…

I’m doing a spaceship shooter game, and I encountered a situation where the only solution was to write a custom xml file next to every one of my models. So I started a content pipeline extension project and began twiddling. I inherited the ModelProcessor to load info from my custom xml file, and I saw a OpaqueData dictionary in the NodeContents so I decided to google it.

With some help from http://blogs.msdn.com/b/etayrien/archive/2007/03/22/opaque-data-from-max-and-maya.aspx I got exactly what I wanted without the xml info file – getting extra information from Maya to XNA.

As the link says, soo

  • 1. Add a custom attribute to a mesh in Maya
  • 2. Read it in the OpaqueData
  • 3. ???
  • 4. Profit!

Simple as that! What you actually want to do in step 3 is pass on that extra information in a Model.Tag, or Mesh.Tag from the content pipeline to your game.

Written by brainzizizi

07.16.2010 at 13:45

zAnimation – exporting models from Maya

leave a comment »

This is a short tutorial which I’m also posting on the zAnimation codeplex wiki. The next one should be about building a new project with zAnimation. This was going to be a video tutorial, but my english speaking abilities sock. As well as my english writing abilities. Also I suck at modeling/animating, so this shouldn’t be taken as a modeling tutorial. It’s a tutorial on how to export stuff.  So let’s get started. Read the rest of this entry »

Written by brainzizizi

12.10.2009 at 12:57

Posted in xna

Tagged with , , ,

zAnimation – on codeplex

with one comment

zAnimation is finally on codeplex. You can find it here: http://zanimation.codeplex.com/.

It’s all very basic for now, no samples or documentation yet. The code is somewhat documented. I believe experienced people will have no problem using it. It’s just a matter of selecting the right content processor, checking out my past blog entry to write a definitions file, and writing model.Play(“Walk”); I won’t be working on the documentation or samples the next 2 weeks, my exams are still more important.

Written by brainzizizi

11.22.2009 at 12:57

zAnimation – a simple XNA animation library

with 3 comments

Before XNA 3.1, there was a bunch of animation frameworks which could to tons of stuff like interpolation between animations and stuff like that. When the 3.1 came out all of these became obsolete – except kw animation which comes with a 3ds max exporter and is great if you’re using max, but I’m using Maya and I needed to write my own animation foundation. zAnimation is a XNA library for animating skinned models exported from Maya. It supports customizable pre-clip interpolation, and per-bone animation. No interpolation between frames or animations yet.

Pre-clip interpolation:

Before a clip is played, the model interpolates over a customizable number of frames to the starting position. It delays an animation a bit but removes jerky transitions between animations.

Per-bone animation:

When defining a clip within the animation, you also define what bones does the clip affect. Based on that you can play an animation that animates all the bones in a model, and easily override the animation on one or more bones to make them move in a different way.

Below I’m listing a couple of things that I encountered while writing zAnimation:

Maya gets all your animation keyframes and exports it in a single take called “Take 001”.

To deal with this I introduced another file (the take definition file) which contains where does a certain animation start and end, and also what bones does it affect.

XNA FBX Importer removes redundant bones.

If a bone has no weights defined on a skin it gets deleted. The same thing happens if the bone doesn’t move (change) in the keyframes. So I introduced 2 special parts of the animation, the “Bind” part and the “Init” part. The bind part acts like a starting transform, and the init part is just there so you don’t forget that you have to animate a bone if you want to have it.

So based on that there are a few rules and limitations to zAnimation:

– smooth binding only

– each bone in each skin has to have some weights, so no root bones with no weights (or it won’t be imported as a bone)

– each bone has to have at least 2 keyframes that are not the same (or it won’t show up in the keyframes at all)

– strictly defined animation timeline:

-at frames 0 and 1 keyframe every bone at its bind pose position. This is the position your animation starts with.

-at frame 3 you should keyframe every bone it any position other than its bind pose. I select all my bones and rotate them in the x-axis about 45 deg.

-at frame 4 you should keyframe your bind pose again.

– after frame 4 animate your model as you wish

– when importing a model create a takes.def file in the same directory as your exported fbx is in the XNA content folders, set its build action to none from Visual Studio

– takes.def file has a specific structure that is line delimited, so the first line should look like this:

Bind, 0, 2, AffectedBone0, AffectedBone1, AffectedBone2

and each line after that should look like this:

AnimationName, StartFrame, EndFrame, AffectedBone0, AffectedBone1, AffectedBone2

here’s an example of a takes file

Bind, 0, 2, root, door
Open, 4, 34, door
Opened, 34, 36, door
Close, 36, 66, door

That’s more or less it. I’ll release it on codeplex in a couple of days. Check it out if you’re a XNA developer working with Maya.


Written by brainzizizi

11.05.2009 at 08:52

Posted in xna

Tagged with , , , ,

GameOfLife – Source code

leave a comment »

O hai! Last time I’ve posted I promised you some code so here it is.

GameOfLifeGPU is a simple project to implement Conway’s Game Of Life algorithm on a GPU. I’m using a 400×300 grid with edge wrapping, loading premade patterns from 400×300 content files and a simple mechanism for switching between those premade patterns. I’m also using a QuadDrawer class which you can find somewhere on Ziggyware.

GameOfLife.cs:


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

namespace GameOfLifeGPU
{
 /// <summary>
 /// This is the main type for your game
 /// </summary>
 public class GameOfLife : Microsoft.Xna.Framework.Game
 {
 GraphicsDeviceManager graphics;
 SpriteBatch spriteBatch;
 private QuadRenderer quadDrawer;

 private int width = 400;
 private int height = 300;
 private RenderTarget2D gridRT;
 private Texture2D texture;

 private Effect clearEffect;
 private Effect updateEffect;

 private string currentTexture = "gliders";

 private KeyboardState keyState;
 private KeyboardState oldKeyState;

 public GameOfLife()
 {
 graphics = new GraphicsDeviceManager(this);
 Content.RootDirectory = "Content";

 quadDrawer = new QuadRenderer(this);
 Components.Add(quadDrawer);
 }

 /// <summary>
 /// Allows the game to perform any initialization it needs to before starting to run.
 /// This is where it can query for any required services and load any non-graphic
 /// related content.  Calling base.Initialize will enumerate through any components
 /// and initialize them as well.
 /// </summary>
 protected override void Initialize()
 {
 graphics.PreferredBackBufferWidth = 1024;
 graphics.PreferredBackBufferHeight = 786;
 graphics.PreferMultiSampling = false;
 graphics.ApplyChanges();

 IsFixedTimeStep = true;
 IsMouseVisible = true;
 TargetElapsedTime = new TimeSpan(0, 0, 0, 0, 10);

 base.Initialize();
 }

 /// <summary>
 /// LoadContent will be called once per game and is the place to load
 /// all of your content.
 /// </summary>
 protected override void LoadContent()
 {
 // Create a new SpriteBatch, which can be used to draw textures.
 spriteBatch = new SpriteBatch(GraphicsDevice);

 clearEffect = Content.Load<Effect>("Effects\\clear");
 updateEffect = Content.Load<Effect>("Effects\\update");
 gridRT = new RenderTarget2D(GraphicsDevice, width, height, 1, SurfaceFormat.Color);

 texture = Content.Load<Texture2D>("glider");
 }

 /// <summary>
 /// UnloadContent will be called once per game and is the place to unload
 /// all content.
 /// </summary>
 protected override void UnloadContent()
 {
 }

 /// <summary>
 /// Allows the game to run logic such as updating the world,
 /// checking for collisions, gathering input, and playing audio.
 /// </summary>
 /// <param name="gameTime">Provides a snapshot of timing values.</param>
 protected override void Update(GameTime gameTime)
 {
 oldKeyState = keyState;
 keyState = Keyboard.GetState();
 if (keyState.IsKeyDown(Keys.Space) && !oldKeyState.IsKeyDown(Keys.Space))
 {
 string[] textures = Directory.GetFiles(Content.RootDirectory);
 for (int j = 0; j < textures.Length; j++)
 {
 textures[j] = Path.GetFileNameWithoutExtension(textures[j]);
 }

 int i = Array.IndexOf(textures, currentTexture);
 texture = Content.Load<Texture2D>(textures[(i + 1)%textures.Length]);
 currentTexture = textures[(i + 1)%textures.Length];
 Window.Title = "GameOfLife - " + currentTexture;
 }

 base.Update(gameTime);
 }

 /// <summary>
 /// This is called when the game should draw itself.
 /// </summary>
 /// <param name="gameTime">Provides a snapshot of timing values.</param>
 protected override void Draw(GameTime gameTime)
 {
 GraphicsDevice.SetRenderTarget(0, gridRT);
 updateEffect.Begin();
 updateEffect.Parameters["Texture"].SetValue(texture);
 updateEffect.Parameters["GridSize"].SetValue(new Vector2(width, height));
 updateEffect.CurrentTechnique.Passes[0].Begin();
 quadDrawer.RenderFullscreen();
 updateEffect.CurrentTechnique.Passes[0].End();
 updateEffect.End();

 GraphicsDevice.SetRenderTarget(0, null);
 texture = gridRT.GetTexture();
 GraphicsDevice.Clear(Color.Black);
 spriteBatch.Begin();
 spriteBatch.Draw(texture,
 new Rectangle(0, 0, GraphicsDevice.PresentationParameters.BackBufferWidth, GraphicsDevice.PresentationParameters.BackBufferHeight),
 Color.White);
 spriteBatch.End();

 base.Draw(gameTime);
 }

 }
}

Just simple pattern switching code in the Update region and the draw mechanism in the Draw region.

Content\Effects\clear.fx:


struct VertexShaderInput
{
 float4 Position : POSITION0;
};

struct VertexShaderOutput
{
 float4 Position : POSITION0;
};

VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
 VertexShaderOutput output;
 output.Position = input.Position;

 return output;
}

float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
 return float4(0, 0, 0, 1);
}

technique Technique1
{
 pass Pass1
 {
 VertexShader = compile vs_1_1 VertexShaderFunction();
 PixelShader = compile ps_1_1 PixelShaderFunction();
 }
}

Content\Effects\update.fx:


texture Texture;
sampler2D TextureSampler = sampler_state
{
 Texture = <Texture>;
 ADDRESSU = WRAP;
 ADDRESSV = WRAP;
 MAGFILTER = POINT;
 MINFILTER = POINT;
 MIPFILTER = POINT;
};

float2 GridSize;

struct VertexShaderInput
{
 float4 Position : POSITION0;
 float2 Texcoord : TEXCOORD0;
};

struct VertexShaderOutput
{
 float4 Position : POSITION0;
 float2 Texcoord : TEXCOORD0;
};

VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
 VertexShaderOutput output;

 output.Position = input.Position;
 output.Texcoord = input.Texcoord;

 return output;
}

float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
 float4 cell = float4(0, 0, 0, 1);
 float4 alive = float4(1, 1, 1, 1);
 float4 dead = float4(0, 0, 0, 1);

 float2 pixel = 1.0f / GridSize;

 float n = 0.0f;

 // count neighbours
 n += tex2D(TextureSampler, float2(input.Texcoord.x - pixel.x, input.Texcoord.y - pixel.y)).r;
 n += tex2D(TextureSampler, float2(input.Texcoord.x - pixel.x, input.Texcoord.y)).r;
 n += tex2D(TextureSampler, float2(input.Texcoord.x - pixel.x, input.Texcoord.y + pixel.y)).r;
 n += tex2D(TextureSampler, float2(input.Texcoord.x, input.Texcoord.y - pixel.y)).r;
 n += tex2D(TextureSampler, float2(input.Texcoord.x, input.Texcoord.y + pixel.y)).r;
 n += tex2D(TextureSampler, float2(input.Texcoord.x + pixel.x, input.Texcoord.y - pixel.y)).r;
 n += tex2D(TextureSampler, float2(input.Texcoord.x + pixel.x, input.Texcoord.y)).r;
 n += tex2D(TextureSampler, float2(input.Texcoord.x + pixel.x, input.Texcoord.y + pixel.y)).r;

 if (tex2D(TextureSampler, input.Texcoord).r == 1.0f)
 {
 if (n == 2.0f || n == 3.0f)
 cell = alive;
 else
 cell = dead;
 }
 else
 {
 if (n == 3.0f)
 cell = alive;
 else
 cell = dead;
 }

 return cell;
}

technique Technique1
{
 pass Pass1
 {
 // TODO: set renderstates here.

 VertexShader = compile vs_2_0 VertexShaderFunction();
 PixelShader = compile ps_2_0 PixelShaderFunction();
 }
}

The algorithm kicks in the update.fx. Space cycles the premade patterns and you can make your own patterns by inserting your own 400×300 images. Check out the premade patterns. Wrapping edges were so easy to do. Easy like writing ADDRESSU = WRAP;  ADDRESSV = WRAP;. In the CPU version they are a bit more complicated. So here you go. Simple and easy. Here’s the complete project in a zip file (73kb), which you can download from MU or RS:

http://www.megaupload.com/?d=PMV3OPJF

http://rapidshare.com/files/290162624/GameOfLifeGPU.zip

EDIT: I’ve corrected a typo in the LoadContent method. The starting texture name shouldn’t be “gliders”, but “glider”. Please correct this in your downloaded project file also.

Written by brainzizizi

10.08.2009 at 07:14

Posted in xna

Tagged with , ,

Abandoned – Shadow mapping screenshots

leave a comment »

You can see that I’ve soften the shadows quite a bit, I think it’s better this way. Also there’s an artifact due to resizing the lighting map to screensize. The screen edges are single colored, if there’s more shadow on the top edge pixel than light, the whole edge will be in shadow. But I’ll think some kind of UI will hide that well. Also this is a sneak preview of my door model. Next time when I’m doing a model I’ll record it ( like the guys @Overgrowth ), so I can show you my work process.

mudbox 2009-09-08 05-46-15-50

Written by brainzizizi

09.08.2009 at 03:50

Posted in xna