My next Book – Match three

My next Book – Match three

I’ve been thinking about doing a 3rd book – something like ‘More C Games, design and programming’ which would have three games, each with a design and then implemented with explanations and bits of source code and all on Github.  The first game is possibly going to be a Match Three game.

Match tree gameMatch Three games have been around for the best part of a decade and have a basic mechanic of swapping two adjacent pieces to make a line up of three, four or five pieces which get removed.

What makes it more challenging and interesting is the almost limitless number of mechanisms you can build on. For instance when you clear four or five you get special items that when swapped with another special item do something interesting. Or could be you have to get a set of special items and so on.

Or you might have special levels where you have to clear all of one particular shape within a time or Boss levels where the baddy is continually adding hard to remove pieces that clog up the game, or you might have a rotate button that flips the board 90 degrees so you can get rid of hard to remove pieces by having them drop into special buckets beneath the board.

Now I just have to come up with two more games. Suggestions welcomed!

The mighty Blit

The mighty Blit

Showing an asteroid being targetted by the player's shipWhat makes possible all of the fast graphics in SDL2 is really one instruction.

SDL_RenderCopy – The link goes to the SDL Wiki.

This copies part of a texture into video RAM (aka VRAM). You must specify which texture is to be copied, a rectangle into the source and a rectangle into the destination VRAM.

So what is a Texture? In SDL2, it’s a structure that manages an area of VRAM. At the start of the game, image files are uploaded into Textures, the file bits are copied from disk and stored in an area in VRAM.

Every frame, a background image (another texture) is copied to the screen area. Then all moving objects are rendered into this area by calling SDL_RenderCopy for each object. The entire object (be it player ship, bullet or asteroid) is then rendered onto the screen area at the correct point. This is sometimes called blitting or more accurately bit blitting; blit is shorthand for bit block transfer.

A rectangle is just a struct holding four ints. The first two ints are the x and y positions and last two are width and height.  The player’s ship consists of a graphic 64 pixels high by 16 x 24 (=1,536) pixels wide. That’s 24 images, each rotated by 15 degrees from the previous one. So the source rectangle is always x = rotation (0-23) x 64, y = 0 and both height and width are 64. Remember, the source x,y is relative to the source texture which is 1536 wide by 64 high.

The ship rotations start with 0 facing up, so the ship on screen is at rotation 18 (Facing Left) , so  x = 1152.

To make sure rendering is a smooth process and there is no tearing of the images, the screen VRAM is always off-screen when the objects are rendered into it. Then after all objects have been rendered (a posh word meaning copy!), the display is toggled so that the bank of VRAM that was off-screen is now on-screen i.e. visible and the other bank is now off-screen.

Objects are always rendered into off-screen VRAM and the flipping is done by a call to this SDL routine.

SDL_RenderPresent

When you create the renderer, you can specify whether SDL_RenderPresent is synced to the video card vertical refresh signal. If it is, then the display will only render 60 frames per second. If you don’t sync then you can have frame rates up to several thousand times per second. I once achieved 5,000 fps, because there was very little processing going on.  However your video card probably doesn’t refresh any faster than 60 fps so it’s a bit pointless!

More on function pointers

More on function pointers

A function pointer is a pointer to a function, i.e. it’s a variable (a pointer) but instead of pointing to some data, it is assigned to a function. Most importantly, the compiler checks that the function you are assigning is compatible to that pointer. This is so, as I discussed earlier that when the function is executed, it correctly retrieves any parameters.

Here’s how you create a function pointer. Let’s start with a function that adds 1 to the input value.

int getValue(int x) {
    return n + 1;
};

This passes in x and returns an int. Let’s create a pointer to this function and this is the full program.


#include <stdio.h>

int getValue(int n) {
    return n + 1;
}

typedef int (*getValueFn)(int);

int main()
{
    getValueFn f = &getValue;
    printf( "Value of getValue = %d\n",f(1));
}

It’s as simple as that. The complicated bit is turning the function signature into the typedef. Start with the function name. Put it in brackets and add a * at the start, and make the name different to the function you are assigning. It’s a new type. So getValue becomes (*getValueFn).

Now add on the return type at the start int and the parameters at the end (int n), but throw away the name n, we only need the type and you get int (*getValueFn)(int);

Finally add typedef, cook for 30 microseconds and you’re done! In the line getValueFn f = &getValue;
I’ve declared an instance of the type f and assigned to it the address of getValue. That gets called with a value f(1) and in this case returns 2.

It’s also good practice to check that the instance variable is not null before you call it.

Function pointers in C

Function pointers in C

The one thing worse for beginners than pointers is … function pointers. A normal pointer holds the address of another variable whereas a function pointer holds the address of some code.

But before I delve into the complexities of function pointers, you have to understand a little bit about functions. A function is defined, not just by what it does but the values you pass in and get back from it. Here are a couple of examples.

int add(int b,int c) {
  return a + b;
}

void DoSomething(int value) {
  //
}

The code generated by the compiler has to pass in the parameters and usually does it by pushing values on the stack or in registers. In the code for the function, the first thing it does it fetch the parameters. So when you use a function pointer, according to the definition of that function pointer, the compiler will generate code in the function to extract parameters.

I’ll look at the syntax of function pointers tomorrow; it’s always the complicated bit, probably the most complicated bit but it dos give your program a bit more flexibility.

I’m now using the Prismatic plugin. Much nicer listing with indentations!

Using recursive fill to count maps

Using recursive fill to count maps

Terrain hexagonsIn the Empire game (yes, just one last mention!) during the map generation the program counts up the size of individual islands and sea areas. This is don by recursion and quite useful. Otherwise, the usual place you see recursion mentioned is in calculating factorials and Fibonacci sequences.

The map struct holds not only the terrain type and other information but a continent number. This is set initially to 0.  After the land and seas have been generated, the program picks a random land point on the map (just keep picking a random location until it has land with a continent number of 0).

It then counts by calling itself 8 times. It calls itself recursively at location y,x with directions (y-1,x-1) that’s NorthWest, (y-1,x)  and so on round to West (y,x-1).  But it only does it as long as each of those locations is land type with a continent number of 0. And as it does it, it sets the continent numbers in each location to 1 for the first continent and so on.

This recursive algorithm means that every contiguous land location gets reached. A similar thing is done with seas and lakes but you have to be careful that the stack is large enough.

void FillIn(int x,int y,int locis) {
  if onMap(x,y) {
    if (locis==map[x][y].locis && map[x] 
 [y].continent==UNALLOCATED) { 
      map[x][y].continent=numconts;
      allconts[numconts].count++;
      FillIn(x-1,y,locis);
      FillIn(x+1,y,locis);
      FillIn(x,y-1,locis);
      FillIn(x,y+1,locis);
      FillIn(x-1,y-1,locis);
      FillIn(x+1,y-1,locis);
      FillIn(x+1,y+1,locis);
      FillIn(x-1,y+1,locis);
    }
  }
}

This is used for both land and sea, so locis can be either. It’s an efficient algorithm and quite quick.

Those graphics? They were the initial hexagon graphics…

About that Empire Map Generator

About that Empire Map Generator

The Circle data used in the Empire map generatorThis post refers to the c sources in the AboutEmpire.zip file in the Github C Games repository.

I first developed the algorithm in 1986 and wrote it in Z80 assembler. It was then rewritten in Turbo Pascal and used in both the Warlord and Quest postal games that are still run by kjcgames.com. It has been rewritten in C in the Empire game. So how does it work?

The idea is to generate continents. Typically between 2 and 3 continents between 1500 and 1800 squares in total on an 80 x 50 map. The map is made up of land squares and sea squares but starts out blank.

First I throw down 30 land points and 50 sea points. I.e. the program randomly picks points.

void AddPoints(enum loctype lt,int numpoints) {
  int i,x,y;

for (i=0;i<numpoints;i++) {
  do {
    x=Random(MAPWIDTH-40)+20;
    y=Random(MAPHEIGHT-40)+20;
    }
  while (map[x][y].locis != lctnull);
  map[x][y].locis = lt;
  genpointsx[pointindex]=x;
  genpointsy[pointindex++]=y;
  }
}

Some of the constants and the loctype enum are defined in common.h. The map itself is built up by adding extra points to each land point and sea point. I’ve defined an array of points in data.h that has 35 rings of points.  Well they’re more squares than rings.  That text file shown in the image is what these rings are derived from. I’ve translated all the points into 35 sets of X,Y offsets in data.h.

These points get added in layers. Starting with the first layer which has 8 points in it around the centre – that’s the A’s in the image, the next layer has 12 B’s and 4 C’s in it and so on.

But I only add a land or sea point if the spot its going into is empty; once it is defined as sea or land it can never change. So sea points and land points bump up against each other as these ‘circles’ expand and you get coasts and all sorts of interesting shapes. After that I fill in all empty spaces as sea, and the count up the connected land and sea squares.

If there are any tiny seas, i.e. less than 5 squares area they get filled in as land and any land point that isn’t surrounded by at least 3 other land point gets sunk. Then so long as there are the right number of continents and the total land squares is between 1500 and 1800, the map is accepted. If not a new one is generated. Adjusting the number of initial land and sea points helps to generate more acceptable maps.

I’m tempted to go Nuklear

I’m tempted to go Nuklear

Gallery Image of GUI developed with NuklearNuklear is a library that is a single-header ANSI C immediate mode cross-platform GUI toolkit. It lets you develop stylish and beautiful GUIs for your applications. It’s written in C but any programming language that can work with C such as C++ or Python can also use it.

Importantly, it also includes documentation so you can make use of it. The best software in the world is useless if you can’t use it and GUI toolkits tend to be a little bit more complicated than say a text editor.  This is nicely written, and though it’s just one document, it’s a long one!

It’s one thing to write a simple GUI as I did in that Empire game but mine was only 600 lines long and pretty rough looking. Nuklear is 18,000 lines long ie 30x as big.  If there’s one thing I’ve found from my software development experience, it’s that a nice looking piece of software will get away with having more bugs than something that looks not as nice.

 

I’m considering switching to C11

I’m considering switching to C11

Programming image
Image by Gerd Altmann from Pixabay

All C code I write in the books is currently to the C99 standard. All the compilers involved (Visual C++ on Windows and Clang on Ubuntu) support C99 but C11 support seems restricted to GCC and Clang.

Microsoft has traditionally supported C++ but their C support seems a bit grudging; realistically they don’t prioritise it which I can understand.

Given though that I’m not going to republish my first e-book for a while (I’d like to add a WebAssembly chapter or two first), I’m going to investigate whether it’s worth switching to C11 for the 2nd book. From what I’ve read all it needs is a flag to tll it to compile to C11 standards. This is for Clang.

-std=c11

But the other question is what will I gain by doing this and I can’t actually see there’s that much benefit.. I don’t need Unicode, I don’t think alignment will really make much difference. You can read about the C11 changes on WikiChip.

So I’ve made the decision. I’ll stick with C99 for now. But for an alternative view, I recommend Danny Kalev’s 2012 article on C11.

 

Other ways to time code

Other ways to time code

Stop Watch photo from Pixabay
Image by Free-Photos from Pixabay

As well as the hr_time code that I used in discussion of sdldemo SDL itself provides some other ways to time. If you are happy with millisecond level accuracy of timing, just call this function which returns an unsigned 32-bit (i.e. 0- 4 billion) giving the number of milliseconds since the SDL library was initialised.

SDL_GetTicks()

The link goes to the Wiki page on libsdl.org  for SDL_GetTicks().

As always, call it twice, once to get the start value and once to get the stop then subtract start from stop to get the elapsed time in milliseconds..

For some operations this can be easier to use. A frame is 16.666666 milliseconds so if your code runs in less than 16 milliseconds, it’s not going to cause problems. In my original Windows code, it ran is a fraction of a millisecond. Compiled C code really is fast and helped because the GPU is doing most of the donkey work!

There’s also a higher accuracy timer. This I guess is just a wrapper round the system call I call in hr_time.

Uint64 SDL_GetPerformanceCounter(void)
Which I haven’t used yet but which I guess returns a processor clock count. To measure time you need to call it twice (start and stop values as before) then divide by the frequency value returned from a call to

Uint64 SDL_GetPerformanceFrequency(void)

My computer returns a clock frequency of 3,500,000,000 clocks per second but the actual value is irrelevant just divide ((stop – start)/ frequency) to get the elapsed time in seconds.