Wednesday, October 22, 2008

XNA Series - Basic AI

For today's post I want to take our first step towards 'AI'. Now please understand this and the following posts are not truly AI, but at least get us moving in a direction towards it. The Wikipedia entry for AI states the following:

...The study and design of intelligent agents,"where an intelligent agent is a system that perceives its environment and takes actions which maximize its chances of success. John McCarthy, who coined the term in 1956, defines it as
"the science and engineering of making intelligent machines."


So our idea is that some element or 'agent' in our game that can take data from it's surroundings and choose an action based on that data to take it toward it's goal. One of the MAJOR components of an AI is that it has a 'goal' something it is trying to accomplish. For instance an AI controlling a car in a racing game's goal is to get across the finish line first while staying on the course. While an AI for a target in a shooting game might want to avoid being hit. Or a "bad guy" AI who want to seek out a target. If you are serious about game AI, I would suggest reading this paper http://www.red3d.com/cwr/steer/gdc99/ on Steering Behaviors.



To start in this post, we will choose a very basic task. Agent A will start at a random location with a random rotation. Object B will start at a random location and do nothing. Agent A will rotate until it is facing Object B and will move forward until it reaches object B. So our agent has 3 tasks: turn, move and stop. Object
B just takes up space.



So what do we need for our example? An Agent A and an Object B. They will both be GameObjects. We can reuse our most recent GameObject Class from XNA Part 10 to start with. We will add a couple things to the game class to make this work.



float rotation = 0;
public Vector2 origin = Vector2.Zero;

Rotation will hold the current rotation of our object and origin will hold a "pivit point" for our object to rotate on. Then, update your draw call to use these parameters
public void Draw(SpriteBatch sb)
{
sb.Draw(sprite, position, texSource, Color.White, rotation,
origin,1,SpriteEffects.None,0);
}

Another addition is a property called Center
public Vector2 Center
{
get
{
return position + origin;
}
}
Which returns a screen based coordinate of the rotational center of our object.

So here is a tank and a missle for it to seek to. They are on one sprite sheet. We will add it to our project and create a game object for our missle, but hold off on the tank for a moment

//In our game class

GameObject b;

//In our Load Content Method

sprites = Content.Load<Texture2D>("tank-missle");
b = new GameObject(sprites,100,100,new Rectangle(50,0,50,50));
b.origin = new Vector2(15, 15);

Now in our GameObject file, after our GameObject declaration we are going to create a new
class derived from GameObject called GameAgent

class GameAgent : GameObject

{

}

So our new class GameAgent will have all the GameObject Stuff, but we can add to it and give it extra variables and methods. First we need to give it a constructor

public GameAgent(Texture2D inSprite, float x, float y, Rectangle src) :
base(inSprite,x,y,src)
{

}

Basically we pass everything on to our base class and let the GameObject set everything up. We will give GameAgent a couple fields


const float MAX_SPEED = 2;
public float speed = 0;

Now for each update, we will make a call to a method of our GameAgent for it to seek. So in our GameAgent class we will create a Method called Seek that takes a GameObject as a parameter.

public float Seek(GameObject target)
{
//First Move ahead along current angle

// The distance between the 2 elements
float distance = Vector2.Distance(position, target.Center);

//if we are far away, speed up to MAX_SPEED
if (distance > 100)
{
speed = MathHelper.Clamp(speed + 0.1f, 0, MAX_SPEED);
}

// If we are getting close, use the SmoothStep method to slow us down
else if (distance <= 100 && distance > 40)
{
speed = MathHelper.SmoothStep(0,MAX_SPEED, (distance - 30) / 70);
}

// If we are closer than 40, stop!
else
{
speed = 0;
}

// Use our current rotation + some trig to set our new location
// I'll explain later
position.X += (float)Math.Cos(rotation) * speed;
position.Y += (float)Math.Sin(rotation) * speed;


// Rotate Towards the Object

// Find Distance between this object and the target's center
float o = target.Center.Y - position.Y;
float a = target.Center.X - position.X;

// Find the angle between our unrotated object and the target
float theta = (float)Math.Atan((double)o / (double)a);

// If we are on the right of the object, we need to think a little backwards
if (position.X > target.Center.X)
{
theta = MathHelper.WrapAngle(theta + MathHelper.Pi);
}

// Add to our Rotation to point to the object
// theta-rotation gives us the difference between our current rotation and the
// offset of the target object to our 0 rotation point. This is ideally
// how much we want to rotate, but our agent can only turn so fast,
// So we need to clamp that change to our maximum turning amount.

rotation += MathHelper.Clamp(MathHelper.WrapAngle(theta - rotation), -0.05f, 0.05f);

// I return theta here so I can output it to the screen later, you don't really need to.
return theta;
}

I've added comments to the function code so you can see what is happening. Now this may of course not be the most optimal way for us to do steering, but it does work. I have been reading the work of Craig Reynolds and it does seem that he has done extensive work and research in this area. He uses a method in which the key points are more accurate to how objects might behave. I am currently trying to implement his concepts in my code and will get back to you when I accomplish something. But moving on.

Then in our LoadContent method we can initialize our agent.


a = new GameAgent(sprites, 300,300, new Rectangle(0, 0, 50, 50));
a.origin = new Vector2(25, 25);

Then in our Update method
a.Seek(b);
and Finally in our Draw method
            spriteBatch.Begin();
a.Draw(spriteBatch);
b.Draw(spriteBatch);
spriteBatch.End();

I also added this in our Update Class so I can move the target.

            KeyboardState ks = Keyboard.GetState();
if (ks.IsKeyDown(Keys.NumPad4))
{
b.position.X -= 3f;
}
if (ks.IsKeyDown(Keys.NumPad6))
{
b.position.X += 3f;
}
if (ks.IsKeyDown(Keys.NumPad8))
{
b.position.Y -= 3f;
}
if (ks.IsKeyDown(Keys.NumPad2))
{
b.position.Y += 3f;
}

When all is compiled, you end up with a missle that you can move and a tank that turns and drive to it and slows down and stops when it arrives. If you were a little lost by the trigonometry, don't fear, I'll have a XNA sidebar on that soon.

Code for this Post

References:

http://creators.xna.com/en-us/sample/aiming

http://www.red3d.com/cwr/steer/

Tuesday, October 21, 2008

XNA - I want to hear from you!

I'm a couple weeks into my XNA posting and I've been trying to get a new post out every day (some are arguably better than others) I've got a bunch of ideas still to come, but I would love to hear about what things you are interested in. If you have an area of XNA you would like me to explore in a post, please either take the poll on my sidebar or leave a comment in this post. I will gladly add your ideas to my list. Now of course I may not know about your requested area already, but I am always up for learning something new. Plus I love to hear from all the people around the world who happen to stumble upon my little blog.

XNA Series - Animation Part 2

In our last installment we created a sprite based animation and today I want to extend that a little. We are going to add a velocity to our character and scale his animation based on it. This is actually very simple. First we create 2 floats

public float velocity = 0;
public float maxVelocity = 1;


Then in our Update method, when we detect our key press, rather than updating the position, we will update the velocity + 0.1 for right and -0.1 for left. Then after the keyboard stuff we will update the position by adding the current velocity to the location.
            KeyboardState ks = Keyboard.GetState();
if (ks.IsKeyDown(Keys.Left))
{
a.velocity -= 0.1f;
a.frameNumber += 0.4f;

}
if (ks.IsKeyDown(Keys.Right))
{
a.velocity += 0.1f;
a.frameNumber += 0.4f;
}
a.position.X += a.velocity;
if (a.velocity > 0) a.direction = 1;
else if (a.velocity < 0) a.direction = 0;


Then we also check to see if our velocity is plus or minus to choose our direction. Now that we have a velocity, we can use that to scale our framerate. So rather than just adding 0.4 to our framecount whenever our key was down we will always add 0.4 scaled by our velocity each update
 a.frameNumber += 0.4f * (float)Math.Abs(a.velocity / a.maxVelocity);


as you can see we scale it by velocity/maxVelocity so when velocity is 0, nothing is added. We also take the Absolute value of the scale so that we are always adding to our value (otherwise our animation would run backwards, which may be desired at times). So now as we press our buttons we will see our character speed up and the animation speed up in relation to it.

Here is the source code: SpriteAnimation2.zip

Monday, October 20, 2008

XNA Series - Animation Part 1

Now, we may not always be using static images as our characters in our games, and sometimes we may want to have an animation, like when our character moves, his legs actually go back and forth. In 3d graphics, we would build these actions into our models, but in 2d we can pre-render these animations in frames and create a sprite sheet with all the different images of our animation.

Here is an example of such a sheet. It has 20 images of the same size, laid out in a strip.

I did this simple animation in Blender3D and then stuck it together using a little program called SpriteStripComposer that I someone put together for this very purpose. I wish Blender had a built in method for doing this, perhaps I should hit up some of my old dev pals for such a feature (or they would say "Code it Yourself!") Anyway,I am going to extend my GameObject class (see example code) with a derived class called AnimGameObject and I will add a few member variables to it
private float frames = 0;
public float frameNumber = 0;
public byte direction = 0;
The frames will hold the total number of frames in the spritesheet, the frameNumber will hold the current frame to be displayed and the direction will tell the Draw method to flip the image or not. We also add a new constructor

 public AnimGameObject(Texture2D inSprite, float x, float y, Rectangle src,float frm)
: base(inSprite, x, y, src)
{
frames = frm;
}
Which sends most of the construction to the base constructor, but also sets the frames to the number of frames passed in. Also note the when we pass in the src rectangle that we will point to the first frame of the animation and then use that data to find the rest. We also add an overridden version of the Draw method
public override void Draw(SpriteBatch sb)
{
Rectangle source = new Rectangle(((int)frameNumber)%(int)frames * texSource.Width,
0,
texSource.Width,
texSource.Height);

SpriteEffects se = SpriteEffects.None;
if (direction == 1)
{
se = SpriteEffects.FlipHorizontally;
}
sb.Draw(sprite, position, source, Color.White,0f,new Vector2(0,0),1f,se, 0);
}

First we build a new source rectangle that takes the float frame number and does a % frames on it so that we have an int between 0 and 20, we then pull the height and width from our original source rectangle. Next we create an object of type SpriteEffects and set it to None. then if direction == 1 we set it to FlipHorizontally. This will render our sprite facing the other way. Then finally we call the sb.Draw function and pass it the new source rectangle rather than the original and later in the call we pass it the SpriteEffects parameter.

Now in our game class we do things alot like we have before we declare an object of type AnimGameObject and load it up in our LoadContent method

a = new AnimGameObject(Content.Load<texture2d>("test"),0,0,new Rectangle(0,0,128,128),20);


and draw it the same in the Draw method

spriteBatch.Begin();
a.Draw(spriteBatch);
spriteBatch.End();


the main difference is in Update where we check our keyboard state and update our position, we also add to the frameNumber of the object. Now keep in mind that by default XNA runs at 60 frames per second, so you would not want to set this to update 1 frame per update, or this 20 frame animation would go all the way through 3 times per second. Instead we will set it to advance the frame 0.4f per update, that will run 24 frames per second or a little under 1 time per second (if we are holding down one of the keys) since we chop off the fractional part, when we use that number as an index, it will only make the frame change after it adds up past a whole number.
if(ks.IsKeyDown(Keys.Left)){
a.position -= 1f;
a.frameNumber += 0.4f;
}
Here is a link to the source code. SpriteAnimation.zip

Next time we will talk about frame rates and we will extend this example to make it more interesting.

Sunday, October 19, 2008

XNA Sidebar - SmoothStep and Lerp

Here is another bit of information for you when you are coding. There is a small class called MathHelper that you should become familiar with. It is in the Microsoft.Xna.Framework namespace. It contains 11 methods and 7 fields. The fields are 3 values of E (E, Log2E, Log10E) and 4 versions of Pi (Pi, Pi/2, Pi/4 and 2Pi) , but the things we want to talk in this post I want to
mention 2 methods in the class.

Lerp and SmoothStep are 2 methods in the MathHelper class that can assist us when trying to change from one value to another. If an object is going at one speed and needs to slow down to another there should be be a smooth transition between the 2 speeds. Or perhaps something needs to change from one value to another at a constant rate. These are the functions for you.

Lerp is short for Linear Interpolation, it makes a straight line between 2 values that you provide and gives you the value on that line at the percentage you pass it. It is the red line in the graphic.

Lerp(LowValue,HighValue,Percentage);

The second method is SmoothStep, you invoke it the same way as Lerp, by passing a low, high and percent (0.0-1.0) value. The difference is in the value it returns. As it's name implies, the value steps down smoothly from the first value to the second using a cubic function. It's example is the blue line in the graphic.

SmoothStep(LowValue,HighValue,Percentage);

So the next time you need to go between 2 values and you can determine how far into the transition you are, you can use one of these 2 methods to make a better transition.



EDIT

If you are interested in the code that I generated this example from, it is not in XNA (although it does reference the Microsoft.XNA.Framework assembly to get the Lerp and SmoothStep methods. Here is the file
LerpandSmoothStep.zip

Saturday, October 18, 2008

GetCals Download Location

For those of you who are looking for a getCals download...

DOWNLOAD GETCALS

XNA Part 10 - The Sprite Sheet


We have taken a little diversions with audio and collisions, but today I want to talk about a handy way to optimize your game. Up until now whenever we have wanted a sprite in our game we would just create an image and load it into our Content Pipeline and draw the whole thing. Now that is fine when you only have a couple...but say you have dozens of sprites. What is the best thing to do? Well here is one answer. A sprite sheet. this is basically a large image file that has your sprites separated into an organized grid. Here is an example of 4 sprites in a file, each in their own 100x100 spot in the file.

Now when we load in this sprite sheet we are not going to load it 4 times, that would be wasteful, instead we will load it once and pass it's reference to each game object that needs it. So I'm going to grab the GameObject class from my last project which keeps a Texture2D, a Position and the info needed for pixel based collisions. I can either extend that class or create a child class from it with new features. For now I will just extend the code for it. I am going to add a Rectangle object for the texture source. This will tell my object what part of the sprite image it needs to draw. I'll call it texSource. I will also add a member to the constructor to pass in a rectangle object to define the rectangle.

I will add a texture2D object to my main game class to hold the sprite sheet and in the LoadContent method, pull the sprite sheet into it, then pass that object to the new GameObjects along with the particular position of that GameObject's sprite in Rectangle format.

Now rather than creating 4 separate GameObjects, I have created an array of GameObjects


GameObject[] actors;

and after I load the sprite sheet in, I initialize the game objects.

actors = new GameObject[4];
actors[0] = new GameObject(spriteSheet, 0, 0, new Rectangle(0, 0, 100, 100));
actors[1] = new GameObject(spriteSheet, 0, 0, new Rectangle(0, 99 , 100, 100));
actors[2] = new GameObject(spriteSheet, 0, 0, new Rectangle(99, 0, 100, 100));
actors[3] = new GameObject(spriteSheet, 0, 0, new Rectangle(99, 99, 100, 100));

Now to siplify things when it comes time to draw these, I am going to make a GameObject draw itself (sort of). We will add a method to GameObject called Draw and it will take a SpriteBatch as a parameter.

public void Draw(SpriteBatch sb)
{
sb.Draw(sprite, position, texSource, Color.White);
}

So then in the Draw method of the Game class we can call

spriteBatch.Begin();
for (int i = 0; i < 4; i++)
{
actors[i].Draw(spriteBatch);
}
spriteBatch.End();

and handle the details of the Drawing call inside the object. Now of course, This will draw the 4 actors all stacked on top of each other, so for giggles, I'll add some Randomness to their initialization.

actors = new GameObject[4];

int x, y;
Random r = new Random();

x = r.Next(0, graphics.GraphicsDevice.Viewport.Width-100);
y = r.Next(0, graphics.GraphicsDevice.Viewport.Height - 100);
actors[0] = new GameObject(spriteSheet, x, y, new Rectangle(0, 0, 100, 100));

x = r.Next(0, graphics.GraphicsDevice.Viewport.Width - 100);
y = r.Next(0, graphics.GraphicsDevice.Viewport.Height - 100);
actors[1] = new GameObject(spriteSheet, x,y, new Rectangle(0, 99, 100, 100));

x = r.Next(0, graphics.GraphicsDevice.Viewport.Width - 100);
y = r.Next(0, graphics.GraphicsDevice.Viewport.Height - 100);
actors[2] = new GameObject(spriteSheet, x, y, new Rectangle(99, 0, 100, 100));

x = r.Next(0, graphics.GraphicsDevice.Viewport.Width - 100);
y = r.Next(0, graphics.GraphicsDevice.Viewport.Height - 100);

Now they should be in 4 different random locations.

From what I have read, the less Content loading you do the better, it is an "expensive" operation. So if you load and store 1 large image and reference parts of it, you are better off then loading many smaller images.

Project files for this post

Friday, October 17, 2008

Layout Changes

Please bare with me as I make some changes to my blog layout. I really didn't like how the default Blogger template was formatting things so I'm starting to mess around with it a bit to try to get a better feel.

XNA Part 9 - Pixel Based Collisions

Let me start by saying that the XNA Creators Club tutorials on collisions are really good and a lot of what I have learned so far has come from them. Check them out!

So on to pixel based collisions. You can of course collide on any data based in the pixels, but in our case we will look at the "Alpha" value. For those of you who are not familiar with the channels in a color, we represent color values with different components. There are several different ways to represent color, but in our case we will be using ARGB. The 'RGB' part should be familiar, this is the Red Green and Blue components of our color. The 'A' part stands for the Alpha, which is simply how opaque your color is. Where 0 is completely transparent and 255 is completely opaque. Notice that the values are between 0 and 255. This is because the 4 values are represented by the 'byte' data type which is an 8 bit integer type. 8 bits can hold 256 values and therefore in this case represent the numbers 0-255.

So the idea behind our pixel based collision is this: we look at the bounds of the 2 objects that we want to test and if they overlap, we examine the overlapping pixels in each image. If a pixel in both images is not transparent and overlapping, a collision has happened.

Now of course it will be up to you if you test for both pixels being 0 alpha for non-collisions or if you allow partial transparency to equal non-collision (i.e. both pixels have to be 255 alpha to collide rather than both being 0 to not collide).

Lets look at how we do this in our code.

We will store our pixel data in an array of Color objects for ease of use. So I'm going to add a Color[] to my GameObject.
public Color[] pixelData;

and in my constructor I am going to initialize it and load it up with my sprite's data.
pixelData = new Color[sprite.Width * sprite.Height]; 
sprite.GetData<color>(pixelData);


So we create the size of our pixelData array to be the sprite's height times width and then call the sprite's GetData method using the color type template and passing it the pixelData array to receive the data. Now we should have a lovely array filled will the pixel values of our sprite.

Now that we have pixel data to compare, we will rewrite our Intersects function to take it into account. We will take out our reference to the rectangle intersects() method. and start with our empty method.
public bool Intersects(GameObject b) { }


First we need to determine what the bounds of interection are. So we compare the tops and sides of the 2 rectangles. Remember that Y goes the opposite direction then we might think, so the top of a rectangle is a smaller number than the bottom. So we will compare the Top of a and b and see which one has a bigger value, meaning which one is LOWER on the screen. So in this case b's Top is a bigger number than a's Top since b's Top is lower on the screen than a's (confusing isn't it). So to find the lowest object Top on the screen we compare and choose the maximum Top between the 2 objects. You should also see that in this image b.Top is the top of our collision area.
int Top = Math.Max(Bounds.Top, b.Bounds.Top);


We also want the highest bottom on the screen so we look for the minimum value of a and b's Bottom.
int Bottom =  
Math.Min(Bounds.Bottom,
b.Bounds.Bottom);

Left and Right are easier since it moves in a more intuitive way. So we want the biggest Left and the smallest Right.
int Left = Math.Max(Bounds.Left,b.Bounds.Left);
int Right = Math.Min(Bounds.Right, b.Bounds.Right);

Now we can loop though using these values and extract the pixelData from the 2 GameObjects and compare them.
for (int y = Top; y < Bottom; y++)
{
for (int x = Left; x < Right; x++)
{

You will see the the for loops will not execute if top > bottom. That way, if the lowest top on the screen is below the highest bottom (ie the object are completely above and below each other) the loops will not happen. Then if they are vertically able to collide but horizontally not able to collide we don't execute the body of the inner loop. But if both work we get to the meat.

To discover where in the array of pixels we need to calculate where a particular pixel is. The pixels were stored by each row. So in this image we have our GameObjects textures as 8x8 grids. pixelData[0] through pixelData[7] would contain the first row. [8] though [15] would contain the next. So conviently we can do a little math to get us to our pixel. We take the row we want to access (starting at 0) and multiply by the width of the row (in this case 8) to give us the starting pixel in a row. Then we simply add the number of the pixel in the row we want to access (starting at 0) to that number and we have the index of the pixel we are looking for. Therefore our pixel index within a sprite becomes


pixelData [ rowNumber*rowWidth+colNumber ]


Now that we know how to access a given pixel how to we use the data we have to find the overlapping pixels and thier data. As we can see in this image, our x value would be starting at pixel 7 of the screen but only index 5 of object a and index 0 of object b. Since we can get the left value of object a (which is 2), we can subtract that from the value of x (7) and get the horizontal pixel index we need in object a (5). That would become our "colNumber" in our index formula. We determine our rowNumber in the same way with the y value. We get the distance of the y value from the "Top" of a by subtracting a's Top from the value of y. This gives us our rowNumber. We would then take the width of a as the rowWidth; so our formula for finding the pixel in a would be
Color colA = pixelData[(y - Bounds.Top) *
Bounds.Width + (x - Bounds.Left)];
Color colB = b.pixelData[(y - b.Bounds.Top) *
b.Bounds.Width + (x - b.Bounds.Left)];

Then we compare the colors and decide if they are a collision.
if (colA.A != 0 && colB.A != 0) 
{
return true;
}

Since it only takes one pixel for a collision, the first time we hit, we finish. After the loops you will want to add a return false if it makes it all the way through without a collision.

Now if you run this again with some objects that have transparency, you should find that they will only intersect when their pixels line up rather than their bounding boxes.

One caveat, this only applies to non-rotated, non-scaled textures. When we come back to collisions again, we will talk about how to handle those situations. But that will not be for a little while.

Thanks big time to the XNA creators club tutorial on Pixel based collisions, it was my primary learning source while preparing to write this post.

Thursday, October 16, 2008

XNA Part 8 - Simple Collisions

Most games that have any kind of movement need to detect object collision. There are many levels of object collision (as I am learning) that we can detect, but to start, we will look at simple rectangular collisions.

Here is the basic idea: First take 2 objects of type Rectangle which is defined this way

Rectangle a = new Rectangle(10, 10, 100, 100);

where we pass the X and Y coords of the top left corner of the rectangle and then the width and height of the rectangle. Then we create another one

Rectangle b = new Rectangle(20, 15, 100, 100);

Now we can call a member of the Rectangle class called Intersects() that will return a bool to tell us if if the 2 rectangles intersect.

So in this case since a and b do intersect,

a.Intersects(b)

would return true. We can use this type of information to help us out. In determining our game logic and behavior.

Here is an idea I came up with for putting this type of functionality into our GameObject Class. We can implement an Intersects method for our GameObject class that takes a GameObject as a parameter and then do our determining there. Here is the code for a simple GameObject

class GameObject
{
public Texture2D sprite;
public Vector2 position;

public GameObject(Texture2D inSprite,float x, float y)
{
sprite = inSprite;
position = new Vector2(x, y);
}

public Rectangle Bounds
{
get
{
return new Rectangle((int)position.X,
(int)position.Y,
sprite.Width,
sprite.Height);

}
}

public bool Intersects(GameObject b)
{
return Bounds.Intersects(b.Bounds);
}
}

We will hold only the texture and the position for now and we set them both in our constructor. Then we add a read only property called Bounds. This dynamically returns a Rectangle object that has been derived from the position vector and the size of the texture. Then in our Intersects() method we will ask our class for it's bounds and then see if it intersects with the bounds of our GameObject b. That way, we can later run code that looks like this.


GameObject a = new GameObject(Content.Load("test"), 10, 10);
GameObject b = new GameObject(Content.Load("test"), 300, 300);
if(a.Intersects(b)){
//Do something here
}

Now of course in this example, both GameObjects are hard coded to a location, so we would want to add code somewhere to get one of these puppies moving. So in our Update method I will add

a.position.X += 1.0f;
a.position.Y += 1.0f;

and flesh out my Draw method with

if(a.Intersects(b)){
graphics.GraphicsDevice.Clear(Color.Red);
} else {
graphics.GraphicsDevice.Clear(Color.Green);
}
spriteBatch.Begin();
spriteBatch.Draw(a.sprite, a.position, Color.White);
spriteBatch.Draw(b.sprite, b.position, Color.Blue);
spriteBatch.End();

So in the end, if a and b intersect, the background is cleared with red otherwise it is green.

This method works great when our Game Objects are rectangles, but if you recall, we are using PNG images which support transparency, so even the transparent part of your GameObjects would cause a collision since we don't care what is drawn in our GameObject we are just checking the bounds. Next we will be taking a closer look at our image to see if, pixel by pixel, we have collisions.

Wednesday, October 15, 2008

XNA Sidebar - Converting a single index into multiple

I was playing around with some coding ideas and thought about this. Say you have a 5x5 grid defined in a multidimensional array int[5,5] and then you create an array of object that will be placed in that grid. Say you want to refer to those grid entries as 0-24 rather than [0,0][0,1]...[4,3][4,4] a neat way to do it is with a little integer math. Division in integers is whole number division and we use the modulus operator to get remainder. So if we know the width of our grid (in this case 5), we can say

int x = 7;
int wid = 5;
grid[x/wid][x%wid];

would give us

grid[1][2]

which if we line things up

0 1 2 3 4
5 6 7 8 9
10 11 12 13 14
15 16 17 18 19
20 21 22 23 24


we see that the index 7 is the second row, 3rd column, which in 0 based notation is 1,2. You may have already known this, but I thought it was pretty handy.

XNA Part 7 - Audio - Sound Effects

In our last installment, we talked a little about the Song object and how to load a music file and play it in our games. In this post we will talk about the SoundEffect Object. From my understanding the difference between these two types is in a. how they are stored and b. how they are played. Sound effects are considered shorter burts of sound that will be played from beginning to end rather than started, paused, stopped, etc. If there is a XNA genius here who wants to add to the finer details of this, please do so in the comments.

So to add a sound effect to our project, we will add it the same way in our content pipeline. We will add a folder under content called sounds and then add our sound file to that folder.

The difference comes in how we access that file. Rather than exposing that sound file with a Song object, we will load it into a SoundEffect object. So at the top of our class we will add a variable of type SoundEffect called fx.

SoundEffect fx;

Then in our LoadContent method, we will call
fx = Content.Load("sounds\\effect");

Now since this sound effect should be triggered by something happening in our game, we want to play it during our update method.

I am going to add it to the block of code that gets executed when we press the spacebar.

if (ks.IsKeyDown(Keys.Space)) { fx.Play(); }

As you can see we do not use the MediaPlayer class to play a SoundEffect file. They have a built in method to play themselves. Now the Play has 3 versions. the first takes no parameters and just plays the sound at the full volume. The second takes a float for volume control (between 0 and 1) and the 3rd takes a float for volume, a float between -1 and 1 for pitch to move the sound down or up an octave, a float for panning (between -1 left and 1 right, 0 center) and a bool to indicate if the sound should just keep looping.

If we just call fx.Play() it is sort of a set it and forget it sort of deal. It plays, ends and that is it. But if you need additional control over the sound effect after it is started, then you need to save the return value of fx.Play() which is an instance of type SoundEffectInstance. So you would do this.

SoundEffectInstance e = fx.Play(.1f, 0.0f, 0.0f, true);

now the variable e can be used to control this instance of the playing sound effect. It has methods such as Stop, Play, Resume and variables like volume, pan, pitch, islooped, and state (which tells us what the sound is currently doing). That way if you created a SoundEffect as looping, you could stop it with e.Stop();

So now as we move along, you can very easily add sound effects to your games and make them a lot more interesting.

One note, as you progress into 3d games, there are ways to place a sound within 3d space and the SoundEffect objects have methods for dealing with this as well.

Tuesday, October 14, 2008

XNA Part 6 - Audio - Music

Today we will take a slight detour from our drawing of textures to another very important part of games. The audio! Music and sound effects are incredibly important parts of games no matter if you are doing a simple pong game to a massively multiplayer online game.

There are 2 basic type of audio that I want to talk about today. Music and Sound Effects. Now please remember what I am going to talk about today is part of XNA Game Studio 3 beta using Visual C# 2008, not XNA Game Studio 2.

Lets start with music. First, just like with textures, we want to add our music to the content pipeline. Depending on how much music and sound you are adding to your project, you may want to create 2 folders under content. One for Music and one for Sound Effects. So right click on content in the solution explorer and add a new folder and call it music. Then right click on the music folder and 'add'->'existing item' change the type to audio files (you will see that you can load xap,wav,wma and mp3 files) and browse to your music file and add it.

In our code, we will add an instance variable to our Game class to hold a reference to a song object. so somewhere after

public class Game1 : Microsoft.Xna.Framework.Game {

add

Song mySong;

and in the LoadContent method, add the line

mySong = Content.Load("music\\musictrack");

where musictrack is the name of your music file. if you want it to start playing immediately, one the next line put

MediaPlayer.Play(mySong);

and that is it, your song will begin playing at the beginning of the program.

Now your mySong object also exposes some info about your song like
Name,Album, Artist, Duration, Genre, etc if they are available, and the MediaPlayer class has several static methods for Playing, Pausing, Changing Volume, Queuing songs, etc. You can set the volume with

MediaPlayer.Volume = 1.0f;

Or in your update call check for certain keys like we did with movement and change the volume based on key presses.

So next time we will look at the equally easy way to cue up sound effects for your game.

XNA - "Always...no, no...Never...forget to check your references"

There is something to be said for really knowing a topic. To be able to have information at your brain's fingertips at all times makes for quick work. But realistically, there is no way for me (rather than becoming a recluse) that I can have a full grasp of everything in XNA. So that being said, I find that gleaning knowledge from people who are smarter than I is a good use of time. Also, having their work/writings as a quick reference is also very handy. So here is a list of references for XNA that I have checked out so far. (Bonus points if you know what movie my post title came from)

The XNA Creator's Club has a LOT of tutorials and samples and videos to get you started and to keep you going. A lot of the information I am presenting to you is my take on what I have learned from this site so far, as well as these following ones.

Here are some blogs that talk about XNA and some of the advanced things you can do with it. Check them out!

Bad Corporate Logo
http://badcorporatelogo.spaces.live.com/

Cornflower Blue
http://blogs.msdn.com/etayrien/default.aspx

Shaw Hargreaves Blog
http://blogs.msdn.com/shawnhar/default.aspx

Michael Klucher's Blog
http://klucher.com/blog/

Ziggyware
http://www.ziggyware.com

These guys are a lot smarter at XNA than I am for sure, so I'm keeping their blogs on my speed dial for when I need some info! I try my hardest to make my tutorials my own and write them in my own conversational style, but sometimes it may seem like my information is VERY close to information posted by these guys. So please check them out too. If you are an XNA blogger/tutorial writer and you feel I have copied you, my apologies, it probably means I got a lot out of your lesson. Just let me know if you feel that I need to give additional credit to you and (if I was inspired by a post of yours) I will gladly give you credit in my post.

Monday, October 13, 2008

XNA Part 5 - Game Object Class

Up until now we have had our sprite be a simple Texture2D object with its position property as a separate Vector2 object. To simplify our coding, we are going to create another class to handle our in game items. First right click on your "Project" in the solution explorer and click add -> Class. Name this class GameObject. A new class will be created in your project within your namespace. You will however want to replace the block of using statements at the top of your new class file with the ones from the Game1.cs file.

Within the class GameObject we will define our basic class members.

class GameObject
{
Texture2D sprite;
Vector2 position;
float rotation;
Color tint;
}

Each game object will contain a Texture2D to hold its image, a position, a rotation and a tint color.

Now for some basic C#. We need to create a constructor to initialize our object;

public GameObject(Texture2D content)
{
sprint = content;
position = Vector2.Zero;
rotation = 0.0f;
tint = Color.White;
}

Our constructor will take a parameter of type Texture2D and we set sprite to it, and then we initialize our other parameters to good basic values;

Now I will add some properties to let the client code update and access our variables.
public Texture2D Sprite
{
get { return sprite; }
set { sprite = value; }
}
public Vector2 Position
{
get { return position; }
}
public float X
{
get { return position.X; }
set { position.X = value; }
}
public float Y
{
get { return position.Y; }
set { position.Y = value; }
}
public float Rotation
{
get { return rotation; }
set { rotation = value; }
}
public Color Tint
{
get { return tint; }
set { tint = value; }
}

Now back in our game code I remove the alien Texture2D object and the position object. and in it's place add

GameObject alien;

I remove the position setting line from Initialize and the change the loading line in LoadContent to the following

alien = new GameObject(Content.Load("sprites\\alien"));

Which creates a reference to a new gameobject passing it a reference to the Texture2D created by the Content.Load call.

In update, I change my references to alien to the following

if (state.IsKeyDown(Keys.Left)) { alien.X -= 5; }
if (state.IsKeyDown(Keys.Right)){ alien.X += 5; }
if (state.IsKeyDown(Keys.Up)) { alien.Y -= 5; }
if (state.IsKeyDown(Keys.Down)) { alien.Y += 5; }

and my draw call to the following

spriteBatch.Draw(alien.Sprite, alien.Position, alien.Tint);

so now all the parameters in the draw call come from an existing object rather than being hard coded into the draw call.

Just for fun, we will return to the update method and add the following check

if (state.IsKeyDown(Keys.Space)){ alien.Rotation += 0.1f; }

and change our draw call to this overloaded method

spriteBatch.Draw(alien.Sprite,
alien.Position,
null,
alien.Tint,
alien.Rotation,
new Vector2(0,0),
1,
SpriteEffects.None,
0);

Which gives 9 parameters rather than 3.
  • The Texture2D,
  • the position,
  • the null is a placeholder for a parameters we are not using at the moment,
  • the tint,
  • the rotation,
  • the "origin" of the texture or point of rotation/position,
  • the scale of the object (how big to draw it),
  • the spriteeffect (if we want to flip the image)
  • the depth to draw the image
Now when you run your program, if you press the spacebar, your image will rotate.

Here is the code from the game file:



using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

namespace TutorialGame
{
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;

GameObject alien;

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

protected override void Initialize()
{

base.Initialize();
}

protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
alien = new GameObject(Content.Load
("sprites\\alien"));
}
protected override void UnloadContent()
{
}
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();

KeyboardState state = Keyboard.GetState();

if (state.IsKeyDown(Keys.Left)) { alien.X -= 5; }
if (state.IsKeyDown(Keys.Right)){ alien.X += 5; }
if (state.IsKeyDown(Keys.Up)) { alien.Y -= 5; }
if (state.IsKeyDown(Keys.Down)) { alien.Y += 5; }
if (state.IsKeyDown(Keys.Space)){ alien.Rotation += 0.1f; }

base.Update(gameTime);
}

protected override void Draw(GameTime gameTime)
{
graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
spriteBatch.Draw(alien.Sprite,
alien.Position,
null,
alien.Tint,
alien.Rotation,
new Vector2(0,0),
1,
SpriteEffects.None,
0);
spriteBatch.End();
base.Draw(gameTime);
}
}
}



and the code from the GameObject File (I've made it a little bigger this time):

using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

namespace TutorialGame
{
class GameObject
{
Texture2D sprite;
Vector2 position;
float rotation;
Color tint;

public GameObject(Texture2D content)
{
sprite = content;
position = Vector2.Zero;
rotation = 0.0f;
tint = Color.White;
}

public Texture2D Sprite
{
get { return sprite; }
set { sprite = value; }
}
public Vector2 Position
{
get { return position; }
}
public float X
{
get { return position.X; }
set { position.X = value; }
}
public float Y
{
get { return position.Y; }
set { position.Y = value; }
}
public float Rotation
{
get { return rotation; }
set { rotation = value; }
}
public Color Tint
{
get { return tint; }
set { tint = value; }
}

}
}

Friday, October 10, 2008

XNA Part 4 - Controls

Now that we have drawn a texture on the screen and made it move on a sine wave, lets make it move in response to our input.

There are 3 basic input devices that you can access. The Keyboard, The Mouse and a Gamepad. The wired XBox 360 controller is USB, so you can plug one straight into your computer. But alas I do not have one (unless someone has one they want to send me), so I'll only mention it here a little bit, if you are writing games for XBox360, you will need to program with it in mind. I'm going to focus on the keyboard, since it ubiquitous on PCs.

We access the keyboard during the update method and look at the keyboard 'state'

KeyboardState state = Keyboard.GetState();

now the object state will contain information about the keyboard at that particular time slice. We can look at that object and based on information in it, make updates to our game. We will pass 4 different keys to the "IsKeyDown" method of the state object which returns true if the key we pass it is indeed pressed at that moment. We pass the IsKeyDown method a variable from the "Keys" enumeration which contains a list of all the keys that we could be pressing. Here is the code for checking and updating.

if (state.IsKeyDown(Keys.Left)) { position.X -= 5; }
if (state.IsKeyDown(Keys.Right)) { position.X += 5; }
if (state.IsKeyDown(Keys.Up)) { position.Y -= 5; }
if (state.IsKeyDown(Keys.Down)) { position.Y += 5; }

So we check each of the 4 keys and update the position accordingly.

Now if we compile and run our game, our arrow keys will move our texture.

To access gamepad information we would do this

GamePadState pad = GamePad.GetState(PlayerIndex.One);
position.X += pad.ThumbSticks.Right.X * 5.0f;
position.Y += pad.ThumbSticks.Right.Y * 5.0f;

pad is a GamePadState object that we get from GamePad.GetState and we give it the player index (One through Four). Then we get the value of the Right thumbstick (which goes from -1 to 1) and use that as a multiplier for the addition to our position. That way the further we press the thumbstick the faster it will move! We do not have that degree of control on a keyboard.

Here is the code:

using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

namespace TutorialGame
{
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Texture2D alien;
Vector2 position = Vector2.Zero;

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

protected override void Initialize()
{
position.Y = graphics.GraphicsDevice.Viewport.Height / 2;
base.Initialize();
}

protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
alien = Content.Load
("sprites\\alien");
}
protected override void UnloadContent()
{
}
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();

KeyboardState state = Keyboard.GetState();

if (state.IsKeyDown(Keys.Left)) { position.X -= 5; }
if (state.IsKeyDown(Keys.Right)) { position.X += 5; }
if (state.IsKeyDown(Keys.Up)) { position.Y -= 5; }
if (state.IsKeyDown(Keys.Down)) { position.Y += 5; }

base.Update(gameTime);
}

protected override void Draw(GameTime gameTime)
{
graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
spriteBatch.Draw(alien, position, Color.White);
spriteBatch.End();
base.Draw(gameTime);
}
}
}

Wednesday, October 08, 2008

XNA - A slight adjustment

In researching audio methods for XNA I have discovered that XNA 3.0 has better (and easier) tools for dealing with audio. So before I get into anything that will be made obsolete when XNA 3 comes out of beta, I am upgrading to 3.0 beta now. Everything so far should be uneffected by this change. Just to let you know that is the platform I am now using. In addition, XNA 3.0 required C#2008 so I upgraded that too.

Tuesday, October 07, 2008

XNA Part 3 - Updating an Object

Now that we have put a graphic on the screen, we want to make it do something. Perhaps we want to make it move on the screen. First off, in the last example we created a variable inside the Draw method to hold the position of our image. This wont do, because we need to update that value. If we leave it inside the Draw function, it gets recreated every time draw is called. So instead, lets move it out to be a class member of our game class. Just under our declaration of Texture2D alien, we will add


Vector2 position = Vector2.Zero;

This will create a variable accessible to our game class the can persist through our game. We also need to remove the Vector2 line from the draw function. This will also initialize our position to 0,0.

Now in the initialize method, lets set our initial position.


position.Y = graphics.GraphicsDevice.Viewport.Height / 2;

This sets the Y (vertical component) to 1/2 the height our game's viewport, which we access through the graphics.GraphicsDevice.Viewport object. We will leave the X component alone for now. You can run the program to see what you have accomplished so far. The top left corner of your image should be at (0, 1/2 window height)

Now lets move the image in time. To do this we alter the position variable during the update method call. Lets move our image on a sine wave for kicks. Inside the update method, right above base.Update(gameTime); add some code to update our position

position.X += 0.15f;

position.X is a float so we will add 0.15f to its current value;

position.Y = position.Y + (float)Math.Sin(position.X);

Here we take position.Y and add the Sine of the X component. Sin() returns a double, so we need to cast it to a float and add it to Y so that we end up with a float to assign to position.Y.

Now if you run your program your image should oscillate up and down as it wiggles from left to right.

XNA Part 2 - Some Simple Drawing

Now that we have a very basic understanding of the framework of our game, we will do something equally as simple. Taking an image, bringing it into our content manager and drawing it on the screen.

There are many image formats that you can use in XNA, but I am going to suggest the PNG format for a couple of reasons. The first is that it supports variable transparency. That is parts of the image can be between 0% and 100% transparent. As opposed to GIF which is either 0% or 100% transparent or JPG or BMP which has no transparency. XNA will respect the transparency of your image, so it is a good choice. It is also a lossless format which means that it does not have the same type of artifacts that JPG has from it's compression.

So the image I'll use in today's example is one I whipped up in Blender and saved as an RGBA PNG file.

So, let's draw this guy on the screen.

First we need to add the image file to the project. First, under the content folder in the Solution Explorer, right click and choose Add, then choose "New Folder". We will make a folder called "sprites". Sprites are small graphics elements that we can use/reuse in our game. So we make a folder for them in our "content pipeline". Once we have a folder called sprites, right click on it, and choose Add, then choose Existing Item(since our graphic file already exists). Browse to your image file and double click it. You will then see the image listed in your Solution Explorer under the content->sprites folder. Right click on it and change the name of the file to "alien.png".

When your game is compiled, XNA will take the resources in the content pipeline and put them in a format it can use in your game.

Now for some code. We store an image in a XNA object called Texture2D. So first we will add a private member to our game class called alien. Go to the top of your game class and just below "SpriteBatch spriteBatch;" add the line

Texture2D alien;

This creates a class variable in our game class to hold a 2d texture (an image). Now in our "LoadContent" method we will load content into this "alien" variable. Go to the LoadContent method and just below

spriteBatch = new SpriteBatch(GraphicsDevice);

add the line

alien = Content.Load("sprites\\alien");

"Content" is the content manager, so we are telling it to load the sprites\alien file. (notice we leave off the extention, and have to escape the backslash) This returns a reference to a texture2d object and puts that reference into the alien variable.

So now we have an object containing our image data ready to be drawn.

So if we want to draw something we do it in the draw method. Scroll down to it. After the line

graphics.GraphicsDevice.Clear(Color.CornflowerBlue);

We will add the following code.

Vector2 position = new Vector2(10,10);
spriteBatch.Begin();
spriteBatch.Draw(alien, position, Color.White);
spriteBatch.End();


Line 1 creates a Vector2 object with the coordinates 10,10. We will use this to position our image. Later we will move this code out of the draw method since it really doesn't belong here. All coordinates in XNA are drawn from the upper left hand corner as 0,0. Keep that in mind.

Line 2 takes our spriteBatch object and calls it's begin method. spriteBatch lets us create a batch of graphical elements and write them to the graphics card in an orderly and efficient manner. So this line begins our batch.

Line 3 adds our image drawing to the batch. There are 7 different ways you can call the spriteBatch.Draw method. The one we have used here takes our Texture2D object, a Vector2 for location, and a color from the Color enumeration that acts as a "tint" for our image. If we do not want to tint our image, we choose Color.White.

Line 4 ends our batch so it can be sent to the graphics card.

This is all the code we need to Draw our image to the game. We can compile and run our program to see the results. You should see your image drawn in your game window.


Here is the complete code for the Game1.cs file

using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

namespace TutorialGame
{
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Texture2D alien;
Vector2 position = Vector2.Zero;

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

protected override void Initialize()
{
position.Y = graphics.GraphicsDevice.Viewport.Height / 2;
base.Initialize();
}

protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
alien = Content.Load
("sprites\\alien");
}
protected override void UnloadContent()
{
}
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
position.X += 0.15f;
position.Y = position.Y + (float)Math.Sin(position.X);
base.Update(gameTime);
}

protected override void Draw(GameTime gameTime)
{
graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
spriteBatch.Draw(alien, position, Color.White);
spriteBatch.End();
base.Draw(gameTime);
}
}
}

Monday, October 06, 2008

XNA Part 1 - Program Structure

To begin, we fire up C# 2005 and choose to create a new project. We will choose a Windows Game 2.0 project.

A new project is created for us with the boilerplate for a basic Windows XNA game. The file Game1.cs is opened for us (dbl click it if it is not already open) you will see at the top a block of using statements

using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;


These import several namespaces from the XNA framework into our current namespace to make coding a little easier.

Now, lets look at some more code.


public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;

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


Our primary game class is a derived class of Microsoft.Xna.Framework.Game
We have some private members for our class to work with, a GraphicsDeviceManager called graphics and a SpriteBatch called spriteBatch (imagine that) We will talk about what those are for a little later.

Now we define our default constructor for our Game1 class. The constructor does 2 things, it allocates a GraphicsDeviceManager for our class and sets a root directory for our game assets. You will notice in the "Solution Explorer" a part called
"Content". This is the base folder for our content pipeline. We will talk more about our content pipeline in the future. It makes your life a little easier.


protected override void Initialize()
{
base.Initialize();
}

protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
}

protected override void UnloadContent()
{
}

protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back ==
ButtonState.Pressed)
this.Exit();
base.Update(gameTime);
}

protected override void Draw(GameTime gameTime)
{
graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
base.Draw(gameTime);
}
}
}


Now for the instance methods of our game class that we override from the base class. There are only 5 of them, not too tough!

Initialize is called once at the beginning after the constructor, but before LoadContent, so we can set stuff up non content stuff if we need to.

LoadContent is called once for loading content of all things

UnloadContent is called once at the end for unloading content

Update is called with a target rate of 60 times per second, we update our game objects here. We check for keyboard, mouse or gamepad state and update our game accordingly.

Draw is called once after the updates, then waits for the next update. So optimally it is called 60 times a second as well.

Now click your compile button to build and run your game, and you should get a little blue screen "CornflowerBlue" to be exact. That is all your game does at the moment. Click the red X to end it.

If you got an error rather than the game, you may not have a graphics card capable of running XNA games. For this I apologize for your wasted time. If your game ran, than you will be ready for our next installment.

Getting Started with XNA

So you want to be a game programmer? Well my answer is yes, so I'm picking up the Microsoft XNA framework for C# as my first step. Some people agree with this and some don't but hey you gotta start somewhere. So I'm gonna take you, my loyal reader on this trip with me.

Right now XNA 2.0 is the current release, but 3.0 is in beta. If you want to use XNA 2.0 you need Visual C# 2005, 3.0 requires Visual C# 2008.

So lets install a couple of things to get going on this...

1. Visual C# 2005 Express

You can pick MS's free version of the visual c# here, get that installed and then get...

2. XNA Game Studio 2.0

Installing XNA will add the XNA classes/framework into Visual C#

Now something to keep in mind is that XNA requires a graphics card that can support shader model v1.1

3. While you are at it, you can visit http://creators.xna.com/ and sign up for an account there. The forums there seem like they are active and people are willing to give tips.

So, do that stuff and we will start looking at some code in our next installment.

How it all started...

What got me "into" computers? I hadn't thought too much about it. It was always something that I was interested in and was drawn towards. But what was it that made it 'click' with me. Well the other night was movie night at our house and there was nothing good on TV. So out of the blue I suggested we watch an old favorite of mine from 1982. TRON. So I dug out my VHS copy and put it in and my kids were amazed by the (now very dated) special effects. They LOVED the light cycles and the tanks and thought 'bit' was hillarious. Then it hit me. This may be it. The movie that convinced me that computers were an exciting area, and that making computer games would be a very cool way to make a living (just like Flynn)

So, here I am 26 years later. I work with computers every day, but am not a game programmer. That brings me to my next series of upcoming posts. I've recently started learning the Microsoft XNA framework. Which is a .NET extension of classes for game programming on the PC, XBOX360 and Zune platforms. I have always found that teaching something helps me learn it better, so I will teach you how to use XNA and take another step closer to my childhood dreams of taking down the MCP with my identity disc.

Thursday, June 26, 2008

Web Programming Toolkit

I am not a "web guru" but I can generally get things done. But I am always on the lookout for tools that will make things easier. Here are some of the tools that I've been using lately in both my primary job and side projects that I work on.



Content Creation - Text Editing

In this area I am 'old school', I'm a text editor kinda guy. Right now my text editor of choice is notepad++. This is a great notepad replacement with line numbering and syntax highlighting and lots of other goodies for a programming editor.

Content Creation - Graphics

As I have mentioned in other posts, I am a big fan of Blender 3d for graphics creation both 3d and 2d. Also Inkscape for vector graphics is another great tool. Paint.Net is also good for getting those 2d images ready for the web.

Database

It is no small suprise that my database of choice would be MySQL. Here is a web standard if I ever saw one. Easy to set up and use and has always been very PHP friendly. I am also doing some looking at SQLite to see if it may hold some possibilities for use in the future for me. Actually I mention this because I've tinkered a little lately with Google Gears which is a component from Google that allows you to create a local site specific database on a client machine (with their permission of course) to let you store relational database information OFFLINE so that they can cache your web based application on their computer and use it while they are disconnected. This is actually how Google Docs and Reader are doing their offline modes. It uses a SQLite engine to accomplish this.

Code

PHP & PEAR

Most of the files you will see coming from my editor are coded in PHP. PHP has become one of the foremost used scripting languages used online these days. It is versatile for mixing dynamic content with static, making it easy to design websites that reuse a lot of code rather than duplicating it page after page. PHP also allows for easy integration with databases. This point brings me to PEAR. PEAR is the PHP Extension and Application Repository. This is a readily available library of tools written to extend the capabilities of PHP. One example is the MDB2 library which allows you to write database applications that don't really care what kind of database is backing it up (as long as the database tables are there) so your application can be just as happy talking to a mysql database as to an mssql or SQLite database. It also allows for "lazy" database connections. You can set up your database connection in a header file then when you code you always have a $db object ready to talk to the database for you. It also makes it easy to get the data back from queries really simple to do in various formats. I'll probably do a example in my next blog post.


JavaScript

I've been using a Javascript Framework called Prototype lately that is really helpful. I've mentioned it before. If all you are looking for is an easy way to get into AJAX, check it out. Also an extention to Prototype called Script.aculo.us makes doing user interfaces easy with JavaScript and AJAX. From animated effects to Edit-In-Place fields to Drag and Drop support it is a great library to get to know.

A recent javascript library that I found for making HTML tables sortable is called Standardista Table Sorting it is very simple to implement in your code and is very fast. I'll have to show you how I added it to a function to take a MDB2 result set and turn it into a sortable database table (based on an idea implemented by a co-worker) in a later post.

So, in short, yes I am firmly planted in the LAMP (Linux Apache Mysql PHP) camp. But I am certainly open to other tools and technologies. Really whatever makes my job easier.

What are your favorite tools, languages, database engines and libraries? Leave a post and let me know!

Thursday, June 19, 2008

Free / Open Source DVD Creation Workflow

Occasionally I will have the need to create a DVD. I'll do slide shows for weddings or special events, videos for family or church. My DVD drive came with it's own burning software but I've been looking for a more portable solution, since I use other computers with DVD burners in them, but no pre-installed burning software. Here is a rundown of how I might put together a slide show DVD with no commercial software.

First I'll need to scan in my images, for this you can use Paint.NET. If you haven't seen Paint.Net yet, it is a great light Photoshop replacement. If all you are doing is scanning, rotating and cropping images and doing minor work on them, it is super. Others would say to use Gimp here, but it has always felt clunky to me. Paint.NET is Windows only, so Mac and Linux users will need to look elsewhere for this part of the chain.

Once you have you images ready, you may need some extra slides as intro or ending slides. For this I go to my old stand by, Blender. Here for instance is a pair of wedding bands that I made for a wedding slide show. I added the text after the fact. You could also use Blender to create menu graphics for your DVD. It has a built in non-linear video editor if you wanted to do any motion video or animation as well. Blender is cross-platform: Windows, Mac and Linux can all use it.

So at this point, I have a folder full of images that I have named numerically in the order I want them (this speeds up the process later) ready to be made into a slide show. Now in the past I have used Windows Movie Maker, but I wanted to get away from that because it really has it's limitations. So in doing a little searching I found SSMM which is a really handy slide show tool. It has a pretty wide selection of transition effects and a pretty simple layout. You can also sync up audio as well (as long as it is in WAV format, see the section on FFMPEG later for help) Once you have all your settings done, it will render an AVI file of your slide show. SSMM is Windows only, so Mac and Linux users will need to look elsewhere. It may run under Wine for you Linux folk, but I don't know.

Now I needed to get this AVI onto a DVD. I found DVDStyler, a Windows/Linux DVD authoring package (Mac users could of course use iDVD). It lets you build your menus and insert movies into your DVD project and burn the DVD as well. There is only one problem with DVDStyler, for videos, it only accepts mpeg and SSMM only outputs AVI. But have no fear, there is always a solution.

If you do any work with video files, FFMPEG can be your best friend. One of the tools in the ffmpeg package is a command line converter. It can convert a TON of formats, including wmv and quicktime. It also does audio formats, so if you have an MP3 file that you want to convert to a WAV so you can use it in SSMM, it'll do that too! So with this simple command I can convert my AVI from SSMM to an mpeg usable by DVDStyler.

ffmpeg -i inputmovie.avi -b 1600kb outputmovie.mpg

Now that it is converted, DVDStyler can add it, I can finish the menus and burn my DVD.

So there you have it it may not be the quickest solution, but if you have a scanner and a DVD burner already, you are good to go. Do you have any suggestions for this production chain? Any tools in your toolbox that you would like to share?

Wednesday, June 04, 2008

Settling In

Well, I'm into my 3rd week at Greenville College. Week one was spent getting re-acclimated to how the IT department was set up, getting my accounts set up as well as my computer and learning that I may well get pegged in the head at any time with a nerf rocket. My second week at the college was not spent there, but in Nashville, TN at the JAM 2008 convention. This is the annual conference for a company called Jenzabar who makes software for higher education. I went with Dan Coulter and Kris Truitt. We went to a lot of sessions about the core software we use at the college, but also spent a bunch of time hanging out. We watched a bunch of RiffTrax and ate ate this a hole in the wall BBQ place called Hog Heaven. So really a great time!
So now the hard work begins, but I'm looking foward to it.

Monday, April 14, 2008

Getting into AJAX with Prototype

I've been working with PHP for about 5 or 6 years. I first got into using it while working as a Database Admin at Greenville College, trying to write a web based reporting interface for the college's student data system. I had previously been using Perl for everything CGI and PHP made working with databases a lot easier. After taking a job as a network admin at a bank, I had a lot less use for PHP. I used it when I could to 'keep my skills up' on freelance work and Bank intranet stuff. Now I had been hearing about AJAX for a couple years and knew it was something I should pick up. I tried reading a few tutorials on it and learned quickly that it was a little different between browsers and took a bunch of code to get working. All the tutorials I found were more about getting it set up rather than what you did with it. They all started with the Asynchronos JavaScript and XML bit, explained the first half and never said what to do with the XML. Well, after a little playing I put it aside for a while. I recent picked it up again and found the same old tutorials and still no luck. I asked an old co-worker of mine Dan Coulter who wrote the phpflickr class if he could give me some assistance. He pointed me to Prototype which is a JavaScript framework that makes dealing with AJAX much nicer. At first I thought it was all about the AJAX, but it isn't. It really makes JavaScript much easier to use cross-platform. First of all there is a utility function for accessing DOM elements. It looks like this

$('myelement')

This returns the element with the ID of myelement. Want to change the content of a DIV called stuff?

$('myelement').update('New Content');

even better the $$() function lets you get lists of objects like

$$('div');

Would return an array of all the div tags in your document or

$('div.myclass');

would return all divs with the class 'myclass'

But what about AJAX?

As I have learned recently AJAX is less about the acronym and more about making calls to other web pages without reloading the current page. This is where PHP & AJAX really make nice friends. With Prototype, making an AJAX call is this simple:

new Ajax.Request('mypage.php',{method:'get'});

This basically opens a call to the mypage.php page and returns the results to the browser. Now this example doesn't do anything with that result. For that you have to extend things a little, and add in the $() stuff

new Ajax.Request('mypage.php',{
method:'get',
onSuccess: function(r){
$('mydiv').update(r.responeText);
}});


This code runs the mypage.php page, takes the results of that page and replaces the contents of the element mydiv with it.

I am still digging into Prototype, and find new things to do with it each time I sit down with it. So, if you are interested in picking up AJAX or just beefing up your JavaScript programming, I would highly recommend it.

Friday, April 11, 2008

Backstage Meetings

I have to say that I am not easily starstruck. My dad was in charge of a lot of conventions when I was young and I met a lot of special guest speakers, in college I was the stage manager or assistant stage manager of the Agape music festival for 3 years and saw and dealt with a lot of artistist there. I ran sound and was stage manager for Nashville North in Taylorville, IL for a couple years, where a lot of big name country acts came through. All that to say I'm generally not impressed by fame. Well, that is until it becomes personal. One of the first cassette tapes I ever owned was Phil Keaggy's Find Me in These Fields and over the years his style has been a major influence of my playing (not that I can play like Phil ) I have seen him in concert a few times. Once on his Crimson and Blue tour back in 1994, on the Keaggy, King, Dente tour, once in a masterclass and concert at Greenville College and last night at Harvester Christian Church. We arrived to find that the "Artist Circle" seating area which we had tickets for was oversold and we had to sit in an "artist circle overflow" area. They were not bad seats, I wasn't really upset by this. At intermission we were told that because of this error, the people who had to sit there would get to have a personal meet and greet with Phil after the show. So after the show we went back and I got to meet Phil. Pretty much a handshake, a couple stupid sounding compliments from me, and a picture. He also gave us all signed copies of his recent CD set, but it was enough. You listen and idolize someone for that long and when you get a chance to meet them face to face, it's pretty cool.

So although I don't easily get starstruck, I do make exceptions.

Monday, November 19, 2007

My Robot has 10,000 Views!

Well, I know it's small change for some, but I was pretty excited to see that my Gibson Robot Guitar Video has over 10,000 views. For those of you who are wondering, I did the animation with Blender. Which is an open source 3d package. Well, Thanks to all who have watched and I'll let you know when you can go vote :)



Sunday, November 18, 2007

Accepting Undeserved Gifts

I recently received a gift. Now mind you, I like gifts, a lot. Who doesn't really? But this was one of those take your breath away sorts of gifts. A gift I did not want to touch in case it was some sort of mistake. But soon it sank in that this brand new guitar in front of me was in fact sent to me by...anonymous. There was no card or tag or from or anything. It did not say who paid the bill or ordered it. It was just sitting there waiting to be picked up, plugged in and played. Being the inquisitive person I am, I immediately called my parents, neither knew a thing about it and so I started trying to figure out who would have done this and WHY! I have ideas of who may have been invovled in this, but I came to a realization. Finding out who sent this gift is not the point. If they wanted a phone call saying thanks, they would have put in a note or called to make sure it arrived intact. Instead, I think the sender of this gift wants me to do what the gift calls for, to be pulled from it's case, tuned up, turned up and played on. To be used in worship is the type of thanks this type of anonymous gift calls for.

Now why has this hit me so hard? I do not deserve this kind of gift. Sure there I days when I feel like I deserve everything I want and then there are days when I know what I have coming and know I deserve every bit of it. Usually the latter is true. But I think that this gift I have received outlines something important. Christ came to earth to die in our place as the biggest undeserved gift ever. We spend so much time trying to figure out why or wrestle with the nuts and bolts of Christian life and forget to just pick up the gift with a greatful heart and use it to the best of our ability. Does Christ expect our thanks? Yes, but I think the thanks he wants is not the thanks that we generally say in our bedtime prayers, but instead using of his gift to glorify his name.

Wednesday, November 14, 2007

Gibson Robot Guitar


Gibson is releasing a self-tuning guitar called the Gibson Robot Guitar. They are having a make your own video contest to win one. So here is my entry....




Hopefully they will add my video to their site soon for voting. I already have over 1000 views on YouTube so at least some people have seen it :) Enjoy.

The Gibson page is here

Wednesday, October 17, 2007

Out with the Old...


So my effects rack of 13 years finally decided to die on me. It was an ART SGX2000 and it just started flaking out. So I have started from the ground up. I have a BOSS volume pedal from many years back that still works great so to that I added a DS-1 Distortion and BD-2 Blues Driver. Also today I got in a CH-1 Chorus pedal. I built a temporary board for them and this is what it looks like. I got the 1-spot 8 pedal power kit and the CoreX2 solderless cable kit. So far I am very happy.

Wednesday, July 11, 2007

The Wishbook

I used to love making wishlists. As a kid I would circle so many things in the Sears "Wishbook", or I would find something I wanted and work hard to save my pennies to get it.

I have kinda gotten out of the habit in recent years, because as a father of 4 I usually do not have any extra cash to spend on myself. But as I go along I have found that day to day life has actually made me stop wishing for things. I don't spend time dreaming of the what ifs. I am not talking about being materialistic, sitting around being jealous of those who have what we want is very unproductive. But I think that wishing for things can be a great motivator for us to tackle new goals, expand our horizons and go after things that may, in our current circumstance, seem unattainable. Things can certainly own us and there ARE wrong reasons for wanting things. To outdo someone or to hoard something, these are not good. On the other hand things can be symbols. Symbols are so important. Take a look at company logos. It is not enough just to have a name, you need a symbol. If we wish for things in our life that are representative symbols of who we want to become, they can not only aid us once we have them, but can motivate us to become that person who 'deserves' that thing, and perhaps help us take our lives in a new direction that we may have only dreamed or wished about.

Recently (as you can see in another blog post of mine) I entered a contest. First place prize is $57,000. I made a decent entry and so I thought "What if I won?" At first my thoughts went to how much debt I could pay off, but then for the first time in a long time I did a little dreaming. My guitar and rig are old, an old rig for a tired guitarist, but then I thought, what if I could spend $$$ on a real setup. So in the spirit of wishing, here is a link to my wishlist of choice.

Guitar Center Wishlist

As you can see, johnnyGizmo wishes to break out of his cubicle and pursue something more. I have a new excitement in my life. I realize that I very well may not win this contest, but the wishing it prompted has given me something that I needed just as much.