Now the player character is moving pretty well. Currently all art work is very basic, as I’ll probably change most shape colours with brushes, but it’s enough to get an idea of what is going on. I'll post a video of it tomorrow.
The character can currently do these things:
- Move up, down, left and right depending on the keys pressed.
- Lay prone when you press the “left shift” key.
- Will look in the direction of the mouse when the player is not moving and laying prone.
The extra actions I’d like to add in the future are:
- The ability to throw a “ball” to distract enemies.
- The ability to shoot, and perhaps punch.
- Animation for moving, laying prone, and crawling.
To get the player to move, you need to give the player class a TranslateTransform object, and a RotateTransform object, and put them into a TransformGroup. This is how you control the player’s rotation and position. The game loop must then update these objects as the user presses keys.
Here’s the code I used to create the objects, and the game loop I used to update said objects:
The Player Constructor and properties (Within the Player Class) :
/// <summary>
/// The speed the player moves at.
/// </summary>
public static int playerMove = 6;
/// <summary>
/// The speed the player moves at when prone.
/// </summary>
public static int playerMoveProne = 3;
Point headCenter;
public DrawingVisual playerChar;
public DrawingVisual crouchPlayerChar;
public byte [] directions;
public double posX, posY;
public RotateTransform rotate;
public PlayerState pState;
private TranslateTransform translate;
private TransformGroup transGroup;
private int moveSpeed;
public Player()
{
headCenter = new Point(0, 0);
directions = new byte[4];
playerChar = new DrawingVisual();
crouchPlayerChar = new DrawingVisual();
pState = PlayerState.Normal;
posX = posY = 0.0;
rotate = new RotateTransform(-90.0, 0, 0);
translate = new TranslateTransform( 0, 0);
transGroup = new TransformGroup();
transGroup.Children.Add(translate);
transGroup.Children.Add(rotate);
playerChar.Transform = transGroup; //new TranslateTransform(posX, posY);
crouchPlayerChar.Transform = transGroup;
moveSpeed = playerMove;
}
The Game Loop (within the GameWindow class):
private void gameTimer_Tick(object sender, EventArgs e)
{
if (gameState == GameState.Playing)
{
mousePoint = Mouse.GetPosition(this);
player.move();
player.setRotate(mousePoint);
}
}
But how do you know what keys are being pressed I hear you ask? That is handled by the GameWindow Class, and it reacts when a button is pressed. Currently keys are hardcoded in the code, but I’ll change that when the options are defined in the future.
private void Window_KeyDown(object sender, KeyEventArgs e)
{
Key key = e.Key;
switch (key)
{
case Key.W:
player.directions[0] = 1;
break;
case Key.S:
player.directions[1] = 1;
break;
case Key.D:
player.directions[2] = 1;
break;
case Key.A:
player.directions[3] = 1;
break;
case Key.Escape:
gameState = GameState.GameOver;
break;
case Key.LeftShift:
if (player.pState != PlayerState.Prone)
{
player.pState = PlayerState.Prone;
player.playerChar.Opacity = 0.0;
player.crouchPlayerChar.Opacity = 1.0;
}
break;
}
}
private void Window_KeyUp(object sender, KeyEventArgs e)
{
Key key = e.Key;
switch (key)
{
case Key.W:
player.directions[0] = 0;
break;
case Key.S:
player.directions[1] = 0;
break;
case Key.D:
player.directions[2] = 0;
break;
case Key.A:
player.directions[3] = 0;
break;
case Key.Escape:
gameState = GameState.GameOver;
break;
case Key.LeftShift:
player.pState = PlayerState.Normal;
player.playerChar.Opacity = 1.0;
player.crouchPlayerChar.Opacity = 0.0;
break;
}
}
You’ll have noticed that I used one drawing object for the prone player, and one for the standing player. There may be a better way to do this in WPF, but I haven’t found it yet, and this works. Also, you’ll see that the method doesn’t affect the position of the player, as that would break the game loop. You want to make sure that event handlers have as little work to do as possible, so your frame rate doesn’t get broken.
Notice how the player class has a “directions” array? that’s how I stop stupid movement if someone presses up and down or left and right at the same time.
Finally, here’s the code in the Player that adjusts the Player’s position.
public void move()
{
if (pState == PlayerState.Prone)
{
moveSpeed = playerMoveProne;
}
else
{
moveSpeed = playerMove;
}
//If up is on and down is not on, then move up
if (directions[0] == 1 && directions[1] == 0)
{
posY = posY - moveSpeed;
}
//If down is on and up is not on, then move down
if (directions[1] == 1 && directions[0] == 0)
{
posY = posY + moveSpeed;
}
//If right is on and left is not on, then move right
if (directions[2] == 1 && directions[3] == 0)
{
posX = posX + moveSpeed;
}
//If left is on and right is not on, then move left
if (directions[3] == 1 && directions[2] == 0)
{
posX = posX - moveSpeed;
}
translate.X = posX;
translate.Y = posY;
headCenter.X = posX;
headCenter.Y = posY;
}
Hope that helps!