/// ----------------------------------------------- /// PRECACHING & STATIC DATA VALUES /// ----------------------------------------------- public static string ClassName = "DemoPlayer"; private static bool HasCached = false; public static void Precache() { bool Cached = MPrecacher.Precache(ClassName, HasCached); if (!HasCached) { StaticAnimHandleIdle = StaticModel.LoadAnimation("Alien_idle.X",true); HasCached = Cached; } } /// // load our player model for use static private MModel StaticModel = MPrecacher.PrecacheModel(ClassName, "Alien.xml"); // it's good practice to set all anim handles should to -1 until we load them static private int StaticAnimHandleIdle = -1; /// ----------------------------------------------- /// ----------------------------------------------- ///
/// <summary> /// Whether we're in Third Person View or not. Default true /// </summary> bool IsInThirdPerson = true; /// <summary> /// ctor /// </summary> public DemoPlayer(MWorld world) : base(world) { Precache(); // let's create a new Model instance of our character Model MyModel = new MModel(); StaticModel.CreateNewInstance(MyModel); // and play the Idle animation on it MyModel.TransitionToAnimation(StaticAnimHandleIdle, 0); // In-game, we want these basic Engine Physics states, // they're ideal for a wall-sliding, stair-climbing, pushable character in the world CollisionFlags = COLLISION_FLAGS.CF_BBOX; PhysicsFlags = PHYSICS_FLAGS.PHYS_PUSHABLE | PHYSICS_FLAGS.PHYS_ONBLOCK_CLIMBORSLIDE; // set the demoplayer's collision box size SetCollisionBox(new MVector(-DemoPlayerBoxWidth, -DemoPlayerBoxHeight / 2, -DemoPlayerBoxWidth), new MVector(DemoPlayerBoxWidth, DemoPlayerBoxHeight / 2, DemoPlayerBoxWidth)); // we'll create the DemoPlayer in slightly different ways // depending on whether we're in Reality Builder or in the actual Game if (MHelpers.EditorMode) { CollisionFlags |= COLLISION_FLAGS.CF_ALLOW_STUCK; PhysicsFlags |= PHYSICS_FLAGS.PHYS_NOT_AFFECTED_BY_GRAVITY; } else { // In-game, let's set this DemoPlayer as the GameCore's avatar, // so that the GameCore will call its input and camera updating functions during the World Tick! GameCore.Game.LocalAvatar = this; // hide the main menu, because we're ready to control this DemoPlayer now if (!MHelpers.IsDedicated()) GameCore.Gui_MainMenu.Hide(); } // let's give this character a dropshadow ShadowType = Shadows.Drop; }
/// <summary> /// This function is called by the GameCore.cs in Tick when you declare this Actor to be the GameCore's avatar /// </summary> public override void UpdateCamera() { IsHidden = !IsInThirdPerson; MMatrix cameraTransform = GetCameraTransform(IsInThirdPerson); MCameraHandler.setToView(cameraTransform.m3, cameraTransform.GetRotationMatrix()); }
/// <summary> /// Gets Third Person or First Person camera transformation for this Player's viewpoint /// </summary> protected MMatrix GetCameraTransform(bool thirdPerson) { MMatrix camTransform; // when the player is in first person view if (!thirdPerson) { // just set the camera to the DemoPlayer's Location plus half the height of the bbox up, // so that his eyes are located at the top of the bbox // and use his Rotation too. camTransform = new MMatrix(Rotation, Location + new MVector(0, m_DemoPlayerBoxHeight / 2, 0)); } else { const float CameraCollisionTestSize = .3f; const float CameraDirOffset = 1.75f; const float CameraYOffset = 0; const float CameraMaxYRadians = 1.3f; MMatrix firstPersonTransform = GetCameraTransform(false); // third person camera MVector startPos = firstPersonTransform.m3; MVector rotDir = firstPersonTransform.GetDir(); // limit the pitch of the translation of the camera so we aren't looking up the character's, er, legs float pitchAngle = rotDir.RadAngle(MHelpers.VectorDown) - (float)Math.PI / 2; if (pitchAngle > CameraMaxYRadians) pitchAngle = CameraMaxYRadians; // get the yaw angle of the character's Rotation so we can reassemble the Rotation Matrix with our new pitch.. float yawAngle = MHelpers.Rad2Deg((float)Math.Atan2((double)rotDir.z, (double)-rotDir.x)) - 90; //.. like so MMatrix cameraRot = MMatrix.LookTowards(MVector.MakeDirection(yawAngle, MHelpers.Rad2Deg(-pitchAngle), 0)); MVector testCamPos = startPos + CameraYOffset * MHelpers.VectorUp + -CameraDirOffset * cameraRot.GetDir(); // ray test the desired camera position so it doesn't go through walls // if a collision is found, put it a little ways in front of the wall MCollisionInfo info = new MCollisionInfo(); if (MyWorld.CollisionCheckRay(this, startPos, testCamPos + CameraCollisionTestSize * (testCamPos - startPos).Normalized(), MCheckType.CHECK_EVERYTHING, info)) { testCamPos = info.point + CameraCollisionTestSize * (startPos - testCamPos).Normalized(); } // camera's rotation should be towards the player's infinite look point, no matter where the Camera itself is camTransform = MMatrix.LookTowards(((startPos + rotDir * 500) - testCamPos).Normalized()); // put the camera's location at our determined point camTransform.m3 = testCamPos; } return camTransform; }
public override void OnRender(MCamera camera) { // since we don't want our entire Player model to actually rotate vertically // where we're look, we'll clear the Model's Y direction here MVector direction = Rotation.GetDir(); direction.y = 0; MMatrix newRotation = MMatrix.LookTowards(direction.Normalized()); // also, let's rotate the Player Model -180 degrees on the Y axis, // to fix the Alien.xml's backwards rotation const float RotationYawFix = -180; // and a -1 Y offset to fix the Alien.xml's Locational offset // from the Location-centered DemoPlayer const float TranslationYFix = -1.1f; newRotation.Rotate(0, RotationYawFix, 0); MVector locationOffset = TranslationYFix*newRotation.GetUp(); MyModel.SetTransform(newRotation, Location + locationOffset); }
public override void Tick() { // set our animations depending on whether this DemoPlayer is running if (Velocity.Length() > 1.8f && CurrentState == STATE_ONGROUND) MyModel.TransitionToAnimation(StaticAnimHandleRun, .3f); else MyModel.TransitionToAnimation(StaticAnimHandleIdle, .3f); base.Tick(); }
//=========== (C) Copyright 2004, Artificial Studios. All rights reserved. ================ /// DemoPlayer: A simple example avatar that processes input and updates the camera /// /// A tutorial that describes the creation of this class is located at: /// http://reality.artificialstudios.com/twiki/bin/view/Main/DemoPlayer /// /// Author: Jeremy Stieglitz //========================================================================================= #region Using directives using System; using ScriptingSystem; using System.ComponentModel; #endregion [Browsable(true)] public class DemoPlayer : MActor { /// ----------------------------------------------- /// PRECACHING & STATIC DATA VALUES /// ----------------------------------------------- public static string ClassName = "DemoPlayer"; private static bool HasCached = false; public static void Precache() { bool Cached = MPrecacher.Precache(ClassName, HasCached); if (!HasCached) { StaticAnimHandleIdle = StaticModel.LoadAnimation("Alien_idle.X",true); StaticAnimHandleRun = StaticModel.LoadAnimation("Alien_runforward.X", true); HasCached = Cached; } } /// // load our player model for use static private MModel StaticModel = MPrecacher.PrecacheModel(ClassName, "Alien.xml"); // it's good practice to set all anim handles should to -1 until we load them static private int StaticAnimHandleIdle = -1; static private int StaticAnimHandleRun = -1; /// ----------------------------------------------- /// ----------------------------------------------- /// private float m_WalkSpeed = 6.0f; [Description("The speed at which the DemoPlayer walks, in meters per second.")] public float WalkSpeed { get { return m_WalkSpeed; } set { m_WalkSpeed = value; } } private float m_JumpVelocity = 8.0f; [Description("The Y velocity with which the DemoPlayer jumps off the ground.")] public float JumpVelocity { get { return m_JumpVelocity; } set { m_JumpVelocity = value; } } private float m_DemoPlayerBoxWidth = 0.4f; [Description("The width of the DemoPlayer's bounding box, in meters.")] public float DemoPlayerBoxWidth { get { return m_DemoPlayerBoxWidth; } set { m_DemoPlayerBoxWidth = value; } } private float m_DemoPlayerBoxHeight = 2; [Description("The height of the DemoPlayer's bounding box, in meters. \nThe DemoPlayer's eyes will be located at the top of this height.")] public float DemoPlayerBoxHeight { get { return m_DemoPlayerBoxHeight; } set { m_DemoPlayerBoxHeight = value; } } /// <summary> /// Whether we're in Third Person View or not. Default true /// </summary> bool IsInThirdPerson = true; /// <summary> /// ctor /// </summary> public DemoPlayer(MWorld world) : base(world) { Precache(); // let's create a new Model instance of our character Model MyModel = new MModel(); StaticModel.CreateNewInstance(MyModel); // and play the Idle animation on it MyModel.TransitionToAnimation(StaticAnimHandleIdle, 0); // In-game, we want these basic Engine Physics states, // they're ideal for a wall-sliding, stair-climbing, pushable character in the world CollisionFlags = COLLISION_FLAGS.CF_BBOX; PhysicsFlags = PHYSICS_FLAGS.PHYS_PUSHABLE | PHYSICS_FLAGS.PHYS_ONBLOCK_CLIMBORSLIDE; // set the demoplayer's collision box size SetCollisionBox(new MVector(-DemoPlayerBoxWidth, -DemoPlayerBoxHeight / 2, -DemoPlayerBoxWidth), new MVector(DemoPlayerBoxWidth, DemoPlayerBoxHeight / 2, DemoPlayerBoxWidth)); // we'll create the DemoPlayer in slightly different ways // depending on whether we're in Reality Builder or in the actual Game if (MHelpers.EditorMode) { CollisionFlags |= COLLISION_FLAGS.CF_ALLOW_STUCK; PhysicsFlags |= PHYSICS_FLAGS.PHYS_NOT_AFFECTED_BY_GRAVITY; } else { // In-game, let's set this DemoPlayer as the GameCore's avatar, // so that the GameCore will call its input and camera updating functions during the World Tick! GameCore.Game.LocalAvatar = this; // hide the main menu, because we're ready to control this DemoPlayer now if (!MHelpers.IsDedicated()) GameCore.Gui_MainMenu.Hide(); } // let's give this character a dropshadow ShadowType = Shadows.Drop; } /// <summary> /// This function is called by the GameCore.cs in Tick when you declare this Actor to be the GameCore's avatar /// </summary> public override void ProcessInput() { // calculate Player Rotation according to mouse yaw and pitch Rotation = MMatrix.LookTowards(MVector.MakeDirection(MInput.mouseYaw, MInput.mousePitch, 0)); MVector newDirection = new MVector(); // User's new attempted direction //basic movement inputs // strafing left and right if (GameInput.ControlDown(GameInput.KEY_STRAFE_LEFT)) newDirection += 0.5f * (-Rotation.GetRight()); else if (GameInput.ControlDown(GameInput.KEY_STRAFE_RIGHT)) newDirection += 0.5f * (Rotation.GetRight()); // moving forward and backwards if (GameInput.ControlDown(GameInput.KEY_WALK_FORWARD)) newDirection += Rotation.GetDir(); else if (GameInput.ControlDown(GameInput.KEY_WALK_BACKWARD)) newDirection -= Rotation.GetDir(); newDirection.y = 0; // demoplayer movement has no Y component if (CurrentState == STATE_ONGROUND) Accelerate(newDirection.Normalized(), WalkSpeed, 46); // ground acceleration else Accelerate(newDirection.Normalized(), WalkSpeed, 7); // air acceleration // check if the jump key is pressed, and if the user's feet are on the ground, jump him if (GameInput.ControlJustPressed(GameInput.KEY_JUMP) && CurrentState == STATE_ONGROUND) Velocity.y = JumpVelocity; } /// <summary> /// This function is called by the GameCore.cs in Tick when you declare this Actor to be the GameCore's avatar /// </summary> public override void UpdateCamera() { IsHidden = !IsInThirdPerson; MMatrix cameraTransform = GetCameraTransform(IsInThirdPerson); MCameraHandler.setToView(cameraTransform.m3, cameraTransform.GetRotationMatrix()); } /// <summary> /// Gets Third Person or First Person camera transformation for this Player's viewpoint /// </summary> protected MMatrix GetCameraTransform(bool thirdPerson) { MMatrix camTransform; // when the player is in first person view if (!thirdPerson) { // just set the camera to the DemoPlayer's Location plus half the height of the bbox up, // so that his eyes are located at the top of the bbox // and use his Rotation too. camTransform = new MMatrix(Rotation, Location + new MVector(0, m_DemoPlayerBoxHeight / 2, 0)); } else { const float CameraCollisionTestSize = .3f; const float CameraDirOffset = 1.75f; const float CameraYOffset = 0; const float CameraMaxYRadians = 1.3f; MMatrix firstPersonTransform = GetCameraTransform(false); // third person camera MVector startPos = firstPersonTransform.m3; MVector rotDir = firstPersonTransform.GetDir(); // limit the pitch of the translation of the camera so we aren't looking up the character's, er, legs float pitchAngle = rotDir.RadAngle(MHelpers.VectorDown) - (float)Math.PI / 2; if (pitchAngle > CameraMaxYRadians) pitchAngle = CameraMaxYRadians; // get the yaw angle of the character's Rotation so we can reassemble the Rotation Matrix with our new pitch.. float yawAngle = MHelpers.Rad2Deg((float)Math.Atan2((double)rotDir.z, (double)-rotDir.x)) - 90; //.. like so MMatrix cameraRot = MMatrix.LookTowards(MVector.MakeDirection(yawAngle, MHelpers.Rad2Deg(-pitchAngle), 0)); MVector testCamPos = startPos + CameraYOffset * MHelpers.VectorUp + -CameraDirOffset * cameraRot.GetDir(); // ray test the desired camera position so it doesn't go through walls // if a collision is found, put it a little ways in front of the wall MCollisionInfo info = new MCollisionInfo(); if (MyWorld.CollisionCheckRay(this, startPos, testCamPos + CameraCollisionTestSize * (testCamPos - startPos).Normalized(), MCheckType.CHECK_EVERYTHING, info)) { testCamPos = info.point + CameraCollisionTestSize * (startPos - testCamPos).Normalized(); } // camera's rotation should be towards the player's infinite look point, no matter where the Camera itself is camTransform = MMatrix.LookTowards(((startPos + rotDir * 500) - testCamPos).Normalized()); // put the camera's location at our determined point camTransform.m3 = testCamPos; } return camTransform; } public override void Tick() { // set our animations depending on whether this DemoPlayer is running if (Velocity.Length() > 1.8f && CurrentState == STATE_ONGROUND) MyModel.TransitionToAnimation(StaticAnimHandleRun, .3f); else MyModel.TransitionToAnimation(StaticAnimHandleIdle, .3f); base.Tick(); } public override void OnRender(MCamera camera) { // since we don't want our entire Player model to actually rotate vertically // where we're look, we'll clear the Model's Y direction here MVector direction = Rotation.GetDir(); direction.y = 0; MMatrix newRotation = MMatrix.LookTowards(direction.Normalized()); // also, let's rotate the Player Model -180 degrees on the Y axis, // to fix the Alien.xml's backwards rotation const float RotationYawFix = -180; // and a -1 Y offset to fix the Alien.xml's Locational offset // from the Location-centered DemoPlayer const float TranslationYFix = -1.1f; newRotation.Rotate(0, RotationYawFix, 0); MVector locationOffset = TranslationYFix*newRotation.GetUp(); MyModel.SetTransform(newRotation, Location + locationOffset); } /// <summary> /// Our Quake-style walk acceleration function /// </summary> protected void Accelerate(MVector wishdir, float wishspeed, float accel) { // apply acceleration towards desired direction, with removal of over-acceleration. float addspeed, currentspeed; //calculate the acceleration vecetor to add to achieve the desired velocity direction currentspeed = Velocity.Dot(wishdir); if (wishspeed == currentspeed) return; // add time-scaled acceleration if (wishspeed > currentspeed) addspeed = accel * MHelpers.DeltaTime; else addspeed = -accel * MHelpers.DeltaTime; // limit acceleration to exact needed value to achieve desired speed if ((currentspeed + addspeed > wishspeed && wishspeed > currentspeed) || (currentspeed + addspeed < wishspeed && wishspeed < currentspeed)) addspeed = wishspeed - currentspeed; // add the calculated acceleration amount in the desired direction to our current Velocity Velocity += addspeed * wishdir; } /// <summary> /// Called right after the World renders, to allow custom canvas drawing with regards to this Actor /// In the DemoPlayer's case, we'll draw a very simple HUD /// </summary> public override void PostRender(MCamera camera) { // Some way cool HUD text if(GamePrefs.Instance.displayHUD) MCanvas.TextCenteredf(MCanvas.MediumFont, MHelpers.ColorFromRGBA(200, 255, 255, 190), 512, 740, "I am a DemoPlayer."); } /// <summary> /// Disposal of the Actor's resources, called when the Actor is destroyed, /// namely by having its LifeTime set to 0, having Destroy() called on it, or upon World unloading/app shutdown /// </summary> protected override void DisposeResources() { // if this actor is currently the GameCore's local avatar, // it's good C# programming practice to nullify the local avatar reference // when this Actor is disposed of. if (GameCore.Game.LocalAvatar == this) GameCore.Game.LocalAvatar = null; base.DisposeResources(); } }