Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / game

Migration - Strategy Game

5.00/5 (18 votes)
7 Nov 2022CPOL7 min read 58.6K   4.1K  
A VB.NET implementation of a city-building game with real-time strategy elements.
The game is set in a medieval time, and controlled via a point and click interface, with the primary goal to build a settlement with a functioning economy, producing sufficient units so as to conquer territories, ultimately gaining control of the entire map.

Image 1

Table of Contents

Technology

Introduction

Migration is a simulation strategy game. The goal of the game is to build a community of workers that perform individual tasks of building a new colony. The game is controlled by a mouse-operated point-and-click interface. The player cannot directly control workers, but instead places orders to construct buildings, manage the manufacture and distribution of goods and attack opponents.

There are 32 kinds of building resources and 11 types of migrants. Idle migrants are recruited to specialized roles when new buildings are finished. For example, a blacksmith appears once a smithy is constructed. Some migrants require specific tools for these roles. A toolmaker's building can create additional tools, and the proportions of each tool being created is controlled by the player.

At the start of the game, the player chooses the location of their castle, which houses the initial settlers and stockpiles. If placement of buildings and roads is not carefully planned, it may lead to traffic congestion. If no counter action is taken (re-routing the goods, constructing more warehouses, better placement of buildings), such single bottlenecks can have a distributed effect across the network, leading to shortages because goods cannot reach their destination fast enough.

Background

Motivation

For years, I've admired games like Maxis' SimCity and Sid Meier's Civilization. I've spent countless hours playing and strategizing with those games. However, I have always wanted to 'tweak' them just a bit.

I have always desired to have my own version of these titles. I just never knew where to start. Coming from a business programming background I could never understand how to get the game loops right. There were never any good examples in VB which is my language of choice. Therefore, I decided to open source this game in VB.NET in an attempt to help others, and perhaps spur some ideas, and understanding about how to create your own Empire Strategy type game.

Scope

The scope for this article is Gaming Loops. In particular, I am going to talk about Game Loops as it relates to VB.NET. Maybe in a follow up article, I will talk about the details, classes, and the interrelationships between those classes.

However, for now, I will stick to the biggest hiccup in creating strategy games. The central component of any game, from a programming standpoint, is the game loop. The game loop is what allows the game to run smoothly regardless of a user's of a user's input or lack thereof.

Of course, in business software programming, we never really have to worry much about this concept. For the most part, we design systems that 'React' to user events. (i.e., Button push, text box entered, etc.). Most traditional business software programs respond to user input and do nothing without it. For example, a word processor formats words and text as a user types. If the user doesn't type anything, the word processor doesn't do anything. Functions may take a long time to complete, but they are all initiated by a user telling the program to 'do' something. Games, on the other hand, continue to operate regardless of a user's input.

This is what the game loop allows. That was a tremendous learning curve for me. Hopefully, this article will help to ease that learning curve for you as you move into or think about moving into game programming.

Note: Please note that this work is in no way complete. There is much work left to be done.
Bookmark: I will try and update this article as I get around to fixing certain bugs.

Installation

Step 1

Initially, once you have downloaded the Migration source code and unzipped the contents.  You will end up with the following directory layout:

Image 2

Step 2 (*edited)

Next, you need to make sure you Download *Required* Resources and the additional 4(four) support files.  There are 4 zip files.  Unzip the content of those files into your "Build" directory.

Image 3

Step 3

Ensure that your "Build" directory has all of the files necessary. Ignore the "textures.cache" file it will be regenerated on program startup. It should look similar to the picture below:

Image 4

Step 4

Ensure that your "Resources" directory looks like below. If not, be sure and remember you must download all of the REQUIRED resources.

Image 5

Step 5

Be sure to place the Animations1  and Animations2  file contents in the "...Build\Resources\Animations" directory.  Your "Animations" directory should look like the following.

Image 6

How It works - The Big Picture

Delegates

Migration uses several Delegates and Pointers to Delegates to accomplish its tasks. Basically, a Delegate acts as a handler for events. That's programmer talk, right? Let me give you an example: Let's say I am checking into a hotel in New York city. When I go to the front desk, the front desk person will usually assign someone else to carry my bags to my room. The baggage handler person is the designated delegate for handling bags. The same is true with delegates in VB.NET. In Migration, we are going to be handing off a lot of functions to other classes for current and future processing.
More information on delegates...

Threading

During Migration game play, the game will determine when to fire off delegates. (i.e., when they will execute). Migration uses threads to accomplish this. Each time through the cycle (i.e., loop) the game determines -using a threshold, if a particular delegate should fire off now or later on. Once the threshold is met during the cycle, a thread will be created and the game continues. Also, note that this new thread may fire other threads, so on, and so forth.

Some delegates need to fire Asynchronously and some Synchronously. What's the difference, you ask? When you send an email, you usually don't expect an immediate answer, but continue doing something else. That's like an asynchronous operation. In a day or two, you will hopefully receive a reply, if it's important, you check your mailbox regularly, possibly sending yourself a reminder to check your box. On the other hand, when you click on a link on a web page, you wait for a response. That's what a synchronous operation is.
More information on threading...

Examples

Example of delegates and threading:

VB.NET
' Use of a Main thread to kickstart things off
' Run this thread in the background (i.e. Asynchronously)
'On the fly, anonymous Delegate ("Sub") used to call InitializeProgram
Dim thread As New System.Threading.Thread(Sub() InitializeProgram())
thread.IsBackground = True
thread.Start()
thread.Join()

Initialization

Once this Main thread is started, it doesn't stop until it's 'told' to stop somehow (i.e., System Exceptions, shut downs, game stop, etc.). Remember that this thread is running on a background thread so it will run and also allow other systems to continue chugging along.

This method further begins the process of kick starting new threads which also get monitored until they also are 'told' to stop.

VB
' Once this Main thread is started it does not stop until its 'told' to stop somehow
Private Shared Sub InitializeProgram()
    Game.Setup.Initialize()
    Game.Setup.Renderer.WaitForTermination()
End Sub
        
...
        
Public Sub WaitForTermination()
    Do While Not IsTerminated
        Thread.Sleep(500)
    Loop
End Sub

...

Class Setup
...
    Public Shared Sub Initialize()

        ' setup renderer
        Renderer = New Renderer(Language.Configuration)

        AddHandler Renderer.OnRenderSprites, AddressOf Render_RenderSprites
        AddHandler Renderer.OnMouseMove, AddressOf Render_MouseMove
        AddHandler Renderer.OnMouseDown, AddressOf Render_MouseDown
        AddHandler Renderer.OnMouseUp, AddressOf Render_MouseUp
        AddHandler Renderer.OnKeyDown, AddressOf Renderer_OnKeyDown
        AddHandler Renderer.OnKeyRepeat, AddressOf Renderer_OnKeyRepeat

        Dim mPath As String = [Global].GetResourcePath("Animations")
        AnimationLibrary.OpenFromDirectory(mPath)

        InitializeGame()
    End Sub
...
End Class
...
        
Private Shared Sub InitializeGame()
    Map = New Migration.Game.Map(512, 59, New RaceConfiguration() { _
          Loader.Open([Global].GetResourcePath("Configuration\Roman.Buildings.xml")) })

    Renderer.AttachTerrain(Map.Terrain)

    m_GUILoaderTimer = New Timer_
             (AddressOf OnTimerCallback, Nothing, 1000, 1000) ' <---- Another thread
    ...
End Sub

Game Loop

Every game consists of a sequence of getting user input, updating the game state, handling AI, playing music, sound effects, and rendering the game. This sequence is handled primarily through the main game loop of Migration called the SimulationLoop(). This game loop is the heartbeat of the game. This is the loop where most updates and events occur. This is also where the game gets saved to disk.

VB
Private Sub SimulationLoop()
    Try
        Dim watch As New Stopwatch()
        Dim lastElapsed As Long = 0
        Dim elapsedShift As Long = 0
        Dim cycleMillis As Long = 0

        If System.IO.File.Exists("GameLog.s3g") Then


    AddOneCycle()
...
End Sub

Cycle Managers

Migration utilizes 'cycle managers' to handle game resource specific items (i.e., movables manager, buildings manager, etc.). These cycle managers are beyond the scope of this article but maybe covered at a later date. Each cycle manager will process a cycle through its ProcessCycle() method. After processing is done, we can then release resources that have been marked for release or whatever clean up is necessary. These resources will be scheduled for clean-up according to what's in the queue in (FIFO) order.

VB
...
        
Friend Sub AddOneCycle()
        If Not IsInitialized Then
            Throw New InvalidOperationException()
        End If

        MovableManager.CurrentCycle += 1

        BuildingManager.ProcessCycle()
        ResourceManager.ProcessCycle()
        MovableManager.ProcessCycle()

        If m_UpdateConfig Then
            m_UpdateConfig = False

            Configuration.Update()
        End If
End Sub

...
 Public Sub Synchronize(ByVal inTask As Procedure)
    MovableManager.QueueWorkItem(inTask)
End Sub

...
Public Sub Synchronize(ByVal inDueTimeMillis As Long, ByVal inTask As Procedure)
    MovableManager.QueueWorkItem(inDueTimeMillis, inTask)
End Sub

Summary

A game loop has more to it than you think. The game loop is the heartbeat of every game, no game can run without it. But unfortunately, for every new game programmer, there aren't any good VB.NET articles on the internet that provide information on this topic. We've reviewed an implementation of using delegates and threading in VB.NET for a strategy game.

Hopefully, this article has inspired some VB.NET coders to go out and start coding that next generation fantastic game.

Copyrights

In addition to all previous copyrights, I also acknowledge the graphic/media contributions of Ubisoft and BlueByte.

History

  • 20th March, 2013: Initial version
  • 26th October, 2022: Article updated

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)