Saturday, April 22, 2017

Z-GDK(MG) Architecture


Game Application Model Overview

I have always been a fond of a good framework which are easy to use and easy to understand by just taking a glance of it's framework overview, where you can already take a good grasp of how the game engine logic flow goes, hopefully I can also bring that to Z-GDK(MG). now to kick things off, here's an early overview wherein I have layout the game application model overview using the Z-GDK(MG).


Creating a new game project

The simplest way to create a new game application using Z-GDK(MG) is to open up the sample empty projects which contains a code templates that derives from Z-GDK(MG) GameFlow, it has an  application main entry point and game application class templates that is ready to run and test a game logic routine,

Now let's take a look at the main program file and see what it look's like:


The Program.cs source file used by Empty Project Template:

==============================================================


//!________________________________________________________________________
//!
//! PROGRAM FILE ID
//!________________________________________________________________________
//!
//! About    : Z-GDK(MG) 2017
//! File     : Program.cs
//! Remarks  : Empty Z-GDK(MG) project template
//!
//!________________________________________________________________________





//!________________________________________________________________________

//!

//! USING DIRECTIVES
//!________________________________________________________________________


#region USNG DIRECTIVES
//!!!
//!!
//!

using System;
//
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
//
using ZGDK;
using ZD  = ZGDK.Device;
using Z3D = ZGDK.D3D;
//!
//!!
//!!!
#endregion USNG DIRECTIVES




//!________________________________________________________________________

//!

//! NAMESPACE CONTEXT

//!________________________________________________________________________
namespace ZGDKGAME
{
   
    /// <summary>
    /// Main program class.
    /// </summary>
    public static class Program
    {

          [STAThread]
        /// <summary>
        /// Program application main entry point.
        /// </summary>       
        static void Main()
        {

            #region DEVICE SETTING
            //!!!
            //!!
            //!

            var m_DeviceSetting = new ZD.DeviceSetting( ZD.DevicePlatform.WindowsDeskTop ); 
            //
            m_DeviceSetting.preferredScreenHeight = 768;
            m_DeviceSetting.preferredScreenWidth  = 1024;
            //

            m_DeviceSetting.preferredMaxFPS       = 64;

            //
            m_DeviceSetting.isFullScreen          = false;
            m_DeviceSetting.isFixedTimeStep       = false;
            m_DeviceSetting.isVerticalSynch       = false;
            //

            m_DeviceSetting.clearScreenColor      = Color.CornflowerBlue;
            m_DeviceSetting.cameraType            = Z3D.Camera.CameraType.FreeSpace;
           
            // Let's leave other device settings to it's default value for now.

           
//!
            //!!
            //!!!
            #endregion DEVICE SETTING


            #region GAME OBJECT CREATION
            //!!!
            //!!
            //!
           
            using ( var m_GameDevice = new ZD.GameDevice( new MyGame(), m_DeviceSetting ) )
            {
                m_GameDevice.Run(); // Let's run the game!
            }


            //!

            //!!
            //!!!  
            #endregion GAME OBJECT CREATION


        }//End Main


    }//End Program

   
}//End Namespace


/* --End of file-- */

==============================================================


The main program.cs file simply creates an application program and defined the preferred device settings that will be needed when creating  the game device before running it as showed from the above codes.

Device setting:

Before creating the game device, it needs to know all the preferred setting of the game like height and width of the screen the preferred maximum frames per second and the like, some setting will be tackle as I continue posting the development of Z-GDK(MG) other features.





The application logic flow

The application logic flow is very simple after the main program entry point is created and the game device begins running.  the game application will starts  OnInitialize and then OnBeginRun followed by the Updates and the Draw calls  methods updates and draw calls methods will be called by the device automagically, until the application EndRun  is called to terminate the application.

Application methods:

BEGINRUN
   OnInitialize()
   OnBeginRun()
UPDATE

   OnUpdate()
   OnPostUpdate()
RENDER 3D

   OnPreDraw3D()
   OnDraw3D()
RENDER 2D
   OnPeDraw2D()
   OnDraw2D()
ENDRUN

    OnEndRun()

From here let's take  look at Application Game Source file and see what it looks like:


The Game.cs source file used by Empty Project Template:

==========================================================


//!________________________________________________________________________
//!
//! PROGRAM FILE ID
//!________________________________________________________________________
//!
//! About    : Z-GDK(MG) 2017
//! File     : Game.cs
//! Remarks  : Empty Z-GDK(MG) project template
//!
//!________________________________________________________________________




//!________________________________________________________________________

//!

//! USING DIRECTIVES
//!________________________________________________________________________



#region USNG DIRECTIVES
//!!!
//!!
//!

using System;
//
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
//
using ZGDK;

using ZD  = ZGDK.Device;
using ZC  = ZGDK.Device.Content;
using Z2D = ZGDK.D2D;using Z3D = ZGDK.D3D;
//!
//!!
//!!!
#endregion USNG DIRECTIVES


//!________________________________________________________________________

//!

//! NAMESPACE CONTEXT

//!________________________________________________________________________

namespace ZGDKGAME
{


    /// <summary>
    ///
    /// </summary>
    public class MyGame : ZD.GameFlow
    {


        #region F I E L D S
        //!!
        //!
            
        ZD.GameDevice       _Device  = null; // Handle to game device
        ZC.FontContent      _Font    = null// Handle to font content
        Z2D.Text.TextEntity _TextFps = null; // Handle to Text entity
        //!
        //!!
        #endregion F I E L D S



        #region  B E G I N  R U N 
        //!!
        //!

        /// <summary>
        /// Occurs right after the game device has been initialized.
        /// </summary>     
        public void OnInitialize(  ZD.GameDevice gameDevice )
        {
               _Device = gameDevice;

        }       

        /// <summary>
        /// Occurs right after the game device begin running.
        /// </summary>
        public void OnBeginRun()
        {
                 // Load some font
          _Font = _Device.Content.FontContentMngr.Create"("TrueTypeFont/ArialTruTypeFont" );
          // Create text entity to display our frame per second on screen
          _TextFps = _Device.D2D.TextEntityMngr.Create(10,0,0,_Font, Color.White);
       }

        //!
        //!!
        #endregion B E G I N  R U N 



        #region U P D A T E
        //!!
        //!

        /// <summary>
        /// Game logic update routine.
        /// </summary>  
        public void OnUpdate( XF.GameTime GT, float elapseTimeMs )
        {
         
 }

        /// <summary>
        /// Occurs right after entities has been updated.
        /// </summary>       
        public void OnPostUpdate( XF.GameTime GT, float elapseTimeMs )
        {

 }

        //!
        //!!
        #endregion U P D A T E




        #region R E N D E R  3 D
        //!!
        //!

        /// <summary>
        /// Occurs just before rendering all 3D entities begin.
        /// </summary>
        public void OnPreDraw3D( float elapseTimeMs )
        {

        }

        /// <summary>
        /// Occurs right after all 3D entities has been rendered.
        /// </summary>
        public void OnDraw3D( float elapseTimeMs )
        {

 }


        //!
        //!!
        #endregion R E N D E R  3 D



        #region R E N D E R  2 D
        //!!
        //!

        /// <summary>
        /// Occurs just before rendering all 2D entities begin.
        /// </summary>      
        public void OnPreDraw2D( float elapseTimeMs )
        {

                    // Save device captured frames per second to text. 
            _TextFpsUps.textContent = "FPS : " + this._Device.FPS ";
        }

        /// <summary>
        /// Occurs right after all 2D entities has been rendered.
        /// </summary>     
        public void OnDraw2D( float elapseTimeMs )
        {

        }



        //!

        //!!
        #endregion R E N D E R  2 D




        #region  E N D  R U N 

        //!!

        //!


        /// <summary>
        /// On game end running
        /// </summary>
        public void OnEndRun()
        {

        }


        //!

        //!!
        #endregion E N D  R U N 



    }//EndClass



 }//EndNameSpace



/* --End of file-- */
===========================================================




Initialization and Begin Running the Game

When the game device has been created from the main entry point and run it, the OnInitialize method immediate occurs and pass the created GameDevice that needs to  be save it's handle from within the game application followed by OnBeginRun where some content that will be use by the game entire lifetime can be loaded from here. Content loading and Unloading can be done anywhere anytime per content on my implementation, since I don't used the MonoGame default content manager, I implemented my own  content manager which is more flexible and manageable. which I will tackle on my next post. The OnBeginRun methods is also a good place to initialize your game entities members.


The Game Update Loop

The application OnUpdate method is responsible for handling the update of game logic, normally this is called by the device more frequently than the Draw methods base on the specified maximum update frames per second on the device setting, the OnPostUpdate method occurs right after the device updated all the entities.


Drawing on Screen

The application draw methods is responsible for informing the game application that a screen refresh has been occurred or repainted. The OnPreDraw3D method occurs just before all 3D entities begins rendering, a the good place to put codes related to rendering not affected by update prior to rendering, the OnDraw3D  on the other hand occurs right after all 3D entities has been drawn followed by  OnPreDraw2D like OnPreDraw3D this occurs just before all 2D entities begins rendering on screen, the OnDraw2D occurs right after all 2D entities has been drawn this is a good place to get how many frames per second has been drawn. The *DEVICE.FPS returns the actual frames per second of the game performed and *DEVICE.UPS displays the number of updates per second. 

The rendering device depends on many factors which includes the total quantity of graphic content needed to be processed on each frame and of course the capabilities of the hardware, but still, the maximum target frames per second  can be specified on the device setting.

m_DeviceSetting.preferredMaxFPS  = 64;

Ending or Quitting the Game

I’ll  be a good citizen by cleaning up mess I put into someone’s computer,  the  OnEndRun occurs when the application shuts down or terminated all device-defined tasks associated with freeing, releasing and resetting framework's related resources. But on some other cases, like for example; if the user closes the application without ending the game or exiting the application normally; it’s a good practice to make sure that the game and device will also shutdown gracefully when this case occurs, so this is a good place to put your clean up codes to destroy all of your content from OnEndRun methods.


Final output





Well, I'm running out of English and grammar so there it is : - D




No comments:

Post a Comment