Author: David

High speed timing in C

High speed timing in C

One of the things I like doing is timing code. Not to benchmark it per se, but to get an idea of performance. I have a small set of functions to do this on most CPUs for the last ten or fifteen years. It uses the high frequency clock, which. on my PC (a five year old I7-5930K), this counts at the rate of 3,500,000,000 per second.

You just read this timer twice, subtract the difference and then divide by the frequency (3500,000,000) to get a time in fractions of a second accurate to nano-seconds. (10-9 seconds).

Here’s the code for Windows. It’s in the several of the ebook chapters, e.g. chapter 48 (download the file asteroids_ch48.zip and unzip) . Or you can just copy from here.

hr_time.h

#include <windows.h>

typedef struct {
LARGE_INTEGER start;
LARGE_INTEGER stop;
} stopWatch;

void startTimer(stopWatch *timer);
void stopTimer(stopWatch *timer);
double LIToSecs(LARGE_INTEGER * L);
double getElapsedTime(stopWatch *timer);

and hr_time.c

#include 

#ifndef hr_timer
#include "hr_time.h"
#define hr_timer
#endif

void startTimer(stopWatch *timer) {
QueryPerformanceCounter(&timer->start);
}

void stopTimer(stopWatch *timer) {
  QueryPerformanceCounter(&timer->stop);
}

double LIToSecs(LARGE_INTEGER * L) {
  LARGE_INTEGER frequency;
  QueryPerformanceFrequency(&frequency);
return ((double)L->QuadPart / (double)frequency.QuadPart);
}
double getElapsedTime(stopWatch *timer) {
LARGE_INTEGER time;
  time.QuadPart = timer->stop.QuadPart - timer->start.QuadPart;
return LIToSecs(&time);
}

Use it like this:

stopWatch s; // declare a stopwatch variable

startTimer(&s);

// your code to be timed here

stopTimer(&s);

printf('It took %10.6f secs',getElapsedTime(&s));
More on pointers in C. The use of typedef

More on pointers in C. The use of typedef

Asteroid about to be destroyedThis bit is slightly controversial. I find all the * makes it harder to read code so I use typedefs to hide them. Here’s an example from the game. Try replacing every pbte with byte * and see if reading it is harder for you.

typedef byte * pbyte;

// mask arrays
byte bulletmask[1][3][3];
byte plmask[24][64][64];
byte a1mask[24][280][280];
byte a2mask[24][140][140];
byte a3mask[24][70][70];
byte a4mask[24][35][35];
byte alienmask[64][64];

pbyte GetMask(int type, int rotation, int size) {
  switch (type) {
    case tAsteroid: // asteroid
      {
        switch (size)
          {
            case 280:
              return (pbyte)&a1mask[rotation];
            case 140:
              return (pbyte)&a2mask[rotation];
            case 70:
              return (pbyte)&a3mask[rotation];
            case 35:
              return (pbyte)&a4mask[rotation];
          }
      };
    case tBullet: // bullet
      return (pbyte)&bulletmask;
    case tPlayer: // player
      return (pbyte)&plmask[rotation];
    case tAlien:
      return (pbyte)&alienmask;
    } 
  return 0; // null - should never get here!
}

In my post about collision detection I mentioned getting mask bytes. This function GetMask returns a pointer to a byte (i.e. the first byte in a particular mask for a particular type of object (asteroid, bullet, player, alien) and for asteroids and the player a particular rotation. The many (pbyte) are needed because the arrays have different sizes. There are 24 player and asteroid masks.

A look at pointers.

A look at pointers.

You cannot be a C programmer without using pointers. It’s the one feature of the language that makes possible much of what you can do in C. Pointers seem to scare novice programmers and it’s true that you can crash a program if you make a mistake, but otherwise they’re not that bad. Pointers as parameters in functions let you change the value of an external variable.

A pointer is just a variable that holds the address of another variable. So here’s my take on pointers.

You define a pointer as a pointer to a variable type like a pointer to an int or a char. There is also a “wildcard” where you define a pointer to a void. That has its uses when passing general pointers into functions. With types, the C compiler can verify assignments.

[perl]int * pInt; // pInt is a pointer to an int
char * pChar; // pChar is a pointer to a char
int a;

void ZeroInt(int * pInt) {
if (pInt) // Check pointer does not have a null value
*pInt = 0;
}

ZeroInt(&a); // Sets a to 0.[/perl]

That ZeroInt() function is a long-winded way of setting whatever int variable it is called with to zero. Yes you can just do a = 0; but that misses the point. What if a was a struct and the ZeroInt was a function to initialise all the fields of the struct?

Games sources code

Games sources code

Text Star Trek gameThat thing in the top right corner of the page that says GAME SOURCES? That’s a list of pages on the site and it’s the first and currently only page apart from the main blog. I’ve added a game conversion that I wrote back in 2006 when I was learning C (I mean comments are /* n.. */ none of this modern // stuff!).

It’s a translation of an old BASIC Star Trek text game, although this was a TinyTrek version. I’ve left the line numbers in relevant functions as comments. If you don’t have high expectations you won’t be disappointed!  Enjoy, er maybe…

Something in my past

Something in my past

For my sins I used to write the About C, C++ and C# website for About .com between 2006 and 2013. There were tutorials, programming contests, curated libraries and the SDL 1 version of Asteroids without the pixel perfect collision detection.  Many of those articles (but not all) are now on the Thoughtco website. I’ll try and dig up some of the older stuff from here.

How pixel perfect collision detection works

How pixel perfect collision detection works

Asteroid and player ship about to collide near an explosionsThere are four types of moving object in the games. Asteroids in four sizes from 35×35, 70×70, 140×140 and 280×280 pixels, the player’s ship (fits in 64 x 64 pixels), alien ships (also in 64 x 64)  and a bullet which is solid 3×3 pixels with the four corners empty.

As these move around the screen at 60 frames per second, they will come into contact and the collision detection has to figure out when they hit or miss.

To make it more complicated, the asteroids and player’s ship come in 24 rotations, each by 15 degrees so detection has to take that into account. The image shows an asteroid just about to hit the player’s ship.. At the bottom you can see where another asteroid has been blown up (the 50 is the score) and there’s a bullet to the right.

The detection occurs in several stages. First each object has a bounding square.This shows the bounding boxes for the player's ship and an asteroid This is an invisible square that just fits round each object. For the player’s ship it’s 64 x 64 and it corresponds to the sizes of each asteroid. As the image shows, the two bounding boxes overlap and it’s in this overlap rectangle that we have to check for a possible collision.

A large asteroid and the cells it overlapsFirst things first. Every frame all objects are moved and we have to detect if there’s a chance of a collision. This is done by dividing the entire playing area (set in the book to 1024 x 768) into 64 x 64 pixels cells.  I chose that as a convenient size. Once the object’s new x,y location has been calculated, I determine which cells it overlaps.

The player’s ship can fit completely into one cell but most times it is either overlapping two or four cells. Even a 3 x 3 bullet will occasionally overlap two or four cells but most of the time it will fit completely in one.  The largest Asteroid (280 x 280) always overlaps five or six cells in each direction so it gets added into to 25,30 or 36 cells each frame.  The image shows the grid of 64 x 64 cells and the asteroid overlaps 25 cells, the player’s ship just overlaps 4 cells. The number is a count of the number of overlapping item in each cell.   It’s the bounding box size that determines if it overlaps which is why the top left and bottom right empty cells of the asteroid still show 1.

In each cell, I keep a list of objects that overlap that cell. The first step is scanning all cells with overlapping objects in to see if there are two or more objects overlapping in that cell. The SDL library includes a function SDL_IntersectRect()  You pass in the two bounding rectangles of overlapping objects and it returns a rectangle of the intersection, which corresponds to the overlap in the image above. If there are multiple objects in a cell e.g. four then you have to check to see if any of those (1,2), (1,3), (1,4), (2,3), (2,4), (3,4) overlap.

A text file representation of a maskThe next bit is what makes it pixel perfect. For every object and its rotations, I have created a mask. It’s a file of bytes with a 1 value corresponding to every coloured pixel in the object and 0 to empty pixels.

I have stretched this image to make it the same aspect ratio and it shows 0s and 1s in the player’s ship mask.

The collision detection algorithm processes the intersection rectangle and calculates where each pixel in that rectangle falls in the corresponding mask (adjusting for rotations) of each object.  If either mask pixel is 0 then no collision occurs but if both are 1 then bam!

Although I could have used a mask of bits, it was quicker to use bytes.

During development I wanted to verify that it was pixel perfect, so I disabled explosions and instead when two pixels overlapped, I output a green pixel to highlight it. The image shows the player’s ship passing through an asteroid!Showing pixel perfect touching

 

 

 

Learn C Games

Learn C Games

Learn C Games Programming Book coverThis blog is about C and Games programming (in C mainly). There are now two ebooks written by David Bolton, author of the Learn C Games Programming for beginners EBook. This is the Windows version, with a Raspberry Pi/Linux one now out.  

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 (20 in the Linux/Raspberry PI) 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 Github. (Windows) or (Linux). More about me. Buy the Windows one on Amazon(UK), Amazon(US) or the Linux/Raspberry PI. (UK). You can buy the book in other regions by changing the region in Amazon to your local one.