Since the last devlog i mainly worked on actually implementing a working multiplayer demo and fixing all the issue i ran into along the way!
Entities and their components are being synced, the server is responsible for creating players…
However, the server is currently not in control of movement, crate placement and collisions which is why those things can’t be synced at the moment. So that’s probably gonna be the last few things I’m gonna work on before shipping :3
#2D-Game-Engine Devlog #6
Most of the time on this devlog was spent working on finishing networking. I was mainly fixing the packet system which had some issues due to the way the packet header and packet queue were implemented. But as you can see, now people are able to join the server!
Next, I’m gonna finally finish the ui and then work on the main remaining features, mostly relating to assets and textures in particular.
Added the ability to use different cameras for specific render operations. Cameras can be applied and un-applied using regular render commands, making them very usable.
Added render layers, so objects get rendered before/behind the player. Still has issues with the x coordinate lol.
Added some rudimentary ui elements like labels and buttons. The ui is direct mode so its pretty much just drop in lol. I also added nine-slice scaling so ui elements can be scaled nicely.
Next, I’m gonna implement collisions and some more ui functionality.
This is another boring internal devlog without flashy things lol. This time I implemented better file paths as well as data saving/loading.
Added a function to tectonic underlying library to resolve file paths. This should help with providing file paths. Also improved the memory situation for asset manager data.
The most exciting part of this devlog is probably the api for loading and saving data that uses a json-like object format. The format supports integers, strings, lists and compound objects (as im writing this im realizing, that i should probably also add support for floats lol).
Yea all in all, not that exciting even tho it took a ridiculous amount of time to get everything to work. Next, I’m gonna work on a small ui abstraction and then probably start polishing the engine to build a simple game with it and ship it.
I spent most of the last 5 hours getting the c toml library i’ve been using to work in my engine. This involved extending the library to support printing toml files, so they can be generated in code ^_^ This is particularly useful for replacing corrupt files and auto-generating files like settings and keybinds…
Since seperating keys in toml with dots means creating a table (this feature is awesome and annoying at the same time 😭 ), i had to find a way to parse nested tables. I did this using recursion and have used it in both the language file loader and the keybinds loader so far!
I also had to figure out a way to parse tables that are part of a nested table for some cases. I did that with a check that looks ahead at the next table’s values and ensures that they are also tables.
Finally got around to implementing more of the Asset Loader. It now supports shaders (which were a bit tricky due to consisting of fragment and vertex shaders). I also added loading for sounds 🎶
This should hopefully be the last piece of packet infrastructure required for the engine. It was mainly about encoding and decoding the packets properly, managing the sub processes and handling the shared resources.
Next, I implemented the render command for drawing text to the screen. Like all rendering actions, the text drawing is stored as a command in an array that keeps the order and then applied at the end of the current game loop iteration. It supports custom font sizes and colors, but I still have to add support for custom fonts in the future.
After text rendering i added events for keyboard and mouse input. This only handles the keys/mouse buttons being pressed and released. For checking if the key or button is held down, one can simply use a function.
On top of that i also added keymaps that allow for easy keybinds with default keys, selecting keys or mouse buttons for an action, reseting and saving to a toml file.
While adding names to the keymap, I realised that a proper engine should also supply a system for easily translating text. So I started adding a very basic translation manager that allows you to set a default locale and then load language files, change the current language…
However both the translation manager and the keymap can not be saved to a config/resource file at the moment. That’s why I am probably gonna have to extend the toml library I used in a previous project to support all those things. Alr, see you next time :3
Since the initial system for network packets was quite unintuitive and not very portable due to relying heavily on macros, I decided to try and simplify this system.
I started by moving packet decoding to the main thread. This means that the packet receiver thread now pushes the raw bytebuf to the packet (data) queue and the main thread decodes then packet right before the user handles it. This way, we can avoid enforcing thread safety for decode context data.
Next up, I rewrote the client thread system to be state-driven, just like the server. That way i can easily handle connecting to a server, disconnecting and stopping the client.
Also had to fix a bug where the thread handler wouldn’t pass the engine as an argument to the thread.
Tomorrow im gonna implement more of the actual packet encoding/decoding/handling, so i can actually make my example game playable
Oh btw, i made this little player dude for my example game lol. I should probably implement input, so that he can move around and isn’t just stuck in one place.
I started this project off, by writing a lot of the api and basic stuff like a backend system and implementation in raylib along with some basic assets and events.
I wanted to create an engine that is extremely simple to use and that allows you to create multiplayer games in a systems language like C without you having to touch stuff like threads and socket libraries.
Since its supposed to be a full on game engine, it should also be able to handle things like assets, events and rendering cleanly, out of the box.
While making the game multiplayer is optional, it is recommended to implement the game with separate client and server processes, to cleanly handle game logic and support future multiplayer.
The client and server process use separate engine data but do share a backend (In the future, the backend might be subject to splitting or at least ifdef guarding so you dont have to compile libraries like raylib on the server).
The main game logic, depending on your implementation can be shared obviously. Communication between sides happens using packets. When creating a packet one can either automatically serialize the packet struct by describing its layout or provide custom functions for encoding and decoding the data.
The actual game logic is mostly up to the user, whether you use an ECS, a more traditional entity approach or something completely different does not matter. To interact between the described processes, the user has to implement handling for packets in their game loop on both the server and the client.
Im probably gonna start working on actually being able to start and connect to servers. This will probably also involve major changes to my sockets library. After that I want to focus on more game engine related things like assets and texture tiling, music, sound and a bunch more.
I finished the app today and I now use it instead of wofi. I added arrow key navigation, scrolling, searching and app launching.
Under the hood the program uses my own .ini parser to parse .desktop files, when launching it substitutes the provided exec command with arguments like .desktop file location, translated name, icon…
The colors used in blank are no longer hardcoded and can now instead be determined while building the ui.
After resolving some issues that annoyed me in the last devlog, I was finally able to start adding more ui elements. The first of which was an image component (Displaying the fancy logo here).
Elements are now clickable. This works through an if check in the app loop that allows you to execute code based on the id of a ui element or the mouse button used.
I wanna add more ui elements and also layouts so people can do things like adding side panels and stuff lol. Might also work on making the existing components and overally style prettier.
Devlog - Rewriting the ui arranging and fixing bad multithreading code
Fixing bad multithreading code
I spent a lot of time recently debugging and fixing issues related to the multithreading code in blank.
Most of the issues were related to missing mutex locks or use-after-frees. They would lead to random crashes at runtime
without sufficient error messages. Using Thread-Sanitizer i was able to address most of them.
Rewriting the layout arranging code
Previously, layout arranging, the process of ordering and placing elements in the ui using a given layout, relied heavily on using ratios
and relative sizes to determine the position and size of individual elements. I have now rewritten the ui element layout process to use
absolute sizes which makes the system more reliable and less prone to floating point errors. I was also able to massively simplify the process,
which will hopefully result in better performance overall.
Next up
Next, i wanna improve the memory management and rely more on arena allocators for things like ui elements and render commands. This will
probably mean including mutexes to make the allocators that are used on multiple threads thread-safe.
I also wanna improve the api (header) to use a single file rather than being split into multiple files.
Groups allow you to group elements with a custom layout. They are stored in an array and then submitted to the regular layout, while still stored in the group component.
To achieve nested layouts i rewrote the way layouts are built to have them first calculate the minimum size of each component, then see what share of the screen they take up and then scale them so the entire screen is covered. While this is not fully functional yet, it allows for nested layouts in the first place. The group components are then flattened and submitted to the regular renderable ui components for rendering.
Next up im gonna work on polishing this, adding vertical support and refining the system to properly calculate how much of the screen gets taken up.
The basic system for ui-elements is now in place as can be seen by the button example. UI Elements need to be submitted, then the layout will be rebuilt and they are assigned their positions and sizes, unless specified directly. They are then rendered.
Some of the next ui components will be labels, text-fields and groups
Layouts allow you to customise the placement of components in a group or at the base ui building.
Right now, only the linear layout is implemented, but in the future i plan on adding grid-layouts and more probably lol
You are now able to handle events like window closing and window resizing in the app thread to rebuild the ui when required.
Next up, im gonna be working on implementing ui-groups and inner layouts for them.
Devlog: Implementing blank’s basic infrastructure
I started by adding a relatively flexible backend system, that allows you to use any backend for rendering, thread-handling… by passing in a single initializer function.
I also implemented very basic multi-threading, and task separation since the intention is to make it a ui with state.
Next up, I will probably work on getting basic ui element submission and rendering working.