Moving my sprite in XNA using classes

Hey, im a newbie at this programming lark and its really frustrating me. I'm trying to move a snake in all directions while using classes. Ive created a vector2 for speed and ive attempted creating a method which moves the snake within the snake class.

Now I'm confused and not sure what to do next.

Appreciate any help. Thanks :D

This is what i've done in terms of the method...

  public Vector2 direction()
{
Vector2 inputDirection = Vector2.Zero;

if (Keyboard.GetState().IsKeyDown(Keys.Left)) inputDirection.X -= -1;
if (Keyboard.GetState().IsKeyDown(Keys.Right)) inputDirection.X += 1;
if (Keyboard.GetState().IsKeyDown(Keys.Up)) inputDirection.Y -= -1;
if (Keyboard.GetState().IsKeyDown(Keys.Down)) inputDirection.Y += 1;

return inputDirection * snakeSpeed;

}


Appreciate any help. Thanks :D

EDIT:
Well let me make everything clear. Im making a small basic game for an assignment. The game is similar to the old snake game on the old Nokia phones. I've created a snake class (even though I'm not sure whether this is needed because im only going to be having one moving sprite within the game). After I written the code above (in the snake class), the game ran with no errors but I couldn't actually move the image :(

EDIT2: Thanks so much for everyones responses!!

• Appologies for the bad quote of my code :/ – user5141 Feb 3 '11 at 16:45
• This seems like a workable approach, but I don't see an actual question here. Are you asking how to make use of the result of your "direction" function to actually move an object? – user1430 Feb 3 '11 at 16:54
• I think if you post the code that actually uses the output from this direction method, we might be able to help. I think the error is in how you are updating the position of the sprite. – Michael Coleman Feb 3 '11 at 21:27
• Upvoting and accepting answers is another way, GD's way to thank your fellow developers who helped you achieve your goal. =) – Will Marcouiller Feb 4 '11 at 11:46

Although I am also a newbie in game development, my bet would be that you are always reinitializing your inputDirection variable to Vector2.Zero.

I don't know much about game development, but as for object-oriented programming, that is another thing! Here what I have come with after having read your comment about classes.

public class Snake {
private Texture2D _snake; // Represents your snake's sprite.
private Vector2 _snakePos; // Field that determines your snake's position.
private Vector2 _snakeSpeed = new Vector2(10.0f, 10.0f); // Field that determines the number of pixels your snake will move at once while moving.

public Snake(Vector2 initialPosition) {
_snakePos = initialPosition;
}

public void MoveDown() {
_snakePos.Y += _snakeSpeed.Y;
}

public void MoveLeft() {
_snakePos.X -= _snakeSpeed.X;
}

public void MoveRight() {
_snakePos.X += _snakeSpeed.Y;
}

public void MoveUp() {
_snakePos.Y -= _snakeSpeed.Y;
}
}

public class Game Game1 {
private Snake _snake = new Snake();

protected override void Update(GameTime gameTime) {
Keys[] keys = Keyboard.GetState().GetPressedKeys();

if (keys != null && keys.Length > 0)
switch (keys[0]) {
case Keys.Escape:
Exit();
break;
case Keys.Down:
_snake.MoveDown();
break;
case Keys.Left:
_snake.MoveLeft();
break;
case Keys.Right:
_snake.MoveRight();
break;
case Keys.Up:
_snake.MoveUp();
break;
default:
break;
}
}
}


I hope this helps, and to be on the right direction to a viable solution! =)

• This seems a long winded way to use a few buttons.. but what do I know lol. I actually have no idea what I'm doing in terms of classes :(. – user5141 Feb 3 '11 at 17:41
• In fact, this is your Snake class that should be aware of its speed and direction. Aside, this is the game that is getting the user inputs. So, in my understanding, you have to make the snake know what direction it shall head next, that is, I believe that you should have, within your Snake class, four methods: MoveDown(), MoveLeft(), MoveRight() and MoveUp(). It is the snake that knows what to do to move one way or another, and since it also knows its speed, it shall move accordingly. Then, in your Game class, instantiate your snake, and input the directions through its methods! – Will Marcouiller Feb 3 '11 at 17:47
• Please, see my edited answer as I have included a possible Snake class exposing four Move methods. The snake doesn't have to know what key has been pressed, rather your game shall get the keys. Then, it is your game that tells your snake where to go depending on the keys that have been pressed by the player. Then, your game tells your _snake instance to MoveLeft, MoveDown etc. depending on the keys that you pressed. Let me know if this helps! And feel free to comment about stuff you don't get working or so, I'll be glad to help the most I can. – Will Marcouiller Feb 3 '11 at 18:01
• Thank you so much, this is exactly what I was looking for in terms of an answer. You called yourself a newbie but showed otherwise :). I'm literally awful at this coding jazz. My confusion is when using classes for everything (which is probably key). – user5141 Feb 3 '11 at 19:14
• Imo, Head First C# is a neat book for getting a good object-oriented primer while actually producing visible results all the way through. – Oskar Duveborn Feb 3 '11 at 21:07

I use code like this to move my sprites, it tends to work quite well for me, it also uses "GameTime" to ensure movement is consistent across frame-rates.

// Sprite Protecteds
Vector2 direction;
Vector2 position;
float speed;

// Sprite Code
void Update(GameTime time, KeyboardState kb)
{
// reset to zero for no keys pressed
direction = Vector2.Zero;

if (Keyboard.GetState().IsKeyDown(Keys.Left)) direction.X = -1;
if (Keyboard.GetState().IsKeyDown(Keys.Right)) direction.X = 1;
if (Keyboard.GetState().IsKeyDown(Keys.Up)) direction.Y = -1;
if (Keyboard.GetState().IsKeyDown(Keys.Down)) direction.Y = 1;

position += direction * speed * time. Milliseconds;
}

// Game "Update" method (not sure of exact code here)
sprite.Update(gameTime, Keyboard.GetState());


Obviously you may want to provide more parameters to the sprite during its update process, so you may very the speed or other things as well.

• There should be giant red stickers all over every XNA tutorial to inform people of the use of GameTime to modify all frame-by-frame events that you want to be updated at a constant real-time rate to provide a consistent player experience regardless of hardware. – Bill Feb 3 '11 at 22:05
• @Bill: My sentiments exactly. – Michael Coleman Feb 4 '11 at 1:11

This question needs more lambdas.

Note this is from a WIP, so there's some unused and implied-but-unimplemented features. Where you see the () => add your inputDirection.X -= -1;. I realize this is for a Gamepad and you're using a keyboard, but the grouping principle, or at least the notion of the action map still applies.

This is probably overkill, but lots of fun!

Setup function that maps the controls:

public void SetController(MyGamePad controller)
{
controller.ClearActions();

controller.BindAction(Buttons.Start, ButtonGroup.FullyExclusive, () => sine.play());

controller.BindAction(Buttons.A,
ButtonGroup.FaceButtons, () => showText("A!"));
controller.BindAction(Buttons.A | Buttons.B,
ButtonGroup.FaceButtons, () => showText("A and B!"));
controller.BindAction(Buttons.B,
ButtonGroup.FaceButtons, () => showText("B"));
controller.BindAction(Buttons.B | Buttons.Y,
ButtonGroup.FaceButtons, () => showText("B and Y!"));
controller.BindAction(Buttons.Y,
ButtonGroup.FaceButtons, () => showText("Y!"));
controller.BindAction(Buttons.Y | Buttons.X,
ButtonGroup.FaceButtons, () => showText("Y and X!"));
controller.BindAction(Buttons.X,
ButtonGroup.FaceButtons, () => showText("X!"));
controller.BindAction(Buttons.X | Buttons.A,
ButtonGroup.FaceButtons, () => showText("X n A, I made a funny!"));
controller.BindAction(0x0,
ButtonGroup.FaceButtons, () => showText("Nothing on the face buttons."));

controller.BindAction(0x0,
ButtonGroup.ShoulderButtons, () => showText("No shoulder buttons"));
controller.BindAction(Buttons.LeftShoulder,
ButtonGroup.ShoulderButtons, () => showText("Left shoulder button!"));
controller.BindAction(Buttons.RightShoulder,
ButtonGroup.ShoulderButtons, () => showText("Right shoulder button!"));

controller.BindAction(0x0,
}


The game component that makes it work (instantiate 1 per player):

using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using System.Collections.Generic;

namespace MyGame
{
[Flags]
public enum ButtonGroup
{
NonExclusive            = 0x00,
FaceButtons             = 0x01,
ShoulderButtons         = 0x04,
LeftSide                = 0x08,
RightSide               = 0x10,
FullyExclusive          = 0xFF,
}

{
private Buttons FaceButtons;
private Buttons DirectionalButtons;
private Buttons ShoulderButtons;
private Buttons LeftSideButtons;
private Buttons RightSideButtons;
private Buttons AllButtons;

private PlayerIndex playerIndex;
private Dictionary<KeyValuePair<Buttons, ButtonGroup>, Action> actionMap = new Dictionary<KeyValuePair<Buttons, ButtonGroup>, Action>();

public InstrumentPad(Game game, PlayerIndex playerIndex) : base(game)
{
this.playerIndex = playerIndex;
}

public void ClearActions()
{
actionMap.Clear();
}

public override void Update(GameTime gameTime)
{
base.Update(gameTime);

updateButtons();

foreach (KeyValuePair<Buttons, ButtonGroup> pair in actionMap.Keys)
{
switch (pair.Value)
{
if (DirectionalButtons == pair.Key)
actionMap[pair].Invoke();
break;
case ButtonGroup.FaceButtons:
if (FaceButtons == pair.Key)
actionMap[pair].Invoke();
break;
case ButtonGroup.ShoulderButtons:
if (ShoulderButtons == pair.Key)
actionMap[pair].Invoke();
break;
case ButtonGroup.LeftSide:
if (LeftSideButtons == pair.Key)
actionMap[pair].Invoke();
break;
case ButtonGroup.RightSide:
if (RightSideButtons == pair.Key)
actionMap[pair].Invoke();
break;
case ButtonGroup.FullyExclusive:
if (AllButtons == pair.Key)
actionMap[pair].Invoke();
break;
case ButtonGroup.NonExclusive:
if ((AllButtons & pair.Key) == pair.Key)
actionMap[pair].Invoke();
break;
}
}
}

public void BindAction(Buttons buttonCombo, ButtonGroup buttonGrouping, Action action)
{
KeyValuePair<Buttons, ButtonGroup> pair = new KeyValuePair<Buttons, ButtonGroup>(buttonCombo, buttonGrouping);
if (!actionMap.ContainsKey(pair))
else
actionMap[pair] = action;
}

private void updateButtons()
{
LeftSideButtons = 0x0;
RightSideButtons = 0x0;

FaceButtons = 0x0;
FaceButtons |= Buttons.A;
FaceButtons |= Buttons.B;
FaceButtons |= Buttons.X;
FaceButtons |= Buttons.Y;

RightSideButtons |= FaceButtons;

DirectionalButtons = 0x0;

LeftSideButtons |= DirectionalButtons;

ShoulderButtons = 0x0;
{
ShoulderButtons |= Buttons.LeftShoulder;
LeftSideButtons |= Buttons.LeftShoulder;
}
{
ShoulderButtons |= Buttons.RightShoulder;
RightSideButtons |= Buttons.RightShoulder;
}

AllButtons = LeftSideButtons | RightSideButtons;

AllButtons |= Buttons.Start;
AllButtons |= Buttons.Back;
}
}
}


Now I'm confused and not sure what to do next.

Does this mean your code isn't doing what you think it should be doing or do you have some feature that you need to implement that you don't know how or do you want advice on what feature to implement next?

Either way...

if (Keyboard.GetState().IsKeyDown(Keys.Left)) inputDirection.X -= -1;
if (Keyboard.GetState().IsKeyDown(Keys.Right)) inputDirection.X += 1;


You don't want to subtract a negative for one direction and add a positive in the other. Those two evaluate to the same thing.

• Well let me make everything clear. Im making a small basic game for an assignment. The game is similar to the old snake game on the old Nokia phones. I've created a snake class (even though I'm not sure whether this is needed because im only going to be having one moving sprite within the game). After I written the code above (in the snake class), the game ran with no errors but I couldn't actually move the image :( – user5141 Feb 3 '11 at 17:26
• @Tom, you should put the clarification in the question itself. – Tetrad Feb 3 '11 at 17:44

Here's how I'm doing this in one of my games on Windows Phone. Bear in mind that I have made some simplifications for the sake of example. In my game, enemies follow a set of waypoints along a path.

In the Update method inside my Enemy.cs class, I evaluate Enemy.Waypoints.Peek() - Enemy.Position (normalized) to determine which direction the enemy should be moving.

this.Direction = this.Waypoints.Peek() - this.Position;
this.Direction.Normalize();


Then, I calculate the velocity (direction + speed) for the current frame using the direction.

this.Velocity = Vector2.Multiply(this.Direction, Settings.Speed * this.Speed);


Finally, I adjust the actual position of the enemy.

// Adjust the position according to the velocity.
this.Position += this.Velocity;


It helps to understand the math involved, but this is how you can move an object.