Cereal Engine Attempt#1 | My game dev journey #5
So if you're subbed to my channel, I believe most of you have already seen this video. It was the first time I tried to make my own game engine! The idea was for me to get a handle on SDL as a way of getting graphics working. I came pretty far on this to the point that I could load images as sprites and even make little animations!
Step 1 was creating a graphics system that would help me open and close windows, set the resolution, enter the basic input, update, render cycle, and finally make fixing the framerate. Usually, players like to run games at an unlocked framerate, which is good for 3D games or games that require fast reflexes. Since the engine was completely 2D, I wasn't going to have many performance issues, none that I couldn't easily fix as it comes up. I still chose to fix the engine at 60fps because otherwise, I was getting almost 6000fps, this doesn't sound like a problem until we try to calculate delta time. The issue was that it was getting difficult to diagnose problems that are framerate independent. Fixing it to 60 allowed me to have a fixed value of delta time, and make a more specific expectation of the engine. The plan was to make the delta time calculation modular such that the player can choose to activate or deactivate it as they desire.
I ended up creating a separate class for Time, where I would call all the time-related functions. I used SDL_GetTicks() but in later attempts, I prefer using std::chronos instead simply because I could use it for an engine regardless of whether I use SDL or OpenGL + GLFW, or whatever. In this case, if I found that maybe instead of SDL I want to use SFML, I would have a hard time since a lot of the core functionality is strongly based on SDL.
Step 2 was to create a system that would easily help me get assets without having to open a file, load up the content, and what-not every time. My solution was simple, every time I asked for a file, it would check if it's already there in memory, if it is then the manager would return that, otherwise it would first load it up into memory and then return a pointer to that place in memory. I did this for just about everything including textures, audio clips, and texts. The texts were the most interesting because the way SDL handles text is it loads up a font, writes the text onto a surface, converts that surface into a texture, and then returns the texture. The text itself wasn't stored anywhere, rather it would store the font, and every time AssetManager::GetText() would have to be called every frame, or maybe if the text doesn't change, you could load up the text, and then store it in a variable elsewhere.
I don't exactly know why, but I chose to create my own Vector2 class. In hindsight, I could have easily used glm which would have been much easier, but at the same time, I wanted to make my own because in my head I was making a system like Unity, and for the most part, Unity has its own math class.
The next thing I did was implement an input class, that just allows me to call Input::GetKey() or Input::GetKeyDown() for the key inputs, and Input::GetMouse() or Input::GetMousePosition() for mouse inputs. It was pretty cut and dry, I couldn't make it easier if I tried, I just take in the input every frame, and then request the state of the keyboard and mouse for that frame as required.
I’m gonna gloss over the game object class because I refactored it into the transform component class as I made the Entity Component System which I’ll talk about later.
The Game Manager was a system that would import all the other systems and load up the entities I required. In hindsight, this is where I should have created a scene class that would open and close scenes as I call for them. That way I wouldn't have to rewrite a game manager for every level. In its current state, I would have to write a new class for each section of the menu, for each level, for the game over state, for every scene transition. It would be too much, it would be easier if I created a little save and load system for scenes and then every time just read and write to the scene files.
I then created an Entity Component System using a tutorial I found online. I had three main functions called Init, Update, and Render, after which I had two-component functions called AddComponent and GetComponent. The Component class had its own overridable Init Update and Render functions that would be called from the Entity class, and the idea was that I would just create a bunch of entities that would get automatically added to a list, and then that list would be iterated on as the game manager requires.
I started with the Transform component, which would allow me to assign a position, rotation, and scale to an object, as well as a parent and child option such that if an object has a parent, its position rotation and scale would move relative to its parents’. I also added a sprite component that would just load up sprites and draw them, as well as an animation component that would load up an image and then show you different parts of the image at a rate specified by a variable.
After releasing this video I got a bit sidetracked and didn't keep up afterward. I do want to bring this back though and I will be doing so by live streaming this on twitch! I think the Cereal Engine 3D was a bit aimless, I had a vague idea of what I wanted but I didn't keep up and never went into the specifics. What I’ll be doing differently this time around is that I’ll make it strictly 2D, and the other thing is that I will be making a 2D hack and slash game along with it. This way I don't just have an engine to make, but an expected outcome! If this is something that excites you then I’d love to see you there! Once this is at a point where I can jump off, I’ll get back to the 3D engine series. I don't want to call time just yet :)
I haven't worked out the scheduling yet, I’m waiting for some stuff to fall in place before I can commit to a proper time. until then be sure to subscribe to my youtube channel as well as my twitch!