Skip to content

Initializing, updating & drawing

Nick Jordan edited this page Jul 5, 2024 · 6 revisions

Page contents

  1. Init, Update and Draw
  2. Setting up the screen
  3. Loading assets
  4. Using assets
  5. Initializing & using UI components
  6. Tilemap reading & drawing

Init, Update and Draw

The three core methods for your game are Init, Update, and Draw. Here's a basic template:

using Microsoft.Xna.Framework;

namespace MonoZenith;

public partial class Game
{
    /* Initialize game vars and load assets. */
    public void Init()
    {
        
    }

    /* Update game logic. */
    public void Update(GameTime deltaTime)
    {
        
    }
    
    /* Draw objects/backdrop. */
    public void Draw()
    {
        
    }
}

Setting up the screen

Modify screen properties using helper methods in the Init method:

/* Initialize game vars and load assets. */
public void Init()
{
   SetScreenSize(800, 600);
   SetBackgroundColor(Color.White);
   SetWindowTitle("My game");     
}

Loading Assets

Assets can be loaded through the DataManager class. This singleton class efficiently manages the addition and loading of assets such as fonts, textures, and audio files.

Adding a New Asset

  1. Declare a Public Variable: Create a public variable for the new asset in the DataManager class.
  2. Initialize the Asset in LoadData: Assign the asset to the variable in the LoadData method. This method is called during the initialization of the DataManager object within the Engine class.

This ensures that all assets are loaded before the game starts, preventing runtime lag.

Example

Below is an example of the DataManager class:

using Microsoft.Xna.Framework.Graphics;

namespace MonoZenith.Engine.Support
{
    public class DataManager
    {
        private readonly Game _game;
        private static DataManager _instance;
        
        // Fonts
        public SpriteFont ComponentFont;
        
        // Textures
        public Texture2D MonoZenithLogo;
        
        // Audio

        // Private constructor to enforce the singleton pattern
        private DataManager(Game game)
        {
            _game = game;
            LoadData();
        }

        /// <summary>
        /// Gets the singleton instance of the DataManager.
        /// </summary>
        /// <param name="game">The game instance.</param>
        /// <returns>The DataManager instance.</returns>
        public static DataManager GetInstance(Game game)
        {
            return _instance ??= new DataManager(game);
        }
        
        /// <summary>
        /// Loads all game data such as fonts, textures, and audio.
        /// </summary>
        private void LoadData()
        {
            // Load fonts
            ComponentFont = _game.LoadFont("Fonts/pixel.ttf", 1);
            
            // Load textures
            MonoZenithLogo = _game.LoadImage("Images/monozenith.png");
            
            // Load audio
        }
    }
}

Explanation

  • Singleton Pattern: The DataManager class uses the singleton pattern to ensure only one instance exists, providing a global point of access to the assets.
  • LoadData Method: The LoadData method is responsible for loading all assets before the game starts. This preloading ensures smooth gameplay without delays.

Using assets

Incorporate assets into your game's logic and rendering:

/* Update game logic. */
public void Update(GameTime deltaTime)
{
   if (GetKeyDown(Keys.Space))
   {
      mySound.Play();
   }
}

/* Draw objects/backdrop. */
public void Draw()
{
   DrawImage(myImage, new Vector2(100, 100));
   DrawText("Hello world!", myFont, new Vector2(100, 100), Color.Black);
}

Initializing & using UI components

Initialize UI components in the Init method. Update and draw them in the Update and Draw methods, respectively:

Button myButton;
    
/* Initialize game vars and load assets. */
public void Init()
{
    SetScreenSize(800, 600);
    SetBackgroundColor(Color.White);
    
    // Initialize button
    myButton = new Button(
        this,                          // Game reference
        new Vector2(400, 300),         // Position
        400, 100,                      // Width, Height
        "Click me!", 2, Color.White,   // Text, Font Size, Text Color
        Color.Black,                   // Button Color
        3, Color.Red);                 // Border Width, Border Color
    }

/* Update game logic. */
public void Update(GameTime deltaTime)
{
    myButton.Update(deltaTime);
    myButton.SetOnClickAction(() => DebugLog("UwU"));
}
    
/* Draw objects/backdrop. */
public void Draw()
{
    myButton.Draw();
}

Tilemap reading & drawing

Tilemaps are a common technique used in game development to efficiently render 2D environments. In MonoZenith, you can read tilemaps and draw individual tiles from them using specific methods. Here's how you can work with tilemaps:

Reading a Tilemap

You can load a tilemap into a Texture2D format using the ReadTileMap method. This method reads a tilemap image and returns a Texture2D representing the entire tilemap.

private Texture2D _tileMap;

public void Init()
{
    _tileMap = ReadTileMap("Textures/tilemap.png");
}

Reading Tiles from a Tilemap

To retrieve individual tiles from a tilemap, you can use the ReadTileFromMap method. This method allows you to specify the tile you want by providing its index and tile size. It returns a Texture2D representing the specified tile.

private Texture2D _tile;

public void Init()
{
    _tileMap = ReadTileMap("Textures/tilemap.png");
    _tile = ReadTileFromMap(_tileMap, 1, 32);
}

Example Usage

Here's an example of how to use the loaded tilemap and a specific tile in your game:

public void Draw()
{
    // Draw an individual tile from the tilemap at position (16, 16)
    DrawImage(_tile, new Vector2(16, 16));
}

These methods and techniques are useful for creating 2D environments and backgrounds in your MonoZenith project. Make sure to customize the code to suit your specific game needs.