Monday, May 11, 2009

Responding to User ‘Clicks’ (XNA 2D)

We have discussed how to get user input for both the Windows and  Xbox platform, but how are we actually carrying out actions afterwards?

The team on Jojamian uses a simple procedure to handle clicking with either the mouse or GamePad.  You can implement this in your 2D game as well.

For every time Update(); is called in Game.cs, we will check for whether the user has clicked, and respond appropriately.

In Game.cs’ Update(); include the following code;

if (clickEnabled)
{

    if (Game.previousGamePadState.Buttons.A == ButtonState.Pressed &&
        Game.gamePadState.Buttons.A == ButtonState.Released)
    {
        switch (gameState)
        {
            case (int)State.Menu:
                menu.aButtClick(ref gameState);
                break;
            case (int)State.Instructions:
                instructions.aButtClick(ref gameState);
                break;
        }
        clickEnabled = false;
    }

Lets break this code down a bit ->

“if (clickEnabled)”

You will need to declare the bool clickEnabled in the Game class declaration and initialize it as true.

  “switch (gameState)”

The gameState is the current state of the game.  In this example there is a Menu and an Instruction state. 

“menu.aButtClick(ref gameState);”

AND

“instructions.aButtClick(ref gameState)"”

The aButtClick(); function is called from the appropriate class corresponding to the current state. The aButtClick(); function should be placed within the class of that particular state.  The content of aButtClick(); checks the position of the cursor (that we created in an earlier post) and verifies if it is over top of any significant button or action area.  For each action area defined, you write the code that should run.

Has your team implemented a different method of responding to user clicks?  Post them below and others can try all of the possible solutions to see what works best for them.

Sunday, May 10, 2009

Detecting a complete ‘Click’ (XNA 2D)

Our 2D games will need to check if the player is clicking on something at some point.  Clicking means that the player has both pressed and released a button.  How can you check for both of these binary (one or the other) conditions at once?

The answer lies in two different states being monitored for the input device. And today we will discuss how to detect a ‘click’ with a 360 GamePad. This can easily be translated to a keyboard as well, but I’ll leave that up to you and the MSDN XNA Game Studio 3.0 Library to figure out.

This code will declare a global variable to hold the previous and current state of a GamePad.  This includes the thumb stick orientation, which buttons are pressed, etc.  I chose to use a global variable so that all of my classes can access the current state at any given time.

Initializing the GamePad in the Game.cs class member declarations:

public static GamePadState previousGamePadState =
    GamePad.GetState(PlayerIndex.One);
public static GamePadState gamePadState =
    GamePad.GetState(PlayerIndex.One);

At the end of the Update(); function in Game.cs and before base.Update(gameTime); is called, add the following:

previousGamePadState = gamePadState;

Now you are able to keep track of both the current state of a GamePad and the one from the last time Update(); was called [Update(); is called at 60fps unless you have specified it to run otherwise]from within any class.

The next article will describe one way to implement this code to respond to user clicks at any given moment.  There are some libraries that can make this easier for you, but before you throw off calculations to code someone else wrote, it would be best to fully understand it yourself.

Saturday, May 9, 2009

Integrating 360 code into a PC project

In the previous post I discussed the code required to make use of a cursor with the Xbox 360.  Today we will discuss specifying the difference between code for the PC and the 360 version of your game.  If you are in the same boat as me and are working on both a PC and 360 version of your game at the same time, you will need to differentiate the two sets of code from each other.

First of all make sure you have two projects – one for PC and one for Xbox.  Depending on which project type you started out with, there will be an option to create the alternative by navigating to Project –> Create Copy of [Project Name] for [Desired Platform].

The commands for splitting up the code are simple:

#if WINDOWS

     //Execute Windows Specific code here

#endif

#if XBOX

     //Execute similar Xbox specific code here

#endif

You will notice one or the other will appear grayed out.  If you opened the file you are currently working on from underneath the Windows project, the Xbox code will be grayed out, and visa versa.  Note: Intellisense will be disabled for the grayed out text as well.

I use the #if statements where clicks from an input device are recognized, and in my cursor class.  Instead of getting the current mouse positions, I had to use the GamePad input gathered with code discussed in the previous post.

Check out a working example in Update(); of the cursor class:

#if WINDOWS
       mouseState = Mouse.GetState();
       this.position = new Vector2(mouseState.X, mouseState.Y);       
#endif

#if XBOX
      this.position = new Vector2(Game.xbCursorX, Game.xbCursorY);       
#endif

As you can see, Update(); will either draw the cursor relative to the mouse pointer’s position if built for Windows, and relative to the input we gathered from the user’s GamePad is built for the Xbox.

Using these #if statements is how I intend to go about solving my graphics dilemma when I begin to tackle that issue.

Try copying some existing code in your project and modifying it a bit.  Add the different #if statements around it, and then build and run the code on both Windows and the Xbox.  You will see that it runs according to the commands you have provided.

Have you used these statements before?  I’m curious…besides input, what other type of code needs to be differentiated between Windows and Xbox? Are there more #if statements to be found?  Leave your  comments below.

Friday, May 8, 2009

Porting PC to 360 (XNA) - Input

This last week I have been porting our game, Jojamian, to the Xbox 360. Two of the largest things that I must convert is input and graphics.

Today I am going to explain a little about input, and give you some sample code that allows GamePad users on the 360 to navigate using the same cursor as their PC friends.

You can look up the MouseState code on the MSDN Library for XNA Game Studio Express 3.0. For the sake of KISS, I’m just going to show you the translation of that for the GamePad.

In the class declaration for your Game.cs, add the following:

//Variables for X and Y position of the cursor

public static int xbCursorX;
public static int xbCursorY;

//Initializing GamePad State

public static GamePadState gamePadState =
GamePad.GetState(PlayerIndex.One);

In the main Game.cs, this was added to Draw();

//Update the state of gamePadState
gamePadState = GamePad.GetState(PlayerIndex.One);

//Update cursor for 360 controller input
if (gamePadState.ThumbSticks.Left.X > 0.0f)
xbCursorX += 5;

if (gamePadState.ThumbSticks.Left.X < 0.0f)
xbCursorX -= 5;

if (gamePadState.ThumbSticks.Left.Y > 0.0f)
xbCursorY -= 5;

if (gamePadState.ThumbSticks.Left.Y < 0.0f)
xbCursorY += 5;

Our Cursor.cs handles where the cursor is drawn:

PC: this.position = new Vector2(mouseState.X, mouseState.Y);

360:this.position = new Vector2(Game.xbCursorX, Game.xbCursorY);

There are two things to note with this cursor input. First of all, the bounds for the cursor are not set, so the user can take the cursor off the screen. Second, I am getting an error with the code. It seems that rapidly tapping left twice on the analog stick causes it to keep moving the cursor to the left. I have yet to deduce whether it is a mechanical error with my single controller or a problem in the code.

Try implementing the same coding concepts into your game and see how it turns out. If it works for you, tell me about it in the comments. If you have a better way of doing it, by all means feel free to comment below as well. GL and GG.

Current Game Project (XNA)

So I’ve been working for the last 2.x months with a team of friends from school.  We’ve been developing an abstract strategy board game called Jojamian.

It works similarly to Othello, Focus, and Attax.  You can either multiply an existing piece into an empty adjacent tile, or take any of your pieces and jump in one direction over one tile into an empty piece.  If your piece touches an opponent’s after moving, it becomes yours.

Currently we have a two player mode available for play, and have recently submitted it to 2beegames.com.  I’ll post when the judging site goes live and Jojamian will be available for download from there.