Slides built from Carter Chapter 5 Some overhead Copy 3d demo - - PowerPoint PPT Presentation
Slides built from Carter Chapter 5 Some overhead Copy 3d demo - - PowerPoint PPT Presentation
Slides built from Carter Chapter 5 Some overhead Copy 3d demo project from last week and rename project folder to InputDemo Open and rename the project in AssemblyInfo.cs and change game id You can just create a new project Ive
Some overhead
Copy 3d demo project from last week and rename
project folder to InputDemo
Open and rename the project in AssemblyInfo.cs and
change game id
You can just create a new project
I’ve done both
Creating a library
File -> new project
Windows Game
Library (3.0)
Name it
XELibrary, also the solution
Adding FPS.cs
Copy file FPS.cs into solution directory Select Project -> Show all files Right click on file name
Select add to project
See the FPS lab from the labs.
Edit file and change namespace
to XELibrary
Let’s also remove the Class1.cs
Right click -> delete
Input Handler
Project->add component Open InputHandler.cs
InputHandler Game Service
using Microsoft.Xna.Framework.Input; public interface IInputHandler { }; public partial class InputHandler : Microsoft.Xna.Framework.GameComponent, IInputHandler game.Services.AddService(typeof(IInputHandler), this);
Partial class can be defined over multiple definitions (ie more than one source file) Inherit from IInputHandler above
Since a service, must add it as a service
Might need this.
Add a camera component
Project -> add new item
Camera game component
Add a variable for our input handler and graphics
protected IInputHandler input; private GraphicsDeviceManager graphics;
Initialize in camera constructor
graphics = (GraphicsDeviceManager)Game.Services.GetSe rvice(typeof(IGraphicsDeviceManager)); input = (IInputHandler)game.Services.GetService(ty peof(IInputHandler));
Protected so can be accessed by base class
Copy camera code from last time
Initialize()
Base.Initialize(); InitializeCamera(); // from last time next slide
Initialize base first so we have access to the graphics device
here which is initialized there.
Add the declarations as well
private Matrix projection; private Matrix view; protected Vector3 cameraPosition = new Vector3(0.0f, 0.0f, 3.0f); private Vector3 cameraTarget = Vector3.Zero; private Vector3 cameraUpVector = Vector3.Up;
InitializeCamera()
private void InitializeCamera() { float aspectRatio = (float)graphics.GraphicsDevice.Viewport.Width / (float)graphics.GraphicsDevice.Viewport.Height; Matrix.CreatePerspectiveFieldOfView( MathHelper.PiOver4,aspectRatio,0.001f,1000.0f,
- ut projection);
Matrix.CreateLookAt(ref cameraPosition, ref cameraTarget, ref cameraUpVector, out view); }
We saw this last time.
Access method for matrices
public Matrix View { get { return view; } } public Matrix Projection { get {reutnr projection; }}
Now we can access the view and projection matrix from the camera in a game that uses this library.
Now create a demo
Can start a new project, or copy the one from last time
Add all of the code from the previous example is starting
anew
Now remove the Matrix view, projection; decls Remove the Initialize camera and all access to the
camera
Project -> add reference -> browse and add a reference
to XELibrary.dll
Add some code in game.cs
using XELibrary;
Declarations
Camera camera;
Initialize()
camera = new Camera(this)
Change Draw()
effect.Projection = camera.Projection; effect.View = camera.View;
Adding keyboard to InputHandler
Declare
private KeyboardState keyboardState;
Update
keyboardState = Keyboard.GetState(); if (keyboardState.IsKeyDown(Keys.Escape)) Game.Exit();
OK so now all we can do is exit on an escape! But this is part of our camera, so including this camera will include this code!
Now for some camera control
Declare
private Vector3 cameraReference = new Vector3(0.0f, 0.0f, -1.0f); private float cameraYaw = 0.0f;
Update() Matrix rotationMatrix; Matrix.CreateRotationY(MathHelper.ToRadians(cameraYaw), out rotationMatrix); Vector3 transformedReference; Vector3.Transform(ref cameraReference, ref rotationMatrix, out transformedReference); // Calculate the position the camera is looking at. Vector3.Add(ref cameraPosition, ref transformedReference, out cameraTarget); Matrix.CreateLookAt(ref cameraPosition, ref cameraTarget, ref cameraUpVector,
- ut view);
In IInputHandler
public interface IInputHandler { KeyboardState KeyboardState { get; } GamePadState[] GamePads { get; } #if !XBOX360 MouseState MouseState { get; } MouseState PreviousMouseState { get; } #endif }
Add access in InputHandler
public KeyboardState KeyboardState { get { return(keyboardState); } } public GamePadState[] GamePads {get { return(gamePads); } } #if !XBOX360 public MouseState MouseState { get { return(mouseState); }} public MouseState PreviousMouseState {get { return(prevMouseState); } } #endif
Use exposed members in camera
Update()
if (input.KeyboardState.IsKeyDown(Keys.Left)) cameraYaw += spinRate; if (input.KeyboardState.IsKeyDown(Keys.Right)) cameraYaw -= spinRate; //reset camera angle if needed if (cameraYaw > 360) cameraYaw -= 360; else if (cameraYaw < 0) cameraYaw += 360;
Back to Game
Decl
private InputHandler input
Constructor
input = new InputHandler(this); Components.Add(input);
We execute and get the objects flying by with our updates as fast as possible.
New constructor for FPS
public FPS(Game game, bool synchWithVerticalRetrace, bool isFixedTimeStep) : this(game, synchWithVerticalRetrace, isFixedTimeStep, game.TargetElapsedTime) {} #if DEBUG fps = new FPS(this); #else fps = new FPS(this, true, false); #endif
Instead of as fast as possible, we can do 60Hz
GamePad
GamePadState[] GamePads { get; } // Iinput Handler
Class InputHandler decls
private GamePadState[] gamePads = new GamePadState[4]; public GamePadState[] GamePads {get { return(gamePads); } }
InputHandler Update()
gamePads[0] = GamePad.GetState(PlayerIndex.One); gamePads[1] = GamePad.GetState(PlayerIndex.Two); gamePads[2] = GamePad.GetState(PlayerIndex.Three); gamePads[3] = GamePad.GetState(PlayerIndex.Four); if (gamePads[0].Buttons.Back == ButtonState.Pressed) Game.Exit();
GamePad: camera class
float timeDelta = (float)gameTime.ElapsedGameTime.TotalSeconds; if (input.KeyboardState.IsKeyDown(Keys.Left) || (input.GamePads[playerIndex].ThumbSticks.Right.X < 0)) cameraYaw += (spinRate * timeDelta); if (input.KeyboardState.IsKeyDown(Keys.Right) || (input.GamePads[playerIndex].ThumbSticks.Right.X > 0)) cameraYaw -= (spinRate * timeDelta);
GamePad: DPad
Suppose we wanted to use the Dpad to also rotate
if (input.KeyboardState.IsKeyDown(Keys.Left) || (input.GamePads[playerIndex].ThumbSticks.Right.X < 0) || (gamePadState.Dpad.Left == ButtonState.Pressed)) cameraYaw += (spinRate * timeDelta);
Dpad behaves like a button
GamePad
Triggers
Return a value between 0=pressed and 1=fully pressed.
Vibration
2 motors, left is low-frequency, right is high-frequency
if (input.GamePads[0].IsConnected) GamePad.SetVibration(PlayerIndex.One, input.GamePads[0].Triggers.Left, input.GamePads[0].Triggers.Right);
Change title to hold these values
This.Window.Title = “left: “ + input.GamePads[0].Triggers.Left.ToString() + “; right: “ + input.GamePads[0].Triggers.Right.ToString();
Mouse
Declare
#if !XBOX360 private MouseState mouseState; private MouseState prevMouseState; #endif
Constructor
#if !XBOX360 Game.IsMouseVisible = true; prevMouseState = Mouse.GetState(); #endif
Mouse
Update
#if !XBOX360 prevMouseState = mouseState; //Set our previous state mouseState = Mouse.GetState(); //Get our new state #endif
Properties
#if !XBOX360 public MouseState MouseState {get { return(mouseState); }} public MouseState PreviousMouseState {get { return(prevMouseState); }} #endif
Mouse: controlling camera
#if !XBOX360 if ((input.PreviousMouseState.X > input.MouseState.X) && (input.MouseState.LeftButton == ButtonState.Pressed)) cameraYaw += (spinRate * timeDelta); else if ((input.PreviousMouseState.X < input.MouseState.X) && (input.MouseState.LeftButton == ButtonState.Pressed)) cameraYaw -= (spinRate * timeDelta); #endif
Improving demo
Add some more quads with
world = SomeTransform(s) DrawRectangle(world);
Also remove culling for now just in case
graphics.GraphicsDevice.RenderState.CullMode = CullMode.None;
Camera Pitch
Just like yaw except use up and down arrow or right
thumbstick
if ((input.PreviousMouseState.Y > input.MouseState.Y) && (input.MouseState.LeftButton == ButtonState.Pressed)) cameraPitch += (spinRate * timeDelta); else if ((input.PreviousMouseState.Y < input.MouseState.Y) && (input.MouseState.LeftButton == ButtonState.Pressed)) cameraPitch -= (spinRate * timeDelta);
Also set camera pitch to go between -90 and 90
if (cameraPitch > 89) cameraPitch = 89; if (cameraPitch < -89) cameraPitch = -89;
FirstPersonCamera: Movement
public partial class FirstPersonCamera : Camera { public FirstPersonCamera(Game game) : base(game) { // TODO: Construct any child components here }
Derive from stationary Camera
FirstPersonCamera: Movement
public override void Update(GameTime gameTime) { movement = Vector3.Zero; //reset movement vector if (input.KeyboardState.IsKeyDown(Keys.A) || (input.GamePads[playerIndex].ThumbSticks.Left.X < 0)) movement.X--; if (input.KeyboardState.IsKeyDown(Keys.D) || (input.GamePads[playerIndex].ThumbSticks.Left.X > 0)) movement.X++;
FirstPersonCamera: Movement
if (input.KeyboardState.IsKeyDown(Keys.S) || (input.GamePads[playerIndex].ThumbSticks.Left.Y < 0)) movement.Z++; if (input.KeyboardState.IsKeyDown(Keys.W) || (input.GamePads[playerIndex].ThumbSticks.Left.Y > 0)) movement.Z--; // don't increase speed if pushing up and over (diagonal) if (movement.LengthSquared() != 0) movement.Normalize(); base.Update(gameTime);
Camera::Update()
//update movement (none for this base class) movement *= (moveRate * timeDelta); Matrix rotationMatrix; Vector3 transformedReference; Matrix.CreateRotationY(MathHelper.ToRadians(cameraYaw), out rotationMatrix); if (movement != Vector3.Zero) { Vector3.Transform(ref movement, ref rotationMatrix, out movement); cameraPosition += movement; }
Camera::Update()
//add in pitch to the rotation rotationMatrix = Matrix.CreateRotationX(MathHelper.ToRadians(cameraPitch)) * rotationMatrix; // Create a vector pointing the direction the camera is facing. Vector3.Transform(ref cameraReference, ref rotationMatrix,
- ut transformedReference);
// Calculate the position the camera is looking at. Vector3.Add(ref cameraPosition, ref transformedReference, out cameraTarget); Matrix.CreateLookAt(ref cameraPosition, ref cameraTarget, ref cameraUpVector, out view);
Split Screen
Declarations
private FirstPersonCamera camera; private FirstPersonCamera camera2; private Viewport defaultViewport; private Viewport topViewport; private Viewport bottomViewport; private Viewport separatorViewport; private bool twoPlayers = true
Why two cameras?
Split Screen
LoadContent()
defaultViewport = graphics.GraphicsDevice.Viewport; topViewport = defaultViewport; bottomViewport = defaultViewport; separatorViewport = defaultViewport;
Split Screen
if (twoPlayers) { topViewport.Height = topViewport.Height / 2; separatorViewport.Y = topViewport.Height - 1; separatorViewport.Height = 3; bottomViewport.Y = topViewport.Height + 1; bottomViewport.Height = (bottomViewport.Height / 2) - 1; camera.Viewport = topViewport; camera2 = new FirstPersonCamera(this); camera2.Viewport = bottomViewport; camera2.Position = new Vector3(0.0f, 0.0f, -3.0f); camera2.Orientation = new Vector3(0.0f, 0.0f, 1.0f); camera2.PlayerIndex = PlayerIndex.Two; Components.Add(camera2); }
Modify Camera
Declare and expose variables for the players index, the viewport,
Position, Orientation, and Target Protected int playerIndex = 0; private Viewport? Viewport; public PlayerIndex PlayerIndex { get { return ((PlayerIndex)playerIndex); } set { playerIndex = (int)value; } } public Vector3 Position { get { return (cameraPosition); } set { cameraPosition = value; } } public Vector3 Orientation { get { return (cameraReference); } set { cameraReference = value; }}
T? is shorthand for System.Nullable<T>
Modify Camera
using Microsoft.Xna.Framework.Graphics; public Viewport Viewport { get { if (viewport == null) viewport = graphics.GraphicsDevice.Viewport; return ((Viewport)viewport); } set { viewport = value; InitializeCamera(); } }
Since viewport nullable, if it is null get viewport from the graphics device We set the viewport, so we need to recalculate our view and projection matrix
InitializeCamera()
private void InitializeCamera() { float aspectRatio = (float)graphics.GraphicsDevice.Viewport.Width / (float)graphics.GraphicsDevice.Viewport.Height; Matrix.CreatePerspectiveFieldOfView( MathHelper.PiOver4,aspectRatio,0.001f,1000.0f,
- ut projection);
Matrix.CreateLookAt(ref cameraPosition, ref cameraTarget, ref cameraUpVector, out view); }
As above, just a reminder.
Modify Game::Draw()
graphics.GraphicsDevice.Viewport = camera.Viewport; DrawScene(gameTime, camera); if (twoPlayers) { graphics.GraphicsDevice.Viewport = camera2.Viewport; DrawScene(gameTime, camera2); //now clear the thick horizontal line between the two screens graphics.GraphicsDevice.Viewport = separatorViewport; graphics.GraphicsDevice.Clear(Color.Black); }
DrawScene()
private void DrawScene(GameTime gameTime, Camera camera) { graphics.GraphicsDevice.Clear(Color.CornflowerBlue); // TODO: Add your drawing code here graphics.GraphicsDevice.RenderState.CullMode = CullMode.None; graphics.GraphicsDevice.VertexDeclaration = vertexDeclaration; effect.Projection = camera.Projection; effect.View = camera.View; effect.EnableDefaultLighting(); effect.TextureEnabled = true; effect.Texture = texture;
Setting up the device and the effect.
DrawScene() (draw some shapes)
world = Matrix.Identity; world = Matrix.CreateTranslation(new Vector3(3.0f, 0, -10.0f)); DrawRectangle(ref world); world = Matrix.CreateTranslation(new Vector3(-3.0f, 3.0f, -10.0f)); DrawRectangle(ref world); world = Matrix.CreateRotationZ(angleX)*Matrix.CreateScale(.3f); DrawRectangle(ref world); world = Matrix.CreateScale(0.75f) * Matrix.CreateRotationX(MathHelper.ToRadians(15.0f)) * Matrix.CreateRotationY(MathHelper.ToRadians(30.0f)) * Matrix.CreateTranslation(new Vector3(-3.0f, -1.0f, -5.0f)); DrawRectangle(ref world);
I rotate :-)
DrawScene()
world = Matrix.CreateTranslation(new Vector3(8.0f, 0, -10.0f)); DrawRectangle(ref world); world = Matrix.CreateTranslation(new Vector3(8.0f, 0, -6.0f)); DrawRectangle(ref world); //Render this one "behind" us and rotate it so it doesn't get culled world = Matrix.CreateRotationY(MathHelper.ToRadians(180f)) * Matrix.CreateTranslation(new Vector3(3.0f, 0, 10.0f)); DrawRectangle(ref world); world = Matrix.CreateRotationX(1.57f) * Matrix.CreateScale(20, 1, 20)*Matrix.CreateTranslation(0,-2,0); DrawRectangle(ref world);
Ground Plane
How to make better?
How to make better?
How about controller speed of camera, could add a
running mode.
Should be passed in to camera class
Collision detection
May need to provide a service to the camera to have it
check to see if it can move from the current position to the new position.
Could also be a function
Reset to home?