I am teaching my kids Sean and Thalia how to program in C, so that we can create video games together. They are learning to use some of the same tools that I use myself, namely Debian GNU/Linux, xterm, bash, vim, cc, make, and git.
Here's a summary of what we did to get started, and some of the things we've learned so far.
Setup
- We created a page on github, so we can share our code.
- We created a page on dev.to, so we can write blog posts in the same place. We think it's a good idea to write about what we are doing, and hopefully some people will follow our progress.
- I installed some libraries we will need on our computers:
sudo apt install libsdl2-dev libsdl2-gfx-dev libsdl2-ttf-dev \
libsdl2-image-dev libsdl2-mixer-dev libglew-dev
For each of my kids, I did the following setup:
- Created a github account.
- Added to our github organization.
- Created an RSA ssh key with
ssh-keygen
. - Copied the ssh private and public keys to our other PC.
- Added the ssh public key to the github account. This enables us to push changes to github.
- Created a dev.to account using github to log in.
For each of my kids, on each of our two main PCs:
- Created a user account.
- Logged into Chrome sync.
- Logged into github and dev.to.
- Disabled programmable completion in
~/.bashrc
. I find it annoying when bash won't complete filenames because it's trying to do something clever. - Cloned our two git repositories:
git clone git@github.com:gamedevfromscratch/gamedev.git
git clone git@github.com:gamedevfromscratch/kisskit.git
Basic shell commands
We learned a few basic shell commands:
-
ls
lists files in the current directory. -
cd foo
"changes directory" tofoo
. -
cd
by itself goes back to the home directory. -
tree
shows a tree of files and directories. -
vi file.c
opensfile.c
in the vim editor (see below). - We can stop a job, such as vim, with ctrl-Z.
-
fg
stands for "foreground", it continues the stopped job.
We can use the up and down arrows to look at previous commands, change them if needed, and run them again.
We can also use ctrl-R for a reverse search through the command history, and ctrl-S to search forwards again... but read how to fix ctrl-S first!
Basic editing in vim
- Vim has several editing modes. It starts in "normal mode".
- Before typing a program, press
i
to enter "insert mode". - To save changes, go back to "normal mode" by pressing Esc, then type
:w
for write, and press enter. - Enter
:q
to quit the editor, or:q!
to exit without saving changes. - When we press
:
to enter a command like:w
, vim goes into "command mode".
Copy-paste in vim
- We can select lines using the mouse to select text. Triple-click then drag to select whole lines. Or we can press
v
for "visual mode" or capitalV
for "visual line mode", and select lines with the arrow keys. - Press
y
to "yank" or copy the selected lines. - You can also press
d
to "delete" or cut the selected lines. - Move to above where you want to paste the lines, using the mouse or arrow keys.
- Press
p
to paste the copied lines below. - When we need to move to a different point in the file, it is generally better to use the mouse, not the arrow keys.
Compiling and running a C program
My daughter described some of the first simple programs she wrote in her post, My Simple Programs.
After we have entered a program, and saved it by pressing Esc then :w
, we need to stop the editor and go back to the shell, with ctrl-Z.
Then we compile the program. The simplest command to do this is:
cc -o hello hello.c
This creates an executable called hello
from the source code file hello.c
. If we omit the -o hello
, and just type cc hello.c
, the compiler will name the executable a.out
, which is not very useful.
The compiler will tell us if there are any errors.
If it compiles successfully, we can run our hello program like this:
./hello
We need to write ./hello
not just hello
, because for safety reasons the shell does not normally look for programs to run in the current directory; who knows what sort of dangerous programs might be lurking around, pretending to be ls
or vi
?
The compiler will give us better warnings about things that might be wrong with our program, if we run it like this:
cc -o hello -Wall hello.c
The -Wall
stands for "warnings: all".
After testing our program, we can go back to the stopped editor by entering fg
.
Sometimes we need to "link" with other C libraries. For example, if our program wants to use the sqrt
function to calculate a square root, we need to link with the math library. The option for this is -lm
. This is the full command to compile a program call math.c
and link with the math library:
cc -o math -Wall math.c -lm
Using the compiler is a bit difficult, so I wrote a wrapper script called ccw
for "C compiler with warnings". This runs the compiler with all the options and libraries we might need. For example:
ccw hello
We can also use a program called make
to run the compiler, taking options and commands from a Makefile
. We'll look at how to do this in another post.
Demo program
Before getting my kids to write their own programs, I wrote a quick demo program to show them some basic stuff in C:
- basic "Hello, world"
- string variables, say hello with the person's name
- int variable, math multiplying
- for loop, print several times
- if, print different messages odd and even
- modulo operator
%
for the remainder after division - subroutines: rep, nl
- function: pythagores
- What's the difference between subroutine and a function?
- the kids wrote a subroutine: praise
- REPEAT macro, for a simpler loop
This is the demo program we wrote. It's a bit of a mess, but shows several features of the language:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
void rep(char c, int n)
{
for (int i=0; i<n; i++)
putchar(c);
}
void nl(void)
{
putchar('\n');
}
float pythagores(float x, float y)
{
return sqrt(x*x + y*y);
}
#define REPEAT(n) for (int i=0; i<10; i++)
void praise(int n, char *name)
{
for(int i=0; i<n; i++) {
printf("%s is the best. ", name);
}
nl();
nl();
}
int main(void)
{
char *name1 = "Thalia";
char *name2 = "Sean";
srandom(time(NULL));
int a = random() % 11 + 2;
int b = random() % 11 + 2;
praise(50, "Nika");
praise(30, "Sam");
praise(25, "Sean");
praise(20, "Thalia");
nl();
nl();
for (int i=0; i<10; i++) {
if (i % 2 == 0)
printf("hello %s %d*%d=%d\n", name1, a, b, a*b);
else
printf("hello %s %d\n", name2, i);
}
nl();
nl();
int size = 10;
for (int i=0; i<size; i++) {
rep(' ', size-i);
rep('*', i*2+1);
nl();
}
for (int i=size-2; i>=0; i--) {
rep(' ', size-i);
rep('*', i*2+1);
nl();
}
nl();
nl();
printf("pythagores(30, 40) = %f\n", pythagores(30, 40));
return 0;
}
Next post: kisskit: Simplifying Game Dev in C, by Sam
Previous post: Loops and Math in C, by Sean
Contents: Game Dev From Scratch
Top comments (0)