Click here to Skip to main content
Click here to Skip to main content

Migration - Strategy Game

, 20 Mar 2013
Rate this:
Please Sign up or sign in to vote.
A VB.NET implemenation of using delegates and threading for game loops.

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 can not reach their destination fast enough.

Background

Housekeeping

Ultimately, first, and foremost, I need to acknowledge the original author of this codebase, Christoph Husse. The original C# code can be found here[^]. It was originally titled Monostrategy[^] His project was intended to be an OpenSource remake of one of the best multiplayer real time strategy games in the world, "The Settlers". [^].

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 download the Migration Source and unzip you will end up with the following directory layout:

Step 2

Next you need to make sure you Download *Required* Resources and the support files. Unzip the content of both files into your "Build" directory.

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:

Step 4

Ensure that your "Resources" directory looks like below. If not be sure and Download *Required* Resources

How it works - The Big Picture

Delegates

Migration uses several Delegates and Pointers to Delegates to accomplish it's 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 my 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:

' 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 its '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.

' 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.

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 it's 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.

...
        
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.

License

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

Share

About the Author

TL Wallace
Founder Arkitech EBC Corporation
United States United States
Developer, consultant, and trainer that specializes in building data-centric applications designed for small businesses, universities, community & faith based organizations. Started by developing Excel VBA macros in 1989 for businesses and never looked back. Since then I have gone on to author several programs using VB.NET, SQL Server, Microsoft Access, and ASP.net.

Comments and Discussions

 
QuestionGreat 5 / 5 Pinmemberalifaris5-Oct-13 7:12 
AnswerRe: Great 5 / 5 PinmemberTL Wallace7-Oct-13 18:55 
AnswerRe: Great 5 / 5 PinmemberTL Wallace7-Oct-13 18:59 
GeneralRe: Great 5 / 5 Pinmemberalifaris8-Oct-13 6:57 
GeneralMy vote of 5 Pinmemberrspercy6520-Mar-13 12:15 
GeneralRe: My vote of 5 PinmemberTL Wallace20-Mar-13 19:04 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.140821.2 | Last Updated 20 Mar 2013
Article Copyright 2013 by TL Wallace
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid