Search code examples
c#xnagame-physicspacman

Remembering a direction, moving to a point, then changing direction. XNA


I'm making a pacman clone in XNA. So far I've drawn the tile map using 2D array, added the pills using another 2D array and made a 2D array that allows movement of pacman.

In the actual game you can press right whilst moving up, and it will wait until you're able to move right and the turn.

I have a system in place that allows a turn only when the spritePosition % 32 = 16. This means the sprite will be centred between the walls.

I need the program to remember the last key pressed or move to the right position before turning, but i cant find a way of doing it. Here is a bit of the code that covers what I'm trying.

public void MovementCheck()
        {
            presentKey = Keyboard.GetState();
            spritePosition = spriteVelocity + spritePosition;
            pacManRec = new Rectangle((int)spritePosition.X,     (int)spritePosition.Y, pacManTex.Width, pacManTex.Height);
            spriteOrigin = new Vector2(pacManRec.Width / 2, pacManRec.Height / 2);

        //Press Right
        if (presentKey.IsKeyDown(Keys.Right) && pastKey.IsKeyUp(Keys.Right))
        {

            Right();
        }
}

private void Right()
        {
            direction = "right"; 
//if the next block in tile map to the right is a 1, and the sprite is centred - allow a turn
            if (inputMap[(int)Math.Floor(spritePosition.Y / 32), (int)Math.Floor(spritePosition.X / 32) + 1] == 1 && (spritePosition.Y % 32 == 16))
            {
                rotation = ((float)Math.PI / 180);
                spriteVelocity.X = 0;
                spriteVelocity.Y = 0;
                spriteVelocity.X = movementSpeed;
            }
        }

Only the right key is shown, the others are similar but the directions all change and the checks to the tile map are changed accordingly. (+1 on the X here)

ive tried things like

while (spritePosition.Y % 32 != 16)
{ spritePosition = spriteVelocity + spritePosition; }

but that just makes the sprite shoot up the screen, (kinda obviously) :(

and I tried a new Method before the Right() call

bool RightCheck()
{
    if ( CONDITIONS MET HERE )
    return true
    else
    { 
      //dont remember if I used this line, but something similar
      spritePosition = spriteVelocity + spritePosition;
      RightCheck()
    }
    return false; //allows program to build
 }

Just an causes infinite recursion.


Solution

  • One solution is adding a int counter = 0; which you update in your gameloop (with counter++;) every frame/time-step. Set to 0 everytime you make a valid input and save that input.

    Outlined code:

    public class GameClassWhereUpdateIsDone
    {
        private enum Directions { None, Up, Down, Left, Right };
    
        private int counter = 0;
        private Directions currentDirection; // Current movement-direction
        private Directions lastInput; // Last direction from input
    
        public void Update(...)
        {
           var keyboardState = Keyboard.GetState();
           if(keyboardState.IsKeyPressed(Keys.Right))
           {
               counter = 0;
               direction = Directions.Right;
           }
    
           if(currentDirection != lastInput && counter < 5) // Allow turning 5 updates ahead.
           {
               // Player want to turn
               if(AllowedToTurn(lastInput)
               {
                    currentDirection = lastInput;
               }
           }
    
           MoveDirection(currentDirection);
    
           counter++;
        }
    
        private bool AllowedToTurn(Directions direction)
        {
           if(direction == Directions.Right)
           {
               return RightCheck();
           }
        }
    }
    

    The key idea is to keep track of movement direction and last direciton that was input...

    In the original Pac-Man "pre-turning" was actually used, meaning you would start moving diagonally if you turned ahead of a corner according to: http://home.comcast.net/~jpittman2/pacman/pacmandossier.html which is an interesting read.