Пример #1
0
        private void CalculateActorsCollisions(double dt)
        {
            if (Actors.Count == 1)
            {
                return;
            }

            Dictionary <Actor, List <Actor> > actorsToUnite = new Dictionary <Actor, List <Actor> >();

            foreach (var actor1 in Actors)
            {
                foreach (var actor2 in Actors)
                {
                    if (actor1.Id < actor2.Id && Box2.Overlap(actor1.Box, actor2.Box))
                    {
                        var collision = actor1.Box.CalcualteCollision(dt * (actor1.Velocity - actor2.Velocity), actor2.Box);

                        if (collision.IsNone)
                        {
                            continue;
                        }

                        bool isXCollision = collision.Vector.X != 0;

                        if (actor1.Size == actor2.Size && actor1.Orientation == actor2.Orientation)
                        {
                            var size        = actor1.Size;
                            var orientation = actor1.Orientation;
                            var midpoint    = actor1.Location + (actor2.Location - actor1.Location) / 2;

                            if (isXCollision && orientation != ActorOrientation.FLAT)
                            {
                                actorsToUnite.Add(new Actor(this, midpoint)
                                {
                                    Orientation = orientation == ActorOrientation.TALL ? ActorOrientation.SQUARE : ActorOrientation.FLAT,
                                    Size        = orientation == ActorOrientation.TALL ? size * 2 : size,
                                },
                                                  new List <Actor> {
                                    actor1, actor2
                                });

                                continue;
                            }
                            else if (!isXCollision && orientation != ActorOrientation.TALL)
                            {
                                actorsToUnite.Add(new Actor(this, new Point2(midpoint.X, Math.Min(actor1.Location.Y, actor2.Location.Y)))
                                {
                                    Orientation = orientation == ActorOrientation.FLAT ? ActorOrientation.SQUARE : ActorOrientation.TALL,
                                    Size        = orientation == ActorOrientation.FLAT ? size * 2 : size,
                                },
                                                  new List <Actor> {
                                    actor1, actor2
                                });

                                continue;
                            }
                        }

                        var unit = isXCollision ? Vector2.X_UNIT : Vector2.Y_UNIT;

                        var m1 = actor1.Mass;
                        var m2 = actor2.Mass;
                        var v1 = actor1.Velocity * unit;
                        var v2 = actor2.Velocity * unit;

                        var u2 = (2 * m1 * v1 + v2 * (m2 - m1)) / (m1 + m2);
                        var u1 = u2 + v2 - v1;

                        actor1.Velocity += unit * (u1 - v1);
                        actor2.Velocity += unit * (u2 - v2);

                        //todo: this is definitely wrong
                        actor1.Location -= collision.Vector / 2;
                        actor2.Location += collision.Vector / 2;
                    }
                }
            }

            foreach (var item in actorsToUnite)
            {
                foreach (var oldActor in item.Value)
                {
                    Actors.Remove(oldActor);
                }

                Actors.Add(item.Key);
                OnActorUnion?.Invoke(item.Key);
            }
        }
Пример #2
0
 Munch LocateOverlappingMunch(Actor actor) => Munches.FirstOrDefault(munch => Box2.Overlap(munch.Box, actor.Box));