Esempio n. 1
0
        protected override void Update(GameTime gameTime)
        {
            foreach (var taxi in taxis)
            {
                taxi.Update(gameTime);

                float volume = Math.Max(0, Math.Min(1, taxi.DeltaVelocity.Length()));
                sound.SetEngineVolume(taxi, volume);

                #region Kollision mit der Wand

                Vector2 sizeHalf = taxi.Size / 2;
                if (taxi.Position.X - sizeHalf.X < 0)
                {
                    taxi.Position  = new Vector2(sizeHalf.X, taxi.Position.Y);
                    taxi.Velocity *= new Vector2(0, 1);
                }
                if (taxi.Position.Y - sizeHalf.Y < 0)
                {
                    taxi.Position  = new Vector2(taxi.Position.X, sizeHalf.Y);
                    taxi.Velocity *= new Vector2(1, 0);
                }
                if (taxi.Position.X + sizeHalf.X > level.Size.X)
                {
                    taxi.Position  = new Vector2(level.Size.X - sizeHalf.X, taxi.Position.Y);
                    taxi.Velocity *= new Vector2(0, 1);
                }
                if (taxi.Position.Y + sizeHalf.Y > level.Size.Y)
                {
                    taxi.Position  = new Vector2(taxi.Position.X, level.Size.Y - sizeHalf.Y);
                    taxi.Velocity *= new Vector2(1, 0);
                }

                #endregion

                #region Kollision mit Blöcken

                Vector2 deltaPosition = taxi.Velocity * (float)gameTime.ElapsedGameTime.TotalSeconds;

                float taxiLeft   = taxi.Position.X - sizeHalf.X;
                float taxiTop    = taxi.Position.Y - sizeHalf.Y;
                float taxiRight  = taxi.Position.X + sizeHalf.X;
                float taxiBottom = taxi.Position.Y + sizeHalf.Y;

                taxi.OnGround = null;
                float scratchVolume = 0f;
                float scratchPitch  = 0f;

                foreach (var block in level.Blocks)
                {
                    if (taxiLeft < block.Size.Right && taxiRight > block.Size.Left &&
                        taxiTop < block.Size.Bottom && taxiBottom > block.Size.Top)
                    {
                        float factorX = 0f;
                        if (deltaPosition.X > 0)
                        {
                            float deltaLeft = taxiRight - block.Size.Left;
                            factorX = deltaLeft / deltaPosition.X;
                        }
                        else
                        {
                            float deltaRight = block.Size.Right - taxiLeft;
                            factorX = deltaRight / -deltaPosition.X;
                        }

                        float factorY = 0f;
                        if (deltaPosition.Y > 0)
                        {
                            float deltaTop = taxiBottom - block.Size.Top;
                            factorY = deltaTop / deltaPosition.Y;
                        }
                        else
                        {
                            float deltaBottom = block.Size.Bottom - taxiTop;
                            factorY = deltaBottom / -deltaPosition.Y;
                        }

                        if (Math.Abs(factorX) > 1f)
                        {
                            factorX = 0f;
                        }
                        if (Math.Abs(factorY) > 1f)
                        {
                            factorY = 0f;
                        }

                        // TODO: Fix Friction
                        if (factorX > factorY)
                        {
                            taxi.Position -= new Vector2(deltaPosition.X * (factorX + 0.05f), 0);

                            if (Math.Abs(taxi.Velocity.X) > 20f)
                            {
                                sound.PlayCrash(Math.Max(0, Math.Min(1f, Math.Abs(taxi.Velocity.X) / 100)));
                            }

                            taxi.Velocity *= new Vector2(0, 1);
                        }
                        else
                        {
                            taxi.Position -= new Vector2(0, deltaPosition.Y * (factorY + 0.05f));

                            if (Math.Abs(taxi.Velocity.Y) > 20f)
                            {
                                sound.PlayCrash(Math.Max(0, Math.Min(1f, Math.Abs(taxi.Velocity.Y) / 100)));
                            }

                            taxi.Velocity *= new Vector2(1, 0);

                            taxi.Velocity -= taxi.Velocity / block.Friction *
                                             (float)gameTime.ElapsedGameTime.TotalSeconds;

                            if (taxi.Position.X - (taxi.Size.X / 2) >= block.Size.Left &&
                                taxi.Position.X + (taxi.Size.X / 2) <= block.Size.Right &&
                                taxi.Position.Y < block.Size.Top)
                            {
                                taxi.OnGround = block;

                                if (taxi.Velocity.LengthSquared() < 100)
                                {
                                    var guest = taxi.Guests.SingleOrDefault(g => g.Destination == block);
                                    if (guest != null)
                                    {
                                        taxi.Guests.Remove(guest);
                                        guest.Position     = new Vector2(taxi.Position.X, guest.Destination.Size.Top);
                                        guest.CurrentBlock = guest.Destination;
                                        points++;
                                    }
                                }
                            }
                        }

                        scratchVolume = Math.Max(0, Math.Min(1, taxi.Velocity.Length() / 100));
                        scratchPitch  = (scratchVolume - 0.5f) * 2;
                    }
                }

                sound.SetScratchPitch(taxi, -scratchPitch);
                sound.SetScratchVolume(taxi, scratchVolume);

                #endregion
            }

            #region Respawn Guests

            if (level.Guests.Count < level.ParallelGuests)
            {
                var platforms         = level.Blocks.Where(b => b.SpawnPlatform & !level.Guests.Any(g => g.Departure == b)).ToList();
                var departurePlatform = platforms[rand.Next(platforms.Count)];
                platforms.Remove(departurePlatform);
                var destinationPlatform = platforms[rand.Next(platforms.Count)];


                Guest guest = new Guest()
                {
                    Position = new Vector2(
                        departurePlatform.Size.X + (departurePlatform.Size.Width / 2),
                        departurePlatform.Size.Y),
                    CurrentBlock = departurePlatform,
                    Departure    = departurePlatform,
                    Destination  = destinationPlatform,
                };

                level.Guests.Add(guest);
                sound.PlayShout();
            }

            #endregion

            foreach (var guest in level.Guests.ToArray())
            {
                #region Einsteigen

                foreach (var taxi in taxis)
                {
                    if (guest.Departure == taxi.OnGround &&
                        (guest.Position - taxi.Position).LengthSquared() < 10000 &&
                        taxi.Velocity.LengthSquared() < 10 &&
                        taxi.Guests.Count < taxi.GuestLimit &&
                        guest.CurrentBlock == guest.Departure)
                    {
                        float guestSpeed = (float)gameTime.ElapsedGameTime.TotalSeconds * 20;
                        guest.Position += new Vector2(Math.Max(-guestSpeed, Math.Min(guestSpeed, taxi.Position.X - guest.Position.X)), 0);

                        if (Math.Abs(taxi.Position.X - guest.Position.X) < 4)
                        {
                            guest.CurrentBlock = null;
                            taxi.Guests.Add(guest);
                        }
                    }
                }

                #endregion

                #region Aussteigen

                if (guest.CurrentBlock == guest.Destination)
                {
                    float guestSpeed = (float)gameTime.ElapsedGameTime.TotalSeconds * 20;
                    guest.Position += new Vector2(Math.Max(-guestSpeed, Math.Min(guestSpeed, guest.Destination.Size.X + (guest.Destination.Size.Width / 2) - guest.Position.X)), 0);

                    if (Math.Abs(guest.Destination.Size.X + (guest.Destination.Size.Width / 2) - guest.Position.X) < 4)
                    {
                        level.Guests.Remove(guest);
                    }
                }

                #endregion
            }

            base.Update(gameTime);
        }