TIL: Learn to Code in C++ by Developing Your First Game (Section 2, Part 1)

Back in early November, I decided to throw some money at a Kickstarter campaign which was created to launch some Unreal Engine training. Mildly silly since I’m now working with Unreal Engine at work. But the thing is, I always like learning new things, and have an interest in learning how to do stuff with UE aside from VFX. The tutorial is designed both to cover UE, and C++.

Unlike a good percentage of the Kickstarter projects I’ve backed, the developer of this content has a good track record for getting stuff delivered, and has so far been releasing the course in segments on Udemy.com as it’s created. Not only am I going to fill up my site with notes on Japanese, but now you’re going to see notes about this course which I’ll be attempting to keep up with as content gets released.

I did Section 1 back in December when it was released (no notes for that, but really, all it was was basic set-up / installation)

Section: 2 – Bulls & Cows Word Game – Your First C++

Lectures 9/10: General

The idea behind this lesson, is to skip the UE4 workflow, and program entirely in the IDE with C++. Since I’m on windows, Visual Studio 2015 is going to be what I use. We’ll be using the Unreal Engine Coding Standard.

Game Design Documents:
– Are created so that we have some sort of plan of action.
– We define the emotional problem that we want the game to solve.
– Concept, Rules, and Requirements
– Architecture
– Document now what we might want to change
– Initial requirements.

A recommended book is Code Complete, by Steve McConnell

This game is a “guess the isogram” game, meaning the words have no repeating letters. The user will have a limited number of guesses. After each guess, the computer will output “bull” if the letter has been guessed right, and “cow” if the letter is right, but not in the right place.

What are the inputs? What format? Outputs? What tasks will we do? Performance limitations? Which assets will we need?
– Plain text instructions for interaction
– Code to help the player make a guess
– Code to check the number of Bulls and Cows in the guess compared to the target word
– Code to keep track of the number of guesses

Possible Future Ideas, but which will not be implemented in the initial game.
– Provide feedback on each key press
– Large dictionary of words
– User selectable difficulty
– Checking to ensure that the guess is in fact an isogram
– Time Limit
– hint system

Lecture 11: Solutions & Projects

In the case of our Visual Studio project, we set it up our Win32 Console application in as simple of a way as we can. This means, it’s an empty project, with no SDL checks. What we need set-up is:
– ~\Unreal\UdemyCPlusPlus > Section_02 <= section / solution - Section_02 > BullCowGame <= project folder - BullCowGame > BullCowGame.vcxproj
– BullCowGame > main.cpp

In the past, I’ve set up version control using Perforce on my pc…. however for the sake of this course, I’m not going to bother with that as I’d like to save disk space.

By Right clicking on the “Solution”, we can add a new item, and tell it to be main.cpp. This automatically adds it to our Source Files. If you use the “File” menu to create, then you have to manually “add existing item” to your solution.

Lecture 12: C++ Function Syntax

Anything we write right now won’t run, since the system doesn’t know what we’re trying to do. If we immediately start without debugging, we will get errors.

We need to write a function.

The syntax of a function in C++ is:


_ ()
{

}

or more vaguely:


int DoubleMe(int number)
{
return number*2;
}

Different types of return types are:
-void (nothing)
-characters/strings
-numbers

The mission for this lecture is to:
-create a return type of int
-function named main
-no parameters
-return 0
-take note that hitting tab will auto-complete for you
-take note that the IDE will provide basic error checking (red dot, if you forget your ๐Ÿ˜‰

Adding this basic function will allow the code to run without error. It doesn’t do anything, but it doesn’t error.

Lecture 13: #include and Namespaces

Until we provide our file with more code, we can’t do much else. We can use a “pre-processor directive” (#) to include pre-built code from a library into our file. In this case, iostream is included so that we have the ability to use input and output. #include , will suddenly open a lot of doors.

We want to output characters, however we can’t because the command we need is wrapped up in a “Namespace”. A namespace is a way of protecting library functions, so that when we import multiple libraries we don’t accidentally end up with multiple functions that have the same name. In this case, we use the “std” or standard namespace to access the member (using ::) cout.

so inside the main(), we can write:
std::cout “Hello World!”;

The problem though, is that cout is an “overloaded operator” and needs some special work as well. we can use << to send the "Hello World!" to the cout.

std::cout << "Hello World!";

This still prints ugliness however when run, because we haven't told the program to move to a new line before it tries to exit. If we want to skip a line, we can add a \n (\ lets the program know that a special character is next).

std::cout << "Hello World!\n";

Though it's cleaner to put it on a separate line:


std::cout << "Hello World!"; std::cout << "\n";

or even better, we can use the std:: to end the line (endl)


std::cout << "Hello World!"; std::cout << std::endl;

OOOOOrrr.... even like this:


std::cout << "Hello World!" << std::endl;

Rather than always have to type out the std::, we can simplify by specifying that we are using the name space. But the disadvantage is that if a function name appears within multiple namespaces that we are "using", you'll no longer be able to specify which you're using.

so:

using namespace std;

allows us to remove the std:: from our code.

Lecture 14: Magic Numbers and Constants

Magic numbers, are when we take a number that "works" and hard code it into our file. Ideally, there should be as few of these as possible so that the numbers can be easily changed, and understood as to where they came from. This means parameterizing or using constant expressions.

In this case, we can use a constant expression (constexpr) which will provide us with a value of x. Constant Expressions get compiled, and become available for use, and cannot be changed.

constexpr WORD_LENGTH= 5;

This doesn't work by itself, as we need to specify what the type is of our constant. Instead declare it:

constexpr int WORD_LENGTH= 5;

We're using all upper case simply because it's common practice and makes it easy to find where you use the variables.

This way, we get something like:

CplusplusUE4

It works, thanks to cout automatically interpreting our int as a string.

Lecture 15: Variables and cin for Input

\n doesn't flush the output buffer! This is a performance thing, which means that multiple lines of text will consume extra memory since it doesn't get a chance to clear before moving to the next line. We live in an era where it's not that big of a deal to use \n, and Ben's stance is that if he has quotation marks open, he'll use \n, and if he doesn't, then he'll use endl;

I'm going to stick with endl;

pseudo code: is a way to let you abstract your thinking, and describe what you want to do before you set out to do it. It can also be used for commenting.

-"//" is used for commenting.
-"cin >>" is used to acquire input

Generally you want cin to write to a variable. constexpr is no good for variables. In this case, we want a string and so declare one called "Guess.

string Guess = "";

We also need to include the string library in order to process strings using "cin >>"

so now we have


#include ;
string Guess = "";

and

cin >> Guess;

included through our main.cpp. And of course, you can add the necessary elements to be able to ask for the guess, and print back what was guessed. The problem that we'll have now, is that it bugs out on us if we attempt to enter a guess that contains a space. We need a better solution.

Lecture 16: Using getline()

getline() is useful because:
- it reads spaces
- it discards the input stream once it reaches the next line
- (yikes the technical documentation is not light reading! be sure to scroll down to see Example code)

So we want to use it rather than cin, particularly to allow users to enter anything they want.

Usage is:


// extract to string
#include
#include

int main ()
{
std::string name;

std::cout << "Please, enter your full name: "; std::getline (std::cin,name); std::cout << "Hello, " << name << "!\n"; return 0; }

Lecture 17: Simplifying with Functions

Copying and pasting is bad. If we have procedures that get repeated often, it's better to create your own function.
You must always "return" at the end of a function.

Abstraction and encapsulation
- a goal is to manage complexity
- allow things to be easy for future self
- abstraction can help us to make code self documenting
- encapsulation ensures that the abstractions are adhered to

in this case, we can package up procedures into functions such as the introduction, or the guess.

function

This will let us call the function whenever we need (though in this case, it will likely only be once). Because WORD_LENGTH is described inside the function, we will only have access to it from within the function. This ensures that our "scope" is nice and narrow.

The same way that we'll often declare a variable at the top, and then do lots of stuff, and then set the variable later... we might want to do the same with functions. By declaring them all at the start of the file, we can make it easy to see what's happening. Then follows the main program, then after it comes the actual description of the function. This helps for human readability.

so:


#include includes

using namespace namespace;

void CustomFunction();

int main(){
program...
return;
}

void CustomFunction(){
program...
return;
}

The way our file is currently set-up, if we try to put everything inside a GetGuess() function... it isn't really named properly because it will both get and print. You can easily rename functions by clicking on it, and then pressing ctrl+r TWO times.

Now when we want to run GetGuessAndPrint(); we can copy and paste as many times as we need it. Except that's bad.

Lecture 18: Iterating with For and While Loops

For loops / While Loops
- when you know what you're in "for" (you know at compile time how many times it will loop) use a for loop
- if you may be looping for a "while" (you don't know how many times you need it to loop) use a while loop

For Syntax: can be further explained at cplusplus.com and at microsoft
for (initialization; condition; increase)

for (int count = 1; count <= limit; count++) { code }

One thing to be aware of, is that the IDE doesn't really do live update for error fixes. If you make a fix, you'll need to recompile for it to fully understand what's been repaired. In my case, I'd typed "for (int guesses = 0; count < TOTAL_NUM_GUESSES; count++)" which supplied a bunch of errors because obviously it doesn't make sense to use "count". When I fixed it however, I was still trying to troubleshoot for a bit because the errors hadn't all gone away. Recompiling let it work without error.

Lecture 19: Introducing Classes

string is a "type", or a "primitive type", or a "class.
a class packages together functions or variables together and is a form of abstraction.

classes will be prefaced with an f, due to the UE4 style guide.

Whew! Time to get some sleep!

1 thought on “TIL: Learn to Code in C++ by Developing Your First Game (Section 2, Part 1)”

Comments are closed.