Ludum Dare 44 – Tank Gauntlet

The year of 2018 is drawing to a close, and so for December what other game jam I should take part in but the 44th Ludum Dare. I decided to take part in the compo as once again I managed to have a free weekend to work on it.

Before the compo commenced, I used my previous experience with game jams including the 11 previous ones I took part in this year to write a set of rules I think other aspiring game devs should follow when they work. Other devs seem to like them so I figured I’d use these rules to go over how I made my Ludum Dare 44 entry, Tank Gauntlet.

These won’t be in the order I originally set them for the sake of describing the progress.

LD43-00010.gif

Know your Tools

I already had my tools in mind before the theme was announced, I used my SFML-based C++ engine “Vigilante, Piskell for animated sprites, Photoshop for any bigger assets, BFXR for SFX and cgMusic with LMMS for music. A lot of which I have used before, but for audio, I feel as though I need to find more other ways to create the SFX I need without the use of a sound library, and maybe diversify my music creativity (I used Megadrive Emulation Soundfonts so there was a bit of a 16 bit vibe to the music).

Small Scope and Stick Mostly with What You Know

I’ve usually been pessimistic the themes for Ludum Dare, as you are given the opportunity to vote on them in multiple rounds but the themes I like the most do not tend to get chosen. Therefore, when the theme was announced to be “Sacrifices must be made”, it wasn’t one that I was entirely keen on, and the only idea I had jotted down was “diet simulator”. While that idea was doable, it wasn’t really that original and a simulator might have been a more laborious task. I slept on it and figured I’d do a tank combat game. To fit the theme and my “1 unique/main, 2 optional mechanics” approach, the unique mechanic would be sacrificing gameplay input for power/speed, with the two optional mechanics being shooting and melee attacks.

Gameplay First

The first thing I did Saturday morning was work on the main game, by setting up a simple tilemap and a rectangle sprite for the player. Then I made sure the player could move, jump and collide with the tilemap, and the player could wrap in all directions.

Oh, a basic tip on how to handle platform jumps: Do math. Don’t bother guessing the right values for acceleration and jump velocity until you get it right, set up some variables and apply some vector maths, the below code will be enough to work out how high and how fast you want to jump, as well as how fast you want the player to move horizontally:

float Height = -85.0f; //Maximum Height of the Jump in Pixels
float Distance = 80.0f; //Distance travelled in Pixels
float Time = 0.5f; //Total Time of Jump
float MoveSpeed = Distance / Time; //Speed in order to travel the set distance in the set time
Player->MaxVelocity = sf::Vector2f(MoveSpeed, -2 * ((2 * Height) / Time));
Player->Acceleration.y = (-2 * Height) / (Time * Time);
Player->Drag.x = Player->MaxVelocity.x * 10;

If you want to extend it further, I’d recommend watching this GDC Talk on Game Maths Programming:

After using the code I have written previously for bullets, tweaking it to my liking, and adding enemy rectangles that can spawn periodically and move at different speed and be of different sides. I had most of what I needed.

LD43-00000.gif

I also added knife melee attacks and enemy damage before I worked on the menu that would handle input sacrifice.

LD43-00001.gif

Make Your Content Easy and Noticeable

For the last Ludum Dare, I made a racoon sprite that had a full running animation and was heavily detailed to the best of my ability, along with a tilemap and background to resemble a temple, and it took five hours. In the end, the environment didn’t look all that great and the racoon sprite was so small that you couldn’t see the detail.

This time around, I decided I wanted something simpler and easy to resemble, a tank. I loosely based the design on the StarFox Landmaster. With it being a tank, there didn’t need to be many frames.

LD43-00004.gif

I decided to keep the sprites and tilemap monochrome, using shading and tones with around 20 shades of grey in total so I could randomize the tint to add some variety to it. The enemies were kept red, as it’s an easy way to convey them as dangerous.

LD43-00007.gif

I found using fonts a bit more frustrating than normal, SFML doesn’t use the nearest neighbour for fonts so on a game with a low resolution (Tank Gauntlet uses 320×180), it’s difficult to use a font that isn’t too big and wouldn’t get blurry if the font size wasn’t set to a specific factor, if I found a way to implement bitmap fonts I might not have this much of an issue.

LD43-00011.gif

621 and Take a Walk

On both Saturday and Sunday, I walked into the town centre to get food and other things to relax my mind and not stress over the game too much. I also tried to get some good sleep, so I didn’t stay up too late and got up at around 8-9am on each day, oh and I took showers.

Find a Friend

One of the comments I got from this rule is that it doesn’t have to apply to team-based projects, having a friend to look over the game or provide feedback is beneficial to a solo project. As such, I’d like to thank my friend Kris for putting up with me sending him screenshots and asking about ways to make the game feel better and if I’m making the game too cruel or not.

I hope you find this simple process interesting, after doing 12 game jams this year I’m kind of happy this one felt mostly streamlined. There were some issues like with audio, not to mention technical issues post-submission, but I hope people find the final product enjoyable.

https://ldjam.com/events/ludum-dare/43/tank-gauntlet-control-vs-power

I was going to include a final statement for 2018 as a year in review here, but with the length of this one I’m going to have to add it as an additional post. Happy New Year everyone!

Advertisements

7DFPS and Desert Bus

Don’t worry to anyone who has been following what I’ve been doing this year, I haven’t missed October or November. I’m so close to finishing this goal of mine for 2018 and my next post will include not only that month’s jam entry but a summary of what I have done over the year. But for now, more jam games.

In October, I took part in 7DFPS, as the name implies the jam is focused around games in the first person shooter genre. The jam itself is probably best known for being the source of the wildly successful indie title SUPERHOT, where the prototype was created for the jam back in 2014. I decided to take part in this jam to see if I can add to the 3D game system I developed in September’s game jam.

7DFPS-00001

One issue I had when working on this system was that I didn’t have a fully working software frustum culling system, this would allow me to avoid draw calls on 3D objects that were not in view of the camera. What you see above was the issue I had before. It took a number of trial and errors and reading on how to properly set up and transform the plans before I had it properly culling the right objects. I also added some other mechanics I need to make this a classic FPS, jumping while taking into consideration multiple floors and shooting projectiles.

As you can see from the projectiles, some of them were clipping unusally. This is a side effect of rendering textured objects in OpenGL with alpha transparency, any objects that are drawn after transparent objects will have the scene’s pixel data overwritten. The solution to this is to sort your 3D objects, first by making sure he fully opaque objects are in front, and transparent objects by their distance from the camera (aka depth/transparency sorting).

7DFPS-00007.gif

Then came the big additions, I used most of the same code from Fursuit Run for the enemies so they had the same 2.5D effect, but changed around the movement code and added the ability for them to shoot as well.

For the game’s hook, I wanted to have a mechanic based on Ikaruga, where only opposing colours hurt you and the enemy. As such I had to give the player and each enemy two batch renderers, one for each colour, to share one bullet group, as well as a flag for their current colour. Then I made sure the game checked what the colour of the bullets, players and enemies were during each collision to make sure that only opposing colours set damage.

7DFPS-00006.gif

Then it came round to the presentation, I decided to make the level much bigger (no easy task considering the original protoype used hard coded map sizes), changed the textures and added bloom so the game’s visuals had a neon aesthetic.

In the last few hours, I struggled to find how to give the game a proper goal for single players. As I was getting tired, I decided just to have an orb that the player must find to collect. The gun in the middle was the last touch, which also helped made distinguishing the player’s colours easier.

I managed to fix a few bugs later on, although I think I’ve done most that I can with this. Although one change that I don’t think will get finished but was cool was I managed to get multiple cameras working for one scene, which makes split-screen gameplay possible! So for making a number of improvements to my engine’s 3D capabilities, I call this a win. You can play RvB here on itch.io.

7DFPS-00010.gif

For November, I took part in the Desert Bus Game Jam, which started last Friday (9th November) and I managed to finish on Thursday (14th November). This jam is done in conjunction with Desert Bus For Hope, a charity video game stream to raise money for Child’s Play. The theme for each DB jam is around the desert bus, which itself is based on a notorious unreleased game of the same name.

I decided after two 3D games to make it slightly easy on myself while being experimental, so for my Desert Bus Game, you would see two perspectives, one to dodge stuff on the road and the other to keep your bus balanced.

DesertBus-00002.gif

Unfortunately, as of writing I do not have a proper physics system in Vigilante, so I made do with the standard collision system. The rear-view had a bus that leaned in the direction by changing the origin of rotation to the bottom corners. One low-level thing I did do for this game was to update the VSprite from using SFML’s sprite object to VertexArrays. This would allow me to adjust each vertex on the fly, instead of being restricted to a single square. It also allowed me to freely change the texture coordinates so I could do the endlessly scrolling roads, as well as skewing them. I hoped I would be able to get proper perspective to work, but even vertex arrays have their limits when it comes to skewed sprites.

You can play Bus on the Desert here.

One month to go!

RainbowJam – Fursuit Run

For the month of September, I needed to take part in a game jam, but initially, I wasn’t sure which one. I looked through all the jams listed on indiegamejams.com and while you are spoilt for choice, not many were catching my eye. That was until one of my friends from the Birmingham Indie Developers, Kirsty Fraser, mentioned a game jam she was organising.

RainbowJam is a two-week games jam about exploring LGBT+ themes, running for its third year it’s partnered with the non-profit organization Queerly Represents Me and encourages representation and to “create games exploring and celebrating identity, gender, sexuality, sex, life, and love!” After working on Re(re4ti0n, I’ve felt a little urge to create some more experimental games that go against what I generally like, which would be arcade retro shooters/platformers with a neon glow or a retro aesthetic. I also knew I had some 3D functionality in Vigilante that deserve to be worked on enough for a complete game, so I spent a few weeks earlier in September to create a basic 3D game system.

Unfortunately, my 3D stuff was limited to what you can render. I consider Vigilante a 2D game framework with 3D elements, so I didn’t bother implementing 3D collision detection, but I had an idea: what if I make the game function in 2D space, but display in 3D space.

What I did was set up a small 2D enviroment with a tilemap and a basic sprite, and I set up the 3D models to display the scene based on the tilemap while the camera’s position and rotation is based on the sprite’s position and angle.

 

As you can see, I got the tilemape to display really well, the floor being a multi-segmented plane that could display mutliple different tiles in one model, and the walls being cubes that are scaled depending on where their neighbours are. Initially I was creating each cube as a separate model, which I felt was dangerously innefficient so I created a batch rendering group, creating one model but using multiple V3DObject instances to specifiy where that model should be rendered. I did need other things in the game though, stuff that the player can interact with, so I created a special model that could render a 2D sprite (including 2D animated sprites!) in a 3D enviroment, always facing the camera.

The last major thing I wanted was to add an additional level, as wondering a single room is good but extremely limited. As such I made a second tilemap, a model to represent a ramp of sorts and added variables and additional groups to tell what floor the player is on, and as such what should be displayed/collided with. The bigger challenge was implementing how the player will climb up stairs, as it also had to factor falling. Combining gravity with the player moving upwards if the sprite is overlapping the area where the said slope is situated took a lot of trial and error before I finally got a dituation where the player could fully explore the floor above and walk back down to the ground floor!

After making the slope look a bit more like steps, the demo was pretty much ready for RainbowJam.

To make a game for Rainbow Jam, I wanted to make a game that is about sharing love and making people happy. I went with a game about being a fursuiter because as a furry, I know the community is very supportive of LGBTQ+ people and as someone who’s performed in fursuits at conventions and meets, I feel the most important aspect is to make anyone you see feel happy, entertained and loved, even if it’s by portraying a character.

Making the attendees you interact with was probably the biggest challenge, I made a dough body sprite with frames for actions at each angle, and made the object switch frames based on what angle it’s facing from the player. As for the AI I considered setting up a finate-state machine, but fearing it would be too much work for a jam I went for a simple state model. I got my code for line of sight and path finding from previous projects in order to get the attendees  to walk around the floors they are on, wave at the player when they see them and either hug or prepare a camera for a photo, responding to what the player does at the same time.

To simulate the limited vision of fursuits was to overlay the screen with a mask. I added a little bobbing while walking for fun, as seen in the tweet below, however a fellow gamedev suggested getting the camera to bob in time as well, which ended up working pretty effectively!

All the graphics and audio was done on the last day, I used the dough sprite as a base while I apply the colour and details over it. I unfortunately realised the limitation I set myself using a 20×20 tile size, but I think there is enough space to see who is who. As for the enviroments I used some references for hotels, such as the carpet and ceilings. There is a chandelier on the ground floor, which I designed myself to be multiple 2D images rotated because I found most 3D models online to be needlessly complex.

At around 11pm on Sunday, I uploaded Fursuit Run to Itch.io making this the game for September. There is still a voting period which begins when the jam officially ends on the 6th October. So far the reception has been fairly positive, mostly from furries, some non-furries don’t appear to like the idea without actually playing the game as of writing. I’m pretty happy with how the game turned out, as well as the 3D system. There is definitely room for improvement, as there isn’t much optimization that could be done such as view frustum culling. I’m hoping to get it improve for my next games jam, 7DFPS.

Ludum Dare 42 – Closing in on Pascal

The game jam for August was Ludum Dare 42, so with it coming to a close, I thought it’d be good to talk about how the submission [Closing in on Pascal](https://ldjam.com/events/ludum-dare/42/closing-in-on-pascal) came about and what I learned from it.

Ludum Dare 42 was particularly exciting for me, as it was the first LD in a long time that I had a completely free weekend. As such, I decided to plan the first day entirely for gameplay, with graphics and audio on the second day. That way I get a solid game and then plenty of time to work on making it look and sound nice, you’ll find out why that plan isn’t flawless as it sounds.

When it came to the theme, I was already very pessimistic that it would be a theme I’d be happy with, it’s been a common trend for people to vote on the theme that no one wants. I even voted against the theme “Running Out of Space” but when it turns out to be the chosen one, I thought it was pretty good.

The concept of running out of space I had was inspired by the cartoon trap of the walls closing in on someone in a temple. I figured a game where the player has to reach an exit before the room crushes them to death.

Fortunately, I have a bit of experience with platformers in my game engine from a previous jam, so the tilemap, jump physics and mechanics such as wall jumping I have previously implemented.

LD42-00000.gif

The jump animations itself was done because I remembered the indie platformer INK having good squash & stretch. To achieve it I modify the scale so that it squashes inwards when going up and stretches outward. If I had more abilities to adjust the individual vertices I could do more fun aspects of moving like skewing.

LD42-00001.gif

Since my idea was inspired by a temple film/TV trope, I already had the visual theme in my mind. I also thought it would be good if I had a little cartoon character who’d look like Indiana Jones. It was fun working with pixel art and animation once again, but if I was to do this again I would have done a much simpler approach. The player character is way too small for the game screen, meaning that its animations are pretty much useless. I also had a bit of issue with making the colours stand out so it doesn’t feel all yellow and brown.

LD42-00002.gif

In the end, it took around 3 – 4 hours to work on the background environments and 5 hours to work on the player sprite and all the obstacles. If I went with a much simpler design or scrapped the temple theming and used the simple colours and shapes it would have been much clearer and easier to look at.

LD42-00009.gif

The sound and music was achieved with LMMS and BFXR. I like making NES-like chiptune in there but I do notice it’s restrictive in areas like tones and tempo, so I couldn’t get the sounds I want. It also didn’t help that thanks to the graphics, I had much less time to work on sound and music so it ended up rushed.

The post-jam has most of what I would have added or done better if I had time. Particle effects, using directional keys as well as the WASD buttons, and a better title logo. I would have also worked on more levels but seeing how many levels players are willing to go through, then maybe the existing levels should have been improved slightly.

I’m a little worried about what the rankings will be for this one, I’m definitely glad I could take part but I feel as though I wasted too much time on the graphics when a simpler approach would have been effective. You can go check out [Closing in on Pascal](https://ldjam.com/events/ludum-dare/42/closing-in-on-pascal).

Games on Command: Making of PEWBALL

For the month of July, I decided to take part in Floppy Jam as my games jam for that month. Floppy Jam was a small jam with a novel idea, make a game that could fit on a single floppy disk with the total memory capacity of 1.44 MB. I decided to take part but there is an issue, most of my typical development environments could not make a game that small, even if I made a completely procedural game. So I decided I should make a new engine, where it has the most basic elements (graphics, sound and input) in its smallest possible code. That’s when I decided to make a games engine using the command prompt.

 

The command prompt looks simple, there isn’t much you can output to the console and it’s typically slow, at least not fast enough for real-time smooth rendering. However, that’s if you use the standard iostream or stdio functions. The Windows library actually treats the console window like any standard window, with a handle for both input and output, as well as a screen buffer.

HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO csbi;

GetConsoleScreenBufferInfo(hConsole, &csbi);

SMALL_RECT rectWindow = { 0, 0, 1, 1 };
SetConsoleWindowInfo(hConsole, TRUE, &rectWindow);

COORD coord = { (short)SCREEN_WIDTH, (short)SCREEN_HEIGHT };
SetConsoleScreenBufferSize(hConsole, coord);

SetConsoleActiveScreenBuffer(hConsole);

It is possible to resize the window by shrinking the screen buffer to the smallest possible size, before scaling it up to the size you want. Frustratingly you cannot set the console to any size you want, as there appears to be a restriction that the size cannot be larger than 800×600 pixels. For the game, I ended up using 108×60 characters to make the game the largest widescreen resolution. You can also set the font and the font size, the window title and window position as well, which is enough customization you need even if it’s not possible to get fullscreen or “high resolution”.

Input can be read from the input handler, including focus, mouse and keyboard events. You can also use GetKeyAsyncKeyState() to get real-time input handling. Mouse positions can only be accessed from the input handler.

HANDLE hConsoleIn = GetStdHandle(STD_INPUT_HANDLE);

INPUT_RECORD inBuf[32];
DWORD events = 0;
GetNumberOfConsoleInputEvents(hConsoleIn, &events);
if (events > 0)
	ReadConsoleInput(hConsoleIn, inBuf, events, &events);

for (DWORD i = 0; i < events; i++)
{
	switch (inBuf[i].EventType)
	{
	case FOCUS_EVENT:
	{
		windowFocus = inBuf[i].Event.FocusEvent.bSetFocus;
	}
	break;

As mentioned earlier, using standard text input/output isn’t fast enough for real-time rendering, it’s also rather limiting. What we need is a way to render a full array of characters to the console screen, so how do we do that? And how do we display colour? Well, the best way deals with both birds with one stone, WriteConsoleOutput(). This function writes a full set of characters to the console, but you do not input strings, but a special Character format that allows you to set either ANSI or Unicode Characters, as well as what foreground and background colours for that element in the array. Command Prompts (as well as most pre-installed terminals) give you a maximum of 16 foreground and background colours each, although with the right character sets and other tricks you could create more colours. Once you have set up an array, you just call WriteConsoleOutput, using your console output handler, the array, the size of the array in width and height as well as the area you wish to draw to. A lot of this info I first discovered from the One Lone Coder through his ConsoleGameEngine tutorial series, as well as a header-only roguelike engine called rlutil.

///Buffer Screen
CHAR_INFO *bufScreen;

void drawChar(int x, int y, short c, int color, int bgColor = 0)
{
	if (x < 0 || y < 0 || x >= SCREEN_WIDTH || y >= SCREEN_HEIGHT)
		return;

	bufScreen[y * SCREEN_WIDTH + x].Char.UnicodeChar = (short)c;
	bufScreen[y * SCREEN_WIDTH + x].Attributes = color | (short)(bgColor * 16);
}

///Drawing the full buffer screen array to the console.
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
WriteConsoleOutput(hConsole, bufScreen, { (short)SCREEN_WIDTH, (short)SCREEN_HEIGHT }, { 0,0 }, &rectWindow);

///Clearing the buffer is as simple as setting all the elements to 0.
void clearScreen()
{
	memset(bufScreen, 0, sizeof(CHAR_INFO) * SCREEN_WIDTH * SCREEN_HEIGHT);
}

For timekeeping, an easy way to get efficient time tracking would be to use the standard library chrono. However, to avoid overhead and allow support with older systems, I needed a more specialised solution. Fortunately, I remembered a Windows-specific method of timekeeping from a video by a game developer going by the name TheCherno. While in more recent videos he recommends newcomers to use chrono, in a C++ game engine tutorial he used QueryPerformance functions. Essentially, you call QueryPerformanceCounter(), which will return you a timestamp accurate to the nearest microsecond of the PC’s performance counter. You can get the timestamp from the start of your loop, and another at the end to work out the total time to process a loop. While it is platform specific, because it’s part of the Windows API there is little overhead, and it’s extremely accurate.

bool StartCounter()
{
	LARGE_INTEGER li;
	if (!QueryPerformanceFrequency(&li))
		return false;

	PCFreq = double(li.QuadPart);

	QueryPerformanceCounter(&li);
	CounterStart = li.QuadPart;
	return true;
}

float GetCounterNanoseconds()
{
	LARGE_INTEGER li;
	QueryPerformanceCounter(&li);
	return (float)((li.QuadPart - CounterStart) / PCFreq);
}

float GetCounterMilliseconds()
{
	return GetCounterNanoseconds() * 1000.f;
}

Finally, for sound, I only wanted the simplest implementation I could find. All I needed was the ability to load Wav and Ogg files, and play them in parallel. Fortunately, that is possible with a single library and a header file. Randy Gaul developed a large collection of self-contained systems, each could be used with a single header. This included cute_sound, which does exactly what I wanted. It does have some minor faults such as crashing if you tried to delay a sound, and needs a significant updated to be friendly with modern compilers because of how it uses goto statements, and unfortunately because of how the Vorbis library works you cannot make it header only, but it’s not complex.

void loadAudio(const char* name, unsigned int id)
{
	freeAudio(id);

	const char *dot = strrchr(name, '.');
	if (!dot || dot == name) return;

	if (!strcmp(dot, ".ogg"))
		load_sound[id] = cs_load_ogg(name);
	else if (!strcmp(dot, ".wav"))
		load_sound[id] = cs_load_wav(name);
}

void playAudio(int id, bool loop, float volume, float pitch, float pan, float delay)
{
	cs_play_sound_def_t def = cs_make_def(&load_sound[id]);
	def.looped = loop ? 1 : 0;
	def.volume_left = volume;
	def.volume_right = volume;
	def.pitch = pitch;
	def.pan = pan;
	def.delay = delay;
	cs_play_sound(ctx, def);
}

The engine’s structure is that the user simply defines preprocessors for constant values, and includes a single header to get the engine’s full functionalities. All they need to do is to set up a function for handling updates and rendering (if they want to use real-time functioning) or event handling, and then call a function called run to start the engine. Keeping it like this basically means it’s possible to create tiny demos and games with whatever external tools they want.

When the jam actually started (yes I built a two-header library about a week before the jam began), I wrote basic state management system for the two scenes I wanted (title and game), as well as renderable objects. Each interactable object used a game object struct that had basic physics for movement and collision checks. The pinball environment was achieved by assigning each wall an ID, and that ID also corresponded with the angle of the slope as well as how it appeared. While most other game objects were defined as sprites, an overridden game object that has an array to represent a single static image, the flippers was a special sprite that manipulated that array based on how long a button was held down for. It also had special collision responses based on what stage the flippers were in, which proved a challenge when sprites could easily go through them.

What made working on this engine quite exciting was it really encouraged you to work with proper limitations. Unlike pico-8, where the limitations are hard-coded into the engine and its fantasy console, the command prompt had a small resolution and a limited colour palette purely because it was not intended for real-time rendering and gameplay, and the 1.44MB meant I had to think outside the box to find ways not to use too much memory, although, in the end, PEWBALL was under 400KB (possibly smaller still if I could get a compress heavy linker like crinkler to work).

One way to optimise was to replace having a particle emitter with particle objects with the rand() function and lots of basic maths to work out where particles would be over time. This technique was used for the starfield at the beginning as well as the explosions enemies and the player has in the game. Guns used a simple fixed sized array as an object pooling system, a similar one was also used for the enemies, which had their own struct that could be overridden for unique behaviour. Ogg files were compressed to their lowest quality, which gives them a small file size as well as gives a slightly distorted retro feel, helped by the 8-bit inspired music and sound effects that I used.

While I could have carried on development up to the deadline on August 10th, I needed to get a game finished for July, so I decided to stop on July 31st and submit it, announcing it’s release on August 1st. Little did I know, there was also a voting session that went on for a while. Out of the 25 submissions managed to achieve 7th, and the overall winners were Floppy Bug (In Quality and Design) and Crates in a Crate (in Gameplay). I’m pretty happy with where I placed considering the challenge I had in creating an entire engine, although I’m definitely impressed with Floppy Bug because the team behind it decided to one-up me and create a full 3D OpenGL engine in two weeks that took up 440KB.

Regardless, this one was a rather fun challenge. It kind of makes me want to look into development for other primitive systems, maybe I could try developing for an old console next, who knows? As for Linux, that might not be as possible as I hoped it would be. The problem with Linux Terminals is that they don’t have the same level of control as the Windows Command Prompt. It is possible to do things like resizing the terminal window, draw characters at certain positions and set the colours of characters using ANSI escape sequence strings, however, it isn’t as stable as I once thought, and there isn’t much documentation on getting it to work.

If you want to check out the engine itself, it’s called KitConsole and can be found on Github, and you can check out PEWBALL on Itch.io.

WizardJam – Re(re4ti0n

So June is almost over, and right now I’m writing as SGDQ is going on, but in the few weeks prior I was working on a game for my game-jam of June.

The game jam for this month is Wizard Jam, the seventh jam organised for the Idle Thumbs website and podcast. This was a jam that was fairly relaxed in comparison to most I take part in, being more than two weeks, with a very open themed convention. Instead of a singular theme, your theme is to choose from one of the many episode titles of the Idle Thumbs podcasts, which did take a while for me to pick, but I decided to choose one based on a little experimental project I was working on.

After being inspired from GDC earlier this year, I started work on a simple facial animation system to be used in the feature of a game. It used SFML’s primitive rendering system with interpolation and managed to get it to speak based on a simple string input. Wizard Jam gave me the opportunity to utilise it in a game with the theme “Read Our Lips” to test how effective it is.

The concept was a game where you were given quotes that are incomplete and corrupted, and your goal is to complete them based on your interpretation. The player had a short amount of time to enter their guess before being shown the next one. I went with giving the game a basic layout of an office, with a futuristic computer screen for the input and a faulty old looking monitor for the broken quotes. Thanks to SFML’s sf::Event::TextEntered, it’s incredibly easy to handle text input. It took less than a day to get the concept done, and an additional two days to get the initial layout done.

While I did take one day out to play around with the sfeMovie library, I spent most of the time polishing the existing game concept, improving the visuals and adding sound. I added camera movement so the text would be easier to see for a short amount of time. I updated the backgrounds so I could give a bit of a parallax effect.

The monitor was updated to use a lot of shaders, the title screen used the same amount of shaders. The main distortion shader was felixturner’s bad-tv-shader, combined with a fish-eye lens and scanline effect. I originally included a noise shader (as you can see in the previous tweet) but I found that darkened the colours so instead replaced it with the bloom shader that I’ve used in Berzerkatron and Gemstone Keeper. Finally, after some feedback, I added a simple chromatic aberration effect by offsetting the colour channels. It appeared to create an old and broken monitor effect that seemed to get some good impressions from people I showed it off on Discord servers.

There is no music for this game, just sound effects and ambient noise. Most of them were sourced from soniss’ GDC audio libraries, with some additional royalty free sounds for TVs and crowds. The name was kind of inspired by l33t speak, as I wanted to summarise the concept of the game (restoration/recreation) with the distortion you deal with.

The gameplay flow of having two minutes to guess as many quotes correctly was actually the last moment idea, originally you had to guess five random quotes with fifteen seconds each, but I felt that made the game too short for anyone finding it easy. One game dev on the Birmingham Indie Dev Discord suggested also making each quote progressively harder to start, but each would slowly become easier over a period of time. That way the game starts easy but gets difficult, but the currently displayed quote will slowly fix itself if you let it wait.

I was hoping to polish up the game a bit more over the weekend, but I went out to a party that unfortunately ended with the theft of one of my bags. While nothing game dev related was stolen, an expensive costume that I wear for public events was taken and it’s been reported to the authorities, although that didn’t stop the moment from dropping my emotional and motivational drive. I did get some last finishing touches done and missed the deadline by a few seconds, however the host was able to add Re(re4ti0n to the jam submission list the following morning.

You can play Re(re4ti0n by clicking the above image or right here.

SFML 2.5.0 Update (Or how I learned to hate RenderTextures)

 

 

On May 6th, the C++ Simple and Fast Media Library (or SFML for short) was updated to stable version 2.5.0, adding various updates including more optimial iOS support, bug fixes, added functionality for Text and Audio and various optimizations. For such a big release, it made sense to upgrade and get my Vigilante Game Framework updated, and why not update Gemstone Keeper while I’m at it?

Well it took nearly a month, but I did manage it in the end. Gemstone Keeper 1.0.5 has been uploaded to Steam, both for Windows and Linux!

As the title suggest, a lot of the work had to do with the updates to the sf::RenderTexture object. However, I don’t absolutely hate them, they are extremely useful for rendering a scene to an area of the screen, or to apply post-processing effects to. However the problem lied in how I was using them, and how the fixes done in the latest update effectively broke my engine’s rendering system.

The initial update showed promise, as my most recent game worked fine, but moving onto the framework’s examples and Gemstone Keeper showed that a lot of things weren’t rendering at all.

Vigilante Framework currently renders 3D models using Modern OpenGL, and while it was working fine with SFML 2.4.2, it rendered nothing with SFML 2.5.0. The solution was embarrassingly simple despite the amount of effort put into fixing it, including implementing my own version of SFML’s glCheck function and re-writing SFML’s own OpenGL example to run with modern OpenGL. When rendering the 3D scene, I modified some of the OpenGL states, which wouldn’t be an issue before but now those OpenGL states carry over into other contexts. The solution was to simply make sure that the GL states were reset BEFORE rendering the scene using a sprite object.

 ///Render 3D scene and apply to a sprite.
 RenderTarget.resetGLStates(); //Reset the GL states to the default for SFML
 Sprite->Draw(RenderTarget); //Render the sprite.

Gemstone Keeper however uses legacy OpenGL, and while I could have updated the VFrame source code but that could take more time to fix. Regardless, I was able to get it working by rearranging other objects that define sf::RenderTexture, including the bloom post processing effect and the help popup terminal.

Gemstone Keeper’s other graphics were another story. The approached I had been using up to this point was to render text objects onto a single rendertexture, and then store the generated texture to be used as a sprite, particle or tilemap. While this was okay for the time, but it is rather inefficient and bad for graphical memory.

I wanted to do a single-texture approach, where all the graphics are rendered onto a single texture, and a rectangle area is specified when creating renderable objects, for a while but I kept putting it off. SFML’s update, causing any newly created render textures to dereference generated textures, it was time to take this approach on. The best part is that most of the work was already done by myself with the additional code of Jukka Jylänki’s MaxRectBinPacker algorithm, all that needed doing was to change how I defined renderables from setting the texture to whatever the name of the genrated texture is to the name of one texture sheet, and to get the correct rectangle from a map/dictionary, searching by string ID.

CaptureCaptureCapture

Now this doesn’t mean the entire game’s visuals are rendered from one texture. Including the 3D gemstones, any assets that use a repeated texture grabs a subsection of the main texture as a copy, same applies to the VBackdrop as well. Getting the icon was a more painful looking process of converting the entire texture sheet to an sf::Image, so I can load in a subsection to a new sf::Texture object, and then convert the new texture object to an sf::Image in order to set it to be the application icon.

sf::IntRect iconArea = TextureData::p()->GetTextureRect(TextureData::p()->GetPortalTextureName(true));
 sf::Image image = VGlobal::p()->Content->LoadTexture("TextureSheet").copyToImage();
 sf::Texture tex;
 tex.loadFromImage(image, iconArea);
 VGlobal::p()->App->setIcon(iconArea.width, iconArea.height, tex.copyToImage().getPixelsPtr());

Like I said, not pretty.

So enjoy Gemstone Keeper, the number of you who own it. Now back to doing more stuff in C++…