Category Archives: Development

Development of the game

Update 78

I have been working on the computer terminal, there is some animations, loading bars that need a lot of tweaking to have a good delay. After that, I have fixed a bunch of bugs and I am doing the last things for the level to be completed.

The game will not be finished the 1st march, I have a lot more polishing to do, add soundtracks, beta test the game.

I have added a lot of new content so the polishing phase is really starting now. With all this content the game will still be short because there are five levels, some levels are bigger than other so I expect the player to complete the levels with this pace:

Level 1 45 min
Level 2 15 min
Level 3 1 h
Level 4 1 h 15min
Level 5 15 min

There are a lot of small puzzle interaction, but I tried my best to make them logic and pretty much obvious once you know what you have to do. I think the difficult part at the beginning is making the first discoveries to understand what to do. There is no tutorial in the game (even for the controls) so you need to make some discoveries by yourself, try things. The game becomes easier after you have discovered some of the mechanism but I tried to add new things along the way to break the pace.

Update 77

This week I have made more content for the last level, a few more things and all the content be in the game. After that, there are some sprites to redo maybe make more animations and a lot of bug fixing.

I still have two weeks full time before job hunting, I know that at the end of the two weeks the game will not be polished enough. Most of the marketing (trailer, screenshots) will be done after the art is complete.

I don’t have the musics for the game yet, so I still have quite a bit of work before having an unpolished complete game. But that’s fine, the game needs to be polished to be ready, and it will be release only if it’s ready. The single most important things for games is quality. Quality takes a lot of trial and error and to do that you need a lot of time. The time can be reduced with experience, but since it is my first “big game” I have to go through almost all the errors. Hard work will eventually show someday…

Update 76

A lot of bug fixing this week and optimization, I have replaced the unordered_maps with less than 35 elements with vectors of pairs.

Q: Where did you find the number of 35?
A: Should you be using something instead of what you should use instead?

This change introduced some new bugs with the lifetime of some objects, and invalid iterators, but overall the speed and the memory footprint is improved.

The level progress well, but there is still a lot of work before it’s complete but mostly the game is at the end of its development. Let’s compare the number of lines of code of the current project vs the old one.

Some of the libraries in C are included in the project such as NFont, SDL_FontCache, theoraplay, and the code generated with glLoadGen. The c++ code has 17269 lines instead of 7360 lines at the time I was working on the big level 4, and I have added a lot of content since then. The functionalities are in C++ and the content is in XML, as you can see now 5476 lines instead of 460 lines. The project becoming more and more complex and “heavy” the debugging is becoming more difficult, but hopefully, I have also improved my skills since the beginning of the game.

 

Update 75

It seems TGA and PSD are the fastest image format read by stb_image. TGA is an old uncompressed format with support transparency layers, uncompressed images have the same size on the disk and in memory. PSD is compressed with RLE which is really simple and fast to decode however it do not compress a lot the image. I think I will be using PSD for the most sprite sheets now.

For my sprite sheets generator, I have had some problems with CImg trying to generate a sprite sheet with a lot of small images. So I now use OpenCV for the generation which seems to be the standard for computer vision. OpenCV is quite heavy, but everything is reliable and really fast compared to CImg.

The last level progresses a little bit each day and becomes bigger and bigger. This level has a lot of big images, for example, the level objects and one map need three sprite sheets. So maybe I will split the objects along maps more to balance the loading time and improve memory footprint.

Update 74

This week I have done more art for the game, and then packing the art into multiple sprite sheets. After that, I have spent multiple days trying to optimize the loading of the sprite sheet.

At first, I have been trying to implement a support for DXT texture, but with SDL_gpu using stb_image to load the texture into an SDL_Surface and then converting it to a GPU_Image. I have tried to decode the DXT textures with GLI, but after that SDL_gpu was not able to recognize the format.

Another problem with DXT texture is the artifacts produced by the compression so I have been trying to find a format lossless and fast. I have made a small benchmark for png with no compression and a lot of compression with stb_image and libpng.

compressed png (stb_image): 360.591 ms
uncompressed png (libpng): 543.351 ms
compressed png (libpng): 330.504 ms

I was expecting the png with no compression to be faster, the time to read the file seems to outweigh the decoding of the png. The small png are compressed with TruePNG and the zopflipng with the max compression settings. To make the game load faster I can first load all the asset for a level in the RAM and then for each map transfer the asset needed into the VRAM. The total memory needed to load the assets of the level is: 30 * 2048 *2048 * 4 = 503 MB. This is fine since most people have at least 4GB of RAM.

To make the game load faster I can first load all the asset for a level in the RAM and then for each map transfer the asset needed into the VRAM. The total memory needed to load the assets of the level is: 30 * 2048 *2048 * 4 = 503 MB. This is fine since most people have at least 4GB of RAM (steam survey).

To make the game load faster I can first load all the asset for a level in the RAM and then for each map transfer the asset needed into the VRAM. The total memory needed to load the assets of the level is: 30 * 2048 *2048 * 4 = 503 MB. This is fine since most people have at least 4GB of RAM.

For the moment, loading on the fly compressed png files seem efficient enough, the loading time is around 1 second for the map with the most sprites to load.

Update 73

The last level is progressing slowly because I have changed the story little bit at one point and there are a lot of art to redo, new dialogs, and even new shaders.

Most of my shaders are a modified version of some shaders found on shadertoy. This time I have combined two shaders to make one.
This one applies a glitchy effect on the image and also radial blur at the position of the uniform mouse.

varying vec4 color;
varying vec2 texCoord;
uniform sampler2D tex0;
uniform sampler2D tex1;
uniform float globalTime;
uniform vec2 resolution;
uniform float Strength;
uniform vec2 mouse;
#define AMPLITUDE 0.2 //0.2
#define SPEED 5 //0.05
float rand(float n){return fract(sin(n) * 43758.5453123);}
vec4 rgbShift( in vec2 p, in vec4 shift, in float Samples) {
shift *= 2.0*shift.w - 1.0;
vec2 rs = vec2(shift.x,-shift.y);
vec2 gs = vec2(shift.y,-shift.z);
vec2 bs = vec2(shift.z,-shift.x);
//vec2 pos = vec2(960.0*(resolution.x/1920.0), 540.0*(resolution.y/1080.0));
vec2 pos = vec2(mouse.x, mouse.y);
vec2 dir = (gl_FragCoord.xy-pos.xy)/resolution.xy*vec2(-1.0,1.0);
float r = 0;
float g = 0;
float b = 0;
float a = 0;
for (int i = 0; i < Samples; i += 2) {
r += texture2D(tex0,p+rs+float(i)/float(Samples)*dir*Strength).x;
g += texture2D(tex0,p+gs+float(i)/float(Samples)*dir*Strength).y;
b += texture2D(tex0,p+bs+float(i)/float(Samples)*dir*Strength).z;
a += texture2D(tex0,p+float(i)/float(Samples)*dir*Strength).w;
r += texture2D(tex0,p+rs+float(i+1)/float(Samples)*dir*Strength).x;
g += texture2D(tex0,p+gs+float(i+1)/float(Samples)*dir*Strength).y;
b += texture2D(tex0,p+bs+float(i+1)/float(Samples)*dir*Strength).z;
a += texture2D(tex0,p+float(i+1)/float(Samples)*dir*Strength).w;
}
return vec4(r,g,b,a);
}
vec4 noise( in vec2 p ) {
return texture2D(tex1, p, 0.0);
}
vec4 vec4pow( in vec4 v, in float p ) {
// Don't touch alpha (w), we use it to choose the direction of the shift
// and we don't want it to go in one direction more often than the other
return vec4(pow(v.x,p),pow(v.y,p),pow(v.z,p),v.w); 
}
void main() {
vec2 p = texCoord;	
vec4 c = vec4(0.0,0.0,0.0,1.0);
vec4 shift = vec4pow(noise(vec2(SPEED*rand(globalTime), 2.0*SPEED*rand(globalTime)/25.0)),11.0)*vec4(AMPLITUDE,AMPLITUDE,AMPLITUDE,1.0);
const int Samples = 64;
c += rgbShift(p, shift, Samples);
gl_FragColor = c/float(Samples);
}

I think most of the shaders of the game are done by now. There is a total of 4 fragment shaders. After that, I have more art to do, maybe some animations and then the ending video of the game (I not sure what to include in the video).

Update 72

This week I have worked exclusively on the last level, adding new things, redoing old stuff. I am trying to add new effects such as this:

With this amount of particles, I doubt the particles system can handle it, I need to make some performance test. The solution good solution is to use shaders, there is this tutorial with WebGL.

In Obduction, the effect is used multiples times, so it needs to be available for multiple cases. I am only using this once in the game, so I can probably prerender this effect with adobe after effect in a video. This is probably the fastest solution if I can make the video fast enough. If I use shaders to make this effect it can add a lot of complexity in adding multiples effects at the same time. And another good thing with video is I don’t have to worry about the frame rate, the video will run at 30 fps

This is probably the fastest solution if making the video is fast. If I use shaders to make this effect it can add a lot of complexity in adding multiples effects at the same time. And another good thing with video is I don’t have to worry about the frame rate, the video will run at 30 fps. I don’t need to have input from the player for the effect, this makes the use of something prerendered possible.

Update 71

A lot of optimization and bug fixing this week, the level did not progress at all.I have optimized the text rendering with a small library

I have optimized the text rendering with a small library NFont developed by the creator of SDL_gpu. I have gained a more stable framerate 60 fps when a shader is used.

I have also improved the loading time of the game by generating sprite sheets for the objects. Doing that I have discovered the rendering of SDL_gpu (which use OpenGL) is not precise when the image is rotated, the image becomes blurry. So I add to replace SDL_gpu with a library specialized in image processing to have something precise. I have chosen a small, simple and header only library: CImg. The replacement is not finished yet, I need to redo the sprite sheets for the animations, maps, and menu.

There are so many unexpected bugs coming along, it became really difficult to have accurate estimations. The only thing I know is I have two months left before the job hunting. Hopefully, everything will be finished by then, if not I will continue working part-time on the game. I am not going to release something unfinished or not polished enough.

Update 70

A lot of profiling and refactoring have been done last week. I have also implemented some dialogs for the last level. I am trying to optimize the allocation of vectors using the function reserve. But first I have searched all over the internet to find the best free profiler. The profiler packed with visual studio 2015 seem to give the most readable result, microProfiler is also a nice one because you can profile in real time.  CodeXL doesn’t have support for intel processor and the interface is not so good.

The profiler packed with visual studio 2015 seem to give the most readable result, microProfiler is also a nice one because you can profile in real time.  CodeXL doesn’t have support for intel processor and the interface is not so good.

I am trying to optimize the text rendering in the game because sometimes when there is a shader applied the framerate drop from 60 fps to 15 fps. Maybe this is only due to the shader and I need to find a shader profiler.

For Christmas, I have received a new graphic tablet: Wacom Intuos medium pro since the small bamboo gives me wrist pain after working several hours on a piece. This tablet is better is every way possible, interface, precision, size, quality. The only downside is the price, like every other Wacom products you need to spend hundreds of dollars to have something good. I think this tablet have the best size and quality for the price since Cintiq are overpriced.

They are other brands like Huion, Ugee, Yiynova, the problem is Wacom have so many patents and years on experience on tablets it’s very difficult for new competitors to achieve the quality. Only maybe a very big corporation like Apple, Microsoft, Samsung can pull off a quality similar. And there are compatibilities problems with drivers of Wacom and other brands.

Only maybe a very big corporation like Apple, Microsoft, Samsung can pull off a quality similar. And there are compatibilities problems with drivers of Wacom and other brands. This tablet is also a best seller on amazon after the cheapest tablet of Wacom.

Update 69

The level 4 is finished, I am now working on the last level. This level is the ending of the game so it’s very short gameplay wise and they are a lot of dialogs.

Last week I have done an explosion with the particles system, this explosion has 100000 particles. At first, 100000 was too much to handle for the particle system.

After a lot of profiling, the engine I have found some interesting things:

rand() is too slow, so replace it with a xorshift generator, in the game engine I use xorshit128:

static uint32_t xor128x = 123456789;
static uint32_t xor128y = 362436069;
static uint32_t xor128z = 521288629;
static uint32_t xor128w = 88675123;
inline uint32_t xor128(void) {
uint32_t t;
t = xor128x ^ (xor128x << 11);
xor128x = xor128y; 
xor128y = xor128z; xor128z = xor128w;
return xor128w = xor128w ^ (xor128w >> 19) ^ (t ^ (t >> 8));
}

Do not use std::vector to store the particles, push_back() and erase(iterator) are too slow. If you do you will see a lot CPU spent on memmove. A dynamically allocated array is way faster, only the initialization take time.

Use batching to reduce the number of draw call, with SDL_gpu the best way is to draw a lot of primitives is to use GPU_TriangleBatch. It adds a lot of code but you can’t have something faster than that.

unsigned short indices[3] = {0, 1, 2};  // These are references to the vertex array's vertices, 3 for a triangle
float values[8 * 3];  // Each vertex will need x, y, s, t, r, g, b, a (8 floats per vertex)
values[0] = x1;  // Position
values[1] = y1;
values[2] = s1;  // Texture coordinates (normalized)
values[3] = t1;
values[4] = r1;  // Color (normalized)
values[5] = g1;
values[6] = b1;
values[7] = a1;
values[8] = x2;  // Position
values[9] = y2;
values[10] = s2;  // Texture coordinates (normalized)
values[11] = t2;
values[12] = r2;  // Color (normalized)
values[13] = g2;
values[14] = b2;
values[15] = a2;
values[16] = x3;  // Position
values[17] = y3;
values[18] = s3;  // Texture coordinates (normalized)
values[19] = t3;
values[20] = r3;  // Color (normalized)
values[21] = g3;
values[22] = b3;
values[23] = a3;
GPU_TriangleBatch(image, target, 3, values, num_indices, indices, GPU_BATCH_XY_ST_RGBA);

With SDL you will need to use OpenGL VBO to achieve efficient batching.