public override void Update(float t, float dt)
        {
            KeyboardState currentState = Keyboard.GetState();

            if (currentState.IsKeyDown(Keys.Escape))
            {
                Game1.Inst.Exit();
            }

            foreach (var input in Game1.Inst.Scene.GetComponents <CInput>())
            {
                CBody body = null;
                if (Game1.Inst.Scene.EntityHasComponent <CBody>(input.Key))
                {
                    body = (CBody)Game1.Inst.Scene.GetComponentFromEntity <CBody>(input.Key);
                }
                var inputValue = (CInput)input.Value;

                if (Game1.Inst.Scene.EntityHasComponent <CCamera>(input.Key))
                {
                    var     transform       = (CTransform)Game1.Inst.Scene.GetComponentFromEntity <CTransform>(input.Key);
                    CCamera cameraComponent = (CCamera)Game1.Inst.Scene.GetComponentFromEntity <CCamera>(input.Key);


                    if (lastMouseState == null)
                    {
                        lastMouseState = Mouse.GetState();
                    }
                    if (currentState.IsKeyDown(inputValue.CameraMovementForward))
                    {
                        transform.Position     += CAMERASPEED * new Vector3((float)(cameraComponent.Distance * Math.Sin(cameraComponent.Heading + Math.PI * 0.5f)), 0, (float)((-cameraComponent.Distance) * Math.Cos(cameraComponent.Heading + Math.PI * 0.5f)));
                        cameraComponent.Target += CAMERASPEED * new Vector3((float)(cameraComponent.Distance * Math.Sin(cameraComponent.Heading + Math.PI * 0.5f)), 0, (float)((-cameraComponent.Distance) * Math.Cos(cameraComponent.Heading + Math.PI * 0.5f)));
                    }
                    if (currentState.IsKeyDown(inputValue.CameraMovementBackward))
                    {
                        transform.Position     -= CAMERASPEED * new Vector3((float)(cameraComponent.Distance * Math.Sin(cameraComponent.Heading + Math.PI * 0.5f)), 0, (float)((-cameraComponent.Distance) * Math.Cos(cameraComponent.Heading + Math.PI * 0.5f)));
                        cameraComponent.Target -= CAMERASPEED * new Vector3((float)(cameraComponent.Distance * Math.Sin(cameraComponent.Heading + Math.PI * 0.5f)), 0, (float)((-cameraComponent.Distance) * Math.Cos(cameraComponent.Heading + Math.PI * 0.5f)));
                    }
                    if (Mouse.GetState().X < lastMouseState.X || currentState.IsKeyDown(inputValue.CameraMovementLeft))
                    {
                        cameraComponent.Heading -= 0.05f;
                        transform.Position       = Vector3.Subtract(cameraComponent.Target, new Vector3((float)(cameraComponent.Distance * Math.Sin(cameraComponent.Heading + Math.PI * 0.5f)), cameraComponent.Height, (float)((-cameraComponent.Distance) * Math.Cos(cameraComponent.Heading + Math.PI * 0.5f))));
                    }
                    if (Mouse.GetState().X > lastMouseState.X || currentState.IsKeyDown(inputValue.CameraMovementRight))
                    {
                        cameraComponent.Heading += 0.05f;
                        transform.Position       = Vector3.Subtract(cameraComponent.Target, new Vector3((float)(cameraComponent.Distance * Math.Sin(cameraComponent.Heading + Math.PI * 0.5f)), cameraComponent.Height, (float)((-cameraComponent.Distance) * Math.Cos(cameraComponent.Heading + Math.PI * 0.5f))));
                    }

                    lastMouseState = Mouse.GetState();
                }
                if (!Game1.Inst.Scene.EntityHasComponent <CBody>(input.Key))
                {
                    continue;
                }

                if (_mapSystem != null)
                {
                    body.Position.Y = _mapSystem.HeightPosition(body.Position.X, body.Position.Z);
                }

                if (currentState.IsKeyDown(inputValue.ForwardMovementKey))
                {
                    body.Velocity.Z -= 50f * dt;
                }
                if (currentState.IsKeyDown(inputValue.BackwardMovementKey))
                {
                    body.Velocity.Z += 50f * dt;
                }
                if (currentState.IsKeyDown(inputValue.LeftMovementKey))
                {
                    body.Velocity.X -= 50f * dt;
                }
                if (currentState.IsKeyDown(inputValue.RightMovementKey))
                {
                    body.Velocity.X += 50f * dt;
                }
                if (currentState.IsKeyDown(Keys.X))
                {
                    body.Velocity.Y -= 50f * dt;
                }
                if (currentState.IsKeyDown(Keys.Z))
                {
                    body.Velocity.Y += 50f * dt;
                }

                body.LinDrag = 0.3f;

                /*
                 *
                 * //((LookAtCamera)Camera).Target = new Vector3(m.M41, m.M42*0.0f, m.M43);
                 * //var ta = ((LookAtCamera)Camera).Target;
                 * var p = b.Position;
                 * var c = ((LookAtCamera)Camera).Position;
                 * var dist = 30f;
                 * var yDist = -20f;
                 * var h = b.Heading;
                 *
                 * // Vi positionerar kamera utifrån karaktärens heading (h), p = karaktärerns position, c = kamerans position, t = kamerans target, dist = avstånd till objektet
                 * // yDist = höjd för kameran, samt t = p -- alltså att kamerans target är position för karaktären.
                 * // Då gäller c=p-[d*sin(h + pi/2), y, (-d)*cos(h + pi/2)]
                 *
                 * c = Vector3.Subtract(p, new Vector3((float)(dist * Math.Sin(h + Math.PI * 0.5f)), yDist, (float)((-dist) * Math.Cos(h + Math.PI * 0.5f))));
                 *
                 * c.Y = -yDist; // Lock camera to given height
                 * p.Y = 0; // Target too because it was really ugly otherwise
                 *
                 * ((LookAtCamera)Camera).Target = p;
                 * ((LookAtCamera)Camera).Position = c;
                 *
                 * return Matrix.CreateLookAt(Position, (Vector3)m_Target, Up);
                 *
                 */
            }
        }
Пример #2
0
        /// <summary>Updates all physical bodies (<see cref="CBody"/>) and solves collisions.</summary>
        /// <param name="t">The total game time, in seconds.</param>
        /// <param name="dt">The time, in seconds, since the last call to this
        ///                  method.</param>
        public override void Update(float t, float dt)
        {
            // Basically, use semi-implicit Euler to integrate all positions and then sweep coarsely for
            // AABB collisions. All potential collisions are passed on to the fine-phase solver.
            mPotentialColls.Clear();
            var scene = Game1.Inst.Scene;

            foreach (var e in scene.GetComponents <CBody>())
            {
                var body = (CBody)e.Value;

                // TODO: Implement 4th order Runge-Kutta for differential equations.
                // Symplectic Euler is ok for now so compute force before updating position!
                body.Velocity += dt * (Gravity - body.InvMass * body.LinDrag * body.Velocity);
                body.Position += dt * body.Velocity;

                // Setup the AABBs and see if they intersect (inner loop). Intersection means we have a
                // *potential* collision. It needs to be verified and resolved by the fine-phase solver.
                var p1    = body.Position;
                var aabb1 = new BoundingBox(p1 + body.Aabb.Min, p1 + body.Aabb.Max);

                //----------------------------
                // Body-world collisions
                //----------------------------

                if (MapSystem == null)
                {
                    // TODO: Maybe refactor into own function? Looks messy.
                    if (aabb1.Min.X < Bounds.Min.X)
                    {
                        body.Position.X  = Bounds.Min.X - body.Aabb.Min.X;
                        body.Velocity.X *= -1.0f;
                    }
                    else if (aabb1.Max.X > Bounds.Max.X)
                    {
                        body.Position.X  = Bounds.Max.X - body.Aabb.Max.X;
                        body.Velocity.X *= -1.0f;
                    }

                    if (aabb1.Min.Y < Bounds.Min.Y)
                    {
                        body.Position.Y  = Bounds.Min.Y - body.Aabb.Min.Y;
                        body.Velocity.Y *= -1.0f;
                    }
                    else if (aabb1.Max.Y > Bounds.Max.Y)
                    {
                        body.Position.Y  = Bounds.Max.Y - body.Aabb.Max.Y;
                        body.Velocity.Y *= -1.0f;
                    }

                    if (aabb1.Min.Z < Bounds.Min.Z)
                    {
                        body.Position.Z  = Bounds.Min.Z - body.Aabb.Min.Z;
                        body.Velocity.Z *= -1.0f;
                    }
                    else if (aabb1.Max.Z > Bounds.Max.Z)
                    {
                        body.Position.Z  = Bounds.Max.Z - body.Aabb.Max.Z;
                        body.Velocity.Z *= -1.0f;
                    }
                }
                else
                {
                    var bodyPositionY = body.Position.Y;
                    var mapHeight     = MapSystem.HeightPosition(body.Position.X, body.Position.Z);

                    if (aabb1.Min.Y < mapHeight)
                    {
                        body.Position.Y  = mapHeight - body.Aabb.Min.Y;
                        body.Velocity.Y *= -1.0f;
                    }
                }
                // Not sure what else to do. Need to update transform to match physical body position.
                ((CTransform)scene.GetComponentFromEntity <CTransform>(e.Key)).Position = body.Position;

                //----------------------------
                // Body-body collisions
                //----------------------------

                foreach (var e2 in scene.GetComponents <CBody>())
                {
                    var body2 = (CBody)e2.Value;

                    // Check entity IDs (.Key) to skip double-checking each potential collision.
                    if (e2.Key <= e.Key)
                    {
                        continue;
                    }

                    var p2    = body2.Position;
                    var aabb2 = new BoundingBox(p2 + body2.Aabb.Min, p2 + body2.Aabb.Max);

                    if (!aabb1.Intersects(aabb2))
                    {
                        // No potential collision.
                        continue;
                    }

                    mPotentialColls.Add(new Pair <int, int>(e.Key, e2.Key));
                }
            }

            SolveCollisions();

            base.Update(t, dt);
        }