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}