Monday, April 9, 2007

XNA Asteroids Part 1---Tutorial #3 : Taking Keyboard Input and Using It.



Alright, so, what we're going to do in this tutorial is we're going to use the arrow keys to move a spaceship around the screen, this will be the first official part of an asteroidish game tutorial.

We will create a spaceship class with a constructor, an update class, and a draw class which will be called on the main Update and Draw functions.
So first as always gather your art assets. All you need is a top down spaceship.

So if you've been following my other tutorials we of course need to start by creating some variables. Not much though.

SpriteBatch batch; //Create the SpriteBatch required to draw in 2D
SpaceShip mainShip;
//Create an instance of our SpaceShip class that will be written soon.

In the Intialize function we want to intialize the spritebatch, the instance, and change the window title.

batch = new SpriteBatch(graphics.GraphicsDevice); //Like before, initalize
mainShip = new SpaceShip(new Vector2(100, 100), //Where do we want to start?content.Load"SpaceShip"));
//SpaceShip is the art asset name of the ship we want to draw.
Window.Title = "Asteroids! Written by (Your Name Here)!"; //Our window title.

Now on the Update Function put this line:
mainShip.Update(graphics.PreferredBackBufferHeight,graphics.PreferredBackBufferWidth);
//We call the mainShip's Update function and input the dimensions of the screen for
//the world wrap function that's in the update function.

In the Draw function put this:

batch.Begin(); //Between Begin() and End() we can draw.
mainShip.Draw(batch); //Call the mainShip's function with the spriteBatch parameter.
batch.End();

Now for the main part of the program. The SpaceShip class.

Depdendencies:

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


using namespace PutNameSpaceHere
{
class SpaceShip
{
private Vector2 pos; //Our position in 2D.
private Texture2D tex; //Our texture
private float speed = 8; //The speed to move.
private float angleOfRotation = 0;
//We will just face whatever direction the art is already facing.
The constructor:
public SpaceShip(Vector2 pos, Texture2D tex) //Parameters needed.
{
this.pos = pos; //Our starting position
this.tex = tex; //Our texture
}
The WorldWrap function:
private void WorldWrap(int worldWidth, int worldHeight) //Take window dimensions
{
if (this.pos.X < 0)
//If we've past the left side of the window
{
//Set on other side of the world.
this.pos.X = worldWidth + this.tex.Width;
}
if (this.pos.X > worldWidth)
//If we've passed the right side of the window
{
//Set on other side of the world.
this.pos.X = this.tex.Width;
}
if (this.pos.Y < 0)
//If we've passed the top side of the window
{
//Set on other side of the world.
this.pos.Y = worldHeight - this.tex.Height;
}
if (this.pos.Y > worldHeight)
//If we've passed the bottom side of the window
{
//Set on other side of the world.
this.pos.Y = this.tex.Height;
}
}
The Update Function:
public void Update(int WorldWidth, int WorldHeight) //Get world dimensions
{
KeyboardState keys = Keyboard.GetState(); //Current state of keyboard
if (keys.IsKeyDown(Keys.A))
{
//We want to turn the ship LEFT
this.angleOfRotation -= 2f; //Rotate it counter-clockwise
}
if (keys.IsKeyDown(Keys.D))
{
//We want to turn the ship RIGHT
this.angleOfRotation += 2f; //Rotate it clockwise
}
if (keys.IsKeyDown(Keys.W))
{
//We're pressing the up key (W) so go Forwards!
this.pos.X += (float)(Math.Cos(this.angleOfRotation * Math.PI / 180) * this.speed);
//Math.Cos(directionInRadians)*SpeedToMoveAt, to move at a certain angle
this.pos.Y += (float)(Math.Sin(this.angleOfRotation * Math.PI / 180) * this.speed);
}
if (keys.IsKeyDown(Keys.S))
{
//We're pressing the down key (S) so go Backwards!
this.pos.X -= (float)(Math.Cos(this.angleOfRotation * Math.PI / 180) * this.speed);
//-= instead of += (float)(...) because we want to go backwards not forwards
this.pos.Y -= (float)(Math.Sin(this.angleOfRotation * Math.PI / 180) * this.speed);
}
//Call the WorldWrap function to check if we need to move the ship.
WorldWrap(WorldWidth, WorldHeight);
}
Draw Function:
public void Draw(SpriteBatch batch)
{
batch.Draw(this.tex, //Texture to use.
this.pos, //Position to draw at
new Rectangle(0, 0, this.tex.Width, this.tex.Height),
//Rectangle to draw. We want the whole thing so (0,0) is top left and (width,height)
//the bottom left corner
Color.White, //No color tint.
(float)((this.angleOfRotation +90)* Math.PI / 180), //Our angle +90 (we face up but the angle says we face right so increase our angle that we draw at by 90).
new Vector2(this.tex.Width / 2, this.tex.Height / 2),
1.0f, //Scale, doesn't really matter right now. 1 = 100% to texture's original scale.
SpriteEffects.None, //No special effects.
1.0f); //Depth, doesn't really matter right now.
//batch.Draw(
} //End Draw function
} //End class
} //End namespace

Done!!! Alright, great. Not that hard huh? We should now be able to move the spaceship around the screen with WASD, W and S to move forwards and backwards and A and D to turn left and right. We can also like in asteroids *teleport* from side to side.

First feedback!

Whoooo!!! I got some feedback from someone and I'm excited, I can't believe people are actually reading what I write about so I'm going to keep going =D. Ok, just had to get that out.

Sunday, April 8, 2007

XNA Tutorial 2: Cursors and Buttons




The second tutorial in a hopefully long list. This tutorial will cover how to create a cursor in XNA, check to see if you have clicked on a button.
First thing you need to do is gather the artwork. You need a cursor, a button, an image that represents Hovering, and another that represents Clicking.
Create your Windows Game project with the name of something like Cursors-Buttons Example.
Add the artwork to the project.
The way we're going to do this is we're going to create a mouseHandler class that will handle drawing the mouse and changing it's position to wherever the mouse is, giving the effect of a cursor. We'll also create a button class that will handle it's own drawing and will be used with a MouseHandler function to check if it's being hovered over which will lead to checking if it's being clicked.
We'll add the button to a Button list that we'll go through during the Draw function to draw every button in the list (only one). We just hardcode the other sprites to appear depending on if we're hovering over the button or clicking it respectively.
On the update we check if we click and/or hover over the button.
Beggining variables:

SpriteBatch batch; //Needed for 2D drawing
MouseHandler ourMouse; //An instance of the MouseHandler class
Texture2D onHover; //The Hover image texture
Texture2D onClick; //The Click image texxture
Vector2 hoverPos; //The position of the Hover sprite
Vector2 clickPos; //The position of the Click sprite
List <>buttonlist; //Our list of buttons
Button mainButton; //An instance of Button
bool Clicking; //Are we clicking?
bool Hovering; //Are we hovering?
MouseState mouseState; //MouseState needed for what checking our mouseClicks and location
That's all pretty much goes without saying, MouseHandler and Button are classes that I created, we will go over them right now.
The MouseHandler class goes in it's own .cs file.
Dependencies:

using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
Code:

class MouseHandler
{
private Vector2 pos;
private Texture2D tex;
private MouseState mouseState;
//We create variables

public MouseHandler(Vector2 pos, Texture2D tex)
{
this.pos = pos; //Inital pos (0,0)
this.tex = tex; //Cursor texture
}
//On Update we will call this function
public void Update()
{
mouseState = Mouse.GetState(); //Needed to find the most current mouse states.
this.pos.X = mouseState.X; //Change x pos to mouseX
this.pos.Y = mouseState.Y; //Change y pos to mouseY
}
//Drawing function to be called in the main Draw function.
public void Draw(SpriteBatch batch) //SpriteBatch to use.
{
batch.Draw(this.tex, this.pos, Color.White); //Draw it using the batch.
}

public bool ButtonClick(Button b)
{
if (this.pos.X >= b.position.X // To the right of the left side
&& this.pos.X < b.position.X + b.tex.Width //To the left of the right side
&& this.pos.Y > b.position.Y //Below the top side
&& this.pos.Y < b.position.Y + b.tex.Height) //Above the bottom side
return true; //We are; return true.
else
return false; //We're not; return false.
}
That's it for the mouseHandler class.
The button class:
Dependencies:

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

class Button
{
public Vector2 position;
public Texture2D tex;
//Set up variables
public Button(Vector2 position, Texture2D tex) //Our constructor
{
this.position = position; //Position in 2D
this.tex = tex; //Our texture to draw
}
public void Draw(SpriteBatch batch) //Draw function, same as mousehandler one.
{
batch.Draw(tex, position, Color.White);
}
}
Alright, almost done.

batch = new SpriteBatch(graphics.GraphicsDevice); //A SpriteBatch is born.

//Handle the button creation
mainButton = new Button(new Vector2(250, 100), content.Load(@"Button"));
//Actually creating the button.
this.buttonlist = new List
<>(); //Actually creating the list
this.buttonlist.Add(mainButton); //Add the button we recently made to the list.

//Handle the cursor creation
ourMouse = new MouseHandler(new Vector2(0, 0), content.Load(@"cursor"));
//Actually creating the MouseHandler now.

//Handle extra sprites.
onHover = content.Load(@"hovering"); //Sets texture to be used
onClick = content.Load(@"clicked"); //Sets texture to be used
hoverPos = new Vector2(250, 200); //Sets position
clickPos = new Vector2(250, 300); //Sets position
Alright, getting there...
Updating the game.
Here's the function that will handle the mouseClicking.

private void HandleMouse()
{
mouseState = Mouse.GetState(); //Get the current state of the mouse
if (ourMouse.ButtonClick(mainButton)) //There's only one button, so we just hardcode it.
//If we're hovering over the mouse
Hovering = true; //We ARE hovering
else
Hovering = false; //Not hovering.
//We don't even need to use ButtonClick() again if we know if we're hovering.
if (mouseState.LeftButton == ButtonState.Pressed && Hovering) //If we're clicking with the Left Mouse Button and we're over the button.
Clicking = true; //We ARE clicking
else
Clicking = false; //Not clicking
}
This function will be called in the Update function.
Heres the added code for the update function:

HandleMouse(); //Check clicking
ourMouse.Update(); //Update the mouse's position.
The Draw function.

batch.Begin();
//Between batch.Begin() and batch.End() we are allowed to draw.
foreach (Button b in buttonlist) //For every button run through the code between the {}
{
//For every button in our list, draw it
b.Draw(batch);
}
if (Hovering) //If we are hovering
{
//Draw the hover sprite
batch.Draw(this.onHover, this.hoverPos, Color.White);
}
if (Clicking) //If we are clicking
{
//Draw the clicking sprite.
batch.Draw(this.onClick, this.clickPos, Color.White);
}
//Draw the mouse.
ourMouse.Draw(batch);
//Done
batch.End();

Wala! Finito! Finished! Enjoy. I may be creating an add onto this tutorial that will cover menus and that kind of thing. Scenegraphs need to be covered too, they're used in the SpaceWars example that comes with XNA and they are really great.

XNA tutorial 1: Drawing a sprite.


First tutorial about XNA, it's going to cover simply how to draw a sprite onto the screen. So first start up C# express and create a new project using the Windows Game template, name it something simple like StubbsTutorial1.


Okay, go find a suitable picture to use for this tutorial, I used the picture at this location:


I just searched for "XNA" on google and found it. Save it and then add it to the project. Either rename the file to xna if it's not already xna.someExtension or change the name xna to whatever the name is when we load it in the initialization function in the code.


Alright, now open up the file Game1.cs, we need to create three variables that will let us draw the sprite.


SpriteBatch batch; //Required to draw the texture
Texture2D tex; //The texture to be drawn
Vector2 position2D; //The position of the texture


Spritebatch is needed to draw the sprites, we only need one. Then we create a Texture2D variable named tex, this will be the texture for our sprite. Then we have the Vector2 position (floatx, floaty), this will tell the computer where to put the sprite on the screen when it's drawn.


Now we need to give these variables some data to hold.


Go to the initialize function in the same Game1 class. Put this code in there:


batch = new SpriteBatch(graphics.GraphicsDevice); //That's the spritebatch.
tex = content.Load(@"xna");

//change xna to whatever the name of the texture file is (example:@"texture")

//We don't need to put the extension, (xna.jpg is not in a folder by the way).
position2D = new Vector2(200, 200); //X pos is 200, Y pos is 200.


So we have finished making the spritebatch, we loaded the texture from the file xna.jpg, and we chose where to put the sprite when we draw it.


Pretty easy huh? Now all that's left to do is to actually tell the computer to draw it.

So, go to the Draw function of the Game1 class.


Put this code in before the line base.Draw(gameTime);


batch.Begin();


We start the batch, whatever is in between batch.Begin() and batch.End() will be drawn, it will give an error if you did batch.Draw() outside of Begin and End.


batch.Draw(tex, position2D, Color.White);


We draw the sprite using tex as the texture, position2D as the x,y position, and we have no color tint which means we use Color.White.


batch.End();


We here end the batch so no more drawing.


Run it, you should get a picture in the window.

Hello All

First post of the blog! I'll just say some stuff of what this blog is going to be all about.

Even though there are already what? 10 Strong XNA/C# sites out there, and something like 10 other XNA blogs, I think that the community hasn't even scratched the surface. This blog is dedicated to XNA/C# support, tutorials, XNA game and site reviews, examples, experiments, articles talking about articles and all that good stuff. If this blog gets successfull I'll start up some forums. I plan to start out by creating some tutorials on some basic things and then try to delve into more complex topics. I hope anyone reading this enjoys the future blog or at least the idea behind it.

-Kevin Stubbs