Difference between revisions of "Game Programming Class6"

esse quam videri
Jump to: navigation, search
(PacMan Class Simplified and Generalized)
(Protability)
Line 12: Line 12:
 
http://www.mataliphysics.com/
 
http://www.mataliphysics.com/
  
==Protability==
+
==Portability==
  
 
Separation of Concerns
 
Separation of Concerns
Line 21: Line 21:
 
*http://en.wikipedia.org/wiki/Single_responsibility_principle
 
*http://en.wikipedia.org/wiki/Single_responsibility_principle
 
*http://www.butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod
 
*http://www.butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod
 +
 +
==MovementController in Monogame==
 +
 +
In MonogameDemos Project is IntroPacManMovementController
 +
 +
file is PacManController.cs
 +
 +
<csharp>
 +
sealed class PacManController
 +
    {
 +
        InputHandler input; //game service to handle input
 +
        public Vector2 Direction {get; private set;}
 +
        public float Rotate { get; private set;}
 +
 +
        //Checks to see if there is anymovement
 +
        public bool hasInputForMoverment
 +
        {
 +
            get
 +
            {
 +
               
 +
                if (Direction.Length() == 0) return false;
 +
                return true;
 +
            }
 +
        }
 +
 +
        public PacManController(Game game)
 +
        {
 +
            //get input handler from game services
 +
            input = (InputHandler)game.Services.GetService<IInputHandler>();
 +
            if (input == null)
 +
            {
 +
                throw new Exception("PacMan controller depends on InputHandler service please add Input Handler as a service first");
 +
            }
 +
        }
 +
 +
        public void Update()
 +
        {
 +
            //Input for update from analog stick
 +
            GamePadState gamePad1State = input.GamePads[0]; //HACK hard coded player index
 +
            #region LeftStick
 +
            Vector2 pacStickDir = Vector2.Zero;
 +
            if (gamePad1State.ThumbSticks.Left.Length() > 0.0f)
 +
            {
 +
                pacStickDir = gamePad1State.ThumbSticks.Left;
 +
                pacStickDir.Y *= -1;      //Invert Y Axis
 +
 +
                float RotationAngle = (float)Math.Atan2(
 +
                    gamePad1State.ThumbSticks.Left.X,
 +
                    gamePad1State.ThumbSticks.Left.Y);
 +
 +
                Rotate = (float)MathHelper.ToDegrees(RotationAngle - (float)(Math.PI / 2));
 +
            }
 +
            #endregion
 +
 +
            //Update for input from DPad
 +
            #region DPad
 +
            Vector2 PacManDPadDir = Vector2.Zero;
 +
            if (gamePad1State.DPad.Left == ButtonState.Pressed)
 +
            {
 +
                //Orginal Position is Right so flip X
 +
                PacManDPadDir += new Vector2(-1, 0);
 +
            }
 +
            if (gamePad1State.DPad.Right == ButtonState.Pressed)
 +
            {
 +
                //Original Position is Right
 +
                PacManDPadDir += new Vector2(1, 0);
 +
            }
 +
            if (gamePad1State.DPad.Up == ButtonState.Pressed)
 +
            {
 +
                //Up
 +
                PacManDPadDir += new Vector2(0, -1);
 +
            }
 +
            if (gamePad1State.DPad.Down == ButtonState.Pressed)
 +
            {
 +
                //Down
 +
                PacManDPadDir += new Vector2(0, 1);
 +
            }
 +
            if (PacManDPadDir.Length() > 0)
 +
            {
 +
                //Angle in radians from vector
 +
                float RotationAngleKey = (float)Math.Atan2(
 +
                        PacManDPadDir.X,
 +
                        PacManDPadDir.Y * -1);
 +
                //Find angle in degrees
 +
                Rotate = (float)MathHelper.ToDegrees(
 +
                    RotationAngleKey - (float)(Math.PI / 2)); //rotated right already
 +
 +
                //Normalize NewDir to keep agled movement at same speed as horilontal/Vert
 +
                PacManDPadDir = Vector2.Normalize(PacManDPadDir);
 +
            }
 +
            #endregion
 +
 +
            //Update for input from Keyboard
 +
#if !XBOX360
 +
            #region KeyBoard
 +
            KeyboardState keyboardState = Keyboard.GetState();
 +
            Vector2 PacManKeyDir = new Vector2(0, 0);
 +
 +
            if (keyboardState.IsKeyDown(Keys.Left))
 +
            {
 +
                //Flip Horizontal
 +
                PacManKeyDir += new Vector2(-1, 0);
 +
            }
 +
            if (keyboardState.IsKeyDown(Keys.Right))
 +
            {
 +
                //No new sprite Effects
 +
                PacManKeyDir += new Vector2(1, 0);
 +
            }
 +
            if (keyboardState.IsKeyDown(Keys.Up))
 +
            {
 +
                PacManKeyDir += new Vector2(0, -1);
 +
            }
 +
            if (keyboardState.IsKeyDown(Keys.Down))
 +
            {
 +
                PacManKeyDir += new Vector2(0, 1);
 +
            }
 +
            if (PacManKeyDir.Length() > 0)
 +
            {
 +
                float RotationAngleKey = (float)Math.Atan2(
 +
                        PacManKeyDir.X,
 +
                        PacManKeyDir.Y * -1);
 +
 +
                Rotate = (float)MathHelper.ToDegrees(
 +
                    RotationAngleKey - (float)(Math.PI / 2));
 +
 +
                //Normalize NewDir to keep agled movement at same speed as horilontal/Vert
 +
                PacManKeyDir = Vector2.Normalize(PacManKeyDir);
 +
            }
 +
            #endregion
 +
#endif
 +
            Direction= PacManKeyDir + PacManDPadDir + pacStickDir;
 +
            if (Direction.Length() > 0)
 +
            {
 +
                Direction = Vector2.Normalize(Direction);
 +
            }
 +
        }
 +
    }
 +
</csharp>
 +
 +
GameConsolePacMan.cs //hadles logging
 +
<csharp>
 +
class GameConsolePacMan : PacMan
 +
    {
 +
        GameConsole console;
 +
        public GameConsolePacMan()
 +
        {
 +
            this.console = null;
 +
        }
 +
 +
        public GameConsolePacMan(GameConsole console)
 +
        {
 +
            this.console = console;
 +
        }
 +
 +
        public override void Log(string s)
 +
        {
 +
            if (console != null)
 +
            {
 +
                console.GameConsoleWrite(s);
 +
            }
 +
            else
 +
            {
 +
                base.Log(s);
 +
            }
 +
        }
 +
    }
 +
</csharp>
 +
 +
MonoGamePacMan.cs
 +
<csharp>
 +
class MonoGamePacMan : IntroGameLibrary.Sprite2.DrawableSprite2
 +
    {
 +
        internal PacManController controller { get; private set; }
 +
        internal GameConsolePacMan PacMan
 +
        {
 +
            get;
 +
            private set;
 +
        }
 +
        protected PacManState pacState;
 +
        public PacManState PacState
 +
        {
 +
            get { return this.pacState; }
 +
            //Change pacman state also
 +
            set {
 +
                if(this.pacState != value)
 +
                    this.pacState = this.PacMan.State = value;
 +
            }
 +
        }
 +
               
 +
        public MonoGamePacMan(Game game)
 +
            : base(game)
 +
        {
 +
            this.controller = new PacManController(game);
 +
            PacMan = new GameConsolePacMan((GameConsole)game.Services.GetService<IGameConsole>());
 +
        }
 +
 +
        protected override void LoadContent()
 +
        {
 +
            base.LoadContent();
 +
            this.SpriteTexture = content.Load<Texture2D>("PacManSingle");
 +
            this.Orgin = new Vector2(this.SpriteTexture.Width / 2, this.SpriteTexture.Height / 2);
 +
            this.Location = new Microsoft.Xna.Framework.Vector2(100, 100);
 +
            this.Speed = 200;
 +
        }
 +
 +
        public override void Update(GameTime gameTime)
 +
        {
 +
            //Elapsed time since last update
 +
            float time = (float)gameTime.ElapsedGameTime.TotalMilliseconds;
 +
           
 +
            this.controller.Update();
 +
 +
            this.Location += ((this.controller.Direction * (time / 1000)) * Speed);      //Simple Move
 +
            this.Rotate = this.controller.Rotate;
 +
 +
            //Change State based on movement
 +
            if (this.controller.hasInputForMoverment)
 +
            {
 +
                if(pacState != PacManState.Spawning && pacState != PacManState.SuperPacMan)
 +
                    this.PacState = PacManState.Chomping;
 +
            }
 +
            else
 +
            {
 +
                if (pacState != PacManState.Spawning && pacState != PacManState.SuperPacMan)
 +
                    this.PacState = PacManState.Still;
 +
            }
 +
 +
            //Keep PacMan On Screen
 +
            if (this.Location.X > Game.GraphicsDevice.Viewport.Width - (this.spriteTexture.Width / 2))
 +
            {
 +
                this.Location.X = Game.GraphicsDevice.Viewport.Width - (this.spriteTexture.Width / 2);
 +
            }
 +
            if (this.Location.X < (this.spriteTexture.Width / 2))
 +
                this.Location.X = (this.spriteTexture.Width / 2);
 +
 +
            if (this.Location.Y > Game.GraphicsDevice.Viewport.Height - (this.spriteTexture.Height / 2))
 +
                this.Location.Y = Game.GraphicsDevice.Viewport.Height - (this.spriteTexture.Height / 2);
 +
 +
            if (this.Location.Y < (this.spriteTexture.Height / 2))
 +
                this.Location.Y = (this.spriteTexture.Height / 2);
 +
 +
            base.Update(gameTime);
 +
        }
 +
    }
 +
</csharp>
 +
 +
==MovementController in Unity==
 +
Unity Project is GameProgrammingUnity
 +
   
 +
Package is PacManWithFood.unitypackage
 +
   
 +
script is PlayerController.cs
 +
<csharp>
 +
    public class PlayerController : MonoBehaviour {
 +
 +
public Vector2 direction = new Vector2();
 +
    private Vector2 keyDirection;
 +
    private Vector2 padDirection;
 +
public bool hasInputForMoverment {
 +
get {
 +
            //Debug.Log(direction.sqrMagnitude);
 +
            if (direction.magnitude == 0) return false;
 +
return true;}
 +
}
 +
 +
    public PlayerController()
 +
    {
 +
        keyDirection = new Vector2();
 +
    }
 +
 +
// Use this for initialization
 +
void Start () {
 +
 +
}
 +
 +
// Update is called once per frame
 +
void Update () {
 +
 +
        keyDirection.x = keyDirection.y = 0;
 +
 +
        //Keyboard
 +
        if (Input.GetKey("right"))
 +
        {
 +
            keyDirection.x += 1;
 +
        }
 +
if (Input.GetKey ("left")) {
 +
            keyDirection.x += -1;
 +
}
 +
 +
        if (Input.GetKey("up"))
 +
        {
 +
            keyDirection.y += 1;
 +
        }
 +
if (Input.GetKey ("down")) {
 +
            keyDirection.y += -1;
 +
}
 +
        direction = keyDirection;
 +
 +
        //Gamepad
 +
        padDirection.x = Input.GetAxis("Horizontal");
 +
        padDirection.y = Input.GetAxis("Vertical");
 +
 +
        if (padDirection.magnitude > 0)
 +
        {
 +
            //Debug.Log(padDirection + " " + padDirection.magnitude + " " + (padDirection.magnitude > 0));
 +
            direction += padDirection;
 +
        }
 +
 +
        //normalize
 +
        direction.Normalize();
 +
}
 +
}
 +
</csharp>
 +
 +
UnityPacMan.cs //Hadles logging
 +
<csharp>
 +
public class UnityPacMan : PacMan {
 +
 +
    private GameObject _gameObject;
 +
 +
    public UnityPacMan(GameObject g) : base()
 +
    {
 +
        _gameObject = g;
 +
    }
 +
 +
    public override void Log(string s)
 +
    {
 +
        Debug.Log(s);
 +
    }
 +
 +
}
 +
</csharp>
  
 
==PacMan Class Simplified and Generalized==
 
==PacMan Class Simplified and Generalized==

Revision as of 03:05, 4 March 2015


Physics

http://box2d.org/

c# Box2D https://code.google.com/p/box2dx/

https://github.com/d-snp/Farseer-Physics

http://farseerphysics.codeplex.com/

http://www.mataliphysics.com/

Portability

Separation of Concerns

Single Responsibility Principle

MovementController in Monogame

In MonogameDemos Project is IntroPacManMovementController

file is PacManController.cs

<csharp> sealed class PacManController

   {
       InputHandler input; //game service to handle input
       public Vector2 Direction {get; private set;}
       public float Rotate { get; private set;}
       //Checks to see if there is anymovement
       public bool hasInputForMoverment
       {
           get
           {
               
               if (Direction.Length() == 0) return false;
               return true;
           }
       }
       public PacManController(Game game)
       {
           //get input handler from game services
           input = (InputHandler)game.Services.GetService<IInputHandler>();
           if (input == null)
           {
               throw new Exception("PacMan controller depends on InputHandler service please add Input Handler as a service first");
           }
       }
       public void Update()
       {
           //Input for update from analog stick
           GamePadState gamePad1State = input.GamePads[0]; //HACK hard coded player index
           #region LeftStick
           Vector2 pacStickDir = Vector2.Zero;
           if (gamePad1State.ThumbSticks.Left.Length() > 0.0f)
           {
               pacStickDir = gamePad1State.ThumbSticks.Left;
               pacStickDir.Y *= -1;      //Invert Y Axis
               float RotationAngle = (float)Math.Atan2(
                   gamePad1State.ThumbSticks.Left.X,
                   gamePad1State.ThumbSticks.Left.Y);
               Rotate = (float)MathHelper.ToDegrees(RotationAngle - (float)(Math.PI / 2));
           }
           #endregion
           //Update for input from DPad
           #region DPad
           Vector2 PacManDPadDir = Vector2.Zero;
           if (gamePad1State.DPad.Left == ButtonState.Pressed)
           {
               //Orginal Position is Right so flip X
               PacManDPadDir += new Vector2(-1, 0);
           }
           if (gamePad1State.DPad.Right == ButtonState.Pressed)
           {
               //Original Position is Right
               PacManDPadDir += new Vector2(1, 0);
           }
           if (gamePad1State.DPad.Up == ButtonState.Pressed)
           {
               //Up
               PacManDPadDir += new Vector2(0, -1);
           }
           if (gamePad1State.DPad.Down == ButtonState.Pressed)
           {
               //Down
               PacManDPadDir += new Vector2(0, 1);
           }
           if (PacManDPadDir.Length() > 0)
           {
               //Angle in radians from vector
               float RotationAngleKey = (float)Math.Atan2(
                       PacManDPadDir.X,
                       PacManDPadDir.Y * -1);
               //Find angle in degrees
               Rotate = (float)MathHelper.ToDegrees(
                   RotationAngleKey - (float)(Math.PI / 2)); //rotated right already
               //Normalize NewDir to keep agled movement at same speed as horilontal/Vert
               PacManDPadDir = Vector2.Normalize(PacManDPadDir);
           }
           #endregion
           //Update for input from Keyboard
  1. if !XBOX360
           #region KeyBoard
           KeyboardState keyboardState = Keyboard.GetState();
           Vector2 PacManKeyDir = new Vector2(0, 0);
           if (keyboardState.IsKeyDown(Keys.Left))
           {
               //Flip Horizontal
               PacManKeyDir += new Vector2(-1, 0);
           }
           if (keyboardState.IsKeyDown(Keys.Right))
           {
               //No new sprite Effects
               PacManKeyDir += new Vector2(1, 0);
           }
           if (keyboardState.IsKeyDown(Keys.Up))
           {
               PacManKeyDir += new Vector2(0, -1);
           }
           if (keyboardState.IsKeyDown(Keys.Down))
           {
               PacManKeyDir += new Vector2(0, 1);
           }
           if (PacManKeyDir.Length() > 0)
           {
               float RotationAngleKey = (float)Math.Atan2(
                       PacManKeyDir.X,
                       PacManKeyDir.Y * -1);
               Rotate = (float)MathHelper.ToDegrees(
                   RotationAngleKey - (float)(Math.PI / 2));
               //Normalize NewDir to keep agled movement at same speed as horilontal/Vert
               PacManKeyDir = Vector2.Normalize(PacManKeyDir);
           }
           #endregion
  1. endif
           Direction= PacManKeyDir + PacManDPadDir + pacStickDir;
           if (Direction.Length() > 0)
           {
               Direction = Vector2.Normalize(Direction);
           }
       }
   }

</csharp>

GameConsolePacMan.cs //hadles logging <csharp> class GameConsolePacMan : PacMan

   {
       GameConsole console;
       public GameConsolePacMan()
       {
           this.console = null;
       }
       public GameConsolePacMan(GameConsole console)
       {
           this.console = console;
       }
       public override void Log(string s)
       {
           if (console != null)
           {
               console.GameConsoleWrite(s);
           }
           else
           {
               base.Log(s);
           }
       }
   }

</csharp>

MonoGamePacMan.cs <csharp> class MonoGamePacMan : IntroGameLibrary.Sprite2.DrawableSprite2

   {
       internal PacManController controller { get; private set; }
       internal GameConsolePacMan PacMan
       {
           get;
           private set;
       }
       protected PacManState pacState;
       public PacManState PacState
       {
           get { return this.pacState; }
           //Change pacman state also
           set { 
               if(this.pacState != value)
                   this.pacState = this.PacMan.State = value; 
           }
       }
               
       public MonoGamePacMan(Game game)
           : base(game)
       {
           this.controller = new PacManController(game);
           PacMan = new GameConsolePacMan((GameConsole)game.Services.GetService<IGameConsole>());
       }
       protected override void LoadContent()
       {
           base.LoadContent();
           this.SpriteTexture = content.Load<Texture2D>("PacManSingle");
           this.Orgin = new Vector2(this.SpriteTexture.Width / 2, this.SpriteTexture.Height / 2);
           this.Location = new Microsoft.Xna.Framework.Vector2(100, 100);
           this.Speed = 200;
       }
       public override void Update(GameTime gameTime)
       {
           //Elapsed time since last update
           float time = (float)gameTime.ElapsedGameTime.TotalMilliseconds;
           
           this.controller.Update();
           this.Location += ((this.controller.Direction * (time / 1000)) * Speed);      //Simple Move 
           this.Rotate = this.controller.Rotate;
           //Change State based on movement
           if (this.controller.hasInputForMoverment)
           {
               if(pacState != PacManState.Spawning && pacState != PacManState.SuperPacMan)
                   this.PacState = PacManState.Chomping;
           }
           else
           {
               if (pacState != PacManState.Spawning && pacState != PacManState.SuperPacMan)
                   this.PacState = PacManState.Still;
           }
           //Keep PacMan On Screen
           if (this.Location.X > Game.GraphicsDevice.Viewport.Width - (this.spriteTexture.Width / 2))
           {
               this.Location.X = Game.GraphicsDevice.Viewport.Width - (this.spriteTexture.Width / 2);
           }
           if (this.Location.X < (this.spriteTexture.Width / 2))
               this.Location.X = (this.spriteTexture.Width / 2);
           if (this.Location.Y > Game.GraphicsDevice.Viewport.Height - (this.spriteTexture.Height / 2))
               this.Location.Y = Game.GraphicsDevice.Viewport.Height - (this.spriteTexture.Height / 2);
           if (this.Location.Y < (this.spriteTexture.Height / 2))
               this.Location.Y = (this.spriteTexture.Height / 2);
           base.Update(gameTime);
       }
   }

</csharp>

MovementController in Unity

Unity Project is GameProgrammingUnity

Package is PacManWithFood.unitypackage

script is PlayerController.cs <csharp>

   public class PlayerController : MonoBehaviour {

public Vector2 direction = new Vector2();

   private Vector2 keyDirection;
   private Vector2 padDirection;

public bool hasInputForMoverment { get {

           //Debug.Log(direction.sqrMagnitude);
           if (direction.magnitude == 0) return false;

return true;} }

   public PlayerController()
   {
       keyDirection = new Vector2();
   }

// Use this for initialization void Start () {

}

// Update is called once per frame void Update () {

       keyDirection.x = keyDirection.y = 0;
       //Keyboard
       if (Input.GetKey("right"))
       {
           keyDirection.x += 1;
       }

if (Input.GetKey ("left")) {

           keyDirection.x += -1;

}

       if (Input.GetKey("up"))
       {
           keyDirection.y += 1;
       }

if (Input.GetKey ("down")) {

           keyDirection.y += -1;

}

       direction = keyDirection;
       //Gamepad
       padDirection.x = Input.GetAxis("Horizontal");
       padDirection.y = Input.GetAxis("Vertical");
       if (padDirection.magnitude > 0)
       {
           //Debug.Log(padDirection + " " + padDirection.magnitude + " " + (padDirection.magnitude > 0));
           direction += padDirection;
       }
       //normalize
       direction.Normalize();

} } </csharp>

UnityPacMan.cs //Hadles logging <csharp> public class UnityPacMan : PacMan {

   private GameObject _gameObject;
   public UnityPacMan(GameObject g) : base()
   {
       _gameObject = g;
   }
   public override void Log(string s)
   {
       Debug.Log(s);
   }

} </csharp>

PacMan Class Simplified and Generalized

<csharp> public enum PacManState { Spawning, Still, Chomping, SuperPacMan }

   public class PacMan 
   {
       protected PacManState _state;
       public PacManState State
       {
           get { return _state; }
           set
           {
               if (_state != value)
               {
                   this.Log(string.Format("{0} was: {1} now {2}", this.ToString(), _state, value));
                   
                   _state = value;
               }
           }
       }
       public PacMan()
       {
           
           //Set default state will call notify so make sure this.Ghosts is intitialized first
           this.State = PacManState.Still;
       }
       //Extra method for logging state change
       public virtual void Log(string s)
       {
           //nothing
           Console.WriteLine(s);
       }
   }

</csharp>

Simple Animation

what extra fields do we need for animation?

http://create.msdn.com/en-US/education/catalog/sample/sprite_sheet

Platformer Example

Show platformer starter kit

http://msdn.microsoft.com/en-us/library/dd254918(v=xnagamestudio.31).aspx

simple and elegant but not that flexible

Animation Classes

Way too many classes for me to type here

  • PacMan States
  • PacMan Dying Animation
  • PacMan Eating

IntroAnimation Project IntroAnimation.zip

Complicated but flexible

  • DrawableAnimatableSprite.cs
  • CelAnimationManager.cs

Homework

Shooting Game

  • must use game components
  • must be multiplayer (both on keyboard or multiple game pads) don't use networking
  • must be able to shoot at each other or work together to shoot enemies
  • include shot manager and or shot manager

PadManShootCapture.PNG