Category: Game

So I thought I’d try Code::Blocks

So I thought I’d try Code::Blocks

Code::blocks compiler options

Code::Blocks is an alternative cross-platform open source IDE for C/C++ (and Fortran!). It doesn’t include a compiler but can work with most of them.  It’s also written in C++ (you’d never guess from the name!) and so is fast.

Installing is just a

sudo apt install codeblocks

When you install it, it looks for installed compilers and gives you the choice of which is the default.

When you create a project there are a few types and one that got me excited was SDL. It creates a skeletal project and it was only when compiling that I realised it was for SDL1, not 2.  It’s the nature of open source that things take time to remedy. So don’t bother with it.

Anyway I copied in my source files and clang objected because it couldn’t find the SDL2 files. The fix isn’t too difficult. In Code::Blocks, navigate to Project Build Options then in Compiler settings > Other compiler options add these lines

-lSDL2

-lSDL2_image

-lSDL2_mixer

and in the Linker settings > Other linker options

-lSDL2

-lSDL2_image

-lSDL2_mixer

Note those are -l () not i or 1.

After that it compiled and linked ok. The compiled code is in the bin/Debug folder. However to get Asteroids to run you need to copy in the images, sounds, and masks folders and the highscore.txt file. After that it runs fine, but note when you compile it seems to delete everything in the folder.

So overall it wasn’t a difficult thing to do and I’m going to install it on a Raspberry Pi and see how that goes. I’ve already got Visual Studio Code installed on it and working but having a second IDE (both using the same compiler) is no bad thing.

Success with gamepad mappings

Success with gamepad mappings

SNES Gamepad
Image by Marco Sberveglieri from Pixabay

My ploy with running gamepad-tool on the Linux laptop worked and I was able to get the correct mappings to use in my game. Though weirdly it seems to have X and Y buttons mixed up as well as A and B.

In the end I hard-coded the mapping string and set it up with this code:

	if (SDL_GameControllerAddMapping("030000001008000001e5000010010000,NEXT SNES Controller2,platform:Linux,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:-a1,dpdown:+a1,dpleft:-a0,dpright:+a0")==-1){
		LogError("Unable to load gamepad mappings from gamepad.txt");
	}

Then in my ProcessEvents() function which handles I/O events, I added this code:

			case SDL_CONTROLLERBUTTONDOWN:
			if (event.cbutton.state== SDL_PRESSED){
				switch(event.cbutton.button){
					case SDL_CONTROLLER_BUTTON_A:
					    fireFlag =1;
					    break;
					case SDL_CONTROLLER_BUTTON_B:						
					    jumpFlag =1;
					    break;
					case SDL_CONTROLLER_BUTTON_X:
					    shieldFlag =1;
					    break;
					case SDL_CONTROLLER_BUTTON_Y:						
					    thrustFlag =1;
					    break;						
					case SDL_CONTROLLER_BUTTON_LEFTSHOULDER:
					    rotateFlag = 1;
					    break;
					case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER:
					    rotateFlag= 2;				
					    break;
					}
				}

There’s similar code for the SDL_CONTROLLERBUTTONUP except it checks for the state = SDL_RELEASED and in the switch statement it sets each flag to 0. So inspite of the code, it’s the Y button that does shields and the X button does thrust, B button fires and A button does the hyper space jump.

My Orange Pi – self resurrected

My Orange Pi – self resurrected

USB JoypadBack in November 2018, I was in Nottingham and passed a stand at the Winter Fayre. It was offering a console with 18,000 games on it for about £70. I bought one and what I got was an Orange PI with a 16 GB SD Card (all but full) and two USB joypads.

The game software used the Retro-Pie software, but the games were a massively illegal collection of games (for about ten different consoles including CBM-64, SNES, ZX Spectrum) put together by the company that supplied these “consoles”. Amazingly I found four games on there that I had written back in the 80s in this collection.

It was a bit of an odd PI. Instead of powering up through the power slot, it came with a USB to 5V connector. Looking about on the web I found it is this model in a nice acrylic case. Anyway, after three months it stopped working and it was pushed in to a drawer where it remained until today. I tried it today and it came back to life, I suspect the mains-to-USB adaptor is broken but as I’ve a drawer full of them it’s not a problem.

The reason for mentioning this is not the Orange Pi, nor the games but the joypads. I had a look on the libSDL website and I hadn’t realised that there was quite extensive support built in to SDL.  So my next task is to add game controller support for the asteroids game.

 

A new mini game console

A new mini game console

playdatePlaydate sounds a tad dodgy but is actually a small handheld game console with a 2.7-inch, 400 × 240 screen (173 ppi) and costing $149. It’s due out sometime this year.

The reason I mention it is it runs games written in C (or Lua).  It also comes with 12 games. No mention of what’s inside it (RAM, CPU) though that’s described as ‘beefy’ but it has Wi-Fi, Bluetooth, USB-C, and a headphone jack.

That thing sticking out of the right is a hand crank. No, not for charging the battery but as a game input device. If you create a side-scroller game you can have it scroll one way by cranking in one direction and reverse it by cranking in the other way. Well that’s certainly original!

There will be a development kit available for it and you will be able to write programs for it though at the moment that looks as if its only on a Mac which is a bit of a shame. Oh I have a Mac but I much prefer my Windows PC or Ubuntu.

Compared to the massive screen sizes available on PCs, 400 x 240 sounds a bit small screen size. If you remember the CBM-64 from the 80s, it is exactly the same size as that screen and there were some great games out for it.

I’m excited about this because I believe it could be a renaissance for C Game programming.

The Joys of C++

The Joys of C++

Maze
Image by Arek Socha from Pixabay

My progress on the C++ asteroids game took a little detour down a one way street. The problem I hit was until then I thought I was being clever by passing in a reference to another class in the constructor. That worked fine until I started implementing array classes.

The issue I got was using my constructor meant that the default constructor was deleted. This happens in any class where you add your own constructor as all the special functions are deleted. You then have to add your own Move or Copy assignments if you are doing things that invoke them. Like iterating through an array (or vector in my case). Although I use Bullet and Asteroid classes, I manage  collections of them through an Asteroids and a Bullets class.

Plus I’d decided that vector class wasn’t perhaps the best class to use. This thing runs at 60 fps, so adding and deleting elements from a vector seems a bit wasteful. Instead by using a std::array, and constructing all elements in it when the managing class is instantiated, all I have to do is scan for the first element with an active flag set false. (all are set false when constructed), set a few fields for velocity and position and there it is on screen.

Is this premature optimisation? I don’t think so. One of the things that programmers are told NOT to do!

So I have cleaned up my constructors now. They are parameterless and no special functions are deleted. It’s this kind of stuff that can do your head in and one of the reasons why I think C++ is considered a harder language to master.  I’m certainly a long long way from that.

The maze? Just a metaphor for C++ programming!

C++ Asteroids is progressing

C++ Asteroids is progressing

C++ AsteroidsThis is a screenshot of it as it stands and yes those asteroids are moving! It looks identical to the C version; the only difference is the code, not the appearance.

What makes it interesting is the structure. The Player and Asteroids classes both inherit from a Common base class that has all the position and move data.

It took a bit of time to get the overall architecture right. There’s a Game class which manages everything; the Player, Asteroid and Lib classes.  But Asteroids and Player classes also use the Lib class so  it took a bit of faffing around to make them all play happily together.

This is the biggest difference between C++ and C; the classes and how they all fit together. My biggest source of frustration has been arm wrestling with the C++ compiler; it sometimes seems as if never get easier! Sometimes a wrongly placed semicolon can generate hundreds of compile errors…

It took half a day to get it right and bullets should fit in much easier. Mind you I’ve had to incorporate two static variables in the Common class. One is a copy of the SDL renderer; this is needed to draw things on screen. The other is a pointer to the Game class so that I can access the DebugFlag state.  This is used to show debug information but I may be able to move the flag itself into the Common base class and change it through a call on a Player method. So long as it is static then changing it for the Player also changes it for the Asteroids and Bullets.

 

Raspberry Pi 4 – Perfect for arcade quality games and development

Raspberry Pi 4 – Perfect for arcade quality games and development

lot s of asteroidsI got my Pi 4 a week ago and have been doing experiments on it with my Asteroids game. If I disable the line of code that kills the player ship in the DestroyObject() function and just add a return after case tPlayer: and uncomment the code that adds Asteroids when you press A then I can have lots of asteroids on screen. Also set the MAXASTEROIDS #define to 128.

Then you get the likes of this screenshot which is a 1024 x 768 size window. It’s still running at 40 fps, there are 116 asteroids on screen, around 60-70 explosions and the Pi’s temperature is still a balmy 44.79 C. I’ve never got the Pi’s temperature (and it does have an internal 3.3V fan) to rise above 51 C.

But what’s also impressive is that with Visual Studio Code and Clang on the PI, I can compile the whole 2,200 lines of C on the PI in about a second. This makes the Pi very usable for developing games. And I say this as someone who is used to powerful Windows PCs for compiling code.

This is it running in debug mode; that’s all the numbers and wire frame bounding boxes around every moving object.

Further experimenting and removing the limitations (I used a While loop to limit it to 60 fps back before I had enabled the hardware video flyback). With that while removed and the hardware video flyback disabled, I was getting over 100 fps with 100 asteroids on screen at once.  I pushed it up to 6,000 asteroids and the frame rate dropped to 10 fps. Given the amount of stuff that was colliding and blowing up, that’s still very good.

Asteroids now runs on a Pi 4

Asteroids now runs on a Pi 4

Asteroids with built in temperature for Raspberry PiI was interested in seeing what frame rate I got out of it and how much it warmed the PI.

The change to get the texture loaded was to split the five image files (four x asteroid + player ship) into two rows each.

I added this code into the DrawPlayerShip function.

    if (Player.dir >= 12) {
	  	spriterect.y = SHIPHEIGHT;
		spriterect.x -= SHIPWIDTH*12;
	}

So for directions 0-11, it uses the top row and 12-23 the 2nd row. There’s similar code in the DrawAsteroids function.

I’m getting about 55 fps, twice the frame rate of the 3B+.  Sustained play over five minutes got the temperature up to 51C, but if I start the game and let asteroids drift about for a while it settles somewhere around 48-50C.

I have a fan fitted plugged into the 3.3V that runs all the time but is almost inaudible. There’s also a 5V setting that can be used for extra cooling but you only need that when temperatures get up to the 80C mark. There’s also 3 copper heat sinks stuck on three chips on the motherboard.

It’s very playable at 55 fps. This isn’t full screen BTW but on a 1024 x 768 playing area. There’s just one last change I’ve added. I combined the uname code to detect if it is running on a Pi and in that case display the temperature  on the Window caption. If you look closely at the image above you’ll see it says 43.82 C. I use a counter and check against so it only reads the temperature once a second and caches the result.

I’ve started on the C++ Windows eBook

I’ve started on the C++ Windows eBook

C++ Code listing photoI made the mistake of starting by trying to convert the final version of Asteroid; all 2,200 lines of C into C++.

It got very messy because I was trying to have all the moving objects (Player ship, asteroids, bullets, aliens ship) all based on a common ancestor class but then was trying to manipulate those instances of the ancestor class and downcast back from the ancestor instances and I don’t think you can in C++. Compiler errors galore!

It was the wrong approach and I wasn’t using virtual functions. So instead I’m doing it step by step, adding on new features. Much like the original C development in 13 different steps.

Here’s the slightly shorter asteroids.cpp:

// Asteroids C++ 2020 Chapter 27
#include "game.h"

int main(int argc,char * args[])
{
	Game g;
	g.InitSetup();
	g.GameLoop();
	g.FinishOff();
    return 0;
} 

There are other classes used from Game. I haven’t put everything in one “God” class!

Fun with Raspberry Pi 4

Fun with Raspberry Pi 4

Bugs!
Image by Ron van den Berg from Pixabay

So it turned up and I setup things up similar to the 3B+. My interest was in seeing what frame rate it can manage compared to the 27 FPS that the 3B+ managed.

When I eventually got Clang, VS Code etc. installed and setup, compiled etc. it crashed just like it did on the 3B+ when first run. And again it failed to load the am2.msk file; I will really have to figure out what’s going on there. But also it would now not load the a1.png image. This is the one with the 24 x 280 x 280 asteroid images.

SDL provides a function SDL_GetError so I added that to the output when an image file fails to load. The error message that came back was Texture dimensions are limited to 4096×4096. Now this is weird for this Pi has 4 GB of RAM (the 3B+ has 1GB) and is outputting on the same 24″ monitor that the 3B+ used as well. Now it’s true that the a1.png file has dimensions of 6,720 x 64, so I can understand why that would cause grief but not why it worked on the 3B+. I suspect it has to do with RAM being allocated between the GPU and CPU so I’ll check that out.

I also installed Clang-6.0 to try that. On the Pi, installing clang defaults to Clang-7 (they changed the name so it no longer has a .0 on the end!). The release notes for Clang-7 suggested a possibility to do with abi incompatibility between Clang-7 and earlier versions. Bit of a longshot but I thought, that might explain the fail to load am2.msk file but no joy.

Well there’s nothing like juicy tender bugs to get my teeth into… the battle is on.