Category: SDL

Update to the Windows eBook

Update to the Windows eBook

Visual Studio configurationA reader asked me how to setup SDL2 for Windows given recent changes in SDL2. Specifically the files and libsdl projects have been moved from the libsdl.org website to GitHub. You can easily find SDL2 Image, Mixer, TTF etc.

However it can still be quite daunting setting up Visual Studio for SDL2. You have to download the specific files, then configure the project properties to specify the include paths for header files and then the lib files, both the path to them and identify the ones you want to use.

As I’m on my new PC, I bit the bullet and went through the process of setting it up. It took just over an hour to configure it.  I’ve put it into a PDF that’s a couple of pages long.

So the game works but only after I disabled the sound code; it was failing in the call to Mix_OpenAudio(). I think recent work on the SDL Mixer needs some work on my part. I need to sit down and look at the SDL Mixer page and figure out what’s failing. Once that’s done, I’ll update the files.

 

New Tutorial on getting started with SDL

New Tutorial on getting started with SDL

SDL REctanglesI had this tutorial pencilled in to do and it’s now done. It’s the old SDL rectangles program that was part of the eBook. I’ve modernised it a bit so the same file will now compile under either MSVC on Windows or VS Code/Clang on Linux without changes.

I used the _WIN32 predefined macro so it compiles the call to Windows cod on Windows. Here’s an example:

#ifdef _WIN32
		sprintf_s(buff, sizeof(buff), "%10.6f", getElapsedTime(&s));
#else
		snprintf(buff, sizeof(buff),"%10.6f",diff(&s));
#endif

I do a similar thing with the path to SDL which is “SDL.h” on Windows but “SDL2/SDL.h” on Ubuntu. Writing code this way makes it  lot less of a hassle.

The game of 2048 in C in your browser

The game of 2048 in C in your browser

2048 game playing in a browserBack in 2014, an Italian developer called Gabriele Cirulli devised a puzzle game called 2048. It has been implemented on many platforms (I have it on my iPhone) and here is a link to a C version of it (in 300 lines) by developer Nishchith Shetty that plays it in a browser using WebAssembly.

The idea behind the puzzle is that you combine the numbered pieces by moving pieces intro same numbered pieces. 2 into 3, 4 into 4 and so on.

WebAssembly is the technology that lets you run programs in many languages (including C and C++) in your browser at speeds up to 50% of native code.  It’s also used in Blazor where you can write C# programs that run in the browser.

To convert the C code to WebAssembly, you have to install a transpiler (a program that converts one programming language to another) called Emscripten, then it’s a single command line instruction to build the WebAssembly from the C sources and SDL2. Or you can just play it online here.

I’ve been meaning to do a WebAssembly version of my asteroids game using Emscripten. it’s just been sheer laziness that I haven’t got round to it.

 

A mini-project- SDL toolkit

A mini-project- SDL toolkit

Coloured Rectangles
Image by Gerd Altmann from Pixabay

I’ve thought about doing this for a while. Build a small toolkit (a library) of helper routines for any program that uses the SDL2 library. That means it will have functions to do the following:

  1. Draw horizontal and vertical lines in a specified colour.
  2. Draw coloured rectangles both filled in and empty.
  3. Draw Circles of specified radius and colour.
  4. Draw hexagons in either orientation and of a specified size, hollow or filled.

Plus any other things that occur to me. I’ll start on this shortly.

Tronus Project 1945 – Coursework

Tronus Project 1945 – Coursework

Project 1945A university student by the pen name of Tronus has put a project from his 3rd year in his degree course on GitHub. The screenshot shows the game running on my PC. The build folder includes a release folder with game exe plus all dlls and game assets in a resources folder below that so you can run it immediately on Windows. ,

I vaguely remember playing a similar game (a vertical scroller) in arcades back in the 1980s. That game was 1942.

The 1945 game has been programmed in C and uses SDL2. As always I took a walk through the source just to compare how it was done say compared to my own efforts. One thing I noticed is that he uses a fixed delay of 11 milliseconds each frame in the game loop by calling SDL_delay(11) rather than setting up the video to sync to the fly back. Is this better or worse? I’m not sure.

I think I prefer my method in case something takes a bit longer. Having a fixed delay means that you could risk overrunning the 16.666 milliseconds allowed per frame. That could never happen with my asteroids game as syncing to the fly back means my game can take as long as 16.66 milliseconds per frame and still not overrun.

 

 

New tutorial on installing SDL on Linux

New tutorial on installing SDL on Linux

SDl Demo programWell you might say, “Don’t many Linux distros have SDL installed so people can play games?” and the answer is yes but not the development files and headers, and that’s what this shows you how to do along with a simple program to test that you can compile and run.

You’ll also need clang or gcc installed but as you can do that with a simple sudo apt install clang, it’s hardly worth a tutorial on its own.

However you also need to install VS Code and the C/C++ extension. Go to the VS Code website, download the Linux x64 version and double click on it to install it. After that from a terminal type code and it’ll appear. You then need to select extensions (5th icon down the left hand side) and pick the Microsoft C/C++ extension and install it.

I’ve added a new tutorial on the Tutorials page How to Install SDL on Linux. That includes a link to a demo file (its just above the screenshot) containing all three source code files and four VS Code configuration files for VS Code.

This program is almost identical to the asteroids_ch25 file (it draws lots of random size and colour rectangles on screen) but has been upgraded for Clang 10 and also what looks like a bug with search paths. There’s an extra line in Tasks.json to include the path to the SDL2 header files or you’ll get a can’t find a particular SDL header error when you compile.

Building code with VS Code is easy to understand once you “get” how the Folder works. I always keep the .vscode folder in there with the four C/C++ JSON configuration files and all source for that whatever it is you are compiling.  In the screenshot below (from WinSCP), you can see the path is /home/david/Projects/Examples and it contains the .vscode folder the three source files and demo which is the compiled code.  In VS Code I opened Examples as the Folder.

VS Code Folder

 

The .vscode folder is greyed out because the . means it’s normally hidden.

How to move a SDL project from Windows to Linux

How to move a SDL project from Windows to Linux

SDL Logo
The SDL Logo is from libsdl.org

It’s not actually that hard to do, there’s just a few things that are different between C and Linux, specifically between MSVC and GCC /Clang.. I did this when I wrote the Asteroids game in the book.

Originally I developed it on Windows then moved it to Linux (Ubuntu) and then I added the bits to have it work on a Raspberry Pi. It worked on the Pi more or less as is on Ubuntu but I added support for game pad, detecting that it was on a Pi and displaying the temperature.

Here’s what I’ve found is different between MSVC and GCC/Clang.

  1. The safe string functions. MSVC has the _s functions so instead of strcpy, there’s strcpy_s on MSVC. This doesn’t exists in GCC/Clang but there are similar functions with an n in the middle e.g. strncpy. In future I’ll create a macro for each function that uses the appropriate type so the compiler will pick the correct type.   However it seems even strncpy may not be all that safe. If there is no \0 in the n characters then the copied string won’t have a terminating \0 and thus could still blow up.  This article says that in order of safety it goes like this with strcpy least safe and strlcpy the most.
    strcpy < strncpy < snprintf < strlcpy

    so maybe I should be using strlcpy instead.

  2. The include path for SDL in GCC/Clang is “SDL\SDL.h” not “SDL.h” as it is in MSVC. Again this could be fixed with a macro prefix for the SDL path so all #include works correctly on either system.

3.  I found that the file type was wrong. This wasn’t just a matter of CR/LF versus LF which you get between Windows and Linux (CR = Carriage return, LF = Line feed). Somehow the Windows file had a different UTF encoding type to what GCC/Clang expected and the compiler did not like it. However Visual Studio Code shows you what encoding it is (on the bottom of the edit window) and lets you change it, so no harm done. You may need to do this once on each file you’ve moved from Windows to Linux.

4. I found that the time header file in Linux needed a bit of work to make it compile. The standard for this dictates that differences aren’t done to the header file but by adding in additional headers.

So I’ll look into strlcpy.

 

 

 

How to install SDL2 in Visual Studio

How to install SDL2 in Visual Studio

Visual Studio IDEThis is the first of a number of longer-piece game related tutorials. You’ll see I’ve added a tutorials link to the top menu. That page will grow as I add tutorials, as each is added to it .

You’ll see I use the terms SDL and SDL2 mostly interchangeably. SDL is the name of the library but we don’t want the older SDL1 instead we want SDL2 which seems more or less permanently at version 2.0.12.

I’ve left the Visual Studio version off as the process is mostly the same whether it’s Visual Studio 2017, 2019 or future versions. Screenshots are from Visual Studio 2019.

You don’t have to do this on Linux as it takes three or four sudo apt installs to add the various SDL2 dev modules in, but with Windows you need to configure Visual Studio and it can be a somewhat confusing process if you are new to Visual Studio.

Also you need to download and fetch the various files. This is made slightly more complicated because there are 32-bit and 64-bit versions and you want to keep them both so you can switch between the two.

Here are the various steps we have to go through.

  1. Download the various files and unzip them
  2. Setup include and lib paths in Visual Studio
  3. Add the lib files into Visual Studio.
  4. Copy the dlls into the folder where the game will run.
  5. Compile and run it.

What you are downloading are basically three types of files.

  1. Header files., This is files like sdl.h.  Your program will #include these.
  2. Lib files. This is the bulk of the SDL code.
  3. Dll files (Dynamic Link Liobraries). Needed for runtime.

Download the various files and unzip them

The SDL website is libsdl.org and if you click the SDL Releases in the bottom right it will take you to the SDL downloads page. WE don’t need the source code (you are welcome to download it and take a look but it’s not needed to use SDL2.

We do however need the development libraries. These include the runtime binaries so we don’t need to download those. as well. Just the one file SDL2-devel-2.0.12-VC.zip

I suggest you create a folder SDL or SDL2 on your drive. My C: drive is for Windows so I use d: \SDL2

If you unzip the files into there you’ll end up with three folders and five .txt files. Just under 7 MB in total. Other than docs there are include and lib.  The lib folder is further split into x64 (64-bit) and x86 (32-bit) . It also includes the runtime dlls. These will have to be in the path for your program but we’ll leave that until later.

Sounds, Images and Truetype fonts

As well as these, you are probably going to want image file support, sounds and possibly truetype font support in your program. These are separate files in the SDL projects folder.

  1. Image file support. Download the development library file from the sdl_image page. As before you want development library file. SDL2_image-devel-2.0.5-VC.zip.
  2. Sounds file support. Download the development library from the sdl mixer page. It’s SDL2_mixer-devel-2.0.4-VC.zip.
  3. ttf file support. Once again a development library downloaded from the SDL_ttf project page. It’s SDL2_ttf-devel-2.0.15-VC.zip.

All three files have similar structure to the SDL2 dev library.  Unzip the include files into the SDL include folder and the lib files into the relevant X86 and X64 lib sub-folders. So all your SDL files that you need are in the same include and lib sub-folders.

I suggest you extract the file folders one by one, do the three include files first then the x64 files and then the x86. Do not get x86 and x64 mixed up. The only way to tell them apart is by size and it’s not always an accurate way.  Don’t worry if it complains about overwriting zlib1.dll. There’s a copy in both the images and sounds zip files.

Setup include and lib paths in Visual Studio

This can be a bit complicated, just follow these instructions exactly.

To configure a C/C++ project in Visual Studio, you have to specify where the compiler gets its include files, where it finds its lib files and which lib files you want to link to.

Solution ExplorerI’ve created a blank C++ project called sdltest in VS 2019.  Now I actually want it to be a C project so just rename the main file sdltest.cpp to sdltest.c. You need to delete all of the C++ code in that file as well.  After renaming the Solution Explorer should look something like this. We will have a sdltest program to run later so just save this for now. You can get the file from GitHub and overwrite sdltest.c.

Now click Project on the top menu then sdltest properties at the foot of the menu.  You should see this form (below).  This is how you specify properties for your project in Visual Studio.

You’ll see I have selected VC++ Directories on the left. This is where you specify some of the directories (folders and directories mean the same thing BTW) .

But the Platforms pull down probably shows Win32 on yours. Change it to All Platforms. Visual Studio lets you specify configurations for all things or for x86 or x64 separately. We’ll use the same include folders for both x86 and x64 but we’ll specify the paths to the lib files individually as the x64 lib files are in the x64 sub-folder and the x86 files in the x86 folder.

Property Pages
To specify the path click on Include Directories, you’ll see a down arrow appear on the right.  Click it and you’ll see <Edit…> appear, click it and a form like this below will popup.
Visual studio folder editClick on the blue area in the form and you’ll be able to paste or type in the path or click the … button to get a file browser appear. Type in, paste or select the folder then press Ok.  You should now see your path in the folders.

Here I typed in d:\SDL\Include. Be careful that you don’t get rid of $(VC_includePath);$(WindowsSDK_IncludePath); in the include path as I did as your program won’t compile!

folder paths

We now have to do the same for the lib paths.  But first we must change the Platform to specify x86 or x64.

If you change it, a popup will appear asking if you want to save your changes. Click the Yes button.

Confusingly the platform choices on mine are Win32 and x64, but Win32 is the same as x86.

You’ll see that the include path you added shows up in the x86/Win32 platforms because we changed it for all platforms.

Now add the path for Library Directories. Click the down arrow then <edit…> and put in the full path to the folder that matches the Platform. x86 for Win32 platform, x64 for x64 platform. After you’ve entered it will show up in the directories.

Visual studio all paths

If you want both x64 and x86 then change the platform and re-enter it. Don’t forget to save!

Add the lib files into Visual Studio

The last configuration to do is specify the lib files that are needed. We’ve specified the paths for include and lib files but the compiler linker doesn’t know what lib files to link.

As linking depends on 32-bit or 64-bit we have to specify this twice as we did for the lib paths. It’s in a different place in the property pages. Click Linker then Input.

Visual Studio Linker Configuration It’s the top line (Additional Dependencies) that we need to work with. Click into it to get the down arrow then click that and the <edit…> as before.

You’ll have noticed that it comes pre-populated with all the various library .lib files.  We’ll be adding some more. The ones we need are

SDl2.lib SDL2_mixer.lib SDL2_ttf.lib SDL2_image.lib and SDL2main.lib

Add these into the edit box one by one and press return after each one.

After you’ve added them and pressed Ok, you’ll see them in a list. Something like this though I’ve not added SDL2_ttf.lib in to it yet.

As before repeat for both x86 and x64.

 

We’re now ready to compile. Only we need a program to do that. I’m not going to list the whole sdltest as it’s 135 lines but you can download the VS project in the file sdltest.zip from GitHub. It should compile with no errors. If you get errors, please recheck the include folders and lib folders and make sure you have configured them correctly.

So it compiles, but it won’t run. If you look in the Debug folder under the x64 (or Win32 if you built that) , you’ll see a whole lot of files. but only sdltest.exe is important. You can delete the rest. Leave sdltest.pdb if you wish to debug.

We have to

Copy the dlls into the folder where the game will run

That folder is this the \sdltest\x64\Debug folder. We need several .dll files from the same lib folder that holds the x64 libs. (Again if you are on Win32 you need dlls from the x86 lib folder).

What files do we need?

Just SDL2.dll. If we were using images we’d also need sdl2_image.dll and zlib1.dll. We don’t currently need the SDL2_mixer.dll or the SDL2_ttf.dll but if you ever use sounds or Truetype then you’ll need those. For sounds you’ll also need some of the lib*.dll files such as libogg-0.dll or libvorbis-0.dll. For image we might need in the future libjpeg-9.dll (if we ever use jpg files).

So you’ve compiled it and should see something like this when you run sdltest.exe. It doesn’t do much except draw coloured rectangles. Press the esc key to close it. On my POC it draws 100,000 coloured rectangles each 120 x 120 pixels in about a second. That’s pretty fast!

The heart of the program is this function:

void DrawRandomRectangle() {
	char buff[20];
	SDL_Rect rect;
	SDL_SetRenderDrawColor(renderer, Random(256) - 1, Random(256) - 1, Random(256) - 1, 255);
	rect.h = 120;// Random(100) + 20;
	rect.w = 120;// Random(100) + 20;
	rect.y = Random(HEIGHT - rect.h - 1);
	rect.x = Random(WIDTH - rect.w - 1);
	SDL_RenderFillRect(renderer, &rect);

	rectCount++;
	if (rectCount % 100000 == 0) {
		SDL_RenderPresent(renderer);
		stopTimer(&s);
		sprintf_s(buff, sizeof(buff), "%10.6f", getElapsedTime(&s));
		SetCaption(buff);
		startTimer(&s);
	}
}

Uncomment the two lines with 120; // Random(100) + 20; to have it draw random sized rectangles. The figure in the caption is how long it takes to draw 100,000 rectangles.

Using small delays in C with SDL ticks

Using small delays in C with SDL ticks

Asteroids game - player ship rotationRunning a game at 60 frames per second means that handling things like key presses can be interesting. In the game, I call various SDL functions and via a giant switch statement set flags. Then later in the game loop, those flags are used to determine actions

So if you press Q to rotate the player ship anti-clockwise (counter-clockwise to yanks!) without some limiting thing, it would whizz round through 900 degrees each second. (There are 24 rotation angles for the ship, each 15 degrees. 60 x 15 = 900) .

I use a very simple technique to limit it. SDL has a function called SDL_GetTicks that returns the number of ticks since SDL was initialized in the game, i.e. when it started running. A tick is 1/1000th of a second, i.e. a millisecond. By calling this function twice, you can measure a time period. It’s not as precise as the nanosecond CPU clock that I use but for the kind of delays I’m talking about it is more than sufficient.

This is the code that is called each frame in the game loop.

void RotatePlayerShip() {
	if (rotateFlag && (SDL_GetTicks() - rotTimer > 40)) {
		rotTimer = SDL_GetTicks();
		if (rotateFlag == 1) // CounterClockwise 
		{
			Player.dir += 23;
			Player.dir %= 24;
		}
		else
			if (rotateFlag == 2) // Clockwise
			{
				Player.dir++;
				Player.dir %= 24;
			}
	}
}

Because the game loop syncs to the vertical fly-back, the time between two successive calls of this would be about 16.666 milliseconds. (=1000/60), but the check to see if 40 ticks have passed slows it down to 25 x 15 = 375 degrees rotation per second, i.e. just over one complete revolution which is more manageable than 900/360 = 2.5 full rotations. Plus if you wish rotation speed to be faster just change the 40 to a lower value.

This measured time delay is used quite a few times in the game. You could use it as a means to make the game get harder by having shorter delays on say aliens moving or firing.

How to Draw a circle in C

How to Draw a circle in C

Asteroids-with shield-round-player-shipIn the asteroids game, when you press the s button to put up a shield, it draws a circle.  I must confess, I didn’t know how to draw a cuircle so looked it up and found an example on StackOverflow. You can use code from StackOverflow, licensed under a MIT license.  I include the link to StackOverflow in the game code (in the chapter 48 zip file) in a comment.

Here’s the code in the game.

void DrawCircle(SDL_Renderer *Renderer, int _x, int _y, int radius)
{
	int x = radius - 1;
	int y = 0;
	int tx = 1;
	int ty = 1;
	int err = tx - (radius << 1); // shifting bits left by 1 effectively
								  // doubles the value. == tx - diameter
	while (x >= y)
	{
		//  Each of the following renders an octant (1/8th) of the circle
		SDL_RenderDrawPoint(Renderer, _x + x, _y - y);
		SDL_RenderDrawPoint(Renderer, _x + x, _y + y);
		SDL_RenderDrawPoint(Renderer, _x - x, _y - y);
		SDL_RenderDrawPoint(Renderer, _x - x, _y + y);
		SDL_RenderDrawPoint(Renderer, _x + y, _y - x);
		SDL_RenderDrawPoint(Renderer, _x + y, _y + x);
		SDL_RenderDrawPoint(Renderer, _x - y, _y - x);
		SDL_RenderDrawPoint(Renderer, _x - y, _y + x);

		if (err <= 0)
		{
			y++;
			err += ty;
			ty += 2;
		}
		else 
		{
			x--;
			tx += 2;
			err += tx - (radius << 1);
		}
	}
}

it’s as simple as that! To make it more interesting, it is called each frame with the shield throbbing  by increasing  the radius from 38 to 46 pixels by 2 then restarting at 38 again. Here’s the code for that. Note that when the shield energy is below 10, it no longer works.

void DisplayShield(SDL_Rect * target) {
	if (shieldFlag && shieldStrength >10) {
		SDL_SetRenderDrawColor(renderer, 0xff, 0xff, 0xff, 0xff);
		DrawCircle(renderer, target->x + (SHIPWIDTH/2), target->y + (SHIPHEIGHT/2), shieldRadius);
		shieldRadius += 2;
		if (shieldRadius == 46) {
			shieldRadius = 38;
		}
	}
	if (shieldStrength < 100) {
		TextAt(target->x + 10, target->y + 58, sltoa(shieldStrength), 0.67f);
	}
}

The number under the player ship is the shield energy which drains while the shield is being displayed and recharges back up to 100 when you take your finger off the shield button. The number is only shown when the value is less than 100.