Monday, November 24, 2008

XNA Series - 3d textures from Blender

A quick note, if you are exporting an object with uv images, you need to add the images to a subfolder of your Content folder called fbx (under the folder you are putting your fbx files) This is where the fbx exporter for blender is saying that the image files related to your object are. Now you don't actually have to create this folder in your solution explorer, just in your directory tree, or you can do it in the solution explorer, but you will need to then right click on the image and say "exclude from project". This is because the fbx import process in XNA does the texture loading behind the scenes. If you leave the file in the content pipeline, it will try to import the image 2 times and you will get unneeded warnings.

Saturday, November 22, 2008

XNA Series - Begining 3D - Part 1

I have been wanting to get some posts on here about 3D. But since it is a much more complex subject than 2D, I have been holding off as I am still getting my head around it. Perhaps we can work through this together and see what we come up with.

To start drawing in 3D, we need a model. I recommend something like Blender3D, since it has all the tools you need to create a working 3d model that you can import into XNA. This is not a tutorial about modeling in blender, perhaps I'll do that later. But once you have a model created in Blender, you want to export it in Autodesk FBX format. You can load that into your content pipeline in the same way you import a sprite. The difference is in the type of C# object we create to load it into. Rather than a texture2d object, we load in this model as a Model object. We will also create a Vector3 object to set it's position rather than a Vector2, since we need to put this model in 3d space.


Project Files


Model tower;
Vector3 pos = Vector3.Zero;
The next 4 objects in our game class declarations are a little more complex.

Vector3 camPos = new Vector3(0.0f, 60.0f, 160.0f);
Vector3 camLookAt = new Vector3(0.0f, 50.0f, 0.0f);
Matrix camProj;
Matrix camView;

Vector3 camPos will store the location of our 3d camera. Our 3d camera can be thought of as a video camera placed into the 3d world at a given location.

camLookAt is a point at which our camera will be pointed in 3d space.

the 2 Matrices camProj and camView are somewhat more complicated and we will set them up later.

To load in our Model's data, in LoadContent we will do this

tower = Content.Load<model>("tower");

that should look familiar, since it is the same way we loaded in images. Except we make sure to tell the Load function it is dealing with Model objects rather than Texture2D.

Next we initialize the camView matrix

camView = Matrix.CreateLookAt(camPos, camLookAt, Vector3.Up);

We create a 4x4 matrix from the position of the camera and the point it is looking at. This matrix gives us a way to alter the way we see the model so that it looks like we are seeing it from the camera. Then we set up the projection matrix

camProj = Matrix.CreatePerspectiveFieldOfView(
MathHelper.ToRadians(45.0f),
graphics.GraphicsDevice.Viewport.AspectRatio,
1.0f,
10000.0f);

which will alter the way we see the model in perspective. We pass this method the width of our view field (45 degrees). the aspect ratio of our graphics device and the near and far limits to what we can see (clipping planes). If you don't fully understand these matrix operations, its ok, just press on for now.


We are almost there, we need to create a method that applies all these things to our model. Since we will want to draw more than one model in the future, we will make a generic function. We call it DrawModel and will pass it a model to be drawn, it's position and a scale (to make it bigger or smaller). In a model object we can have many meshes. So we need to loop through them all. Then each mesh has a list of "BasicEffects" which control how that mesh will be drawn, so we loop through those too. For each basic effect we will do the following
  • enable lighting
  • set lighting preferences
  • set the World, Projection and View transformation matrices for the effect
Then for each mesh, we draw the mesh

void DrawModel(Model model, Vector3 modelPosition,float scale)
{
foreach(ModelMesh mesh in model.Meshes){
foreach (BasicEffect effect in mesh.Effects)
{
effect.EnableDefaultLighting();
effect.PreferPerPixelLighting = true;

effect.World =
Matrix.CreateTranslation(modelPosition)*
Matrix.CreateScale(scale)
;

effect.Projection = camProj;
effect.View = camView;
}
mesh.Draw();
}
}

All that is left at this point is to call DrawMesh from our Draw method with appropriate parameters.

DrawModel(tower, pos,10f);

I've added a couple extra calls to DrawModel in the project file so you can see a little "scene"


Friday, November 21, 2008

Trying Tubes in a Crate V33-212

I like to tinker. So it should be no suprise that now that I have a tube amp I want to do a little testing to see what it is capable of.  I emailed Crate to see about the best way to get into the amp and they provided me with the Final Assembly Schematics for the amp, which showed that removing 2 screws allowed the amp assembly to pivot down.



So what you see here is the transformer, the 4 EL84 tubes and the 3 12AX7 tubes.  I borrowed a 12AU7 tube from a friend to see what that would do inserted into the V3 position (the leftmost tube in the front row of this picture). Being that the 12AU7 has a substationally lower gain than a 12AX7 it cleared up the clean channel which when it was on 0 volume had a slight low hiss, but since now the power tubes were getting a lot less power from the inverter tube, it was much quieter. I did have to turn the amp up much louder to get the same volume and it started to break up the clean channel at a lower volume then before. But there was a bit of fullness that I seemed to lose. Not sure I am ready to make this change. I need to test some more first. My friend also recommended rather than a 12AU7 a 12AT7 which has a gain level somewhere in between the U and the X. All I know is that either way the amp sounds really good, I'm just not sure which way sounds better yet.






Free Chord and Scale Diagram Paper

In teaching guitar I spend a lot of time teaching my students chords and scales. I have several pages that I have made up with chords and scales on them, but they are a bit much for the beginner. Too many chords or too many scales that it is hard to focus. So I generally like to write out the couple of scales or chords that I want them to practice for that week on a sheet of paper. But again if I make them too small they are hard to read from. So I created some nice sheets you can print off with 9, 4 fret chord blocks and 6, 8 fret scale blocks. So I hope there are helpful to you.

These links are fixed now. Sorry for the previous inconvenience.

Chord Blocks
Scale Blocks

Monday, November 17, 2008

Blog Posts, Christmas Music and Sweet Tracks

Well I got off to a pretty good start there on the XNA series, but unfortunately my lack of free time has caught up with me. I'll be posting again in the XNA series soon, I'm just not sure how soon. So for those of you who are coming here for XNA, I apologize for my lack of material. For those of you who come here for other reasons...I'm not really sure why you are coming here :)

For those of you in the St Louis area and want to come see a program of instrumental Christmas music ranging from Rock to Jazz to Classical. Come on out to the Greenville First Christian Church on Sunday, November 30th at 7:00pm. Admission is free with the donation of a canned good for the local food pantry. I'll be playing guitar along with half a dozen other very talented musicians. including Luke DeJaynes, the drummer from a great band out of St. Louis, MO, Fundamental Elements. Seriously, if you have not heard FE, check out their website, it has some of their tunes on it you can stream. Take a listen. I absolutely recommend their new album, you can get it on iTunes, it's called "The Cycle We're Livin' In".

Anyway, if you are interested in the Christmas show and you want to know where that is, it's here, we would all love for you to come out:

Friday, November 07, 2008

A Simple but Good Game Creation Article

I came across a good article on a path to Game development. It seems the original site is now non responsive, but the web archive of it still exists. This short article was a recommendation from an indie game developer about a series of game clones to try to complete in an effort to learn by doing. The article is from 1999, but I think it has some good suggestions. The idea is that you create these clones from your knowledge of the games listed and to make a complete game out of each. The games he suggests are

A Tetris type game
A Breakout type game
A Pac-Man type game
A Platformer (Super Mario type game)

He gives reasons for each and this seems like a good path. He really stresses the importance of making each of these into a finished working game, so that you have the experience of FINISHING a game rather than starting one, over and over.

The original article is here on the web archive.

Wednesday, November 05, 2008

XNA Series - Game Components

Ok, I know I said the next article would be about steering, but the next article for that topic is not ready yet, so I thought I would talk about a pretty cool class in XNA called GameComponent and its child Class DrawableGameComponent. These classes are made to add components to your game in a modular way. A component is something that needs to update with your game. DrawableGameComponent inherits GameComponent and adds functionality so that the component is also drawn at proper times as well. You could actually re-design our GameObject class as a DrawableGameComponent or at least inherit a class from DrawableGameComponent to give us the added functionality. Now from my reading, it seems that a lot of people think GameComponents are are really aimed at single game objects like a tank, but to add a TankManager class that would deal with the updating and drawing of all the tank objects in our game. But it certainly doesn't hurt to learn the type in an easy way.

We will create a UserTank class that is derived from DrawableGameObject. We just need to implement the basic constructor which takes a Game Object. So our UserTank will get all the functions (except private ones) of the DrawableGameObject class.


public class UserTank : DrawableGameObject
{
public UserTank(Game g)
: base(g)
{
}
}


To begin this is actually all we need to add this tank to our game. In our game class we would add


UserTank hero;


and in our constructor we would initialize it in the same old way


hero = new UserTank();


but we do something a little different after that


Components.Add(hero);


Since the hero tank is a UserTank which is derived from DrawableGameObject which is Derived from GameComponent, we can put it in the GameClasses list of GameComponents. These GameComponents all get called on updates and if they are drawable, they get their draw methods called.

So now even though there is nothing "in" our UserTank class, it is being updated with our game. Lets add a couple bits of info to the UserTank class that will help us out. To save time and space, I will implement the fields of the component as public rather than making them Properties. This is lazy, don't follow my lead in this.


public Vector2 location = Vector2.zero;
public Texture2D sprite;
SpriteBatch spriteBatch;


So we can store our location, sprite and a spritebatch to draw to. Then we simply override LoadContent, Update and Draw.


protected override void LoadContent()
{
spriteBatch = new SpriteBatch(this.GraphicsDevice);
sprite = this.Game.Content.Load("tank");
base.LoadContent();
}

public override void Draw(GameTime gameTime)
{
spriteBatch.Begin();
spriteBatch.Draw(sprite, location, Color.White);
spriteBatch.End();
base.Draw(gameTime);
}

public override void Update(GameTime gameTime)
{
KeyboardState ks = Keyboard.GetState();
if (ks.IsKeyDown(Keys.Up))
{
location.Y -= 1;
} else if (ks.IsKeyDown(Keys.Down))
{
location.Y += 1;
}

if (ks.IsKeyDown(Keys.Left))
{
location.X -= 1;
} else if (ks.IsKeyDown(Keys.Right))
{
location.X += 1;
}
base.Update(gameTime);
}


So as you see we initialize the spritebatch and load it's sprite. Then we call the base classes LoadContent method. In the Draw method we Begin our spritebatch, make a Draw call and End the SpriteBatch and then call the base classes Draw method. Then finally in the Update method we look at the KeyboardState and make some updates to the location and once again call the base classes Update method. So now that you have this component we could add it and it's logic in a very simple manner.



Here are the files for this project.

Tuesday, November 04, 2008

Stop Reading This Post

If you are a US Citizen of voting age and are still reading this, stop immediately and go vote. I won't tell you who or what to vote for, that is up to you. I am just telling you to go VOTE!

That is all. For the rest of my visitor's, enjoy watching the spectacle of the American political process.

Monday, November 03, 2008

XNA Series - AI - Better Steering - Part 1

I have been reading Steering Behaviors For Autonomous Characters by Craig Reynolds and after several reads I have decided to try to implement it in my own code and I think I am ready to explain it to you my loyal reader.

In his paper Mr Reynolds take a different approach that we have been taking thus far. Rather than having our steering be a simple rotation and moving forward at a set speed. He takes several other aspects into consideration, making a much more detailed simulation. To start we think about it in these terms: First we decide what direction and "magnitude" we need to move in that direction to steer us toward our goal. This is called our "Steering Vector". If we applied the steering vector all at once, we would immediately be put on the right path, but that would make for a very non-realistic simulation. Instead, rather, in the application of the steering vector, we take into consideration our current velocity, direction, mass and maximum force we can exert. We then factor these items against our steering vector to get an acceleration in a new direction to be added to our current velocity, we truncate this new velocity to our maximum speed and in that timestep we take a step towards steering to our goal.

The benefit of this method really lies in the Steering Vector. Since vectors can be scaled, added, subtracted, etc. We could apply several steering vectors. Say an object was following waypoints, we could say if an enemy is within a given distance, add the Flee steering vector times 50% and the Waypoint vector times 50%. We would then apply this new steering vector rather than just Waypoint or Flee, so that the object is still trying to do the waypoints, while evading.

In my next post, I will start looking at how we can adapt this method into our GameObject class.

The paper to which I am referring.

Saturday, November 01, 2008

XNA Series - A Simple Particle System

Sometimes you need to create a an effect like smoke or an explosion. This is when you can turn to a particle system. You can think of a particle system as an emitter. It emits points on given velocities, and each of those points has a lifetime. Once that lifetime is over they are no longer updated or drawn. This example will be a simple "fountain"

First, we will create a class to represent each particle. We will call it Particle

public class Particle
{
public bool alive = false;
public Vector2 position = Vector2.Zero;
public Vector2 velocity = Vector2.Zero;
public int lifeTime = 0;
}

So each particle has a field that shows if it is to be drawn an updated. A current position and velocity as well as a counter for how many updates it has been alive.


public class ParticleSystem
{
public int totalParticles = 500;
public Vector2 position = Vector2.Zero;
public Texture2D sprite;
public Particle[] parts;
public int current = 0;
public int end = 60;
public bool started = false;


In our particle system class we keep track of how many particles are in the system, the position of the emitter, the texture of the particles, an array of particles, a counter of how many updates the system has been through and if the system is running.


public void Init(){
Random r = new Random();
parts = new Particle[totalParticles];
for (int i = 0; i < totalParticles; i++)
{
parts[i] = new Particle();
parts[i].velocity = new Vector2(0 +(float)r.Next(-100,100)/100f,
-3 + (float)r.Next(-100,100)/100f);
}
}


Here is an init function. This will instantiate the particle array and set each member to new particle. I was also lazy here and set the initial velocity to [0,-3] with each component getting a number between -1 and 1 added to it for some randomness.


public void Start()
{
started = true;
}


This method simply starts the system

public void Update(GameTime gameTime)
{
if (started)
{
current++;
if (current < totalParticles)
{
parts[current].alive = true;
parts[current].position = position;
}
for (int i = 0; i < totalParticles; i++)
{
if (parts[i].alive)
{
parts[i].lifeTime++;
if (parts[i].lifeTime > end)
{
parts[i].alive = false;
} else
{
parts[i].velocity.Y += 9.8f/50f;
parts[i].position = parts[i].position + parts[i].velocity;

}
}
}
}
}


The update method first checks to see if the system is started. If so, it increments the total updates for the system and if we still have particles left, we set the next one to alive and set it's position to that of the emitter. Then for each alive particle, we increment it's life, if its been alive too long we kill it, if not, we add some gravity to it's velocity (taking into account elapsed time, and then add it's velocity to it's position.




public void Draw(SpriteBatch sb)
{
for (int i = 0; i < totalParticles; i++)
{
if (parts[i].alive)
{
Color c = Color.White;
c.A = (byte)((1-(parts[i].lifeTime / (float)end))*255f);
sb.Draw( sprite,
parts[i].position,
null,
c,
0f,
new Vector2(12, 12),
parts[i].lifeTime / (float)end,
SpriteEffects.None,
0
);
}
}
}
}


The draw method is very simple. I have added a couple extra things in it to make it more interesting. First we simply iterate over the particles and if they are alive, we draw them to the spritebatch. Now to make it more interesting I divide the life of that particle by it's total time to live. Then use that as a percentage to alter the alpha value of the drawing color and also to alter the scale of the object. I just to them in reverse so that the scale goes from 0 to 1 and the then the alpha goes from 1 to 0 (then I multiply it by 255 to convert it to a byte).

So yes, this is a VERY simple particle system, In the project files you will see that I update the position of the system based on keyboard controls, so you can move the emitter around.



The Project Files