Category: Game

Back writing book two

Back writing book two

Hexagons
Image by Clker-Free-Vector-Images from Pixabay

This time it’s about Learning to program games in C on the Raspberry Pi. Most of the books I’ve seen are about programming in Python, but C combined with SDL2 gives you an edge. I already know that I can get 150 frames per second in Asteroids on a Raspberry Pi 4B.

The three games for the book are

  1. Asteroids. Fully developed
  2. MatchThree. About 1/2 developed.
  3. Empire type game. Map generator plus large scrolling hexagon map with fog-of-war shrouding and computer AI opponents. This will be based on the existing Empire code.

The third game is one I originally wrote thirty-three years ago (Dark Empire) in Z80 assembler for the Zx Spectrum. I then converted all 5000 lines of code into CBM-64 6502 assembly in one month working seven all-nighters, with the last three on three successive days. That one wasn’t in hexagons but squares and of course there was no mouse.

On the morning after the last all-nighter I drove across Manchester to deliver the tape master copy to a railway station to be sent to the publisher in London and when I got home, I slept for 24 hours solid. I doubt I could do an all-nighter now, but 33 years ago …

 

Working with Mice in SDL

Working with Mice in SDL

Computer mouse
Image by OpenClipart-Vectors from Pixabay

On the Match three game, I’m at the point where I need to be able to click on a piece and drag it to the next piece (horizontal or vertical) and then start the two animating to swap positions.

In SDL, I’ve got a simple mouseclick function that is called from ProcessEvents (my function for handling all input) with the x,y coordinates on the screen where clicked. These have to be  converted from screen coordinates to board coordinates (or ignored if not on the board) to identify the piece clicked. However the mouse now needs to drag this piece to an adjacent piece.

As usual I’m not the first person to ask this and there’s a StackOverflow Question with an answer. So I’ll be following this answer and hopefully get it working. This is possibly the key mechanic in a MatchThree game so it’s important to get it right. After that I’ll get teh touchscreen working again which should in theory use the same code apart from reading the game controller..

Slight change of pace

Slight change of pace

Networking
Image by Gordon Johnson from Pixabay

I’ve managed one blog entry per day for the last 134 days but a change in side project (I was writing a book to be published, not an Ebook)  but that has to be delayed by at least a year because of an issue at the publisher. In fact I may just publish what I’ve done as my 2nd Ebook.

I’m currently working on networking on a Raspberry Pi. Unfortunately it has to be in C# not C. Networking is a lot easier in C#- you have OOP, task parallel library (far easier than threads), thread pools,. concurrency with async/await and a lot more.  And I can use C# with .NET core or Mono on the Pi.

That said, I will still continue on with game development on the PI. I’ve got my Match Three game half done; I’m quite proud of it and want to get it finished. But I may switch to a slightly less frequent blog posting schedule…

 

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.

Added the sources of another game

Added the sources of another game

Basic Computer games bookThis was a text mode game, my idea being to do something like the old Star Trek BASIC game but better. I called it Star Empires and it’s on GitHub, just follow the link to GitHub on the C Games sources link.

The zip file includes both C and a C++ version. Both will compile with Visual C++ 2019 Community edition. There is a minor compile error, a = that should be == in the C++ source. I ill get round to fixing it and uploading a replacement.

I do get a bit of pleasure (more like an exercise in masochism!) converting old BASIC games to C. I’m looking at the two Creative Computing books (and while 95% of the games are not exactly great (well lets be generous and say they were good 45 years ago!) but there’s one or two that might be worth the effort! I bought these in 1982 lost those and then bought them a few years back again.

Plus when you think how the games industry has matured since the late 70s and 80s, and many of those early programmers will have cut their teeth on games like that before learning more advanced stuff, so  lets not be too harsh!

 

Browsing the source code of old and commercial games

Browsing the source code of old and commercial games

 

Archive photos
Image by Pexels from Pixabay

This page on a website called WikiZero has a long and very extensive list of games whose source code is available. That doesn’t always mean you can build the game. Many games are very old and in BASIC or assembly (.g. Elite is available in various forms).

It might have been created for a different platform or more likely the source code is available but the graphics and sound assets aren’t, unless you have bought the game, perhaps from sites like gog.com and so have them.

One thing to be aware of, many of the links on WikiZero go to the excellent wayback machine which is part of archive.org. This is under threat by some commercial publishers because they have lent ebooks during the Covid lockdown period without any limitation.  So if you are interested in anything I suggest you check it out sooner rather than later, just in case.

For instance here is the C source code for a TRS-80 game from 1979 called Paravia. It looks like a much expanded version of the Classic Computer game Hammurabi.  Note the wayback machine can take a few seconds to retrieve a webpage. They have a very large chunk of the web’s websites in there…

Progress on the Match Three game

Progress on the Match Three game

Match Three game Having a week off work has let me work on this game a bit more. I’ve put in about eight hours and it is now correctly dropping.

I’d never programmed one of these before so my first version used a board of pieces plus a secondary array for holding “transitions”. A transition was a struct that held information about two pieces being swapped and the current coordinates of each piece.  It seemed to be quite messy code and was quite buggy with pieces on top of other pieces.

So I then switched to a system where each board cell had a pointer to a struct for a piece (held in an array).  If the piece wasn’t moving the program calculated its pixel coordinates from the board coordinates and drew it there. If it was moving, it would no longer have board coordinates and would use the pixel coordinates to draw it.

That was better but then I thought why not just have the board just be a 2D array of structs with one struct for each piece.

This is the struct for each piece.

 

struct Cell {
	int piece;
	int moving;
	int scEndX, scEndY;
	float scCurrentX, scCurrentY;
	float velY, velX;
	int bdEndX;
	int bdEndY;
	int angle;
	int lock;  //1 = locked. Display padlock
	int size; // used when killing to diminish size
};

SDL2 does rotation very nicely; you don’t need to pre-render shapes just call SDL_RenderCopyEx instead of SDL_RenderCopy and specify the angle and one or two other parameters. When a piece is removed, it animates for about a half-second, rotating and shrinking in place. That’s the purpose of the angle and size fields.

If the lock value is 1 then the piece stays in place and won’t drop. You have to remove the lock by forming a line that includes the locked piece. When the line is removed, all locked pieces in the line remain but without the lock.

So far the game is currently about 800 lines of code. There’s no game level structure, high-score table, sounds, bonus pieces or even a basic piece matching algorithm. I’ve been testing by just randomly removing three vertical or horizontal pieces and then having unlocked pieces above fall down.

This 3rd version does not suffer from the Mexican-wave problem that the first and second version had. Sometimes when a column of pieces moved down, instead of all pieces moving together they moved one-by-one. New pieces get added in when the top row piece finishes dropping away.

So now on with the book and the next part of the game.

Working on the Match Three game

Working on the Match Three game

Match three gameThe second game is Match Three and I’d made some good progress. You can view some .mp4s from earlier this month here. The first one (MatchThree) shows rotations, something I’d never realised SDL is very good at doing. Graphics are from the excellent Dutch website (it’s in English) Kenney.nl.

The second mp4 (transitions) shows some animations. And the MatchThreeDropping shows pieces both being removed (first rotating and shrinking) and pieces dropping. However it also shows a flaw.  Sometimes all the pieces move together, other times (and this is the flaw) it shows them dropping one by one- Mexican wave-like, rather than all moving together.

My original algorithm, which I am now scrapping, had a transitions table. When the space or spaces below a piece became blank, a transition was created which had start and end positions. The piece was removed from the board (a simple 2d array) and reinstated in the board when it had finished moving to the end pixel position.

I think I have a much better method now, I still use a board but each element has a pointer to a piece in a big array of piece structs. I track both the coordinates in the board (0-9,0-9) and in pixels as each piece is 64 x 64. When a space is created in the board, all the pointers are shuffled and each piece is told to move from it’s old pixel position to its new one.

The move algorithm operates purely on the all pieces in the piece array not the board. The flawed algorithm worked on both the board and transition array and was quite messy. Sometimes you have to start with a clean slate than try and fix code that is working correctly.

Array vs pointer in C

Array vs pointer in C

Grid array
Image by Anja🤗#helpinghands #solidarity#stays healthy🙏 from Pixabay

A common pattern (I use the word loosely) in my C programs is to have an array of structs to hold things like asteroids and bullets in the game. There are two ways to process an array:

  1. As an array e.g. asteroids[index].
  2. As a pointer to an individual array element. Asteroid * pAsteroid = &(asteroids[index]); then refer to pAsteroid ->

One of the tents of software design though not that often said is that the easier the code is to read, the easier it is to understand. Programmers spend a lot of time reading code. Anything that lightens the cognitive load is good. I suspect it might also be faster, but not by a great deal.

Of course pointers make some programmers nervous. To me though they simplify the code. There is however another way to simplify the code. Use #define so you might have something like this:

#define table asteroids[index]

So everywhere you have a asteroids[index]., you put in table instead.
This for example from Chapter 36 DrawAsteroids()

	for (int i = 0; i<MAXASTEROIDS; i++) {
		if (asteroids[i].active) {
			numAsteroids++;                    // keep track of how many onscreen
			int sizeIndex = asteroids[i].size; // 0-3
			int asize = sizes[sizeIndex];      // asteroid size 280,140, 70,35
			target.h = asize;
			target.w = asize;
			asteroidRect.h = asize;
			asteroidRect.w = asize;
			asteroidRect.x = asize * asteroids[i].rotdir;
			target.x = (int)asteroids[i].x;
			target.y = (int)asteroids[i].y;

Would become

	for (int i = 0; i<MAXASTEROIDS; i++) {
		if (table.active) {
			numAsteroids++;                    // keep track of how many onscreen
			int sizeIndex = table.size; // 0-3
			int asize = sizes[sizeIndex];      // asteroid size 280,140, 70,35
			target.h = asize;
			target.w = asize;
			asteroidRect.h = asize;
			asteroidRect.w = asize;
			asteroidRect.x = asize * table.rotdir;
			target.x = (int)table.x;
			target.y = (int)table.y;

What do you think?