public void Update() { if (!Status.IsLiving) { return; } #region begin //gather current data float oldPosX = Properties.Position.X; float oldPosY = Properties.Position.Y; float oldPosZ = Properties.Position.Z; float oldFacing = Agk.GetObjectWorldAngleY(Properties.ResourceNumber); var animSet = AnimationHandler.GetAnimationSet(Properties.Filebase + ".anim"); //a character should NEVER not have an animation. if (AnimationQ.Count == 0) { var tAnim = new AppliedAnimation(this, animSet, "0000L") //add basic idle { IsLoop = true, Speed = 1.0f }; AnimationQ.Add(tAnim); } string tAnimState = AnimationQ[0].Animation.Name.Substring(0, 4).ToLower(); string tAnimStage = AnimationQ[0].Animation.Name.Substring(4, 1).ToLower(); //I L O #endregion #region handle vitals if (Status.Health.Max > 0) { if (App.Timing.Timer - Status.Health.RegenMark > Status.Health.RegenInterval) { Status.Health.Current += (int)Math.Floor(Status.Health.RegenAmount); if (Status.Health.Current > Status.Health.Max) { Status.Health.Current = Status.Health.Max; } Status.Health.RegenMark = App.Timing.Timer; } } if (Status.Stamina.Max > 0) { if (App.Timing.Timer - Status.Stamina.RegenMark > Status.Stamina.RegenInterval) { //stamina if affected by locomotion and exhaustion if (Status.MotionState == MotionStates.Sprinting) { //sprint costs stamina Status.Stamina.Current -= 2; } else if (Status.MotionState != MotionStates.Running) { //run suppresses regen, otherwise recover Status.Stamina.Current += (int)Math.Floor(Status.Stamina.RegenAmount); } if (Status.Stamina.Current > Status.Stamina.Max) { Status.Stamina.Current = Status.Stamina.Max; } if (Status.Stamina.Current > Status.Stamina.Max * 0.2f) { //clear exhaustion if stamina has recovered > 1/5 of max Status.IsExhausted = false; } if (Status.Stamina.Current <= 0) { //if stamina runs out, apply exhaustion Status.Stamina.Current = 0; Status.IsExhausted = true; if (Status.MotionState == MotionStates.Sprinting) { //drop out of sprint if exhausted if (Status.IsRunLocked) { Status.MotionState = MotionStates.Running; } else { Status.MotionState = MotionStates.Walking; } } } } } #endregion #region handle position bool mustCalcPosition = true; //update speed switch (Status.ActionState) { case ActionStates.Idle: if (Status.MotionState == MotionStates.Walking) { //immediate stop when walking cus aint no body got time for iceskating Properties.Speed = 0.0f; } if (Properties.Speed > 0.0f) { //new state is idle, meaning we stopped, but we have speed meaning we were moving //immediately drop from sprint to run, but if running transition to walk over time. //this means if speed remains, we also have to enforce a moving state if (Properties.Speed > CharacterHandler3d.Config.NormalMaxSpeed) { Properties.Speed = MathUtil.CurveValue(10.0f, Properties.Speed, Agk.ScreenFPS() * CharacterHandler3d.Config.NormalDeceleration * 0.5f); Status.MotionState = MotionStates.Running; Status.ActionState = ActionStates.Moving; } else if (OldStatus.MotionState == MotionStates.Running) { Properties.Speed = MathUtil.CurveValue(10.0f, Properties.Speed, Agk.ScreenFPS() * CharacterHandler3d.Config.NormalDeceleration); Status.MotionState = MotionStates.Walking; Status.ActionState = ActionStates.Moving; } else { Properties.Speed = 0.0f; } } if (Properties.Speed < 25.0) { //cut the curve transitions short if they get low enough, it feels better Properties.Speed = 0.0f; Status.MotionState = MotionStates.Stationary; Status.ActionState = ActionStates.Idle; } break; case ActionStates.Moving: switch (Status.MotionState) { case MotionStates.Walking: if (Status.StanceState == StanceStates.Sneaking) { Properties.Speed = MathUtil.CurveValue(CharacterHandler3d.Config.SneakMaxSpeed * Properties.SlopeModifier, Properties.Speed, Agk.ScreenFPS() * CharacterHandler3d.Config.SneakAcceleration); } else { Properties.Speed = MathUtil.CurveValue(CharacterHandler3d.Config.NormalMaxSpeed * Properties.SlopeModifier, Properties.Speed, Agk.ScreenFPS() * CharacterHandler3d.Config.NormalAcceleration); } break; case MotionStates.Running: Properties.Speed = MathUtil.CurveValue(CharacterHandler3d.Config.RunMaxSpeed * Properties.SlopeModifier, Properties.Speed, Agk.ScreenFPS() * CharacterHandler3d.Config.NormalAcceleration); break; case MotionStates.Sprinting: Properties.Speed = MathUtil.CurveValue(CharacterHandler3d.Config.SprintMaxSpeed * Properties.SlopeModifier, Properties.Speed, Agk.ScreenFPS() * CharacterHandler3d.Config.SprintAcceleration); break; } if (Status.MotionState != MotionStates.Forced) { //if a slope or other effect has reduced our speed to less than half of the max run speed, enforce a walking state. it looks weird to run or sprint in slow motion... if (Properties.Speed <= (CharacterHandler3d.Config.RunMaxSpeed * 0.5f) && (Status.MotionState == MotionStates.Running || Status.MotionState == MotionStates.Sprinting)) { Status.MotionState = MotionStates.Walking; } //if slope is too steep to maintain forward speed, enforce stoppage. we don't want to crawl glacially slow up a steep hill and we don't want to generate a bunch of collision data if (Properties.Speed < (CharacterHandler3d.Config.SneakMaxSpeed * 1.5f) && Properties.SlopeModifier < 1.0f) { //TODO: apply slide downslope instead of just stopping //NOTE: slide down will need to set to a forced state / ability animation which takes the character far enough down to avoid jitter // handling this through a forced move ability can probably deprecate the need for slopeLock. can just use the falling animation key Properties.Speed = 0.0f; Status.MotionState = MotionStates.Stationary; Status.ActionState = ActionStates.Idle; Status.IsSlopeLocked = true; } if (Properties.SlopeModifier > 1.00f) { Status.IsSlopeLocked = false; } } break; case ActionStates.Jumping: //jumps are complex and composed of multiple stages if (OldStatus.ActionState == ActionStates.Jumping) { //if jump is in a prep stage, position is controlled by character handler. while in flight/fall position is controlled by arc handler if (tAnimStage != "i") { mustCalcPosition = false; Properties.Position = Properties.ArcPath.GetPosition(App.Timing.Timer, App.Timing.PauseElapsed); //jump is in flight/fall -- are we ascending or descending? if (Properties.Position.Y < oldPosY) { Status.ActionState = ActionStates.Falling; } } } break; case ActionStates.Falling: mustCalcPosition = false; Properties.Position = Properties.ArcPath.GetPosition(App.Timing.Timer, App.Timing.PauseElapsed); break; } if (mustCalcPosition) { Properties.Position.X += Agk.Sin(Properties.Heading) * Properties.Speed * (App.Timing.Delta * 0.001f); //speed is in terms of units per second, delta is in ms Properties.Position.Z += Agk.Cos(Properties.Heading) * Properties.Speed * (App.Timing.Delta * 0.001f); } #endregion #region handle collision /* * var colRay = new CollisionRay(); * int collisionState = 0; * * //lateral slide * if(Status.ActionState > ActionStates.Idle) * { * colRay.SphereCast * ( * new AGKVector3(oldPosX, oldPosY + (Properties.Height * 0.5f), oldPosZ), * new AGKVector3(Properties.Position.X, Properties.Position.Y + (Properties.Height * 0.5f), Properties.Position.Z), * CharacterHandler3d.Config.CollisionBufferDistance, true * ); * if (colRay.HitObjectNumber > 0) * { * Properties.Position.X = colRay.HitPosition.X; * Properties.Position.Z = colRay.HitPosition.Z; * collisionState = 1; * } * } * * //vertical down * * float tHeight = 0.0f; * //TODO: tHeight = get terrain height * * colRay.RayCast * ( * new AGKVector3(Properties.Position.X, Properties.Position.Y + 100.0f, Properties.Position.Z), * new AGKVector3(Properties.Position.X, Properties.Position.Y - 100.0f, Properties.Position.Z) * ); * * //TODO: compare collision height to terrain height * //TEMP: just use col * if (colRay.HitObjectNumber > 0) * { * tHeight = colRay.HitPosition.Y; * } * * if (Properties.Position.Y < tHeight) * { * Properties.Position.Y = tHeight; * collisionState = 2; * } * * if (Properties.ArcPath != null) * { * if (collisionState == 1) * { * //hit a vertical surface, change arc to fall straight down * Properties.ArcPath.Dispose(); * Properties.ArcPath = ArcHandler.Create(this, 400.0f, 270.0f, Properties.Heading); * Status.ActionState = ActionStates.Falling; * } * else if(collisionState == 2) * { * //hit a horizontal surface, end the arc * Properties.ArcPath.Dispose(); * Status.ActionState = ActionStates.Idle; * Status.MotionState = MotionStates.Stationary; * } * } * else * { * //no arc, just force to horizontal surface * Properties.Position.Y = tHeight; * * //slope / cliff ? * var tDiff = oldPosY - Properties.Position.Y; * if(tDiff < 0.0f && Status.IsSlopeLocked) * { * //negative diff means ascending * * if(App.Timing.Timer - Status.SlopeMark > 200) * { * Properties.SlopeModifier = 0.0f; * } * Properties.Speed = 0.0f; * Status.ActionState = ActionStates.Idle; * Status.MotionState = MotionStates.Stationary; * Properties.Position.X = oldPosX; * Properties.Position.Y = oldPosY; * Properties.Position.Z = oldPosZ; * } * else if(tDiff > Properties.Height * 0.5f) * { * //positive diff means descending, if descending more than waist height, change to falling * * Properties.Position.Y = oldPosY; * Properties.ArcPath = ArcHandler.Create(this, 100.0f + Properties.Speed, 30.0f, Properties.Heading); * Status.ActionState = ActionStates.Falling; * Status.StanceState = StanceStates.Basic; * Status.MotionState = MotionStates.Forced; * } * else * { * //NOTE: negative tDiff# indicates character moved uphill, larger the negative, the steeper the hill. * //NOTE: slopeMod is a speed increase 1.3 = speed * 1.3, 0.0 = stop. * //TODO: use a fixed length sample, currently rate of movement and framerate affect the slope result. * //NOTE: slopeMark / threshold smooth against jitter * if(App.Timing.Timer - Status.SlopeMark > 200) * { * float slopeThreshold = -0.4f; * if(tDiff > 0.0f || tDiff < slopeThreshold) * { * Properties.SlopeModifier = 1.0f + tDiff; * if(Properties.SlopeModifier < 0.0f) { Properties.SlopeModifier = 0.0f; } * if(Properties.SlopeModifier < 1.3f) { Properties.SlopeModifier = 1.3f; } * } * else * { * Properties.SlopeModifier = 1.0f; * } * } * * //TEMP: disable slopeMod * Properties.SlopeModifier = 1.0f; * } * } */ #endregion #region apply to object Agk.SetObjectRotation(Properties.ResourceNumber, 0.0f, MathUtil.CurveAngle(Properties.Facing, oldFacing, Agk.ScreenFPS() * CharacterHandler3d.Config.NormalTurnSpeed), 0.0f); Agk.SetObjectPosition(Properties.ResourceNumber, Properties.Position.X, Properties.Position.Y, Properties.Position.Z); #endregion #region handle animation //get new animation state string tState = ((int)Status.StanceState).ToString() + ((int)Status.ActionState).ToString() + ((int)Status.MotionState).ToString() + ((int)Status.DirectionState).ToString(); string tOldState = ((int)OldStatus.StanceState).ToString() + ((int)OldStatus.ActionState).ToString() + ((int)OldStatus.MotionState).ToString() + ((int)OldStatus.DirectionState).ToString(); string tBaseStance = ((int)Status.StanceState).ToString(); string oldBaseStance = ((int)OldStatus.StanceState).ToString(); string tBaseState = tBaseStance + "000"; string keyBaseIdleStationaryUp = ((int)ActionStates.Idle).ToString() + ((int)MotionStates.Stationary).ToString() + ((int)DirectionStates.Standard).ToString(); //for convenience if (tState != tAnimState && tAnimState + "O" != AnimationQ[0].Animation.Name && tAnimState + "I" != AnimationQ[0].Animation.Name) { //animation state has changed, clear the current animation stack and rebuild under the new state AnimationQ.Clear(); if (tState == tBaseState && tBaseStance == oldBaseStance) { //transition old state out var tAnimO = new AppliedAnimation(this, animSet, tAnimState + "O") { IsLoop = false, }; AnimationQ.Add(tAnimO); //transition new state in if (Status.StanceState != OldStatus.StanceState) { var tAnimI = new AppliedAnimation(this, animSet, tState + "I") { IsLoop = false, }; AnimationQ.Add(tAnimI); } } else { //dont need to transition old state out, just transition new state in if (Status.ActionState == ActionStates.Jumping) { float tJumpAngle; if (Properties.Speed > 0.0f) { tJumpAngle = 30.0f; } else { tJumpAngle = 90.0f; } dynamic jumpArgs = new { Angle = tJumpAngle, Speed = 400.0f + Properties.Speed, Owner = this }; if (Properties.Speed > CharacterHandler3d.Config.NormalMaxSpeed) { //if running/sprinting, skip stage i and go straight into jump proper AddJump(jumpArgs); } else { //walking or stationary, we need a bit of animation prep. for the feels. var tAnimI = new AppliedAnimation(this, animSet, tState + "I") { IsLoop = false, Callback = "CharacterEntity3d.AddJump", CallbackArgs = JsonConvert.SerializeObject(jumpArgs) }; AnimationQ.Add(tAnimI); } } else { if (Status.StanceState != OldStatus.StanceState) { var tAnimII = new AppliedAnimation(this, animSet, tState + "I") { IsLoop = false, }; AnimationQ.Add(tAnimII); } } } //always proceed into state Loop -> characters should never be static! var tAnimL = new AppliedAnimation(this, animSet, tState + "L") { IsLoop = true, }; AnimationQ.Add(tAnimL); } //update animation frame bool isDone = AnimationQ[0].Update(); if (isDone) { AnimationQ.RemoveAt(0); } #endregion }
public static void GetGameplayInput(object rArgs) { App.Log("controls3d", LogLevel.Notice, "main", "> Begin GetGameplayInput"); //reset forced UserInterface.Status.MouseModeForced = ""; UserInterface.Status.KeyModeForced = ""; //exit early if user does not have control /* * if(App.Status.LoadState < 3) * { * return; * } */ if (CharacterHandler3d.MyCharacter == null) { return; } if (!CharacterHandler3d.MyCharacter.Status.IsLiving) { return; } if (UserInterface.Status.KeyMode != "gameplay" || CharacterHandler3d.MyCharacter.Status.MotionState == CharacterEntity3d.MotionStates.Forced) { return; } if (ActiveCamera.ControlMode != Camera3d.CameraMode.Anchored) { return; } bool animWait = false; if (CharacterHandler3d.MyCharacter.AnimationQ.Count > 0) { animWait = CharacterHandler3d.MyCharacter.AnimationQ.First().Animation.Wait; } //grab old state CharacterHandler3d.MyCharacter.OldStatus = JsonConvert.DeserializeObject <CharacterEntity3d.CharacterStatus>(JsonConvert.SerializeObject(CharacterHandler3d.MyCharacter.Status)); //reset states that need to be held by user if (CharacterHandler3d.MyCharacter.Status.StanceState == CharacterEntity3d.StanceStates.Sneaking) { CharacterHandler3d.MyCharacter.Status.StanceState = CharacterEntity3d.StanceStates.Basic; } if (CharacterHandler3d.MyCharacter.Status.ActionState == CharacterEntity3d.ActionStates.Moving) { CharacterHandler3d.MyCharacter.Status.ActionState = CharacterEntity3d.ActionStates.Idle; } if (CharacterHandler3d.MyCharacter.Status.MotionState != CharacterEntity3d.MotionStates.Forced) { CharacterHandler3d.MyCharacter.Status.MotionState = CharacterEntity3d.MotionStates.Stationary; } CharacterHandler3d.MyCharacter.Status.DirectionState = CharacterEntity3d.DirectionStates.Standard; //get mouse input if (UserInterface.Status.MouseMode == "gameplay") { } //get keyboard input if (UserInterface.Status.KeyMode == "gameplay" && !animWait) { if (CharacterHandler3d.MyCharacter.Status.MotionState != CharacterEntity3d.MotionStates.Forced) { //toggle strafelock if (Hardware.IsKeyDown(MovementKey.StrafeToggle) && UserInterface.Status.InputReady) { UserInterface.Status.InputMark = App.Timing.Timer; CharacterHandler3d.MyCharacter.Status.IsStrafeLocked = !CharacterHandler3d.MyCharacter.Status.IsStrafeLocked; } //toggle runlock if (Hardware.IsKeyDown(MovementKey.RunToggle) && UserInterface.Status.InputReady) { UserInterface.Status.InputMark = App.Timing.Timer; CharacterHandler3d.MyCharacter.Status.IsRunLocked = !CharacterHandler3d.MyCharacter.Status.IsRunLocked; } //apply run if locked if (CharacterHandler3d.MyCharacter.Status.IsRunLocked && CharacterHandler3d.MyCharacter.OldStatus.StanceState == CharacterEntity3d.StanceStates.Basic ) { if (CharacterHandler3d.MyCharacter.OldStatus.ActionState == CharacterEntity3d.ActionStates.Moving && CharacterHandler3d.MyCharacter.OldStatus.MotionState < CharacterEntity3d.MotionStates.Sprinting ) { CharacterHandler3d.MyCharacter.Status.MotionState = CharacterEntity3d.MotionStates.Running; } } //sneak if (Hardware.IsKeyDown(MovementKey.SpeedSlow)) { CharacterHandler3d.MyCharacter.Status.StanceState = CharacterEntity3d.StanceStates.Sneaking; } //sprint if (Hardware.IsKeyDown(MovementKey.SpeedBoost)) { if (CharacterHandler3d.MyCharacter.Status.StanceState == CharacterEntity3d.StanceStates.Basic && CharacterHandler3d.MyCharacter.OldStatus.ActionState == CharacterEntity3d.ActionStates.Moving && CharacterHandler3d.MyCharacter.Status.MotionState != CharacterEntity3d.MotionStates.Forced ) { CharacterHandler3d.MyCharacter.Status.MotionState = CharacterEntity3d.MotionStates.Sprinting; } } //jump if (Hardware.IsKeyDown(MovementKey.Upward) && UserInterface.Status.InputReady) { //don't allow a jump if sneaking or already in a jump if (CharacterHandler3d.MyCharacter.Status.StanceState == CharacterEntity3d.StanceStates.Basic && CharacterHandler3d.MyCharacter.Status.ActionState < CharacterEntity3d.ActionStates.Jumping ) { UserInterface.Status.InputMark = App.Timing.Timer; CharacterHandler3d.MyCharacter.Status.ActionState = CharacterEntity3d.ActionStates.Jumping; CharacterHandler3d.MyCharacter.Status.MotionState = CharacterEntity3d.MotionStates.Forced; } } float camY = MathUtil.Wrap(Agk.GetCameraAngleY(1) + 180.0f, 0.0f, 360.0f); //forward if (Hardware.IsKeyDown(MovementKey.Forward)) { CharacterHandler3d.MyCharacter.Status.ActionState = CharacterEntity3d.ActionStates.Moving; if (CharacterHandler3d.MyCharacter.Status.MotionState == CharacterEntity3d.MotionStates.Stationary) { CharacterHandler3d.MyCharacter.Status.MotionState = CharacterEntity3d.MotionStates.Walking; } CharacterHandler3d.MyCharacter.Properties.Facing = MathUtil.Wrap(camY + 180.0f, 0.0f, 360.0f); CharacterHandler3d.MyCharacter.Properties.Heading = MathUtil.Wrap(camY + 180.0f, 0.0f, 360.0f); } //backward if (Hardware.IsKeyDown(MovementKey.Backward)) { CharacterHandler3d.MyCharacter.Status.ActionState = CharacterEntity3d.ActionStates.Moving; if (CharacterHandler3d.MyCharacter.Status.MotionState == CharacterEntity3d.MotionStates.Stationary) { CharacterHandler3d.MyCharacter.Status.MotionState = CharacterEntity3d.MotionStates.Walking; } if (CharacterHandler3d.MyCharacter.Status.IsStrafeLocked) { CharacterHandler3d.MyCharacter.Properties.Facing = MathUtil.Wrap(camY + 180.0f, 0.0f, 360.0f); CharacterHandler3d.MyCharacter.Properties.Heading = camY; CharacterHandler3d.MyCharacter.Status.DirectionState = CharacterEntity3d.DirectionStates.Backward; } else { CharacterHandler3d.MyCharacter.Properties.Facing = camY; CharacterHandler3d.MyCharacter.Properties.Heading = camY; } } //left if (Hardware.IsKeyDown(MovementKey.Left)) { CharacterHandler3d.MyCharacter.Status.ActionState = CharacterEntity3d.ActionStates.Moving; if (CharacterHandler3d.MyCharacter.Status.MotionState == CharacterEntity3d.MotionStates.Stationary) { CharacterHandler3d.MyCharacter.Status.MotionState = CharacterEntity3d.MotionStates.Walking; } if (CharacterHandler3d.MyCharacter.Status.IsStrafeLocked) { if (Hardware.IsKeyDown(MovementKey.Forward)) { CharacterHandler3d.MyCharacter.Properties.Facing = MathUtil.Wrap(camY + 180.0f, 0.0f, 360.0f); CharacterHandler3d.MyCharacter.Properties.Heading = MathUtil.Wrap(camY + 180.0f - 45.0f, 0.0f, 360.0f); CharacterHandler3d.MyCharacter.Status.DirectionState = CharacterEntity3d.DirectionStates.Standard; } else if (Hardware.IsKeyDown(MovementKey.Backward)) { CharacterHandler3d.MyCharacter.Properties.Facing = MathUtil.Wrap(camY + 180.0f, 0.0f, 360.0f); CharacterHandler3d.MyCharacter.Properties.Heading = MathUtil.Wrap(camY + 45.0f, 0.0f, 360.0f); CharacterHandler3d.MyCharacter.Status.DirectionState = CharacterEntity3d.DirectionStates.Backward; } else { CharacterHandler3d.MyCharacter.Properties.Facing = MathUtil.Wrap(camY + 180.0f, 0.0f, 360.0f); CharacterHandler3d.MyCharacter.Properties.Heading = MathUtil.Wrap(camY + 90.0f, 0.0f, 360.0f); CharacterHandler3d.MyCharacter.Status.DirectionState = CharacterEntity3d.DirectionStates.Left; } } else { if (Hardware.IsKeyDown(MovementKey.Forward)) { CharacterHandler3d.MyCharacter.Properties.Facing = MathUtil.Wrap(camY + 180.0f - 45.0f, 0.0f, 360.0f); CharacterHandler3d.MyCharacter.Properties.Heading = MathUtil.Wrap(camY + 180.0f - 45.0f, 0.0f, 360.0f); CharacterHandler3d.MyCharacter.Status.DirectionState = CharacterEntity3d.DirectionStates.Standard; } else if (Hardware.IsKeyDown(MovementKey.Backward)) { CharacterHandler3d.MyCharacter.Properties.Facing = MathUtil.Wrap(camY + 45.0f, 0.0f, 360.0f); CharacterHandler3d.MyCharacter.Properties.Heading = MathUtil.Wrap(camY + 45.0f, 0.0f, 360.0f); CharacterHandler3d.MyCharacter.Status.DirectionState = CharacterEntity3d.DirectionStates.Standard; } else { CharacterHandler3d.MyCharacter.Properties.Facing = MathUtil.Wrap(camY + 90.0f, 0.0f, 360.0f); CharacterHandler3d.MyCharacter.Properties.Heading = MathUtil.Wrap(camY + 90.0f, 0.0f, 360.0f); CharacterHandler3d.MyCharacter.Status.DirectionState = CharacterEntity3d.DirectionStates.Standard; } } } //right if (Hardware.IsKeyDown(MovementKey.Right)) { CharacterHandler3d.MyCharacter.Status.ActionState = CharacterEntity3d.ActionStates.Moving; if (CharacterHandler3d.MyCharacter.Status.MotionState == CharacterEntity3d.MotionStates.Stationary) { CharacterHandler3d.MyCharacter.Status.MotionState = CharacterEntity3d.MotionStates.Walking; } if (CharacterHandler3d.MyCharacter.Status.IsStrafeLocked) { if (Hardware.IsKeyDown(MovementKey.Forward)) { CharacterHandler3d.MyCharacter.Properties.Facing = MathUtil.Wrap(camY + 180.0f, 0.0f, 360.0f); CharacterHandler3d.MyCharacter.Properties.Heading = MathUtil.Wrap(camY + 180.0f + 45.0f, 0.0f, 360.0f); CharacterHandler3d.MyCharacter.Status.DirectionState = CharacterEntity3d.DirectionStates.Standard; } else if (Hardware.IsKeyDown(MovementKey.Backward)) { CharacterHandler3d.MyCharacter.Properties.Facing = MathUtil.Wrap(camY + 180.0f, 0.0f, 360.0f); CharacterHandler3d.MyCharacter.Properties.Heading = MathUtil.Wrap(camY - 45.0f, 0.0f, 360.0f); CharacterHandler3d.MyCharacter.Status.DirectionState = CharacterEntity3d.DirectionStates.Backward; } else { CharacterHandler3d.MyCharacter.Properties.Facing = MathUtil.Wrap(camY + 180.0f, 0.0f, 360.0f); CharacterHandler3d.MyCharacter.Properties.Heading = MathUtil.Wrap(camY - 90.0f, 0.0f, 360.0f); CharacterHandler3d.MyCharacter.Status.DirectionState = CharacterEntity3d.DirectionStates.Right; } } else { if (Hardware.IsKeyDown(MovementKey.Forward)) { CharacterHandler3d.MyCharacter.Properties.Facing = MathUtil.Wrap(camY + 180.0f + 45.0f, 0.0f, 360.0f); CharacterHandler3d.MyCharacter.Properties.Heading = MathUtil.Wrap(camY + 180.0f + 45.0f, 0.0f, 360.0f); CharacterHandler3d.MyCharacter.Status.DirectionState = CharacterEntity3d.DirectionStates.Standard; } else if (Hardware.IsKeyDown(MovementKey.Backward)) { CharacterHandler3d.MyCharacter.Properties.Facing = MathUtil.Wrap(camY - 45.0f, 0.0f, 360.0f); CharacterHandler3d.MyCharacter.Properties.Heading = MathUtil.Wrap(camY - 45.0f, 0.0f, 360.0f); CharacterHandler3d.MyCharacter.Status.DirectionState = CharacterEntity3d.DirectionStates.Standard; } else { CharacterHandler3d.MyCharacter.Properties.Facing = MathUtil.Wrap(camY - 90.0f, 0.0f, 360.0f); CharacterHandler3d.MyCharacter.Properties.Heading = MathUtil.Wrap(camY - 90.0f, 0.0f, 360.0f); CharacterHandler3d.MyCharacter.Status.DirectionState = CharacterEntity3d.DirectionStates.Standard; } } } } } //mouse steers character if moving and not strafe locked if (UserInterface.Status.MouseMode == "gameplay") { if (CharacterHandler3d.MyCharacter.Status.ActionState == CharacterEntity3d.ActionStates.Moving && !CharacterHandler3d.MyCharacter.Status.IsStrafeLocked ) { CharacterHandler3d.MyCharacter.Properties.Facing = MathUtil.CurveAngle(CharacterHandler3d.MyCharacter.Properties.Facing + Hardware.Mouse.MoveX, CharacterHandler3d.MyCharacter.Properties.Facing, ActiveCamera.Precision); } } //sprint camera effect if (CharacterHandler3d.MyCharacter.Status.MotionState == CharacterEntity3d.MotionStates.Sprinting) { ActiveCamera.FOV = MathUtil.CurveValue(65.0f, ActiveCamera.FOV, Agk.ScreenFPS() * CharacterHandler3d.Config.SprintAcceleration); } else if (ActiveCamera.FOV != Camera3dHandler.DefaultFOV) { ActiveCamera.FOV = MathUtil.CurveValue(Camera3dHandler.DefaultFOV, ActiveCamera.FOV, Agk.ScreenFPS() * CharacterHandler3d.Config.SprintAcceleration); } //TEMP: if (Hardware.IsKeyDown((int)Keys.Y)) { Controls3d.ActiveCamera.Offset.Y += 0.1f; } if (Hardware.IsKeyDown((int)Keys.H)) { Controls3d.ActiveCamera.Offset.Y -= 0.1f; } //TEMP: toggle active if (Hardware.IsKeyDown((int)Keys.C) && UserInterface.Status.InputReady) { UserInterface.Status.InputMark = App.Timing.Timer; Controls3d.SetActiveCamera(Camera3dHandler.CameraList.FirstOrDefault(c => c.Name != Controls3d.ActiveCamera.Name)); } //ENDTEMP App.Log("Controls3d", LogLevel.Notice, "main", "> End GetGameplayInput"); }
static void Main(string[] args) { //-------------------------------------------- #region boilerplate inits var attrs = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyTitleAttribute), false).FirstOrDefault() as AssemblyTitleAttribute; //init Agk if (!App.Init(args, attrs.Title)) { return; } //init modules new Hardware(); new Media(); new Devkit3d(); new AnimationHandler(); new CharacterHandler3d(); new World3d(); new Controls3d(); new Camera3dHandler(); new ArcHandler(); new UI.UserInterface(); UI.UserInterface.ControllerList.Add(new UI.CommonController()); UI.UserInterface.ControllerList.Add(new UI.GameMenuController()); UI.UserInterface.PreloadImages(); //clean up UpdateHandler.SortUpdateList(); //init 3D physics Agk.Create3DPhysicsWorld(); App.Log("Program.cs", 3, "main", "> Init Complete"); #endregion //-------------------------------------------- //TEMP setups var floorObj = Agk.CreateObjectBox(40.0f, 2.0f, 40.0f); var floorEnt = new WorldEntity3d(); floorEnt.Properties.ResourceNumber = floorObj; floorEnt.Properties.IsObject = true; var floorFx = Media.GetShaderAsset("media/shaders/SurfaceColorLit.vs", "media/shaders/SurfaceColorLit.ps", true); floorEnt.SetShader(floorFx); Agk.SetShaderConstantByName(floorFx.ResourceNumber, "u_color", 0.8f, 0.8f, 0.8f, 0); floorEnt.Properties.Position.Y = -1.0f; World3d.WorldEntityList.Add(floorEnt); Agk.Create3DPhysicsStaticBody(floorEnt.Properties.ResourceNumber); /* * var ent = new WorldEntity3d(); * var tObj = Media.LoadObjectAsset("media/characters/woman.dae", true, false, Guid.NewGuid().ToString()); * Agk.SetObjectScalePermanent(tObj.ResourceNumber, 30.0f, 30.0f, 30.0f); * Agk.FixObjectPivot(tObj.ResourceNumber); * var tImg = Media.GetImageAsset("media/characters/woman_d.png", 1.0f, 1.0f); * Agk.SetObjectImage(tObj.ResourceNumber, tImg.ResourceNumber, 0); * tImg = Media.GetImageAsset("media/characters/woman_n.png", 1.0f, 1.0f); * Agk.SetObjectImage(tObj.ResourceNumber, tImg.ResourceNumber, 1); * tImg = Media.GetImageAsset("media/characters/woman_s.png", 1.0f, 1.0f); * Agk.SetObjectImage(tObj.ResourceNumber, tImg.ResourceNumber, 2); * ent.Properties.ResourceNumber = tObj.ResourceNumber; * ent.Properties.IsObject = true; * ent.Properties.Filebase = "media/characters/woman"; * var wFx = Media.GetShaderAsset("media/shaders/SurfaceDiffSpec.vs", "media/shaders/SurfaceDiffSpec.ps", true); * ent.SetShader(wFx); * World3d.WorldEntityList.Add(ent); */ //var tChar = new CharacterEntity3d("media/characters/automata"); var tChar = new CharacterEntity3d("media/characters/adventurer-carliet"); CharacterHandler3d.MyCharacter = tChar; //Agk.SetObjectVisible(tChar.Properties.ResourceNumber, false); var cam0 = new Camera3d("main"); cam0.UpdateFromAgk(); cam0.ControlMode = Camera3d.CameraMode.Anchored; cam0.Anchor = floorEnt; cam0.Target = floorEnt; var cam1 = new Camera3d("myOtherCam"); cam1.UpdateFromAgk(); cam1.Position.X = 0.0f; cam1.Position.Y = 10.0f; cam1.Position.Z = -20.0f; cam1.ApplyToAgk(); Controls3d.SetActiveCamera(cam0); //ENDTEMP //App main while (App.LoopAGK()) { App.Log("Program.cs", 1, "main", "--- Begin main loop ---"); //Always update timing, and do it first App.UpdateTiming(); //sync internal physics Agk.Step3DPhysicsWorld(); App.Log("Program.cs", 1, "main", "Processing " + App.UpdateList.Count.ToString() + " updates in queue"); foreach (var u in App.UpdateList) { if (!App.Status.IsRunning) { break; } if (App.Timing.PauseState != 1 || u.IgnorePause) { App.Log("Program.cs", 1, "main", "Process from queue " + u.FunctionName); Dispatcher.Invoke(u.FunctionName, null); } } if (!App.Status.IsRunning) { break; } Agk.Print(Agk.ScreenFPS().ToString() + " " + App.Timing.Delta.ToString()); Agk.Print("Camera: " + Controls3d.ActiveCamera.Name); Agk.Print("Cam Pos: " + Controls3d.ActiveCamera.Position.X + ", " + Controls3d.ActiveCamera.Position.Y + ", " + Controls3d.ActiveCamera.Position.Z); Agk.Print("Cam P/T: " + Controls3d.ActiveCamera.Phi + ", " + Controls3d.ActiveCamera.Theta); Agk.Print(CharacterHandler3d.MyCharacter.Properties.Position.AsString()); Agk.Print(CharacterHandler3d.MyCharacter.Properties.Heading.ToString() + " " + CharacterHandler3d.MyCharacter.Properties.Facing.ToString()); Agk.Print(CharacterHandler3d.MyCharacter.Properties.Speed.ToString()); Agk.Print("Press C to toggle active camera"); Agk.Print("F1 to debug light"); Agk.Print("Esc to quit"); /* * var anim = CharacterHandler3d.MyCharacter.AnimationQ.First(); * Agk.Print(anim.Animation.Name); * * string animName = Agk.GetObjectAnimationName((uint)anim.Owner.Properties.ResourceNumber, 1); * float totalTime = Agk.GetObjectAnimationDuration((uint)anim.Owner.Properties.ResourceNumber, animName); * int totalFrame = (int)Math.Floor(totalTime * anim.Animation.Framerate); * float animTime = (anim.CurrentFrame * totalTime) / totalFrame; * * Agk.Print(Math.Floor((double)anim.CurrentFrame).ToString() + " / " + totalFrame.ToString()); * Agk.Print(animTime.ToString("0.00") + " / " + totalTime.ToString("0.00")); */ App.Sync(); } App.CleanUp(); }