Learn C Games

Learn C Games

Learn C Games Programming Book coverThis blog is about C and Games programming (in C mainly). It’s written by David Bolton, author of the Learn C Games Programming for beginners EBook. This is the Windows version, with the Linux one due out about in April.  

The first 20 chapters introduce and teach C programming with many examples. This link is to an .mp4 of the asteroids game from the book. It’s about 90 seconds long and demonstrates all of the features of the game. High score table, rotating asteroids (four sizes), sound, explosions, ship hyper-jump and shields.

The remaining 30 chapters builds up to full source code, about 2,000 lines, in 13 stages and I explain how each feature works and is implemented.  All of the book’s source code is on GithubMore about me.

 

Visual Studio Vs Visual Studio Code?

Visual Studio Vs Visual Studio Code?

I wrote the first book on Windows and used Visual Studio Community Edition 2017 (VS). For Linux I’m using Visual Studio Code (VSC) but if you are working on Windows you have the choice. So which is better suited to you?

Disassembly of OutputDebugString program

Given that my full time job involved Visual Studio Professional, it wasn’t a difficult choice for me, though having used VSC on Linux, I’m now warming to it.

I found the configuration messy but if you stick at it you get there It’s a fairly simple product but once you get into all the configuration and extensions, there’s a lot more to it.

VS (now at 2019 version) is an excellent tool and the navigation features and debugging are better than VSC. You can also view disassembly of C code as the screenshot shows.

But if you are also working on Linux or Mac and using VSC, it might be easier or at least more consistent using it for all platforms. Mind you there’s also the question of MSVC vs Clang to sort as well.

VS has extensions but only 3271 currently compared to 16934 for VSC and many of the VS extensions are trial while it appears that all of VSC are free. There’s also nearly ten times as many programming language extensions for VSC (3427) compared to VS (351).

So there’s no outright clear winner here. YMMV as the saying goes. (Your mileage may vary). Here for your delectation is that disassembly including the original C lines. Don’t worry, I won’t publish too many of these!

int main()
{
00E31700  push        ebp  
00E31701  mov         ebp,esp  
00E31703  sub         esp,0CCh  
00E31709  push        ebx  
00E3170A  push        esi  
00E3170B  push        edi  
00E3170C  lea         edi,[ebp-0CCh]  
00E31712  mov         ecx,33h  
00E31717  mov         eax,0CCCCCCCCh  
00E3171C  rep stos    dword ptr es:[edi]  
00E3171E  mov         ecx,offset _1EF31893_ods@c (0E3C00Ch)  
00E31723  call        @__CheckForDebuggerJustMyCode@4 (0E3120Dh)  
    wchar_t * text=L"Hello World!\n";
00E31728  mov         dword ptr [text],offset string L"Hello World!\n" (0E37B30h)  
    OutputDebugString(text);
00E3172F  mov         esi,esp  
00E31731  mov         eax,dword ptr [text]  
00E31734  push        eax  
00E31735  call        dword ptr [__imp__OutputDebugStringW@4 (0E3B000h)]  
00E3173B  cmp         esi,esp  
00E3173D  call        __RTC_CheckEsp (0E31217h)  
}
00E31742  xor         eax,eax  
00E31744  pop         edi  
00E31745  pop         esi  
00E31746  pop         ebx  
00E31747  add         esp,0CCh  
00E3174D  cmp         ebp,esp  
00E3174F  call        __RTC_CheckEsp (0E31217h)  
00E31754  mov         esp,ebp  
00E31756  pop         ebp  
00E31757  ret  
Logging on Windows – OutputDebugString

Logging on Windows – OutputDebugString

Shows OutputDebugString being calld in the debuggerIn the post about rsyslog three days ago, I explained how to log from Linux programs using the rsyslog daemon.

It’s slightly different in Windows. There’s a built in function called OutputDebugString(LPCWSTR str) that you can call from anywhere in your program. It dumps the string str into the Output window if you are debugging it in Visual Studio.

If you are running this outside of a debugger, the output is lost unless you can capture it with a suitable utility. DebugView from SysInternals.com (it redirects to Microsoft) is one such utility. That’s a screenshot of it below.

Showing DebugView in actionJust run DebugView and leave it there. It might catch other stuff from Windows, but when you run your program from the command line or double click on it, it will execute quickly and you’ll see any strings captured like this one.

 

This is the program that I ran. In Release it compiles to a 9 KB exe! Because OutPutDebugString needs a LPCWSTR  (Long Pointer to a WideString), I declared the text as wchar_t.

#include <Windows.h>

int main()
{
    wchar_t * text=L"Hello World!\n";
    OutputDebugString(text);
}

At work I developed a very large program that only worked running on another computer. I used OutputDebugString extensively and without it, debugging would have been much harder.

Comparing MSVC vs Clang

Comparing MSVC vs Clang

Listing of some C codeI originally created Asteroids for Windows using Visual Studio 2017 Community Edition. Since then I’ve started the Clang version on Ubuntu and there haven’t been too many differences but there are just a few so in this post I’ll list what I’ve found so far.

Include Paths

On Windows, I was able to get away with #include <SDL.h> but on Linux, I’ve had to include the path so it’s #include <SDL2/SDL.h>. This was probably because I included the full path in the MSVC configuration.

Link Failures

The asteroids.c code in chapter 29 uses sin and cos for the first time and the linker was unhappy with that. So in tasks.json, I’ve explicitly had to add it into args, along with SDL2 and SDL2_image,

            "args": [
                "-g",
                "${file}","${workspaceFolder}/Asteroids/hr_time.c",
                "-o",
                "${fileDirname}/asteroids",                
                "-lSDL2",
                "-lSDL2_image",
                "-lm"
            ],

That “-lm” does that for maths.

Safe functions

Microsoft has its own set of safe functions many with an _s and extra length parameter.

On Linux, there don’t seem to be so many.

So sprintf_s on Windows becomes snprintf.

fopen_s just becomes standard fopen

linux/time.h

As well as time.h in the includes, I needed to add linux/time.h as well.

SSSnakes – a game for the next Ebook

SSSnakes – a game for the next Ebook

Screenshot of snake gameI’ve done a snake game in the past for About. That’s the picture and today I’ve uploaded it complete with source to Github. The thing with snake is, everyone knows it, its old hat and not particularly exciting.

Back in the early 80s the same was true about Breakout games. It was a common trope for game programming, bouncing a ball off a bat to break through a wall.

But then in 1987 along came the Arkanoid game which could be best described as Breakout re-imagined.  More balls, special bricks when when hit gave different features. It made Breakout games cool again for a few years.

So Ssnakes, is my name for a re-imagined snake game.  We’ll throw away losing your life when the snake hits a wall or itself. Only if your snake runs out of space is it dead, or if it is killed by an enemy. And as it travels around it picks up food which gives it energy. You can burn this energy is making it longer, moving faster or .. spawn off a new snake! Also you can attack enemy snakes – spitting venom directly ahead or sinking fangs into an enemy body if  your snake’s head is next to it.

Having 2, 3 or 4 snakes on the go will make it a bit more stressful to control. You only lose a life when you only have one snake left in play and you lose it.

Plus instead of a plain empty arena there will be a few static objects in it.

 

Using rsyslog to log

Using rsyslog to log

logging
Image by OpenClipart-Vectors from Pixabay

I’m a great fan of logging; it helps you find out what’s happening in a program even if you can’t debug it. Linux, well Ubuntu has a service (sorry Daemon!)  called rsyslog that logs messages from all sorts of processes and it’s quite easy to use in our programs as well.

If we don’t do the next steps all the log messages will go into a file called syslog in /var/log and as this gets a lot of stuff it can grow reasonably quickly. But if you do the following steps, all logged output will instead go into

/var/log/asteroids.log.

From a terminal type the following command:

sudo gedit /etc/rsyslog.d/30-debugging.conf

Type this in and then save it (click the Save button) and close gedit.

if $programname == 'asteroids' then /var/log/asteroids.log
& ~

Now run this command:

sudo service rsyslog restart

It should return immediately and means that any logging to syslog from a program called asteroids will from now on be redirected to /var/log/asteroids.log.

Using rsyslog in a C program

Here’s a short C Program that puts a message in the asteroids file.

#include <syslog.h>
#include <stdio.h>

int main() {
    openlog("asteroids",LOG_CONS | LOG_PID | LOG_NDELAY, LOG_USER);    
    syslog(LOG_INFO,"Test Message %d",1);
    closelog();
}

In a typical program you’d put the openlog statement in main() near the start and the closelog() near the end of main, and uses as many syslog() calls throughout your program as you need.

Now what I suggest you do is open another terminal and run this command before you run your main program. This will just sit there printing out each message line as it appears in asteroids.log. You can stop tail by hitting ctrl-c.

tail -f /var/log/asteroids.log

H/T to this StackExchange answer from almost 8 years ago and answer by giuspen.

Problems debugging SDL2 with Visual Studio Code

Problems debugging SDL2 with Visual Studio Code

500 numbers blitted to screen by SDL2So my demo program runs fine when I run it from the terminal. It creates a SDL Window and blits lots of numbers, but if I try to start it in the debugger, it gets to this function and fails in the SDL_CreateWindowAndRenderer.

void InitSetup() {
	srand((int)time(NULL));
	SDL_Init(SDL_INIT_EVERYTHING);
	SDL_CreateWindowAndRenderer(WIDTH, HEIGHT, SDL_WINDOW_SHOWN, &screen, &renderer);
	if (!screen) {
		LogError("InitSetup failed to create window");
	}
	SetCaption("Example Two");
	LoadTextures();
}

And in the Debug Console I can see two of these:

@”error: XDG_RUNTIME_DIR not set in the environment.\r\n”

followed by my error message InitSetup failed to create window.

I’ve looked online and there’s one or two mentions. Now possibly it might be because I’m running Ubuntu 18.04 LTS under Hyper-V Manager.  I’ll try this on a laptop where I’ve installed the same version of Ubuntu on and see if the same thing happens.

 

Linux E-book Progress

Linux E-book Progress

Screenshot of the chapter 28 executableMy Linux rewrite continues with progress as far as chapter 38.

This is the first Linux version of asteroids on the left and is a demo of the text writing routines and also loading images from files.

It;s drawing all digits from 0 to 99 at random locations on the screen every frame.

The number at the top is how long it takes to output the text. That value if you can’t read it is 0.000622, which means it takes 622 microseconds to output 100 numbers or 6.22 micro-seconds each.

This is the routine that does that.

void RenderEveryThing() {
	int atX, atY;

	renderTexture(textures[PLBACKDROP], 0, 0);
	startTimer(&s);
	for (int i=0;i<100;i++) {
		atX = Random(WIDTH-50) + 1;
		atY = Random(HEIGHT) + 20;
		TextAt(atX, atY, SDL_ltoa(i,buffer,10));
	}	
	stopTimer(&s);
	SDL_RenderPresent(renderer);
	frameCount++;
	UpdateCaption();
}

The most recent uploaded code version (chapter 37) lets you move the player’s ship around (press q, w or ctrl) , fire bullets (space bar), press a to see random asteroids rotating and moving round (and off) the screen. Press the b key to blow up a few asteroids with explosions and sounds. Enjoy!

Zipped up source code, graphics etc from the forthcoming Linux book can be downloaded from Github.

A tale of two diffs

A tale of two diffs

Screenshot of devart code compareI’ve used diff and merge tools since the year dot. They let you compare two files and see on what lines they differ. You can also copy individual or blocks of lines from one to the other; that’s the merge. My all-time favourite was the commercial Araxis Merge which did a three way comparison and could be controlled by COM. I did this to compare two code bases.

Ten years earlier code for Base Metals (commodities trading) had been forked from Oil Trading software. There were ten years of changes to both sets of code and my job was to merge them back into one code base. I wrote a program to walk Araxis Merge through all folders of both code sets and out-put the differences, Then I could start merging where they differed. It still took about two months but I couldn’t have done it as quick without Araxis.

However most of us don’t have access to Enterprise tools, so here are two alternatives. The first is Devart’s Code Compare (that’s the image above) and the second is a free Extension for Visual Studio Code called Diff & Merge. I’ve added both to the Links to C utilities page.

Some useful tips for Visual Studio Code

Some useful tips for Visual Studio Code

The more I use Visual Studio Code, the more I like it and it is definitely one of the slickest pieces of software running on Linux. But I’ve found a few minor problem that are easily fixed so before I forget the fixes, here they are:

UTF-16 Instead of UTF-8

You copy a file in from somewhere but when you try to compile it you get: fatal error: UTF-16 (LE) byte order mark detected in ‘/home/david/Projects/Asteroids/asteroids.c’, but encoding is not supported.

Fixing this is quite easy; you just need to change the file type from UTF-16 to UTF-8. Visual Studio Code shows the file details at the bottom:

File details for Visual Studio code

Here you can see it’s UTF-16 LE. Click on UTF-16 and you’ll get a popup menu. Click Save with Encoding and you’ll get a list of Encodings. Just pick UTF-8 and the problem is solved.

Changing the type of a Visual Studio Code file

You want to save or copy the C/C++ JSON files

But you can only do it by copying and pasting when its in the editor. The problem is they are in a hidden folder under the main folder. Visual Studio Code’s C/C++ extension uses these to hold build, debug etc. configuration details. It’s handy saving them out with source files but a bit slow doing it individually via the editor.

Visual Studio Code uses the main folder (I call mine Projects) and the four JSON files are in ~/Projects/.vscode

On Linux any folder that starts with a . is hidden.

If you use File Explorer, you can tell it to show hidden folders and files by clicking the top button (highlighted) then ticking the Show Hidden Files box. The three folders that were hidden including .vscode are now visible and you can browse, view, copy files etc.

Showing the hidden Files setting

New page added to Website

New page added to Website

Word Cloud
Made with WordArt

I thought it about time to add a list of curated C utilities such as compilers, IDES etc. So you’ll see that bar under the title now includes Links To C Utilities.

One of the included links is to Cheerp which is a C/C++ compiler that can output WebAssembly. One of my goals is to add a WebAssembly chapter to my first EBook, after the 2nd one on Linux is done.  I want to play my asteroids game in the browser.

I have used EmScriptem to do this but I’d like to see what other tools are available.