void CreateCharacter() { var cache = ResourceCache; Node objectNode = scene.CreateChild("Jack"); objectNode.Position = (new Vector3(0.0f, 1.0f, 0.0f)); // Create the rendering component + animation controller AnimatedModel obj = objectNode.CreateComponent<AnimatedModel>(); obj.Model = cache.GetModel("Models/Jack.mdl"); obj.SetMaterial(cache.GetMaterial("Materials/Jack.xml")); obj.CastShadows = true; objectNode.CreateComponent<AnimationController>(); // Set the head bone for manual control //obj.Skeleton.GetBoneSafe("Bip01_Head").Animated = false; // Create rigidbody, and set non-zero mass so that the body becomes dynamic RigidBody body = objectNode.CreateComponent<RigidBody>(); body.CollisionLayer = 1; body.Mass = 1.0f; // Set zero angular factor so that physics doesn't turn the character on its own. // Instead we will control the character yaw manually body.SetAngularFactor(Vector3.Zero); // Set the rigidbody to signal collision also when in rest, so that we get ground collisions properly body.CollisionEventMode = CollisionEventMode.Always; // Set a capsule shape for collision CollisionShape shape = objectNode.CreateComponent<CollisionShape>(); shape.SetCapsule(0.7f, 1.8f, new Vector3(0.0f, 0.9f, 0.0f), Quaternion.Identity); // Create the character logic component, which takes care of steering the rigidbody // Remember it so that we can set the controls. Use a WeakPtr because the scene hierarchy already owns it // and keeps it alive as long as it's not removed from the hierarchy character = new Character(); objectNode.AddComponent(character); }
protected override void OnUpdate(float timeStep) { Input input = Input; if (character != null) { // Clear previous controls character.Controls.Set(CtrlForward | CtrlBack | CtrlLeft | CtrlRight | CtrlJump, false); // Update controls using touch utility class touch?.UpdateTouches(character.Controls); // Update controls using keys if (UI.FocusElement == null) { if (touch == null || !touch.UseGyroscope) { character.Controls.Set(CtrlForward, input.GetKeyDown(Key.W)); character.Controls.Set(CtrlBack, input.GetKeyDown(Key.S)); character.Controls.Set(CtrlLeft, input.GetKeyDown(Key.A)); character.Controls.Set(CtrlRight, input.GetKeyDown(Key.D)); } character.Controls.Set(CtrlJump, input.GetKeyDown(Key.Space)); // Add character yaw & pitch from the mouse motion or touch input if (TouchEnabled) { for (uint i = 0; i < input.NumTouches; ++i) { TouchState state = input.GetTouch(i); if (state.TouchedElement == null) // Touch on empty space { Camera camera = CameraNode.GetComponent<Camera>(); if (camera == null) return; var graphics = Graphics; character.Controls.Yaw += TouchSensitivity * camera.Fov / graphics.Height * state.Delta.X; character.Controls.Pitch += TouchSensitivity * camera.Fov / graphics.Height * state.Delta.Y; } } } else { character.Controls.Yaw += (float)input.MouseMove.X * YawSensitivity; character.Controls.Pitch += (float)input.MouseMove.Y * YawSensitivity; } // Limit pitch character.Controls.Pitch = MathHelper.Clamp(character.Controls.Pitch, -80.0f, 80.0f); // Switch between 1st and 3rd person if (input.GetKeyPress(Key.F)) firstPerson = !firstPerson; // Turn on/off gyroscope on mobile platform if (touch != null && input.GetKeyPress(Key.G)) touch.UseGyroscope = !touch.UseGyroscope; if (input.GetKeyPress(Key.F5)) { scene.SaveXml(FileSystem.ProgramDir + "Data/Scenes/CharacterDemo.xml", "\t"); } if (input.GetKeyPress(Key.F7)) { scene.LoadXml(FileSystem.ProgramDir + "Data/Scenes/CharacterDemo.xml"); Node characterNode = scene.GetChild("Jack", true); if (characterNode != null) { character = characterNode.GetComponent<Character>(); } physicsWorld = scene.CreateComponent<PhysicsWorld>(); physicsWorld.SubscribeToPhysicsPreStep(HandlePhysicsPreStep); } } // Set rotation already here so that it's updated every rendering frame instead of every physics frame if (character != null) character.Node.Rotation = Quaternion.FromAxisAngle(Vector3.UnitY, character.Controls.Yaw); } }