Ejemplo n.º 1
0
        /// <summary>
        /// A teensy quadtree baby.
        /// </summary>
        private QuadTree(byte level, Rectangle bounds, List<PhysicalObject> objects)
        {
            byte level1 = level;
            Rectangle bounds1 = bounds;
            _center = bounds.Position + bounds.Size / 2f;
            Point childSize = bounds.Size / 2f;

            if (objects.Count > MaxObjects)
            {
                //decide in what childtree an object would fit and add it there
                List<PhysicalObject> childObjects0 = new List<PhysicalObject>();
                List<PhysicalObject> childObjects1 = new List<PhysicalObject>();
                List<PhysicalObject> childObjects2 = new List<PhysicalObject>();
                List<PhysicalObject> childObjects3 = new List<PhysicalObject>();

                foreach (PhysicalObject obj in objects)
                {
                    bool[] fits = FitObject(obj);
                    if (!fits[4])
                    {
                        if (fits[0])
                            childObjects0.Add(obj);
                        else if (fits[1])
                            childObjects1.Add(obj);
                        else if (fits[2])
                            childObjects2.Add(obj);
                        else
                            childObjects3.Add(obj);
                    }
                    else
                        _objects.Add(obj);
                }

                //create subtrees and add everything that fits inside of em
                _children[0] = new QuadTree((byte)(level1 + 1), new Rectangle(bounds1.Position, childSize), childObjects0);
                _children[1] = new QuadTree((byte)(level1 + 1), new Rectangle(new Point(_center.X, bounds1.Position.Y), childSize), childObjects1);
                _children[2] = new QuadTree((byte)(level1 + 1), new Rectangle(new Point(bounds1.Position.X, _center.Y), childSize), childObjects2);
                _children[3] = new QuadTree((byte)(level1 + 1), new Rectangle(_center, childSize), childObjects3);
            }
            else
                _objects = objects;
        }
Ejemplo n.º 2
0
        private static void Step()
        {
            //push input state
            Input.PushState();

            //process all SDL.SDL_events
            SDL.SDL_Event e;
            while (SDL.SDL_PollEvent(out e) == 1)
            {
                switch (e.type)
                {
                    //let Input handle input related events
                    case SDL.SDL_EventType.SDL_MOUSEBUTTONDOWN:
                    case SDL.SDL_EventType.SDL_MOUSEBUTTONUP:
                    case SDL.SDL_EventType.SDL_MOUSEWHEEL:
                    case SDL.SDL_EventType.SDL_MOUSEMOTION:
                    case SDL.SDL_EventType.SDL_KEYDOWN:
                    case SDL.SDL_EventType.SDL_KEYUP:
                    case SDL.SDL_EventType.SDL_TEXTINPUT:
                    case SDL.SDL_EventType.SDL_CONTROLLERDEVICEADDED:
                    case SDL.SDL_EventType.SDL_CONTROLLERDEVICEREMOVED:
                    case SDL.SDL_EventType.SDL_CONTROLLERBUTTONDOWN:
                    case SDL.SDL_EventType.SDL_CONTROLLERBUTTONUP:
                    case SDL.SDL_EventType.SDL_CONTROLLERAXISMOTION:
                        Input.InputEvent(e);
                        break;

                    //let Window handle window related events
                    case SDL.SDL_EventType.SDL_WINDOWEVENT:
                        Window.WindowEvent(e);
                        break;

                    //global quit, not only the window's exit button
                    case SDL.SDL_EventType.SDL_QUIT:
                        Exit();
                        break;
                }
            }

            Input.UpdateMousePosition();
            Input.ApplyButtonMaps();

            foreach (GameObject obj in Resources.Objects)
            {
                if (!obj.Destroyed)
                obj.Step();
            }

            //collision time!
            Profiler.Start("collision");

            float minX = float.PositiveInfinity;
            float minY = float.PositiveInfinity;
            float maxX = float.NegativeInfinity;
            float maxY = float.NegativeInfinity;
            foreach(PhysicalObject obj in Resources.PhysicalObjects)
            {
                obj.UpdateCoverableArea();

                if (obj.CoverableArea.Position.X < minX)
                    minX = obj.CoverableArea.Position.X;
                if (obj.CoverableArea.Position2.X > maxX)
                    maxX = obj.CoverableArea.Position2.X;
                if (obj.CoverableArea.Position.Y < minY)
                    minY = obj.CoverableArea.Position.Y;
                if (obj.CoverableArea.Position2.Y > maxY)
                    maxY = obj.CoverableArea.Position2.Y;

                //set before the actual collision check phase
                obj.SpeedLeft = 1f;
                obj.CollisionCandidates = null;
            }

            //create and fill quadtree for this step
            QuadTree = new QuadTree(new Rectangle(minX, minY, maxX - minX, maxY - minY));

            //create list of objects to process and calculate all first collision speedfractions for those objects
            List<PhysicalObject> processingObjects = new List<PhysicalObject>(Resources.PhysicalObjects);
            foreach (PhysicalObject obj in Resources.PhysicalObjects)
            {
                if (obj.Speed == Point.Zero)
                    continue;

                processingObjects.Add(obj);
                obj.CalculateClosestCollision();
            }

            while (processingObjects.Count > 0)
            {
                //get closest collision, process it/the pair of objects
                PhysicalObject obj = processingObjects.MinBy(o => o.ClosestCollisionSpeedFraction + 1 - o.SpeedLeft);

                obj.PerformClosestCollision();

                //remove/recalculate collisions
                if (obj.SpeedLeft == 0f)
                    processingObjects.Remove(obj);
                else
                    obj.CalculateClosestCollision();

                //recalculate for all possibly influenced objects (if needed)
                if (obj.CollisionCandidates != null)
                {
                    foreach (PhysicalObject influencedObj in obj.CollisionCandidates)
                        influencedObj.CalculateClosestCollision();
                }
            }

            Profiler.Stop();

            Resources.ObjectAdditionAndRemoval();
            Resources.CleanupFontTextures();
        }