Page 1. Microsoft XNA's Hello World w/ MonoGame

Prerequisites

Installing MonoGame

You can install MonoGame using one of the following methods:

Option 1: Downloading from MonoGame's Official Website

  1. Click on the download link for your operating system.

  2. Follow the prompts to install MonoGame for Visual Studio.

Option 2: Installing from Visual Studio

  1. Open Visual Studio.

  2. Click on Extensions > Manage Extensions.

  3. In the search bar, type "MonoGame" and find MonoGame Project Templates.

  4. Click Download, then Install.

  5. Restart Visual Studio if prompted, or close and reopen it manually to ensure the changes take effect.

Important Note

Regardless of the method you choose, you must restart Visual Studio after the installation for the changes to take effect.


Creating a New Project

  1. Open Visual Studio.

  2. Select File > New > Project....

  3. Choose MonoGame Windows Project.

  4. Enter a project name and location, then click Create.


Using Custom Fonts in Your MonoGame Project

The ability to display text using various fonts can significantly enhance your game. This section will guide you on how to integrate custom fonts into your MonoGame project. Even if you've never dealt with fonts in game development before, don't worry. We'll take it step by step.

Adding the Font to Your Project

  1. Locate the Content Pipeline: Open the Content folder within your MonoGame project.

  2. Adding a New Item: Right-click on the folder, navigate to Add > New Item.

  3. Adding a Font Manually

    1. Create a Fonts Directory: First, create a new folder inside your MonoGame project's "Content" folder and name it "Fonts."

    2. Add SpriteFont File: Create a new file saving it with the extension .spritefont

      • Paste the following SpriteFont XML code into it:

      <?xml version="1.0" encoding="utf-8"?>
      <XnaContent xmlns:Graphics="Microsoft.Xna.Framework.Content.Pipeline.Graphics">
        <Asset Type="Graphics:FontDescription">
          <FontName>Arial</FontName>
          <Size>14</Size>
          <Spacing>0</Spacing>
          <UseKerning>true</UseKerning>
          <Style>Regular</Style>
          <CharacterRegions>
            <CharacterRegion>
              <Start>&#32;</Start>
              <End>&#126;</End>
            </CharacterRegion>
          </CharacterRegions>
        </Asset>
      </XnaContent>
      • Save this file

    1. Open Content.mgcb: In your MonoGame project, locate the Content.mgcb file. You can edit it with the MonoGame Pipeline Tool by double-clicking it or by manually adding your .spritefont file via text editor.

    2. Add .spritefont File: Add your .spritefont file to the content pipeline if it isn't already there. In the MonoGame Pipeline Tool, right-click on the Content node and choose Add -> Existing Item. Navigate to your .spritefont file and add it.

    3. Build Content: After adding the .spritefont, save the .mgcb file and build it. This should produce a .xnb file in your output directory (bin/Debug/net6.0-windows/Content or similar). If you're in the MonoGame Pipeline Tool, you can do this by clicking Build -> Rebuild All.

    4. Check Output: Make sure the .xnb file gets placed in the directory that matches your Content.RootDirectory setting in your Game1.cs file.

    5. Run Your Project: Finally, try running your MonoGame project again. It should now be able to find MyFont.xnb.


Starting from Scratch

Once the project is created, navigate to the Game1.cs file. Delete all existing code inside this file, and we'll rebuild only what's necessary for our "Hello World" application.


Importing Necessary Packages

Before defining our Game1 class, it's essential to import the packages we'll be using. These packages give us access to various functionalities in MonoGame.

// Core MonoGame namespace; includes essential classes for game development.
using Microsoft.Xna.Framework;

// Graphics-related classes; enables rendering of textures, sprites, and fonts.
using Microsoft.Xna.Framework.Graphics;

// Input-related classes; handles input devices like keyboards, mice, and gamepads.
using Microsoft.Xna.Framework.Input;

What Do These Packages Do?

  1. Microsoft.Xna.Framework: This is the backbone of MonoGame and provides the core functionalities for game development, such as the Game and GameTime classes.

  2. Microsoft.Xna.Framework.Graphics: As the name suggests, this package is all about graphics. It contains classes and methods that allow us to draw shapes, images, and text on the screen.

  3. Microsoft.Xna.Framework.Input: This package helps us capture user inputs from various devices like keyboards, mice, and gamepads. It's crucial for interactivity in our game.


Namespace: The Address of Your Code

Before we dive into the Game1 class, let's talk about a line of code that acts like the address of your 'coding house'. Yep, it's the namespace.

namespace GameLoops
  • Namespace: Imagine your code is like a big family, and families usually live in the same house, right? A namespace is like your code's house address. It groups your classes together and helps you avoid naming conflicts. So, if you have a Dog in one namespace and a Dog in another, no problem! The namespace keeps them separate.

  • GameLoops: This is the name of your house. You can name your house whatever you like, but remember, the postman (in this case, the compiler) needs to know this address to deliver the right things to the right place.


Defining the Game1 Class

When we make a video game, we can think of the main class as the game's "control center." This is where we tell the computer how our game is meant to work.

// Game1 class inherits from the Game class in XNA
public class Game1 : Game
{
    GraphicsDeviceManager graphics; // Manages the graphics device
    SpriteBatch spriteBatch; // Enables drawing of 2D images

    public Game1()
    {
        graphics = new GraphicsDeviceManager(this);
        Content.RootDirectory = "Content"; // Set the content directory
    }
}

What is the Game1 Class?

  • Game1: This is the name of our main class. You can change this name, but if you do, you must also change the name in other places where Game1 is used, like in the Program.cs file.

  • : Game: This means that our Game1 class is a special type of class called a Game. It's like having a recipe that already has some ingredients, and we add our own to make our unique game.

GraphicsDeviceManager

  • GraphicsDeviceManager graphics;: This is like hiring a manager to take care of everything related to drawing on the screen. It helps set the screen size, color, and more.

  • graphics = new GraphicsDeviceManager(this);: Here, we're telling the computer to create this manager for our game (that's what this refers to). It's like saying, "Hey, we need someone to manage our game's graphics, so let's hire this GraphicsDeviceManager."

Content.RootDirectory

  • Content.RootDirectory = "Content";: Think of this like telling the computer where to find all the pictures, sounds, and other things we want to use in our game. By setting the Content.RootDirectory, we're saying, "All our game's stuff is in a folder called 'Content', so look there!"

By understanding these pieces, you're learning the building blocks of game development. You're telling the computer how to set up the screen and where to find everything it needs for your game.


Initializing the Window

When you start building a game or application with the XNA Framework, one of the first things you need to do is set up the window where everything will be displayed. In this section, you'll learn how to create a window with specific dimensions and prepare it for drawing 2D graphics.

// Initialize method sets up the game window and resources
protected override void Initialize()
{
    // Set the window dimensions
    graphics.PreferredBackBufferWidth = 800;
    graphics.PreferredBackBufferHeight = 600;
    graphics.ApplyChanges();

    // Create the SpriteBatch object for 2D drawing
    spriteBatch = new SpriteBatch(GraphicsDevice);

    base.Initialize();
}

Explanation:

  • Setting the Window Size

    • graphics.PreferredBackBufferWidth = 800; - This sets the window's width to 800 pixels.

    • graphics.PreferredBackBufferHeight = 600; - This sets the window's height to 600 pixels.

    • graphics.ApplyChanges(); - This command makes sure the changes we made to the window size take effect. Without this, the window would ignore our size settings.

  • Preparing to Draw 2D Graphics

    • spriteBatch = new SpriteBatch(GraphicsDevice); - We're creating a tool called "SpriteBatch" that helps us draw pictures and shapes. The GraphicsDevice part is telling the SpriteBatch where to draw. Without this, the SpriteBatch wouldn't know where to paint the images.

  • Finishing the Initialization

    • base.Initialize(); - This line tells the game that we're done setting up and ready to move on to the next part of our game-making process.


Loading Content

In a game, you'll often want to display text, images, or other media. Before you can use them, you need to load them into the game. This section explains how to load a font and set its position on the screen. Imagine this like picking a specific pen and deciding where you're going to start writing on a piece of paper.

// Declare variables for the font and position of the text
SpriteFont font;
Vector2 position;

// Load the content (font) and set the position
protected override void LoadContent()
{
    font = Content.Load<SpriteFont>("Fonts/MyFont");
    position = new Vector2(400, 300); // Center of the screen
}

Explanation:

  • Declaring Variables

    • SpriteFont font; - Think of this as choosing a specific style of pen but not picking it up yet. We're saying we'll use a font but haven't defined which one.

    • Vector2 position; - This is like marking a spot on the paper where you want to write but not moving your pen there yet. We're setting aside a place for the text position but haven't given it coordinates.

  • Loading the Font and Setting the Position

    • font = Content.Load<SpriteFont>("Arial"); - Now we've picked up the "Arial" pen. This line loads a font named "Arial" into our game so we can write with it.

    • position = new Vector2(400, 300); - We've decided to start writing at coordinates (400, 300) on the paper. This puts our text in the center of the screen.


Drawing "Hello World"

Now that you have set up your window and loaded your content, you're ready to display something on the screen. In this part, you'll learn how to draw the text "Hello, World!" in your game window. Think of this as finally putting pen to paper and writing a greeting.

// This method is responsible for drawing everything on the screen
protected override void Draw(GameTime gameTime)
{
    // Clear the screen with a specific color
    GraphicsDevice.Clear(Color.CornflowerBlue);

    // Start drawing
    spriteBatch.Begin();

    // Draw the text "Hello, World!" using the Arial font, centered on the screen, in white color
    spriteBatch.DrawString(font, "Hello, World!", position, Color.White);

    // End drawing
    spriteBatch.End();

    // Continue with the usual drawing process
    base.Draw(gameTime);
}

Explanation

  • Clearing the Screen

    • GraphicsDevice.Clear(Color.CornflowerBlue); - This line clears the screen and fills it with a specific color (Cornflower Blue). It's like starting with a fresh piece of paper.

  • Starting to Draw

    • spriteBatch.Begin(); - This line tells the game that we're starting to draw something. Think of it as uncapping the pen.

  • Drawing the Text

    • spriteBatch.DrawString(font, "Hello, World!", position, Color.White); - This line actually writes the words "Hello, World!" on the screen. Let's break it down:

      • font - This is the specific style of writing we picked earlier (Arial).

      • "Hello, World!" - This is the text we want to write. It's a variable of type string.

      • position - This tells the game where on the screen to write the text.

      • Color.White - This tells the game what color the text should be (white).

  • Ending the Drawing

    • spriteBatch.End(); - This line tells the game that we're done drawing. It's like capping the pen.

  • Finishing Up

    • base.Draw(gameTime); - This line tells the game to carry out the usual drawing process after our custom drawing.

Deeper Explanation of Keywords

  • protected - This keyword means that the drawing method can be accessed by this class and any class that inherits from it.

  • override - This keyword indicates that we are changing how a method in a base class works in this specific class.

  • void - This keyword means that the method doesn't return any value; it performs an action but doesn't give anything back.

Questions You Might Have

  • Why do we need to clear the screen? - Clearing the screen ensures that previous drawings don't interfere with what we're about to draw.

  • What's the importance of Begin and End? - They tell the game when we're starting and finishing a specific drawing, ensuring everything is drawn in the correct order.

Summary

Drawing "Hello, World!" involves several steps, from preparing the screen to using specific writing tools and styles. By understanding each part of this process, you've taken a significant step in learning how to create visuals in your game. You now know how to display text, control its appearance, and understand some essential programming concepts.

Final Complete Example

public class Game1 : Game
{
    GraphicsDeviceManager graphics;
    SpriteBatch spriteBatch;
    SpriteFont font;
    Vector2 position;

    public Game1()
    {
        graphics = new GraphicsDeviceManager(this);
        Content.RootDirectory = "Content";
    }

    protected override void Initialize()
    {
        graphics.PreferredBackBufferWidth = 800;
        graphics.PreferredBackBufferHeight = 600;
        graphics.ApplyChanges();
        spriteBatch = new SpriteBatch(GraphicsDevice);
        base.Initialize();
    }

    protected override void LoadContent()
    {
        font = Content.Load<SpriteFont>("Arial");
        position = new Vector2(400, 300);
    }

    protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.CornflowerBlue);
        spriteBatch.Begin();
        spriteBatch.DrawString(font, "Hello World!", position, Color.Black);
        spriteBatch.End();
        base.Draw(gameTime);
    }
}

Knowledge test

Question 1: Understanding Variables

What is the purpose of a variable in code, and can you identify a variable used in the "Drawing 'Hello, World!'" code snippet?

Question 2: The Drawing Process

In the code, what is the significance of spriteBatch.Begin();, and why is it followed by spriteBatch.End();?

Question 3: Text Positioning

What does the position variable represents in spriteBatch.DrawString(font, "Hello, World!", position, Color.White);, and how can it be modified?

Practice Question 1: Experimenting with Text

Update the code to draw your own custom message on the screen. Change the text from "Hello, World!" to something personal, like your name or a favorite quote.

Practice Question 2: Playing with Colors

Modify the code to change the text color from white to another color of your choice. Experiment with different colors and observe how they affect the appearance of the text.

Last updated