A game engine for top-down 2D RPG games.
rpg
game-engine
raylib
c99
1#include "keraforge/actor.h"
2#include "keraforge/math.h"
3#include "keraforge/world.h"
4#include <raylib.h>
5#include <raymath.h>
6#include <keraforge.h>
7#include <stdio.h>
8#include <stdlib.h>
9
10static Camera2D cam;
11static f32 dt = 0;
12static struct kf_vec2(u32) select = { 0, 0 };
13
14static void _player_tick(struct kf_world *world, struct kf_actor *self)
15{
16 bool w = IsKeyDown(KEY_W), s = IsKeyDown(KEY_S);
17 bool a = IsKeyDown(KEY_A), d = IsKeyDown(KEY_D);
18 struct kf_vec2(f32) v = {0, 0};
19
20 if (w && s)
21 v.y = 0;
22 else if (w)
23 v.y = -1;
24 else if (s)
25 v.y = 1;
26
27 if (a && d)
28 v.x = 0;
29 else if (a)
30 v.x = -1;
31 else if (d)
32 v.x = 1;
33
34 if (v.x || v.y)
35 kf_actor_addforce(self, kf_normalize_vec2(f32)(v));
36
37 if (IsKeyPressed(KEY_SPACE) && self->speedmod <= 1.0f)
38 self->speedmod = 3.0f;
39
40 kf_actor_move(world, self, dt);
41}
42
43static void _player_draw(struct kf_world *world, struct kf_actor *self)
44{
45 (void)world;
46 DrawCircle(self->pos.x, self->pos.y, 4, RED);
47
48 cam.target.x = self->pos.x;
49 cam.target.y = self->pos.y;
50}
51
52int main(int argc, const char *argv[])
53{
54 (void)argc;
55 (void)argv;
56
57 SetTraceLogLevel(LOG_WARNING);
58 InitWindow(800, 600, "Keraforge");
59 SetTargetFPS(60);
60
61 kf_tiles.color[0] = GREEN;
62 kf_tiles.color[1] = BROWN;
63 kf_tiles.color[2] = GRAY;
64 kf_tiles.collide[2] = true;
65
66 if (!DirectoryExists("data"))
67 MakeDirectory("data");
68
69 struct kf_world *world = NULL;
70 if (!kf_exists("data/map.bin"))
71 {
72 printf("-> creating world\n");
73 world = kf_world_new(128, 128, 0);
74 for (size_t i = 0 ; i < world->width*world->height ; i += (size_t)((float)(rand())/RAND_MAX*10))
75 world->map[i] = (rand()/(float)RAND_MAX*3);
76 printf("-> saving world\n");
77 size_t len = kf_world_getsize(world);
78 printf("-> writing of %lu bytes\n", len);
79 if (!kf_writebin("data/map.bin", (u8 *)world, len))
80 {
81 fprintf(stderr, "error creating map: failed to save map.bin\n");
82 free(world);
83 exit(1);
84 }
85 }
86 else
87 {
88 printf("-> loading world\n");
89 size_t len = 0;
90 world = (struct kf_world *)kf_readbin("data/map.bin", &len);
91 printf("-> world is %lu bytes\n", len);
92 }
93 if (!world)
94 {
95 fprintf(stderr, "error: failed to load world\n");
96 exit(1);
97 }
98
99 struct kf_actor *player = kf_actor_new();
100 player->pos.x = world->width / 4.0f * KF_TILE_SIZE_PX;
101 player->pos.y = world->height / 4.0f * KF_TILE_SIZE_PX;
102 player->vel.x = 0;
103 player->vel.y = 0;
104 player->size.x = 6;
105 player->size.y = 6;
106 player->speed = 25;
107 player->speedmod = 1;
108 player->friction = 1.25f;
109 player->collide = true;
110 player->tick = _player_tick;
111 player->draw = _player_draw;
112
113 cam = (Camera2D){{GetScreenWidth() / 2.0f, GetScreenHeight() / 2.0f}, {0, 0}, 0, 2};
114 while (!WindowShouldClose())
115 {
116 player->tick(world, player);
117
118 Vector2 v = GetScreenToWorld2D(GetMousePosition(), cam);
119 select.x = v.x / KF_TILE_SIZE_PX;
120 select.y = v.y / KF_TILE_SIZE_PX;
121
122 BeginDrawing();
123 ClearBackground(WHITE);
124
125 BeginMode2D(cam);
126 kf_world_draw(world, cam);
127 if (select.x < world->width && select.y < world->height)
128 DrawRectangleLines(select.x * KF_TILE_SIZE_PX, select.y * KF_TILE_SIZE_PX, KF_TILE_SIZE_PX, KF_TILE_SIZE_PX, WHITE);
129 player->draw(world, player);
130 EndMode2D();
131
132 DrawFPS(0, 0);
133 DrawText(TextFormat("%f", dt), 0, 20, 20, RED);
134
135 EndDrawing();
136
137 dt = GetFrameTime();
138 }
139
140 if (world)
141 {
142 if (!kf_writebin("data/map.bin", (u8 *)world, kf_world_getsize(world)))
143 fprintf(stderr, "error: failed to save map.bin\n");
144 free(world);
145 }
146 CloseWindow();
147
148 return 0;
149}