Friday, 31 December 2021

LP's 12 Months of Games // Alien Invaders Part 1 [C++ & SFML]

Completed Independently

So the final game of "Beginning C++ Games Programming" by John Horton was a clone of "Space Invaders". I skimmed the first chapter of the project and he starts talking about Entity component systems, Factory class designs etc and I just completely zoned out and decided to make it myself. 

This took me a while as Back 4 Blood added an offline mode and there's nothing quite like hitting zombies with a baseball bat. Also the Witcher season 2 and Lost In Space season 3.

So anyway, I kept getting annoyed with myself whilst making this game; I was trying to make the code as beautiful as possible right off the bat; which is impossible unless your Bjarne or Scott Meyers or something. I asked many colleagues how they would go about implementing Space Invaders and amusingly, the more senior the engineer the more the answer became "just do it all in main, who cares?"

So, I've written some terribly hacky code that only gets worse as time goes on but I have a game! This is labelled part 1 because it's not finished however, there is a title screen, a game and a game over. It saves the high score between runs and loops after game over so it is a game...regardless of how finished.

I'm quite into the task now and the shields are ready to be implemented, as are the sounds. Then the flying saucer needs some attention as do the shot exploding animations but then I'll have a full Space Invaders clone!

I've given myself a few little extras that involve creating a CRT shader and making it look as though you're playing the game on an arcade machine.

Result:
Space Invaders Clone Using C++ and SFML

I'm extremely happy with what I've done so far. I'm really trying my best to make it look and feel exactly like the original. I'm going so far as implementing the same bugs using this site which comments all the assembly:

There are some issues which you may have already noticed; my game over text isn't displaying and the high score isn't updating. That will be fixed next but the code is in place.

I just really wanted to get something uploaded for this month and I've already learnt so much from attempting to do this by myself. I'm glad I ignored the book as this game is deceptively hard but a great place to start when making a complete game from scratch for the first time.

I almost gave up a couple weeks ago as I find it difficult to find the motivation to finish things. I have about 70 started projects but I thought to myself, the whole point of this challenge is to get better at making games and I won't get better if I don't at least try! So I managed to scrape the code together enough to call it a "game".

It also made me realise that I hate UI programming with a burning passion.

Code:


Friday, 24 December 2021

C++ & SFML // Creating The Disintegrating Shields in Space invaders

Whilst making a clone of Space Invaders, I got to the point where I had to make the shields. They are interesting as only parts of them get destroyed when hit by bullets:


The damage done to the shields is based on the type of bullet and where they hit. It reminds me of the old Worms and Lemmings games that have disintegrating terrain due to explosions.

The player's shot and 2 of the invader shots deal the same type of damage. However the "plunger" looking invader shot is the most powerful and deals more damage. Therefore, having the shields as sprites make no sense as you can't manipulate the pixels in a sprite, so I started looking into ways to draw and modify pixels in SFML as well as do per-pixel collisions.

I eventually came across this post:

This seems super long winded for what I want as it copies the image from the gpu into an array of pixels, then you modify those pixels and then send that array back to the texture. But it's also the closest to how the original game implements the shields (in a way).

I then found this after googling "sfml array of pixels":

I was able to write a program that can draw individual pixels to the screen:

This is more along the lines of what I wanted, as I could now simply create a vector of vertices in the shape of the shield. SFML already provides this type called VertexArray which can be passed directly to a RenderWindow's draw call.

Here's a simple program I wrote that uses a VertexArray to create a rectangle with a gradient fill:

In my version, the shields are 66x48 pixels, with each vertex needing 4 uint8's of data (RGBA), so that means I need to supply 12,672 uint8's and I don't really want to type that out. So I had to start looking for a way to read in that data from something. SFML does not provide a way to convert textures or images to VertexArrays. I can get the pixel colour data by using the first method and copying the texture to an image but that doesn't provide pixel positions (which a vertex wants). So I wrote a method to combine the two. 

It creates a temporary texture, copies the texture to an image then loops through every pixel, pushing back a new Vertex after all 4 pieces of the pixel have been collected. The positions are calculated using an offset from the top left hand corner. So after 66 vertices have been pushed back, the y co-ord is shifted down 1 pixel. However there is still a glaring problem with this method; I have 4 arrays containing 3168 elements.

So I went back to the drawing board and found this post:

Using the code from Laurent (the developer of SFML) I managed to write a program that creates a "mask" from a png and uses that to turn pixels transparent:

C++ & SFML // Creating The Disintegrating Shields in Space invaders

Armed with this knowledge I then set about creating a cannon that fires lasers at the doge image to destroy it:
C++ & SFML // Creating The Disintegrating Shields in Space invaders

The next issue to solve was the per-pixel collisions as the laser was still colliding with the bounding box of the sprite. I hackily solved this by writing a very simple collision check:

C++ & SFML // Creating The Disintegrating Shields in Space invaders

First, it only does a per-pixel check if the laser has collided with the bounding box of doge. Then, it checks to see if 3 spots on the laser have hit solid pixels. If they're all transparent then the laser can pass through.

This isn't perfect, but it's good enough.

Thursday, 16 December 2021

Chapter 22 // Exercise 15 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2019 and a modified version of the std_lib_facilities header found here.

Chapter 22 // Exercise 15

Write a program that, given a file of (name, year) pairs, such as (Algol,1960) and (C,1974), graphs the names on a timeline.


I finally did this exercise after much procrastination. I also hate Bjarne because the scattergraph class I made back in chapter whatever doesn't exactly fit this example.

Instead of continuing to procrastinate I decided to hack it together one night....it's not exactly a timeline but well I guess it is. There is a line and there are times...done.


I had a look for rotated text in FLTK and it looks like it's just been implemented in 1.3.8, which was released last month. I'm still on 1.3.7 but I'll update at some point as that would've made this much easier.

Friday, 19 November 2021

C++ & SFML // Simple Event Queue System with Timings

In a previous post (C++ & SFML // Simple Timer), I showed how you can create a simple timing system in SFML to display messages on the screen.

In this one I created a very simple "Messaging Dispatcher" that receives messages and displays them. I followed along with the Ring Buffer design by Robert Nystrom in "Game Programming Patterns" to create this little demonstration.

C++ & SFML // Simple Event Queue System with Timings

Here, when E is released, it fires a message to the dispatcher. Each message has a random time to display between 1 and 4 seconds.

The code can be found here:

There are a few caveats with this simple system:
  • The queue is a fixed size so it will reject messages when full,
  • The queue doesn't create an empty slot until the top message has finished displaying; if this was set to display for 5 minutes and all the other messages in the queue only want to display for 1 second, the queue will be held up waiting for the top message to finish.
  • The dispatcher shouldn't really be handling the time.
  • Everything is passed by value.
All these things are fixable with some brain power but getting the first implementation out of the way is key to figuring the fixes out. For the next step, it would make sense to create a class that handles the updating and displaying of the messages that it receives from the dispatcher. This way the dispatcher only has to worry about getting the messages to the right place each update.

As the class is static, you could have anything send messages to the dispatcher. it could also be modified to display sprites or play sounds (although I would define a set of events as enums instead of sending the sprite/sound itself).

The code may look a little odd in the dispatcher but the above link to the chapter in Robert's book explains what it's doing far better than I will be able to.

Thursday, 18 November 2021

C++ & SFML // Simple Timer

So I'm currently working my way through making a clone of Space Invaders using SFML and I got to the point where I needed to do something after X amount of seconds. Usually I use FLTK and that would've been simple using it's callback system however SFML is event based and as such doesn't really supply a "timer system" out of the bag like fltk.

Therefore I googled and eventually found pieces of what I was looking for and managed to put this simple demonstration together for those who just want to figure out how to get seconds displayed on the screen. This is what the "tutorial" will give you:

C++ & SFML // Simple Timer displaying seconds passed

The program does 2 things:
1) Display the number of seconds since the program started
2) Every second it chooses a random message (from 4) to display.

Very exciting. Let's begin.

Here is the full code:

Have a look, it's all in main for simplicity. 

There is a clock that is restarted at the beginning of the main loop and assigned to DeltaTime.
SFML have handily provided a way to get the DeltaTime as seconds. All you have to do then is += that to a variable defined outside the loop and you have your seconds since the program started.

For the text, I just made a variable that holds the max time we want to show the text for (maxDelay) and another variable to hold the elapsedTime. Getting the elapsed time is the same as getting the seconds above only when updating which message to display, there is a check to see if the elapsed time has gone above the max delay. If so, it changes the message and resets the elapsed time back to zero.

The concepts here can be used for many other things like displaying a sprite for a given amount of time as well creating more complicated things, like an event queue system that dispatches events based on the elapsed time (much more useful for larger projects than above).

for an example on how this can be put together.