Last weeks release was admittedly somewhat on the smaller and more basic side. So this time, let's have something a but more meaty: a library for loading game assets, from a folder on disk and/or a compressed zip file.
https://github.com/mattiasgustavsson/libs/blob/master/assetsys.h
The main thing here, is that it is possible to "mount" any number of folders or archives (zip files), optionally give each mount a prefix, and load/enumerate files and subdirectories as if all mounts were the same virtual file system.
Let's have a look at some code for how to use it:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49 | #define ASSETSYS_IMPLEMENTATION
#include "libs/assetsys.h"
#include <stdio.h> // for printf
void list_assets( assetsys_t* assetsys, char const* path, int indent )
{
// Print folder names and recursively list assets
for( int i = 0; i < assetsys_subdir_count( assetsys, path ); ++i )
{
char const* subdir_name = assetsys_subdir_name( assetsys, path, i );
for( int j = 0; j < indent; ++j ) printf( " " );
printf( "%s/\n", subdir_name );
char const* subdir_path = assetsys_subdir_path( assetsys, path, i );
list_assets( assetsys, subdir_path, indent + 1 );
}
// Print file names
for( int i = 0; i < assetsys_file_count( assetsys, path ); ++i )
{
char const* file_name = assetsys_file_name( assetsys, path, i );
for( int j = 0; j < indent; ++j ) printf( " " );
printf( "%s\n", file_name );
}
}
int main( int, char** )
{
assetsys_t* assetsys = assetsys_create( 0 );
// Mount current working folder as a virtual "/data" path
assetsys_mount( assetsys, ".", "/data" );
// Print all files and subfolders
list_assets( assetsys, "/", 0 ); // Start at root
// Load a file
assetsys_file_t file;
assetsys_file( assetsys, "/data/readme.txt", &file );
int size = assetsys_file_size( assetsys, file );
char* content = (char*) malloc( size + 1 ); // extra space for '\0'
assetsys_file_load( assetsys, file, content );
content[ size ] = '\0'; // zero terminate the text file
printf( "%s\n", content );
free( content );
assetsys_destroy( assetsys );
}
|
I guess this is pretty straightforward. It shows how to mount a folder, enumerate all files/subfolders, and load a file from it. The documentation in the library itself should be fairly exhaustive.
A good thing about multiple mounts, and one I often use in my own programs, is that I can mount a folder to load assets from during development, and a zip file to load from at release. It is easier to modify files in the folder as I go, and when I come to release the game, I just compress the folder into a zip archive, and then delete the folder. And the code just automatically uses the zip file, as the folder is no longer there - without me having to change the code.
An additional benefit of using assteys, is that it enforces the same path separator (forward slash) on all platforms, and also ignores upper/lower case on all platforms, unifying the way I access files, which can be a great help.
Now, this library differs from the previous ones in two ways. First off, it uses the open source "miniz" library to read zip files. This library is embedded inside assetsys.h, so you wouldn't know it when just using it. There's a way to have assetsys.h exclude the miniz definitions, if you'd rather include miniz into your project yourself.
Second, it has a dependency on another of my libraries, "strpool.h", which I released a few weeks ago. This one is not embedded though, so in order to use assetsys.h, you need to have strpool.h in the same path. I could have embedded it I guess, but I found this to be a bit awkward when continuing to develop my libraries.
So is this still a single header library? I guess technically it isn't, but I still choose to view it like that. It follows the same patterns as my other single header libs though, so at least it should feel familiar.
I am open to feedback on this. Maybe it would be better to embed strpool.h as well (with an option to use an external definition)? It is not unlikely I will consider this once the libraries have settled a bit.