2021-04-05 - Game Programing Vol 1.

Introduction

First, when learning how to make a game, remember that you want to start with small projects, and work up. Think about how that game flows in a specific way, how the cards interact, and try to think about your first game idea in a similar way. A lot of people first make a simple card game like War or something. I think its a good idea to make text based games before anything else because that way you can get a basic understanding of things like game flow. Then, you want to select a programming language. Most programming languages will allow you to do a simple text based game pretty easily, so you can start from practically any language. However, some are easier to get running than others.

Most commonly, people start development with games in languages like Python, C#, C++ or sometimes Java (although that is falling out of favor and I wouldn’t recommend it). With all of these languages, you will have to construct certain aspects of the application that handle the flow of the application. There are also many game engines, but its important to look into the license terms. They range from things like Unity, which has a completely prefabbed physics engine and has a lot of plugin and asset support, to UE4, which is very professional looking but expensive, there is Game Maker which has a nice advantage of being royalty free with its game releases. There are also simpler engines that provide the assets you need for game development but not its own ide, like Monogame or Pygame. Some game engines have specialized uses like Renpy (for visual novels) or Pico-8 (limited engine with 8-bit graphics).

If you are unfamiliar with programming, I recommend searching for one of these languages and running a “Hello World” program. There are many tutorials online. Once you feel comfortable with this, I can introduce some beginner game design aspects. Also, try reading about variables, datatypes, conditions, loops and functions and make yourself familiar with these concepts before continuing this tutorial.

Functional Text Based Game

This tutorial uses C# but I haven’t tested it to compile so please assume it’s pseudocode.

Making a text based game can be as simple as making a bunch of if-else statements that interact with a ReadKey or similar command (which reads the next key of input that the player submits), or it can be complex, involving many different worlds, items, stats and procedural generated worlds. To start, we have to think of a game as a kind of program that the player can interact with and desires certain outputs.

Let’s take this extremely simple example:

// If I say y, I win the game. Otherwise, I lose the game.

Console.WriteLine("Press 'y' to win. (This should be easy!)");

string letter = Console.ReadLine();
if(letter == "y"){
	Console.WriteLine("You win!");
} else {
	Console.WriteLine("Try Again!");
}

In this example, there are actually three components:

These components are a part of every game. Why is this important to point out? Well, if we wanted to make a game a bit more complicated, making it out of a bunch of if-else blocks is going to make things VERY confusing. Also, its hard to tell which parts of the program do what. So we can use functions to split this up. We can then call the functions, and it will transfer execution to that function we’re calling. This allows us to split up a program into logical parts, like “output” and “input”.

// This splits the program into 4 functions, "InputMain",
// "OutputMain", "ProcessMain", and "Main."

// Main is where the program calls its function from when you build
// a C# program.

static void Main(string[] args){
	int GameState = 0; // This is the game state.
						// For this example, assume that
						// 0 = running
						// 1 = pass
						// 2 = fail
	
	char InputState = ''; // This char represents the current
							// input for this particular processing
							// cycle.
	
	// While the game state equals 0 ...
	
	while(GameState == 0){
		OutputMain(GameState);
		InputState = InputMain();
		GameState = ProcessMain(InputState);
	}
	
	// we output one last time, after the loop breaks.
	OutputMain(GameState);
}

// input main handles the input state.
public char InputMain(){
	return Console.ReadKey();
}

// process main handles how the input state is processed.
public int ProcessMain(char key){
	if(key == 'y'){
		return 1; // pass!
	} else {
		return 2; // fail!
	}
}

// output main handles the output state.
public void OutputMain(int result){
	// when the result is 1, the game is won
	// if its 2, the game is lost.
	// Otherwise, print the main message.
	if(result == 1){
		Console.WriteLine("You win!");
	} else if (result == 2){
		Console.WriteLine("You lose!");
	} else {
		Console.WriteLine("Press 'y' to win. (This should be easy!)");
	}
}

What we have here are 4 functions - 1 main function and 3 other functions - and 2 variables inside the main function to keep track of the game and input’s state. Functions often can only see variables inside of themselves under normal conditions, so you have to pass values to tell the functions what values to work with. There are important exceptions - but that’s beyond the scope of this simple tutorial. Here, we use InputState to transfer the result from InputMain to ProcessMain. Afterwards, we output the value to ProcessMain and get a result for the game state. If this result is not 0, it will exit, and print the end result of the game. You might notice currently the game state will never be set to ProcessMain, and this reflects the behavior from our original game - but now its much easier to make it into a more complicated game that can keep going after one response.

While this example is much longer, it does make it much easier to see how the input, output and processing work. If I want to make this game a lot more complicated, all I have to do is elaborate on the different parts to add more depth to the game, instead of trying to navigate the difficult trees of ifs and elses. In fact, it can be more efficient to build a program this way because you can call the same function many times instead of repeating code.

This kind of programming style is called “Functional Programming”. It’s when parts of a program work together like pieces of a machine, by outputing one part to another part, and changing the state of information over time.

Object Oriented Text Based Game

Some programming languages support some thing called “Object Orientation”. Instead of seeing things as a machine, it instead labels parts of that machine as “objects”. Instead of designing towards a program changing its internal state over time, it has abstract objects with properties and functions, sometimes called “methods”. In object oriented languages we make Processors that Process things, as shown in this example:

// This splits the program into 4 functions, "InputMain",
// "OutputMain", "ProcessMain", and "Main."

// Main is where the program calls its function from when you build
// a C# program.


public class Program {

	static void Main(string[] args){
		int GameState = 0; // This is the game state.
							// For this example, assume that
							// 0 = running
							// 1 = pass
							// 2 = fail
		
		int InputState = 0; // This int represents the current
								// input for this particular processing
								// cycle.
		// We have to make "instances" of the objects in order
		// to use them. Notice how we can declare them just
		// as processors though. This is because they all
		// inherit a Processor interface.
		
		Processor input = new InputProcessor();
		Processor output = new OutputProcessor();
		Processor process = new ProcessProcessor();
		
		// While the game state equals 0 ...
		
		while(GameState == 0){
			Output.process(GameState); // Notice that we don't have
										// to necessarily put a value
										// in a variable... it just
										// gets discarded.
			InputState = input.process(GameState); // However, we
										// still need to use a variable
										// here because the argument
										// always requires an integer.
			GameState = process.process(InputState); // This produces the final game state.
		}
		
		// we output one last time, after the loop breaks.
		Output.process(GameState);
	}
}

// this is an interface. It represents an abstract processor.
// The Input, Output and processing processors all "process"
// things.

public interface class Processor{
	int process(int input)
}

// This class is the input processor.

public class InputProcessor : Processor
{
	public int process(int input){
		return Console.ReadKey();
	}
}

// This class is the main processor.

public class ProcessProcessor : Processor
{
	public int process(int input){
		char key = (char)input; // this "casts" the int as a char.
								// since ints are bigger than chars.
		if(key == 'y'){
			return 1; // pass!
		} else {
			return 2; // fail!
		}
	}
}

// This class is the output processor.

public class OutputProcessor : Processor
{
	public int process(int input){
		// when the result is 1, the game is won
		// if its 2, the game is lost.
		// Otherwise, print the main message.
		if(input == 1){
			Console.WriteLine("You win!");
		} else if (input == 2){
			Console.WriteLine("You lose!");
		} else {
			Console.WriteLine("Press 'y' to win. (This should be easy!)");
		}
	}
}

As you can see, Object Oriented code can be very long. But many game engines like Unity use Object-Oriented languages in their interfaces, so its important to understand how it works.

Conclusion

While not as exciting as a cool new Pokemon game, text-based games help you understand the basics of a core game engine with basic code. While you can make a game faster using a game engine with a prefabricated interface and physics, being able to build simple text-based games helps give you the skills to help organize those engines into a coherent gameplay structure that engages the player. Remember, the input and the output is where the player meets the machine!

Good luck, and have fun!

[top]

[newer] | [older]