Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I've made two simple 2D games while following tutorials for the XNA libraries, and I wanted to make something myself, with only the knowledge I gained from these tutorials.

This will be my first serious attempt at game development, as well as my first C#/XNA project. I migrated from Java a week ago. Now, both of the tutorials I've followed made the whole game using only one class. And while it's possible, it isn't organized enough for me, and I want most of the functions to be organized in separate classes. So, I started with Input so I can have an easy way of exiting the game during testing right away.

Here's the important bits, I think:

From my Game1.cs:

protected override void Update(GameTime gameTime)
{
    Input input = new Input();
    input.PollInput();

    // TODO: Add your update logic here

    base.Update(gameTime);
}

From my Input.cs:

namespace MyFirst2DGame
{
    class Input
    {
        Game1 game = new Game1();

        public void PollInput()
        {
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                game.Exit();
        }
    }
}

However, when I run the project, the Back button on the XBox 360 controller does nothing. My question, is am I missing something? I have no idea how to do anything with multiple classes, as all of my Java projects were quite small and had need for only one class.

share|improve this question
    
Is your controller really conected with the player index 1? You could try to check for a pressed key on your keyboard in PollInput() to eliminate a problem with your controller. –  mpistrich Oct 17 '11 at 6:33
    
if (Keyboard.GetState().IsKeyDown(Keys.Escape)) game.Exit(); –  Chris Vollink Oct 17 '11 at 6:44
    
I placed that under the GamePad if statement, and the problem persists. So there must be a problem with the code. :/ –  Chris Vollink Oct 17 '11 at 6:45
add comment

3 Answers

You are creating a new game1 object in your PollInput command, since that's not your original game object, calling exit on it does nothing.

Usual practice would be to pass in your existing game object in the constructor of your Input class.

I'd also avoid creating a new Input object every loop of Update. Create it once and re-use it. This particularly matters when developing on the xbox (i guess you are since you're using a gamepad, not keyboard) since the garbage collection engine isn't as good as the PC, so you want to reuse objects as much as possible.


You could make your Input class inherit from GameComponent, calling it something like InputHandler, or InputComponent if you like. You'd then pass in the Game into the base constructor, and override the Update method.

If you do this, you can add to your game's Components in your game's constructor, which would make its update method get called automatically.

You don't have to use that part of the framework though, so really it's up to you.


Also, it's bad practice to depend on PlayerIndex.One, better is to use a loop:

for(var PI = PlayerIndex.One;PI <= PlayerIndex.Four; PI++)
{
    if (GamePad.GetState(PI).Buttons.Back == ButtonState.Pressed)
        game.Exit();
}

Although normally you'd have a 'Press Start' screen and only use that player's index. The code for that could look like the above.


It's probably worth going to the Creators App Hub.

Take a look at their samples for standard ways to lay code out. Particularly the Game State Management sample.

share|improve this answer
add comment

I think the problem is in your PollInput(). You instantiate a new Game1 object in your Input class. When you press the button on your controller, you exit the game object of the newly generated game class, not the game class which generated your Input.

One solution would be to pass the game object to the constructor of the Input like this:

public Input(Game game)
{
    this.game = game;
}
share|improve this answer
    
Lol, this question was asked an hour ago, and we both answered within one minute of eachother! –  George Duckett Oct 17 '11 at 7:02
    
Yeah, what a coincidence :) –  mpistrich Oct 17 '11 at 7:11
add comment

One problem you'll run into very quickly is putting too much game logic into your input class. You're better off creating an intermediate class that handles game logic and input. Your input classes should be just wrappers around the various devices and provide some utility functions.

Something like this:

class MyGame : Game
{
    Input _input;                // Utility class that provides helpers for input
    UnitManager _units;          // Tracker for units
    InputHandler _inputHandler;  // Connects game units with input

    protected override void Initialize()
    {
        _input = new Input();
        _units = new UnitManager(this);

        // InputHandler will probably want the game, units, and the input helper.
        // (Or it internally manages the input util class)
        _inputHandler = new InputHandler(this, _input, _units);

        base.Initialize();
    }

    protected override void Update(GameTime time)
    {
        _input.Update(time);  // Update input states - new clicks, presses, etc...
        _units.Update(time);  // AI moves
        _inputHandler(time);  // Check input for clicks, button presses, etc...

        base.Initialize();
    }
}

Edit: Further examples...

The Input class I use is just a wrapper and some utility functions.

InputManager - Just holds three helpers for keyboard, mouse, and controller. I make this relatively global by creating it in my Game instance and passing it down into the various screens and components.

Helpers:

ControllerHelper, KeyboardHelper, MouseHelper - These all get updated and store the last and current state so you can have easier helpers like Input.Keyboard.IsNewKeyPress(Keys.W) and Input.Keyboard.IsKeyHeld(Keys.Space). Makes checking and storing that information much easier - your logic class doesn't have to concern itself with handling input states, just checking for state changes.

I use an entity system which is a whole other topic, but it gives me the InputHandler class mentioned above. Here's some roughcode for it:

public class InputHandler
{
     MyGame _game;   // Assuming Input is a property here
     Player _player;

     // Constructor - pass any dependencies here
     public InputHandler(MyGame game, Player player)
     {
         _game = game;
         _player = player;
     }

     // Update, as usual
     public void Update(GameTime time)
     {
         if (_game.Input.IsKeyDown(Keys.W))
         {
             _player.Position.X += 1;
         }

         if (_game.Input.IsKeyDown(Keys.S))
         {
             _player.Position.X -= 1;
         }

         // And so on...
         // You probably wouldn't be using 1 as a speed, factor in
         // the elapsed time since the last update for smoother movement
         // in case of slow-downs and add in a speed variable to
         // control that.

         // XBox controller input is pretty much the same, just you can
         // get 0.0 - 1.0 Vector2's from the thumbsticks.

         // Not all your input has to go here either.  If you use a game
         // state system, each game state might have it's own InputHandler
         // class (ie, a menu state would handle up/down differently than
         // in game.

         // Elsewhere would be a camera class that takes the player as
         // a dependency and updates the view matrix from player position
         // and rotation.
     }
}
share|improve this answer
    
Could you maybe be more clear about the difference between Input and InputHandler? Maybe show some pseudocode. This seems very interesting. –  pek Oct 19 '11 at 1:45
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.