How to write a game on Monogame without attracting the attention of orderlies. Part 0, introductory

1. Introduction

With this article, I open a series of development diaries for the third reincarnation of my future game KARC. The first version has reached the minimum playable form and is made available to the public. However, I didn’t like how I designed the structure of the application. Therefore, mistakenly believing that I understood how to properly design the architecture of the application, I made a second version from scratch. In it, I was able to load a scene with a player’s typewriter that responds to the keyboard. However, I did not consider it expedient to develop this version further, because, having carried away, I wound up too much of everything and, most importantly, incorrectly. As a result, the code became very difficult to navigate. So the project would have remained frozen for an indefinite period, like my dream of making games, if I had not once again decided to try to understand the architectural patterns, in particular, MVP, and I would suddenly fail to do this. And I liked MVP so much that I realized how I wanted to rewrite the KARC architecture. This time I decided to record all my steps on paper, and then put them in the public domain. The fact is that I am making a game on the Monogame framework, but I did not find a clear guide on the net on how to make something complete on it. There are many videos and articles on how to make some individual elements (for example, which method loads a sprite, but not how best to do this if you have a lot of them and there are several of them for each game object) or small games that are pulled in at best, on a tech demo, but not to create any complete game as a whole (I actually found something, and there will be links in subsequent articles, but in general I didn’t like it). Therefore, perhaps, the description of my path will be useful to someone.

2. Materials and methods

The game KARC will be a simple top-down arcade game where the player’s car moves along a straight road, dodging other cars. The game will be developed in C# using the Monogame framework.

Why Monogame? I really love the C# language and I want to develop a game in it. However, no matter how many times I approached Unity, it invariably caused me rejection – Unity is a full-fledged universal engine, and it was always difficult for my brain to grasp its device. And, if I don’t understand from beginning to end how something works, at least in general terms, then it’s extremely uncomfortable for me to use it. I copied several projects to Unity that I found in the lessons on the network, but there was no understanding, and I abandoned it. Someday I will return simply because it is interesting, but not because it is necessary – Monogame is more than enough for the realization of my modest game development appetites.

However, I’m getting ahead of myself. So my childhood dream of designing my own toys would have remained unfulfilled, but somehow on Metanit I stumbled upon the Monogame manual, the first time I learned about its existence. After reading the first few lessons, I realized that this is exactly what I need. The fact is that Monogame is not a game engine – it is a pygame-type framework written in C#. In fact, this is just a set of libraries that contain classes and methods for loading resources, launching a simple game loop, and working with graphics and geometry. How to put it all together and use it, everyone decides for himself. Do you want physics in your game? Write it down, friend! Monogame will allow you to create instances of the Rectangle class, for which there is a static method that answers the question – do the two specified rectangles intersect? Further – himself. Nobody limits you! For me it was a real salvation, because, having gone down to the level below the engine, I finally understood how games work. The lack of opportunities for me was a plus, because, as a result, there was no congestion – if I needed something, I wrote it myself. In the process of working on the first and second versions of KARC, I even began to better understand the Unity device, because in order to implement my ideas, it was necessary to create functionality similar to it.

Later, I even realized that I didn’t need a framework to make a game – for fun, I wrote a couple of simple projects like the Predator-Prey model with 2D graphics and collision calculation using C # + Windows Forms. And, having raised the level of his skill, he decided to complete the implementation of his first idea, because the matter must be brought to the end. Since the whole game will be written in C# , this series of articles is designed for people who already know the syntax and features of this language, represent what classes, methods, properties and events are. However, the author does not pretend to write the ideal code, and the solutions he proposes are the most optimal, so he will always be happy with constructive criticism.

3. Theory

3.1 Preparing the working environment

As I said, the development will be carried out on the Monogame framework. I will write the project in Visual Studio 2019 (looking ahead – then it will be 2022). In order to use the latest Monogame version 3.8, you need to download the appropriate extension.

You can go the other way – create an empty project and download the appropriate packages to it via NuGet, but I don’t advise you – you will have to manually download the packages for each project (and there are more than one package), and then manually write the initial code in order to be happy worked as it should (connecting graphics and so on). While installation via extensions will create a new project template in the Studio, in which everything that is needed is written right away.

Creating a new Monogame project
Creating a new Monogame project
Launching a new Monogame project
Launching a new Monogame project

Let’s go through the structure of the automatically generated code in detail.

3.2 Project structure

The entry point to a program, as always in C#, is the static Main method of the static Program class. If we look in the corresponding tab, we will see some boring lines, similar to those that can be seen, for example, in Windows Forms:

This code unambiguously hints to us that the Main method creates an instance of a certain Game1 class, from which it calls the Run method (which just starts our game). We can conclude that all the most interesting things happen inside Game1, and, looking ahead, this is true. Let’s walk through the structure of this class. Let’s start from the top.

From the very beginning (1) we see that the class uses three libraries whose names begin with Microsoft.XNA. Do not be surprised – Monogame grew out of the Microsoft framework, which they stopped supporting. People didn’t accept this – and that’s how Monogame appeared. Next (2) we see that our class Game1 inherits from Game. If you are interested, you can go to the definition of the parent class and see what other fields and methods there are in addition to those that we will meet next. After that (3) we see two private fields that are responsible for the graphics, but are not used yet. We will fix this soon. The constructor (4) connects the graphics, sets the root directory for the game resources and makes the mouse visible. Next comes the overridden Initialize(5) method, which is called when our game is initialized. As planned by the authors, here we should put all sorts of resources that are not related to graphics. Right now, only the parent Initialize method is called there, which runs the next overridden method, LoadContent (6). Here, just, you should load graphic resources such as sprites and everything else that is not directly related to the code. Technically, sharp, of course, does not distinguish which method is needed for what. Your resources such as sprites, sounds and music will be stored after loading in normal fields, so no one bothers you to load resources even inside the Initialize method, even inside the game loop, even write your own method and call it in the constructor, except that in most cases it is just stupid. Therefore, I advise you to stick to this division. Then the fun begins.

If everything before that was called once, then the Update and Draw methods are run every game cycle. In Update, the “logic” of the game should be updated, and Draw draws the playing field every loop. Again, the division is relatively conditional, so if you’re a particular aesthete, you can stuff the logic into the Draw method, and the rendering into the Update method, and it will even work. Relatively conditional division because Update is called first in the game loop, and only then, which is logical, Draw, so if, for example, you try to draw an object that has not yet been created, the program will not like it.

To sum up, the structural differences of what we saw from the usual C# project are small: in fact, it is the need to use the Update and Draw methods, which together make up the game loop. In all other respects, we see the usual C # – code with some specific tools, which we will touch on next time. In my next article, we will think about how to fit the MVP pattern that I like so much into the Procrustean bed of the game loop, and also create something tangible, in addition to the blue screen.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *