Month: April 2020

A small C++ Tip. Return values from Constructors

A small C++ Tip. Return values from Constructors

C++ LogoYou can’t return anything from a constructor.  One way is to use exceptions but those can bring their own issues. Google’s C++ guidelines actually stipulate no exceptions and I’ve heard it from others as well that they prefer not to use them. Some people avoid it by having a mostly empty constructor and then an init() method to do the real initialisation and return a success/fail state.

But there is a simple trick that you can use, just return the state as a reference. Here’s an example. If you want to return more values, use a struct.

#include <iostream>
using namespace std;

class Simple {
public:

    Simple(bool& failure) {
        failure = true;
    }

    ~Simple() {
    }
};

int main() {

    bool fail_flag = false;
    Simple f(fail_flag);
    if (fail_flag)
        cout << "failed " << endl;
    else
        cout << "Success" << endl;
}
C++ enum class vs enum

C++ enum class vs enum

C++ LogoI’d read about enum class in C++. It’s a slight strengthening of the compiler checking compared to plain old enums.  Why you may wonder? Well,

  • Conventional enums can implicitly convert to int, causing errors when someone does not want an enumeration to act as an integer.
  • Conventional enums export their enumerators to the surrounding scope, causing name space pollution.
  • The underlying type of an enum cannot be specified, causing confusion, compatibility problems, and makes forward declaration impossible.

Additionally you can declare the underlying storage type, which lets the compiler catch bugs where a value is too large for the storage. Here’s a made up example to show this:


enum class byteThings : unsigned char {
Thing1 = 0x01,
Thing2 = 0x02,
Thing3 = 0x04,
BigThing = 0x120  // Compiler will complain!
}

The downside is that to get the int value, you now need to do a static cast but it does make your code safer.

byteThings b = Thing2; 
int i= static_cast(thing); // 2

 

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.

 

Slight change in direction – more C++ and Pi

Slight change in direction – more C++ and Pi

Raspberry Pi
Image by planet_fox from Pixabay

As I said recently, writing about C and games probably isn’t enough to sustain this site, but if I extend it to include C++ and Raspberry Pi and still maintain the overall direction of writing about game development then that I think will do it.

So I’ve added a new page for C++. I’m currently working on the C++ version of Asteroids and making good progress.

I’m striving to write it in modern C++. To that end, the first entry in the C++ page is a link to a very long document: C++ Core Guidelines written by two luminaries of the C++ world Herb Sutter and Bjarne Stroustrup (creator of C++). You should definitely give it a read.

Interesting fact about the Raspberry PI. Did you know that in March 2020, they sold 640,000! That’s pretty amazing! And while that article says that AAA game playing isn’t something you can do on a Pi, we now know that you can run simple 2D arcade quality games on a Raspberry Pi 4.

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.

Here’s the Raspberry Pi temperature code

Here’s the Raspberry Pi temperature code

To add temperature to the frame caption, I first do a check to see that it is running on a Raspberry Pi. This function does that.

void SetPiFlag() {
	struct utsname buffer;
	tempFlag = 0;
    if (uname(&buffer) != 0) return;
    if (strcmp(buffer.nodename,"raspberrypi") !=0) return;
	if (strcmp(buffer.machine,"armv7l") != 0) return;
	piFlag=1;
}

Note you have to add this include

#include <sys/utsname.h>

Now you need to call this function to return the temperature as a float.

float ReadPiTemperature() {
    char buffer[10]; 
	char * end; 
	if (!piFlag) return 0.0f;
	if (SDL_GetTicks() - tempCount < 1000) {	
		return lastTemp;
	}
	tempCount = SDL_GetTicks() ;
	FILE * temp = fopen("/sys/class/thermal/thermal_zone0/temp","rt"); 
	int numread = fread(buffer,10,1,temp); 
	fclose(temp); 
	lastTemp = strtol(buffer,&end,10)/1000.0f;
	return lastTemp;
}

Things to notice.

  1. If it’s not running on a Pi it always returns 0.0C.
  2. No matter how often it’s called, it only reads the temperature once a second.
  3. In between reads it caches the temperature in a variable lastTemp

When I first wrote this, it was reading the temperature on every frame. It actually changes that quickly but that made it hard to read. So once a second is fine.

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.

Two bugs on Raspi – one fixed

Two bugs on Raspi – one fixed

asteroids screenshotAs always bugs are the fault of the creator and mea culpa (my bad!). I can trace this back to my conversion from the Windows source to the Ubuntu version. This line in LoadMask

int numread = fread_s(mask, sizeofmask, sizeofmask, 1, fmask);

Became this line in the Ubuntu version.

int numread = fread(mask, sizeofmask, sizeofmask, fmask);

But should have been this instead.

int numread = fread(mask, sizeofmask, 1, fmask);

It affected numread and failed just on the masks/am2.msk load.
The other bug only applies on Raspberry Pi 4 and is a limitation of the implementation of SDL2 texture size.
One of the asteroids graphics is 6720 x 280 and the error it returns is Textures can’t be bigger than 4096×4096.

What is odd that it works on a Raspberry Pi 3B+ but not on the 4 which has 4 GB of RAM. Anyway I’m writing a program to transform the graphics from 24 x 1 shapes to 12 x 2. So the 280 x 280 shape file will be 3360 x 560. This will affect the player ship and all asteroids and need a slight change to the DrawPlayerShip() and DrawAsteroids() functions.

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.