s.Yep Yep!!
Back again this time with more changes, it is probably the last stop (I hope) before I start to talk about the new game on its own.
So what is new. Let see the main function for an overview, here is a test for almost all the features of the game engine:
BKP_Entity_Agent * G[3] ;
BKP_PlatformMap * Map;
BKP_Vec2i g_scr;
BKP_Vec2 TWH; //screen ratio based on game artist TWH.w = sprite.w * screen.w / expected.w same with TWH.h
int main(int argc, char **argv)
{
//bkp_setMouse(GLFW_CURSOR, GLFW_CURSOR_DISABLED, mouse_callback, scroll_callback);
//bkp_setLogInfo("logdir/",BKP_LOGGER_DEBUG, BKP_LOGGER_FILEOUT | BKP_LOGGER_TERMOUT, BKP_LOGGER_OAPPEND)
//change default log
//void bkp_setOpenGLInfo(3, 1) //minimal version 3.1
//bkp_setWindowInfo(1024, 768, BKP_TRUE,"BKP Test"); //fullscreen 1024x768
bkp_setWindowInfo(0, 0, BKP_FALSE,"BKP Test"); // window mode, auto detect screen resolution
if(bkp_startEngine(argv) != BKP_TRUE)
return EXIT_FAILURE;
bkp_input_Init();
g_scr = bkp_graphics_getWindowDimensions();
TWH = bkp_graphics_getTWH(1920, 1080);
bkp_input_setKeyPauseTimer(.05);
G[0] = (BKP_Entity_Agent *) bkp_memory_getTicket(sizeof(BKP_Entity_Agent));
G[1] = (BKP_Entity_Agent *) bkp_memory_getTicket(sizeof(BKP_Entity_Agent));
G[0]->spritesheet = bkp_graphics_2dloadSurface("data/graphics/h_none.png");
G[1]->spritesheet = bkp_graphics_2dloadSurface("data/graphics/platform.png");
init_player(G[0]);
setMap();
BKP_Font * myfont;
myfont = bkp_graphics_newFont("data/fonts/DejaVuSans.ttf", 64, 128);
BKP_ScreenText * fps = bkp_graphics_appendTextPool("do not care", 64, myfont, bkp_vec2(20 * TWH.w,64 * TWH.h), bkp_vec2(.3 * TWH.w,.3 * TWH.h), bkp_vec4(0.98f,0.98f,0.2f,1.0f));
BKP_ScreenText * mem = bkp_graphics_appendTextPool("can't see me", 128, myfont, bkp_vec2(20 * TWH.w,96 * TWH.h), bkp_vec2(.3 * TWH.w,.3 * TWH.h), bkp_vec4(1.0f,1.0f,1.0f,1.0f));
while(G[0]->input->Cancel == 0)
{
bkp_input_capture(G[0]->input);
manage_platforms(Map); //rotating and moving platforms
manage_player(G[0]);
bkp_graphics_2dscroll(G[0]->dyn.gbox);
Ugp_draw();
_update_fps_counter( fps);
_update_memUsage(mem);
}
bkp_graphics_releaseTextPool(fps);
bkp_graphics_releaseTextPool(mem);
bkp_graphics_freeFont(myfont);
unsetMap();
bkp_memory_releaseTicket(G[0]->input);
bkp_memory_releaseTicket(G[0]->spritesheet);
bkp_memory_releaseTicket(G[1]->spritesheet);
bkp_memory_releaseTicket(G[0]);
bkp_memory_releaseTicket(G[1]);
bkp_logger_write(BKP_LOGGER_INFO,"\t________________________________\n");
bkp_logger_write(BKP_LOGGER_INFO,"\t*POOLS* Allocated : %.1f Kb\n",(float)bkp_memory_allocated() / 1024);
bkp_logger_write(BKP_LOGGER_INFO,"\t*POOLS* Used : %.1f Kb\n",(float)bkp_memory_usage() / 1024);
bkp_logger_write(BKP_LOGGER_INFO,"\t*POOLS* Free : %.1f Kb\n",(float)bkp_memory_free() / 1024);
bkp_stopEngine();
return EXIT_SUCCESS;
}
For those who have an allergy to global variables don't worry it is just for testing :P.
So, now before starting the engine, it is possible to change some engine states by using functions like bkp_set*(); here they are commented.
When the engine starts it will set up my memory pools. Those are a number of memory stacks of a different size. Every time I require some memory it will give me a "ticket" (pointer of size N) popped from stack #n. All allocations are made at the first time an object of size N is required. For example, if I want 64bytes and the pool is empty it will malloc(64 * default_number_of_object) then later I will just need to pop the ticket or push it back. There is no garbage collector but memory leaks are detected and logged.
PRO: the number of calls to malloc is very low or at least computable before a game starts.
CON: the default values may waste memory. However, using bkp_set_memory*() allows changing the parameter for pools of the same memory. Anyway, I will need to make statistics for each game to calculate how to set up the memory manager.
G[0] = (BKP_Entity_Agent *) bkp_memory_getTicket(sizeof(BKP_Entity_Agent));
This line shows how to ask a ticket (pop a block). I can show the details of the memory manager if asked.
Next is the text-engine (if I can call it like this), it is still temporary as I am still a beginner with freetype and I am not sure I will continue with it at the moment, I used it because I want a result and don't want to reinvent the wheel. The function to draw is the following, it needs a font loaded by bkp_graphics_newFont (not sure if I want to separate Text module and Graphics module yet)
void bkp_graphics_renderText(const char * str, BKP_Font * font, BKP_Vec2 pos, BKP_Vec2 scale, BKP_Vec4 color)
In the previous code you don't see any calls of that function because I use an OnscreenTextBuffer, it is a buffer of linked lists where each node contains everything to draw a text on screen such as Text, Position, Scale, Color. Any text can be added to buffer with the following:
BKP_ScreenText * fps = bkp_graphics_appendTextPool("do not care", 64, myfont, bkp_vec2(20 * TWH.w,64 * TWH.h), bkp_vec2(.3 * TWH.w,.3 * TWH.h), bkp_vec4(0.98f,0.98f,0.2f,1.0f));
Here a pointer to the buffer entry is returned to "fps", so you guess for which purpose. 64 is the size in bytes of the text length. Once set, the size cannot change but the content can be changed, for example, like this:
sprintf(fps->text, "%s : %d", "fps = ", vfps);
void _update_memUsage(BKP_ScreenText * stext)
{
ssize_t s = bkp_memory_using();
sprintf(stext->text,"memory pool : %.2fMb | %ldKb |%ld bytes", (float)(s/ 1024) / 1024, s / 1024, s);
return;
}
and the internal function will write all texts like this:
void bkp_graphics_OnScreentext()
{
if(NULL == stc_Btext->head) return;
BKP_ScreenText * ps = stc_Btext->head; // if text not initialize will segfault. Warning
for(; NULL != ps; ps = ps->next)
bkp_graphics_renderText(ps->text, ps->font, ps->pos, ps->scale, ps->color);
return;
}
The last thing I did was scrolling. I didn't do anything fancy or special here, just adding a VIEW matrix in the shader. Every time I move the view portbkp_graphics_2dscroll(G[0]->dyn.gbox); in the GPU otherwise it keeps its values. It is a single function that takes as a parameter a rectangle to focus on. In the following example, the center of the player's bounding box is used as the point of focus:
bkp_graphics_2dscroll(G[0]->dyn.gbox);
Something I didn't show here is that is possible so set an autoscroll by just giving a default x/y speed to the scroller once again with a function like bkp_set*().
If I comment one of the bkp_memory_releaseTichet() lines at the end we get this in the log file or/and screen:
[ INFO ][ 2018-06-21 15:56:08 ] -> Graphics Engine stopped [OK]
[WARNING][ 2018-06-21 15:56:08 ] -> Ticket for Memory pool are not all released, **MEMORY LEAK** P(4) s:320
[ INFO ][ 2018-06-21 15:56:08 ] -> Destroying Memory pools[OK]
The memory leak is detected in the Pool number 4 (320 bytes/ticket) unfortunately I do not provide a way to find exactly where it is. However, it is already a good hint to find it.
Now a small video to show everything. I made the character bounce to show clearly all platforms' properties.
What will come next?
So far in my learning process I start to go away from my main goal, indeed if this demo shows a Mario like a game, it is not at all what I am making but some features I needed are now present. As an example, the double jump will not be in my game but I implemented it. It is time to pause the game engine development and go to game dev. Next step should be creating the main character and his/her basic movements.
I spend a lot of time separating tasks, making the project ready to receive other contributors. That's why I am creating and documenting all the functions.
I also have an artist now, not official yet but... Anyway, my experience made me suspicious.
Something I have to recognize I am bad at is levelling. I needed such a long time to pass all basic levels of Soul of Mask, this game is difficult and the difficulty doesn't come crescendo, it is too sudden. I didn't even finish the last level, it looks impossible for me.
And as always thanks for reading.
Until next time
ps: I am thinking about making the game engine open-source, for those who read it please tell me in the comment what you think about that Idea.
Nice job on the platforms and rotations.