+56
etc/style.c
+56
etc/style.c
···
1
+
#ifndef __main__
2
+
#define __main__
3
+
4
+
5
+
/*
6
+
Include order doesn't really matter to me, however I do like to keep them reasonably organized:
7
+
1. "Header" includes (i.e, keraforge/_header.h).
8
+
2. Macro/common headers (i.e, keraforge/log.h).
9
+
3. Internal library includes (i.e, keraforge/*.h).
10
+
4. External library includes (i.e, raylib.h, raymath.h, etc).
11
+
5. C standard library includes.
12
+
*/
13
+
#include <keraforge.h>
14
+
#include <stdio.h>
15
+
16
+
17
+
/*
18
+
Please follow good practice when defining macros:
19
+
- #undef after usage.
20
+
- Use do/while blocks for parameterized macros.
21
+
- Wrap constant macros in parenthesis, unless its a string that can be safely concatenated.
22
+
*/
23
+
24
+
25
+
/* Additional keywords (excl. const) should be on their own line. */
26
+
static
27
+
/* All public items should be prefixed with kf_. All static items should use _kf_. */
28
+
int _kf_parse(int argc, /* Attach pointers with the identifier, not the type. */ char *argv[])
29
+
/* Allman braces */
30
+
{
31
+
/* Tabs for indentation, spaces for alignment. */
32
+
33
+
/* Space out your semicolons in for loops. */
34
+
for (int i = 0 ; i < argc ; i++)
35
+
fprintf(stderr, "%s", argv[i]);
36
+
37
+
if (true)
38
+
{
39
+
/* ... */
40
+
}
41
+
else
42
+
{
43
+
/* ... */
44
+
}
45
+
46
+
return 1;
47
+
}
48
+
49
+
int main(void)
50
+
{
51
+
(void)_kf_parse(0, NULL);
52
+
return 0;
53
+
}
54
+
55
+
56
+
#endif
+73
etc/style.txt
+73
etc/style.txt
···
1
+
2
+
Style Guidelines
3
+
================
4
+
5
+
As a preface: I break these guidelines occasionally. It is
6
+
important to note that I often find myself up into the
7
+
early morning hours (sometimes even as early as 03:00)
8
+
developing Keraforge. Late-night coding sessions tend to
9
+
lead to mistakes that I accidentally push to prod. Feel
10
+
free to point these mistakes out to me!
11
+
12
+
Zen
13
+
---
14
+
15
+
1. Keep types simple.
16
+
- If your type is complex enough to be unreadable, maybe
17
+
you should change your type.
18
+
- Function pointers may be disgraceful to write, but if
19
+
you write your code in such a way that avoids writing
20
+
the type more than once then you'll be fine.
21
+
- See: `struct kf_actorregistry`. I use some quirky
22
+
types there, but nothing too unreadable. Notice how I
23
+
never rewrite those types again and notice that I am not
24
+
using a typedef either.
25
+
- Additionally, if the user is never going to use that
26
+
type then it almost definitely does not need to be
27
+
typedef'd.
28
+
2. Documentation is important.
29
+
- "Self-documenting code" is not sufficient. If the item
30
+
is public then it should have an explanation.
31
+
- The ONLY exceptions to this rule are blatantly obvious
32
+
struct fields, such as `position`, `velocity`, etc.
33
+
- A few lines of documentation will save you a massive
34
+
headache in the future.
35
+
3. Macro magic is garbage, but unmaintainable code is worse.
36
+
- Using macro magic sparingly can help prevent you from
37
+
being smitten by the DRY deities. Save yourself today!
38
+
- See: math.h, log.h, and bini.h for cases where macro
39
+
magic is acceptable.
40
+
4. Keep names terse but readable.
41
+
- I don't want to see stdlib-style function names, but I
42
+
would much rather that over a name ripped from an
43
+
object-oriented C.
44
+
- If you must use a stdlib-style function name to remain
45
+
terse, then please provide a sentence in its docs to
46
+
explain the name.
47
+
5. Most importantly: Be simple.
48
+
- This often means sitting at your screen pondering the
49
+
best implementation for something rather than simply
50
+
using the first one that comes to mind.
51
+
- It's okay to sacrifice a bit of performance for more
52
+
maintainable code.
53
+
- If you must write complex code, please explain why via
54
+
a brief comment.
55
+
56
+
Basics
57
+
------
58
+
59
+
See <etc/style.c> for a sample of the style with comments
60
+
explaining each main point.
61
+
62
+
For more specifics, please give a skim throughout the
63
+
codebase itself.
64
+
65
+
- Prefer [iuf](8|16|32|64) over (float|double|(u?int(8|16|32|64)_t)).
66
+
- Do not typedef function pointers (see Zen #1), structs, enums, or unions.
67
+
- Use global variables instead of requiring the user to maintain state.
68
+
See: kf_uiconfig, kf_actors, kf_actorregistry, kf_state, etc.
69
+
- Use `struct kf_vec2(type)` instead of `struct kf_vec2f32`.
70
+
- Do not modify libraries included in the source.
71
+
Those are: bini.h.
72
+
- I'm not afraid to postfix _t to typedef'd types. The standard is useless here since we prefix kf_ anyway.
73
+
(I think this standard is useless *to begin with*, but I digress)
+11
-7
include/keraforge/actor.h
+11
-7
include/keraforge/actor.h
···
2
2
#define __kf_actor__
3
3
4
4
5
-
#include "keraforge/bini.h"
6
5
#include <keraforge/_header.h>
7
6
#include <keraforge/math.h>
8
7
#include <keraforge/world.h>
9
8
#include <keraforge/math.h>
10
9
#include <keraforge/sprites.h>
10
+
#include <keraforge/bini.h>
11
11
#include <raylib.h>
12
12
13
13
···
19
19
TODO: This will probably be better as a hash table (especially for kf_actor_getregistryid). */
20
20
struct kf_actorregistry
21
21
{
22
+
/* Amount of actor types currently registered. */
22
23
int count;
24
+
/* Keys for each actor. */
23
25
char *key[KF_MAX_ACTOR_TYPES];
24
-
/* Save the actor to a binary stream. */
26
+
/* Save actor to a binary stream. */
25
27
void (*serialize[KF_MAX_ACTOR_TYPES])(struct kf_actor *self, struct bini_stream *bs);
26
-
/* Load the actor from a binary stream. */
28
+
/* Load actor from a binary stream. */
27
29
void (*deserialize[KF_MAX_ACTOR_TYPES])(struct kf_actor *self, struct bini_stream *bs);
28
-
/* Called every frame to update the actor. Don't forget about deltatime (kf_dts, kf_dtms)! */
30
+
/* Called every frame to update actor. Don't forget about deltatime (kf_dts, kf_dtms)! */
29
31
void (*tick[KF_MAX_ACTOR_TYPES])(struct kf_actor *self);
30
-
/* Called every frame to render the actor. */
32
+
/* Called every frame to render actor. */
31
33
void (*draw[KF_MAX_ACTOR_TYPES])(struct kf_actor *self);
32
-
/* Spritesheet for the actor. */
34
+
/* Spritesheet for actor. */
33
35
struct kf_spritesheet sprite[KF_MAX_ACTOR_TYPES];
34
36
};
35
37
/* Global actor registry instance. */
···
38
40
/* Represents any kinematic body in the world (players, NPCs, etc). */
39
41
struct kf_actor
40
42
{
41
-
/* Integer identifier for this actor, comes from kf_actorregistry. */
43
+
/* Integer identifier for this actor, comes from kf_actorregistry.
44
+
This is unique per-actor-type, not per-actor. */
42
45
int id;
43
46
/* The actor's position. */
44
47
struct kf_vec2(f32) pos;
···
67
70
};
68
71
/* Linked list of actors. */
69
72
extern struct kf_actor *kf_actors, *kf_actors_last;
73
+
/* Number of actors currently in the world. */
70
74
extern u32 kf_actor_count;
71
75
72
76
+2
include/keraforge/error.h
+2
include/keraforge/error.h
+11
include/keraforge/graphics.h
+11
include/keraforge/graphics.h
···
10
10
/* Represents either a model or a menu. */
11
11
struct kf_modal
12
12
{
13
+
/* The title of this modal. */
13
14
char *name;
15
+
/* Called when this modal is closed. */
14
16
void (*exit)(void);
17
+
/* Called when this modal is opened/ */
15
18
void (*init)(void);
19
+
/* Called every frame before rendering anything. */
16
20
void (*update)(void);
21
+
/* Called every frame to render the world. */
17
22
void (*render_world)(void);
23
+
/* Called every frame to render the UI. */
18
24
void (*render_ui)(void);
25
+
/* Any extra data this needed.
26
+
You are expected to allocate and free this yourself in init/exit respectively. */
19
27
void *data;
20
28
};
21
29
···
63
71
extern f32 kf_dts;
64
72
65
73
74
+
/* Measure text using the default font. */
66
75
int kf_measuretext(int size, char *text);
76
+
/* Draw text using the default font. */
67
77
void kf_drawtext(Color c, int x, int y, int size, char *text);
78
+
/* Draw text with a shadow using the default font. */
68
79
void kf_drawtextshadowed(Color c, int x, int y, int size, char *text);
69
80
70
81
+6
-1
include/keraforge/input.h
+6
-1
include/keraforge/input.h
···
6
6
#include <raylib.h>
7
7
8
8
9
+
/* Represents an unknown mouse button. Provided by Keraforge, not by Raylib. */
9
10
#define MOUSE_BUTTON_UNKNOWN ((MouseButton)-1)
11
+
/* Represents an unknown gamepad axis. Provided by Keraforge, not by Raylib. */
10
12
#define GAMEPAD_AXIS_UNKNOWN ((GamepadAxis)-1)
11
13
12
14
#define KF_INPUTBIND_MAX UINT8_MAX
···
17
19
/* Struct-of-Arrays for keybindings. */
18
20
struct _kf_inputbinds
19
21
{
20
-
kf_inputbind_t count; /* must start at 1. 0 is the `none` keybind. */
22
+
/* Amount of input bindings registered.
23
+
Must start at 1. 0 is the `none` keybind. */
24
+
kf_inputbind_t count;
25
+
/* String IDs of each binding. */
21
26
char *id[KF_INPUTBIND_MAX];
22
27
KeyboardKey key[KF_INPUTBIND_MAX];
23
28
KeyboardKey alt[KF_INPUTBIND_MAX];
+1
include/keraforge/inputbinds.h
+1
include/keraforge/inputbinds.h
+8
-2
include/keraforge/log.h
+8
-2
include/keraforge/log.h
···
1
1
#ifndef __kf_log__
2
2
#define __kf_log__
3
3
4
+
4
5
#include <stdio.h> /* fprintf, stderr */
5
6
#include <stdlib.h> /* exit */
6
7
#include <stdarg.h>
7
8
9
+
10
+
/* Log a message. */
8
11
void kf_vlog(char *level, char *fmt, va_list va);
12
+
/* Log a message. */
9
13
void kf_log(char *level, char *fmt, ...);
14
+
/* Log a debug message. */
10
15
void kf_logdbg(char *fmt, ...);
16
+
/* Log an info message. */
11
17
void kf_loginfo(char *fmt, ...);
18
+
/* Log a error message. */
12
19
void kf_logerr(char *fmt, ...);
13
20
14
-
/* Errors */
15
21
16
22
/* Throw a formatted error message without printing a traceback or exiting. */
17
23
#define KF_THROWSOFTER(MSG, ...) \
···
36
42
} \
37
43
while (0)
38
44
39
-
/* Sanity Checking */
40
45
41
46
#ifdef KF_SANITY_CHECKS
42
47
/* Indicate that the given expression should never resolve to false and throw an error if it manages to. */
···
61
66
# define KF_SANITY_CHECK(EXPR, MSG, ...) do { ; } while (0)
62
67
# define KF_UNREACHABLE(MSG, ...) do { ; } while (0)
63
68
#endif
69
+
64
70
65
71
#endif
+3
include/keraforge/sprites.h
+3
include/keraforge/sprites.h
···
10
10
Can be used for animations or texture atlases. */
11
11
struct kf_spritesheet
12
12
{
13
+
/* The texture to pull sprites from. */
13
14
Texture2D texture;
15
+
/* Width and height of each sprite in this sheet. */
14
16
u16 spritewidth, spriteheight;
17
+
/* Number of sprites in this sheet. */
15
18
u32 nsprites;
16
19
};
17
20
+1
include/keraforge/string.h
+1
include/keraforge/string.h
+3
include/keraforge/time.h
+3
include/keraforge/time.h
+11
-11
include/keraforge/world.h
+11
-11
include/keraforge/world.h
···
8
8
#include <raylib.h>
9
9
10
10
11
+
/* Size of tiles in pixels. */
11
12
#define KF_TILE_SIZE_PX 16
12
13
14
+
/* Number of bits to use for storing tile IDs. See: struct kf_tile. */
13
15
#define KF_TILE_IDWIDTH 10
16
+
/* Number of bits to use for storing tile datum. See: struct kf_tile. */
14
17
#define KF_TILE_DATAWIDTH 4
15
18
16
-
#define KF_TILEID_MAX (1023) /* 2^10-1 */
19
+
/* Number of max tiles. This should be (2^KF_TILE_IDWIDTH-1). */
20
+
#define KF_TILEID_MAX (1023)
17
21
18
22
/* Used to store tile IDs. Stored in 10 bits; max value is 1023! */
19
23
typedef u16 kf_tileid_t;
···
31
35
32
36
33
37
/* Represents a singular tile in the world. */
34
-
// struct kf_tile
35
-
// {
36
-
// kf_tileid_t subid : KF_TILE_IDWIDTH;
37
-
// kf_tileid_t id : KF_TILE_IDWIDTH;
38
-
// kf_tiledatum_t data : KF_TILE_DATAWIDTH;
39
-
// } __attribute__((packed));
40
38
struct kf_tile
41
39
{
42
-
kf_tileid_t subid ;//: KF_TILE_IDWIDTH;
43
-
kf_tileid_t id ;//: KF_TILE_IDWIDTH;
44
-
kf_tiledatum_t data ;//: KF_TILE_DATAWIDTH;
45
-
};// __attribute__((packed));
40
+
kf_tileid_t subid : KF_TILE_IDWIDTH;
41
+
kf_tileid_t id : KF_TILE_IDWIDTH;
42
+
kf_tiledatum_t data : KF_TILE_DATAWIDTH;
43
+
} __attribute__((packed));
46
44
47
45
/* Represents a world (or a subworld, often called "rooms"). */
48
46
struct kf_world
···
93
91
bool transparent;
94
92
};
95
93
94
+
/* Register a tile. */
96
95
kf_tileid_t kf_addtile(struct kf_tile_opts opts);
96
+
/* Register a tile. */
97
97
#define KF_ADDTILE(...) (kf_addtile((struct kf_tile_opts){ __VA_ARGS__ }))
98
98
99
99
/* Create a world using the given width and height.
+14
readme
+14
readme
···
60
60
`sh run.sh build run`
61
61
is all you'll need to run while developing.
62
62
63
+
Please note that I will be hesitant to accept PRs to this
64
+
codebase. I am very nitpicky with my code style and if your
65
+
PR does not match it (or if it goes out-of-scope, adds
66
+
useless/redundant functions, further pollute global scope,
67
+
etc), then I will likely decline the PR or request a number
68
+
of changes. Ideally, please communicate with me before
69
+
submitting a PR just for it to get closed. You can find my
70
+
contact information on my website. I don't want you wasting
71
+
your time or effort!
72
+
73
+
Additionally, please read through <etc/style.txt> before
74
+
attempting to contribute. It'll make your life much easier
75
+
if you understand my style *before* attempting a PR.
76
+
63
77
License
64
78
-------
65
79