Welcome, Guest
You have to register before you can post on our site.

Username
  

Password
  





Search Forums

(Advanced Search)

Forum Statistics
» Members: 3
» Latest member: Andy16823
» Forum threads: 4
» Forum posts: 4

Full Statistics

Online Users
There are currently 10 online users.
» 0 Member(s) | 9 Guest(s)
Google

Latest Threads
What is a Game Element?
Forum: Tutorials and Guides
Last Post: Andy
07-01-2024, 02:25 PM
» Replies: 0
» Views: 19
Game behaviour and the ad...
Forum: Tutorials and Guides
Last Post: Andy
06-30-2024, 08:23 PM
» Replies: 0
» Views: 18
Create your first project...
Forum: Tutorials and Guides
Last Post: Andy
06-30-2024, 04:03 PM
» Replies: 0
» Views: 51
Welcome to our Forum
Forum: News and Updates
Last Post: Andy
06-30-2024, 12:30 PM
» Replies: 0
» Views: 21

 
  What is a Game Element?
Posted by: Andy - 07-01-2024, 02:25 PM - Forum: Tutorials and Guides - No Replies

As the name suggests, a game element is a central part of the engine. With the help of a GameElement, various objects can be integrated into the game. To be more precise, the GameElement class is an abstract class that provides various functions and properties that are used by the engine.

Because the class is abstract, you can also create your own game elements. At the moment there are already a lot of game elements in the engine. For example a sprite, a static 3D element, a 3D model with animations and many more. These can either be displayed visually or, like the NavMesh for example, perform logical functions.

Let us take a closer look at the sprite game element for this tutorial.

Code:
using Genesis.Graphics;
using Genesis.Math;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;

namespace Genesis.Core.GameElements
{
    /// <summary>
    /// Represents a sprite element in a 2D or 3D environment.
    /// </summary>
    public class Sprite : GameElement
    {
        /// <summary>
        /// Gets or sets the texture of the sprite.
        /// </summary>
        public Texture Texture { get; set; }

        /// <summary>
        /// Gets or sets the color of the sprite.
        /// </summary>
        public Color Color { get; set; } = Color.White;

        /// <summary>
        /// Gets or sets the texture coordinates of the sprite.
        /// </summary>
        public TexCoords TexCoords { get; set; } = new TexCoords();

        /// <summary>
        /// Gets or sets a value indicating whether occlusion culling is enabled for the sprite.
        /// </summary>
        public Boolean OcclusionCulling { get; set; }

        /// <summary>
        /// Initializes a new instance of the Sprite class with specified name, location, size, and texture.
        /// </summary>
        /// <param name="name">The name of the sprite.</param>
        /// <param name="location">The initial location of the sprite.</param>
        /// <param name="size">The size of the sprite.</param>
        /// <param name="texture">The texture for the sprite.</param>
        public Sprite(String name, Vec3 location, Vec3 size, Texture texture)
        {
            this.Name = name;
            this.Location= location;   
            this.Size= size;
            this.Texture= texture;
            this.OcclusionCulling = true;
        }

        /// <summary>
        /// Initializes the sprite element.
        /// </summary>
        /// <param name="game">The game instance.</param>
        /// <param name="renderDevice">The render device used for rendering.</param>
        public override void Init(Game game, IRenderDevice renderDevice)
        {
            base.Init(game, renderDevice);
            renderDevice.InitSprite(this);
            if(Texture != null)
            {
                if (Texture.RenderID == 0)
                {
                    renderDevice.LoadTexture(Texture);
                }
            }
        }

        /// <summary>
        /// Renders the sprite element.
        /// </summary>
        /// <param name="game">The game instance.</param>
        /// <param name="renderDevice">The render device used for rendering.</param>
        public override void OnRender(Game game, IRenderDevice renderDevice)
        {
            base.OnRender(game, renderDevice);

            if(game.SelectedScene.Camera.GetRect().Intersects(this.GetBounds2D()))
            {
                renderDevice.DrawSprite(this);
            }
        }

        /// <summary>
        /// Handles cleanup and resource disposal when the sprite is destroyed.
        /// </summary>
        /// <param name="game">The game instance.</param>
        public override void OnDestroy(Game game)
        {
            base.OnDestroy(game);
            game.RenderDevice.DisposeTexture(Texture);
        }

        /// <summary>
        /// Gets the 2D bounds of the sprite.
        /// </summary>
        /// <returns>A rectangular region representing the 2D bounds of the sprite.</returns>
        public Rect GetBounds2D()
        {
            return new Rect(Location.X, Location.Y, Size.X, Size.Y);
        }

        /// <summary>
        /// Gets the center location of the sprite.
        /// </summary>
        /// <returns>The center location of the sprite.</returns>
        public Vec3 GetCenterLocation()
        {
            return new Vec3(Location.X + (Size.X / 2), Location.Y + (Size.Y / 2));
        }

        /// <summary>
        /// Calculates the vertex coordinates of the sprite.
        /// </summary>
        /// <returns>An array containing the vertex coordinates of the sprite.</returns>
        public float[] CalculateVerticies()
        {
            float LeftX = this.Location.X - (Size.X / 2);
            float RightX = this.Location.X + (Size.X / 2);
            float top = this.Location.Y + (Size.Y / 2);
            float bottom = this.Location.Y - (Size.Y / 2);
           
            return new float[]
            {
                LeftX, bottom, 0.0f,
                LeftX, top, 0.0f,
                RightX, top, 0.0f,

                LeftX, bottom, 0.0f,
                RightX, top, 0.0f,
                RightX, bottom, 0.0f
            };
        }

    }
}

What is noticeable is that some sprite specific variables or properties have been created. There is also a constructor, which gives various variables an inherited and own property.

Code:
public Sprite(String name, Vec3 location, Vec3 size, Texture texture)
{
    this.Name = name;
    this.Location= location;   
    this.Size= size;
    this.Texture= texture;
    this.OcclusionCulling = true;
}

The next function we see is the Init function. As with the game behaviours, this function is called as soon as the element is created or the game is initialised. In this function we also pass the sprite to the RenderDevice to initialise it or to load it into the GPU memory. However, the standard renderers use so-called instantiated shapes, which would normally not make it necessary to initialise the sprite. The function is called for compatibility reasons.

The next step is to check if the texture already has a RenderID, i.e. if it does, it is already in the graphics card's memory. If not, it will be loaded from the renderer.

Code:
public override void Init(Game game, IRenderDevice renderDevice)
{
    base.Init(game, renderDevice);
    renderDevice.InitSprite(this);
    if(Texture != null)
    {
        if (Texture.RenderID == 0)
        {
            renderDevice.LoadTexture(Texture);
        }
    }
}

The OnRender function passes the sprite to the RenderDevice so that it can draw the sprite on the screen.

Code:
public override void OnRender(Game game, IRenderDevice renderDevice)
{
    base.OnRender(game, renderDevice);

    if(game.SelectedScene.Camera.GetRect().Intersects(this.GetBounds2D()))
    {
        renderDevice.DrawSprite(this);
    }
}

The last function we want to look at is the OnDestroy function. This is called when the game is finished, so that we can free up the memory in the graphics card that we have occupied with the sprite.

Code:
public override void OnDestroy(Game game)
{
    base.OnDestroy(game);
    game.RenderDevice.DisposeTexture(Texture);
}

Print this item

  Game behaviour and the advantages
Posted by: Andy - 06-30-2024, 08:23 PM - Forum: Tutorials and Guides - No Replies

In the last tutorial we looked at how to create a game project with GFX, now we want to look at how to create the game logic.

For this we will use GameBehaviors. But what is a GameBehaviour? Simply put, it is a class that contains various functions that are called by the engine at certain times. For example, when the game is initialised, every time the game is updated, during rendering and many more. You can read more about the functions in the documentation on the following page.

Class IGameBehavior | GFX (gfx-engine.org)

The best way to work with the behaviours is to create your own or use the ones that are already there. In this tutorial we will create a simple behaviour for the player control. We will create a new class and make it inherit the IGameBehaviour.

Code:
public class PlayerBehavior : IGameBehavior
{
    public override void OnDestroy(Game game, GameElement parent)
    {
       
    }

    public override void OnInit(Game game, GameElement parent)
    {

    }

    public override void OnRender(Game game, GameElement parent)
    {
       
    }

    public override void OnUpdate(Game game, GameElement parent)
    {
       
    }
}

As you can see, we only have several functions with which we can work. For our behaviour we want to use the Init and Update function, that means once when the game element is initialised and once at every update.

On initialisation we want our behaviour to place the player on the left edge of the screen.

Code:
public override void OnInit(Game game, GameElement parent)
{
    var startX = this.Parent.Location.X - (game.Viewport.Width / 2) + 64;
    this.Parent.Location.X = startX;
    this.Parent.Rotation.Z = Utils.ToRadians(-90.0f);
}

If we now go through the code, we can see that our behaviours have a Parent property, which is the GameElement to which the behaviour is assigned. We also have a parameter of the class Game, which contains the current viewport. With the help of these two properties we can now calculate the location vector. It is important to note that in OpenGL the point X:0 Y:0 is in the middle of the screen. For this reason we need to move the character to the left by the size of the viewport. We also rotate the player by 90°. Again, note that we are not directly assigning 90 degrees, but rather converting the 90 degrees into radii and then assigning them.

Once we have moved our player, the result should look like this

   

Now we come to the movement control, this is quite simple, we check in the update function, also in every frame, if the user has made an input with the WASD keys. It is important to note that I have done two if checks, so that the user can move on the X and Y axis at the same time.

I also calculated the speed and the movement time using DeltaTime, which ensures that the speed is the same for each frame rate.

When the user makes an input, a variable is incremented or decremented to reflect the new position on the screen.

To prevent the user from leaving the screen, I added a function that checks if the player is in the viewport area. If so, the position is changed in the parent, otherwise not.

Code:
public class PlayerBehavior : IGameBehavior
{
    public override void OnDestroy(Game game, GameElement parent)
    {
       
    }

    public override void OnInit(Game game, GameElement parent)
    {
        var startX = this.Parent.Location.X - (game.Viewport.Width / 2) + 64;
        this.Parent.Location.X = startX;
        this.Parent.Rotation.Z = Utils.ToRadians(-90.0f);
    }

    public override void OnRender(Game game, GameElement parent)
    {
       
    }

    public override void OnUpdate(Game game, GameElement parent)
    {
        /// Calculate the speed for the player
        float speed = (float)(game.DeltaTime) * 0.5f;
        float newX = this.Parent.Location.X;
        float newY = this.Parent.Location.Y;


        /// Move the player on the Y axis
        if(Input.IsKeyDown(System.Windows.Forms.Keys.W))
        {
            newY += speed;
        }
        else if (Input.IsKeyDown(System.Windows.Forms.Keys.S))
        {
            newY -= speed;
        }

        /// Move the player on the X axis
        if (Input.IsKeyDown(System.Windows.Forms.Keys.A))
        {
            newX -= speed;
        }
        else if (Input.IsKeyDown(System.Windows.Forms.Keys.D))
        {
            newX += speed;
        }

        /// Check if the new position from the player is on the viewport
        if(IsPlayerOnViewport(game.Viewport,newX, newY, this.Parent))
        {
            this.Parent.Location.Set(newX, newY, 0f);
        }
    }

    private bool IsPlayerOnViewport(Viewport viewport, float x, float y, GameElement element)
    {
        float vpStartX = -(viewport.Width / 2);
        float vpHalfWidth = viewport.Width / 2;
        float vpStartY = -(viewport.Height / 2);
        float vpHalfHeight = viewport.Height / 2;
        float playerX = x - (element.Size.X / 2);
        float playerY = y - (element.Size.Y / 2);

        if(playerX >= vpStartX && playerX + element.Size.X <= vpHalfWidth && playerY >= vpStartY && playerY + element.Size.Y <= vpHalfHeight)
        {
            return true;
        }
        return false;
    }
}

Now that we have created our GameBehavior, we need to assign it to our player sprite in the main class.

Code:
// Create an player
m_player = new Sprite("player", new Vec3(0, 0), new Vec3(64, 64), m_game.AssetManager.GetTexture("f_004.png"));
m_player.AddBehavior(new PlayerBehavior());
scene.AddGameElement("BaseLayer", m_player);

We have now created our first behaviour Smile Congratulations

Print this item

  Create your first project with GFX
Posted by: Andy - 06-30-2024, 04:03 PM - Forum: Tutorials and Guides - No Replies

Hello Community Smile

with this tutorial i like to show you how to create your first Project with GFX. For this you need the latest version from Visual Studio. You can download it from here https://visualstudio.microsoft.com/en. After you downloaded and installed visual studio you can download the project template. This template will help you create and setup new projects with the visual studio assistant like in the screesnshot below. If you dont know how to install visual studio templates you can have a look here: Locate and organize project templates - Visual Studio (Windows) | Microsoft Learn.

   

After you created your new project with the template you need to build the project for the first time. Importan you need to create an x64 build from the project. After your first build you can open the Form1.cs code and should see something like the code bellow:

Code:
using Genesis.Core;
using Genesis.Graphics;
using Genesis.Graphics.RenderDevice;
using Genesis.Math;
using Genesis.Physics;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace GFXGame
{
    public partial class Form1 : Form
    {
        private Game m_game;

        /// <summary>
        /// Initial the game
        /// </summary>
        public Form1()
        {
            InitializeComponent();

            // Create the render settings
            var renderSettings = new RenderSettings()
            {
                gamma = 0.5f
            };

            // Setup the game class and load the assets from the "Resources" folder. Make sure you copy them into the output directory!
            m_game = new Game(new GLRenderer(this.Handle, renderSettings), new Viewport(this.ClientSize.Width, this.ClientSize.Height));
            m_game.AssetManager.LoadTextures();

            // Setup a demo scene with an camera and an physics handler
            var scene = new Scene("MyTestScene");
            scene.AddLayer("BaseLayer");
            scene.Camera = new Camera(new Vec3(0, 0), new Vec3(m_game.Viewport.Width, m_game.Viewport.Height), -1.0f, 1.0f);
            scene.PhysicHandler = new PhysicsHandler2D(0f, 0f);

            // Hook into the update event. You can use this lambda or create an own function for it.
            m_game.OnUpdate += (game, renderer) =>
            {
                Console.WriteLine(game.FPS);
            };

            // Add the scene to the game and run it
            m_game.AddScene(scene);
            m_game.LoadScene("MyTestScene");
            m_game.Start();
        }

        /// <summary>
        /// Resize the game
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form1_Resize(object sender, EventArgs e)
        {
            m_game.Viewport.SetNewViewport(ClientSize.Width, ClientSize.Height);
            if (m_game.SelectedScene != null)
            {
                m_game.SelectedScene.ResizeScene(m_game.Viewport);
                m_game.SelectedScene.Camera.Size = new Vec3(m_game.Viewport.Width, m_game.Viewport.Height);
            }
        }

        /// <summary>
        /// Stops the game
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            m_game.Stop();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }
    }
}

From this point on you can Run the project and should see an black screen which is totaly normal because you dont have any GameElement in your scene yet. This is the point where you can start to create your scene and build your game. For models, Textures and sprites you want to add into your project you can simply copy them into the Resources folder within your Visual Studio solution and select the option to copy the file into the output directory (see the screenshot bellow).

   

Print this item

  Welcome to our Forum
Posted by: Andy - 06-30-2024, 12:30 PM - Forum: News and Updates - No Replies

Like any other engine or software project, we have also created a forum for GFX. Here it is possible to talk about various topics around the engine and programming. The forum should be a central point for the community.

Furthermore you have the possibility to report your bugs here, so that they can be fixed faster.

Print this item