예제 #1
0
 /// <summary>
 /// Renders the standard view's 3D data.
 /// </summary>
 /// <param name="view">The view object.</param>
 public void Render3D(View3D view)
 {
     try
     {
         StackNoteHelper.Push("GameEngine3D - Render All Entities", this);
         // TODO: Out View Rendering!
         GL.ActiveTexture(TextureUnit.Texture1);
         Textures.NormalDef.Bind();
         GL.ActiveTexture(TextureUnit.Texture0);
         foreach (ClientEntity ce in EntityList)
         {
             // TODO: layering logic of some form instead of this overly basic stuff.
             if (ShouldRender(ce.Renderer, view.RenderingShadows))
             {
                 try
                 {
                     StackNoteHelper.Push("GameEngine3D - Render Specific Entity", ce);
                     ce.Renderer?.RenderStandard(MainContext);
                 }
                 finally
                 {
                     StackNoteHelper.Pop();
                 }
             }
         }
     }
     finally
     {
         StackNoteHelper.Pop();
     }
 }
예제 #2
0
 /// <summary>
 /// Starts the game engine, and begins the primary loop.
 /// </summary>
 /// <param name="initialFlags">The initial window flag.</param>
 public void Start(GameWindowFlags initialFlags = GameWindowFlags.FixedWindow)
 {
     try
     {
         StackNoteHelper.Push("GameClientWindow - Start, run", this);
         SysConsole.Output(OutputType.INIT, "GameEngine loading...");
         Window                = new GameWindow(WindWid, WindHei, new GraphicsMode(24, 24, 0, 0), StartingWindowTitle, initialFlags, DisplayDevice.Default, 4, 3, GraphicsContextFlags.ForwardCompatible);
         Window.Load          += Window_Load;
         Window.RenderFrame   += Window_RenderFrame;
         Window.Mouse.Move    += Mouse_Move;
         Window.Closed        += Window_Closed;
         Window.Resize        += Window_Resize;
         Window.ReduceCPUWaste = CPUWastePatch;
         SysConsole.Output(OutputType.INIT, "GameEngine calling SetUp event...");
         OnWindowSetUp?.Invoke();
         SysConsole.Output(OutputType.INIT, "GameEngine running...");
         if (CPUWastePatch)
         {
             double rate = DisplayDevice.Default.RefreshRate;
             Window.Run(rate, rate);
         }
         else
         {
             Window.Run();
         }
     }
     finally
     {
         StackNoteHelper.Pop();
     }
 }
예제 #3
0
 /// <summary>
 /// Removes an entity from the world.
 /// </summary>
 /// <param name="ent">The entity to remove.</param>
 public void DespawnEntity(T ent)
 {
     if (!ent.IsSpawned)
     {
         SysConsole.Output(OutputType.WARNING, "Despawing non-spawned entity.");
         return;
     }
     try
     {
         StackNoteHelper.Push("BasicEngine - Despawn Entity", ent);
         foreach (Property prop in ent.EnumerateAllProperties())
         {
             if (prop is BasicEntityProperty <T, T2> bep)
             {
                 bep.OnDespawn();
             }
         }
         ent.OnDespawnEvent?.Fire(new EntityDespawnEventArgs());
         RemoveEntity(ent);
         ent.IsSpawned = false;
     }
     finally
     {
         StackNoteHelper.Pop();
     }
 }
예제 #4
0
 /// <summary>
 /// Renders all entities and render helpers.
 /// </summary>
 /// <param name="lights">Whether to include things that don't cast shadows.</param>
 /// <param name="shouldShadow">The method to determine if an object should cast a shadow.</param>
 private void RenderAll(bool lights, Func <ClientEntity, bool> shouldShadow)
 {
     try
     {
         StackNoteHelper.Push("GameEngine2D - RenderAll", this);
         Textures.White.Bind();
         RenderHelper.SetColor(Vector4.One);
         RenderAllObjectsPre?.Invoke(lights);
         // This dups the list inherently, preventing glitches from removal while rendering, helpfully!
         foreach (ClientEntity ent in Entities.Values
                  .Where((e) => ShouldRender(e.Renderer, lights) && (shouldShadow == null || shouldShadow(e)))
                  .OrderBy((e) => e.Renderer.RenderingPriorityOrder))
         {
             try
             {
                 StackNoteHelper.Push("GameEngine2D - Render Specific Entity", ent);
                 ent.Renderer.RenderStandard2D(MainRenderContext);
             }
             finally
             {
                 StackNoteHelper.Pop();
             }
         }
         RenderAllObjectsPost?.Invoke(lights);
         GraphicsUtil.CheckError("Render - all Entities rendered");
     }
     finally
     {
         StackNoteHelper.Pop();
     }
 }
예제 #5
0
 /// <summary>
 /// Renders a single frame of the game, and also ticks.
 /// </summary>
 /// <param name="sender">Irrelevant.</param>
 /// <param name="e">Holds the frame time (delta).</param>
 private void Window_RenderFrame(object sender, FrameEventArgs e)
 {
     try
     {
         StackNoteHelper.Push("GameClientWindow - Render and tick frame", this);
         // First step: check delta
         if (e.Time <= 0.0)
         {
             return;
         }
         // Mouse handling
         PreviousMouse = CurrentMouse;
         CurrentMouse  = Mouse.GetState();
         // Standard pre-tick
         PreTick(e.Time);
         ErrorCode ec = GL.GetError();
         while (ec != ErrorCode.NoError)
         {
             SysConsole.Output(OutputType.WARNING, "Uncaught GL Error: " + ec);
             ec = GL.GetError();
         }
         // Second step: clear the screen
         GL.ClearBuffer(ClearBuffer.Color, 0, ScreenClearColor);
         GL.ClearBuffer(ClearBuffer.Depth, 0, DepthClear);
         GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0);
         GL.DrawBuffer(DrawBufferMode.Back);
         GraphicsUtil.CheckError("GameClient - Pre");
         // Tick helpers
         Models.Update(GlobalTickTime);
         GraphicsUtil.CheckError("GameClient - PostModelUpdate");
         // Third step: general game rendering
         CurrentEngine.RenderSingleFrame();
         GraphicsUtil.CheckError("GameClient - PostMainEngine");
         // Add the UI Layer too
         MainUI.Draw();
         GraphicsUtil.CheckError("GameClient - PostUI");
         // Fourth step: clean up!
         GL.BindTexture(TextureTarget.Texture2D, 0);
         GL.BindVertexArray(0);
         GL.UseProgram(0);
         // Semi-final step: Tick logic!
         GraphicsUtil.CheckError("GameClient - PreTick");
         // Main instance tick.
         Tick();
         // Primary UI tick
         MainUI.Tick();
         Resized = false;
         GraphicsUtil.CheckError("GameClient - PostTick");
         // Final step: Swap the render buffer onto the screen!
         Window.SwapBuffers();
         GraphicsUtil.CheckError("GameClient - Post");
     }
     finally
     {
         StackNoteHelper.Pop();
     }
 }
예제 #6
0
 /// <summary>
 /// Ticks the instance's scheduler.
 /// </summary>
 public void TickScheduler()
 {
     try
     {
         StackNoteHelper.Push("GameInstance - Tick Scheduler", Schedule);
         Schedule.RunAllSyncTasks(Delta);
     }
     finally
     {
         StackNoteHelper.Pop();
     }
 }
 /// <summary>
 /// Constructs the server game instance.
 /// </summary>
 public ServerGameInstance()
 {
     try
     {
         StackNoteHelper.Push("ServerGameInstance construction, preparating of default engine", this);
         Engines.Add(new ServerEngine());
         DefaultEngine.LoadBasic();
     }
     finally
     {
         StackNoteHelper.Pop();
     }
 }
예제 #8
0
 /// <summary>
 /// Ticks the instance and all engines.
 /// Called automatically by the standard run thread.
 /// Call <see cref="PreTick(double)"/> first.
 /// </summary>
 public void Tick()
 {
     try
     {
         StackNoteHelper.Push("GameInstance tick sequence - Tick", this);
         foreach (T2 engine in Engines)
         {
             engine.Delta = Delta;
             engine.Tick();
         }
     }
     finally
     {
         StackNoteHelper.Pop();
     }
 }
예제 #9
0
 /// <summary>
 /// The internal engine tick sequence.
 /// </summary>
 public void Tick()
 {
     try
     {
         StackNoteHelper.Push("BasicEngine - Tick Scheduler", Schedule);
         Schedule.RunAllSyncTasks(Delta);
     }
     finally
     {
         StackNoteHelper.Pop();
     }
     try
     {
         StackNoteHelper.Push("BasicEngine - Update Physics", PhysicsWorld);
         PhysicsWorld.Internal.Update(Delta);
     }
     finally
     {
         StackNoteHelper.Pop();
     }
     try
     {
         StackNoteHelper.Push("BasicEngine - Tick all entities", this);
         // Dup list, to ensure ents can despawn themselves in the tick method!
         IReadOnlyList <T> ents = EntityListDuplicate();
         for (int i = 0; i < ents.Count; i++)
         {
             if (ents[i].Ticks)
             {
                 try
                 {
                     StackNoteHelper.Push("BasicEngine - Tick specific entity", ents[i]);
                     ents[i].TickThis();
                 }
                 finally
                 {
                     StackNoteHelper.Pop();
                 }
             }
         }
     }
     finally
     {
         StackNoteHelper.Pop();
     }
 }
 /// <summary>
 /// Ticks the server and all engines.
 /// Called automatically by the standard run thread.
 /// </summary>
 /// <param name="delta">How much time has passed since the last tick.</param>
 public void Tick(double delta)
 {
     try
     {
         StackNoteHelper.Push("ServerGameInstance tick sequence - Tick", this);
         tpsc++;
         Delta           = delta;
         GlobalTickTime += delta;
         Schedule.RunAllSyncTasks(delta);
         foreach (ServerEngine engine in Engines)
         {
             engine.Delta = delta;
             engine.Tick();
         }
     }
     finally
     {
         StackNoteHelper.Pop();
     }
 }
예제 #11
0
 /// <summary>
 /// Loads the engine.
 /// </summary>
 public void Load()
 {
     try
     {
         StackNoteHelper.Push("GameEngineBase - Loading", this);
         SysConsole.Output(OutputType.INIT, "GameEngine starting load sequence, start with basic...");
         LoadBasic();
         SysConsole.Output(OutputType.INIT, "GameEngine loading shaders...");
         GetShaders();
         SysConsole.Output(OutputType.INIT, "GameEngine core load complete, calling additional load...");
         PostLoad();
         SysConsole.Output(OutputType.INIT, "GameEngine prepping audio systems...");
         Sounds = new SoundEngine();
         Sounds.Init(this);
         SysConsole.Output(OutputType.INIT, "GameEngine load sequence complete.");
     }
     finally
     {
         StackNoteHelper.Pop();
     }
 }
예제 #12
0
 /// <summary>
 /// Spawns an entity into the world.
 /// </summary>
 /// <param name="ticks">Whether it should tick.</param>
 /// <param name="configure">A method to configure the entity prior to spawn or property add, if one applies.</param>
 /// <param name="props">Any properties to apply.</param>
 /// <returns>The spawned entity.</returns>
 public T SpawnEntity(bool ticks, Action <T> configure, params Property[] props)
 {
     try
     {
         StackNoteHelper.Push("BasicEngine - Spawn Entity", this);
         T ce = CreateEntity(ticks);
         ce.EID = CurrentEID++;
         try
         {
             StackNoteHelper.Push("BasicEngine - Configure Entity", ce);
             configure?.Invoke(ce);
             for (int i = 0; i < props.Length; i++)
             {
                 ce.AddProperty(props[i]);
             }
             AddEntity(ce);
             ce.IsSpawned = true;
             foreach (Property prop in ce.GetAllProperties())
             {
                 if (prop is BasicEntityProperty <T, T2> bep)
                 {
                     bep.OnSpawn();
                 }
             }
             ce.OnSpawnEvent?.Fire(new EntitySpawnEventArgs());
         }
         finally
         {
             StackNoteHelper.Pop();
         }
         return(ce);
     }
     finally
     {
         StackNoteHelper.Pop();
     }
 }
        /// <summary>
        /// Starts and runs the entire server game instance.
        /// Will take over present thread until completion.
        /// </summary>
        public void StartAndRun()
        {
            // Tick
            double    TARGETFPS = 30.0;
            Stopwatch Counter   = new Stopwatch();

            DeltaCounter = new Stopwatch();
            DeltaCounter.Start();
            TotalDelta = 0;
            double CurrentDelta = 0.0;

            TargetDelta = 0.0;
            int targettime = 0;

            try
            {
                StackNoteHelper.Push("ServerGameInstance main loop - StartAndRun", this);
                while (true)
                {
                    // Update the tick time usage counter
                    Counter.Reset();
                    Counter.Start();
                    // Update the tick delta counter
                    DeltaCounter.Stop();
                    // Delta time = Elapsed ticks * (ticks/second)
                    CurrentDelta = ((double)DeltaCounter.ElapsedTicks) / ((double)Stopwatch.Frequency);
                    // Begin the delta counter to find out how much time is /really/ slept+ticked for
                    DeltaCounter.Reset();
                    DeltaCounter.Start();
                    // How much time should pass between each tick ideally
                    TARGETFPS = Target_FPS;
                    if (TARGETFPS < 1 || TARGETFPS > 600)
                    {
                        TARGETFPS = 30;
                    }
                    TargetDelta = (1.0d / TARGETFPS);
                    // How much delta has been built up
                    TotalDelta += CurrentDelta;
                    double tdelt = TargetDelta;
                    while (TotalDelta > tdelt * 3)
                    {
                        // Lagging - cheat to catch up!
                        tdelt *= 2; // TODO: Handle even harder tick loss
                    }
                    // As long as there's more delta built up than delta wanted, tick
                    while (TotalDelta > tdelt)
                    {
                        if (NeedShutdown)
                        {
                            return;
                        }
                        lock (TickLock)
                        {
                            Tick(tdelt);
                        }
                        TotalDelta -= tdelt;
                    }
                    // The tick is done, stop measuring it
                    Counter.Stop();
                    // Only sleep for target milliseconds/tick minus how long the tick took... this is imprecise but that's okay
                    targettime = (int)((1000d / TARGETFPS) - Counter.ElapsedMilliseconds);
                    // Only sleep at all if we're not lagging
                    if (targettime > 0)
                    {
                        // Try to sleep for the target time - very imprecise, thus we deal with precision inside the tick code
                        Thread.Sleep(targettime);
                    }
                }
            }
            catch (ThreadAbortException)
            {
                return;
            }
            catch (Exception ex)
            {
                SysConsole.Output("Server crash", ex);
            }
            finally
            {
                StackNoteHelper.Pop();
            }
        }