finally passed my mental block

This commit is contained in:
Emilia(SleepeeSoftware) 2026-02-18 17:20:25 +01:00
parent 1f79497145
commit cb6c5ac0c6
29 changed files with 986 additions and 621 deletions

View File

@ -1,12 +1,14 @@
NAME := MarhaEngine
SRC := $(wildcard source/*.c)
OBJ := $(SRC:source/%.c=obj/%.o)
SRC := source/client.c
#$(wildcard source/*.c)
CC := gcc
CFLAG := -ggdb -Wall -Wextra -Werror -Wpedantic -I include -O0 -std=c99
ifeq ($(OS), Windows_NT)
CFLAG += -I C:\raylibs\include
LFLAG := -lraylib -lopengl32 -lgdi32 -lwinmm -lpthread
endif
ifeq ($(shell uname -s), Linux)

View File

@ -9,15 +9,18 @@
#include <stdio.h>
//#include <stdarg.h>
#include <stdlib.h>
#include <pthread.h>
#include <complex.h>
#include <math.h>
#include <unistd.h>
#include <raylib.h>
#include <rlgl.h>
#include <raymath.h>
#include <raygui.h>
#include <extern/toml.h>
#include <extern/FastNoiseLite.h>
//#include <extern/toml.h>
//#include <extern/FastNoiseLite.h>
#endif

View File

@ -1,323 +1,7 @@
#ifndef ENGINE_H
# define ENGINE_H
#include <core.h>
# ifndef ENGINE_ENUM
# define ENGINE_ENUM
typedef enum {
EVT_HUNGER_TICK,
EVT_DAMAGE_TAKEN,
EVT_ITEM_OBSERVED,
EVT_ORDER_RECEIVED,
EVT_MEMORY_TRIGGERED,
} EVENT_TYPE;
typedef enum {
ACT_IDLE,
ACT_WORKING,
ACT_FIGHTING,
ACT_FLEEING,
ACT_UNCONSCIOUS,
ACT_DEAD,
} ACTIVITY_STATE;
typedef enum {
PHYSICAL_DMG,
MAGICA_DMG,
} DAMAGE_TYPE;
typedef enum {
STATS_STRENGHT,
STATS_DEXTERITY,
STATS_WITHDOM,
STATS_INTELLIGENCE,
STATS_
} STATS_TYPE;
typedef enum {
LIMB_ARM,
LIMB_LEG,
LIMB_HAND,
LIMB_FOOT,
LIMB_HEAD,
LIMB_NECK,
} LIMB_TYPE;
typedef enum {
LIMB_DAMAGED,
LIMB_PARALIZED,
LIMB_CUT,
LIMB_MISSING,
LIMB_SEVERE,
LIMB_INTACT,
LIMB_OK,
LIMB_INVINCIBLE,
} LIMB_STATE;
typedef enum {
SKILL_NONE,
SKILL_PASSIF,
SKILL_MASTERY,
SKILL_ACTIF,
SKILL_LABOR,
SKILL_COMBAT,
SKILL_KNOWLEDGE,
SKILL_PROGRESSION,
SKILL_INATE,
} SKILL_TYPE;
typedef enum {
ENTITY_DEAD,
ENTITY_ALIVE,
ENTITY_UNCONCIOUS,
} ENTITY_STATE;
typedef enum {
CRITICAL_FAIL,
FAIL,
SUCCESS,
CRITICAL_SUCCESS,
} CHECK_STATE;
typedef enum {
ITEM_EQUIPABLE,
ITEM_CONSUMABLE,
ITEM_PLACEABLE,
ITEM_QUEST,
} ITEM_FLAGS;
typedef enum {
SPLASH_SCREEN,
GAMELOOP_SCREEN,
CREDIT_SCREEN,
GAMEOVER_SCREEN,
SERVER_SCREEN,
SECRET_SCREEN,
DEBUG_SCREEN,
} ENGINE_STATE;
typedef enum {
QUEST_SUCCESS,
QUEST_FAILURE,
QUEST_TAKEN,
QUEST_KNOW,
QUEST_UNKNOW,
QUEST_COMPLETE,
} QUEST_STATE;
typedef enum {
ACTION_FORWARD,
ACTION_BACKWARD,
ACTION_LEFT,
ACTION_RIGHT,
ACTION_PRIMARY,
ACTION_SECONDARY,
ACTION_USE,
ACTION_GRAB,
ACTION_JUMP,
ACTION_DASH,
ACTION_SKILL1,
ACTION_TOOLBAR1,
} PLAYER_ACTION;
typedef enum {
DENDRITIC_VOLTAGE,
LAZENBYCOMP_LIQUID,
LAZENBYCOMP_SMOOTH,
POTRA,
} FONTS_ENUM;
# endif
#ifndef ENGINE_STRUCT
# define ENGINE_STRUCT
typedef struct {
Font fonts[4];//
Texture textures;//
Model models;//
Sound sound;
} Assets;
// Render
typedef struct {
Shader gbuffer;
Shader deferred;
Shader filter;
} ShaderRD;
typedef struct {
unsigned int framebufferId;
unsigned int normal_tex_id;
unsigned int albedoSpec_tex_id;
unsigned int depth_tex_id;
} GBuffer;
typedef struct {
uint16_t height;
uint16_t width;
void* window;
//RenderTexture rendtex;
GBuffer gbuffer;
Camera3D camera3d;
Camera2D camera2d;
ShaderRD shader;
bool hud_on, debug_on;
} RenderCtx;
// Event
typedef struct {
EVENT_TYPE type;
int value;
double time;
char* info;
int initiator;
int actors;
int actions;
} Event;
//cities
//hideout
//tiles
//level
//npc
//clan
//army
//team
typedef struct {
} Damage;
typedef struct {
EVENT_TYPE trigger;
ACTIVITY_STATE required_state;
bool (*condition)(int e, Event ev);
void *(*effect)(int e, Event ev);
} virtualRule;
typedef struct {
EVENT_TYPE trigger;
ACTIVITY_STATE required_state;
bool (*condition)(int e, Event ev);
void *(*effect)(int e, Event ev);
} physicalRule;
typedef struct {
int strenght;
int agility;
int toughness;
int proprioception;
int earing;
int touch;
int eyesight;
} BodyStats;
typedef struct {
int intellect;
int fortitude;
int charisma;
int eloquence;
int perception;
} MentalStats;
typedef struct {
LIMB_TYPE type;
LIMB_STATE state;
} Limb;
typedef struct {
Limb limbs[10];
BodyStats body_stats;
MentalStats mental_stats;
int mass;
Vector3 pos;
Vector3 velocity;
int health;
} Body;
typedef struct {
Body body;
int faction;
ENTITY_STATE state;//can be multiple flag
} Entity;
typedef struct {
Entity entity;
void (*ai)(void);
} Mob;
// Item
typedef struct {
int number;
int description;//ref to item description table
int name;//ref to item name table
int rarity;
int flags;
int stack;
} Item;
typedef struct {
int size;
int capacity;
Item storage[100];
} Inventory;
// Player
typedef struct {
char *name;
char *gender;
char *nickname;//can be changed, what npc refers to when talking to you, also npc do not know you until you interact with them
} Identity;
typedef struct {
} Skill;
typedef struct {
Entity entity;
Identity identity;
Skill skills[10];
Inventory inventory;
} Player;
//give more enphasis on the character than the item used (~60% ,~30%)
// Quest & Task
typedef struct {
int id;
int prerequisite;
int objectiv;
int status;//unknow, known, accepted, achieved, completed, unavailable
} Quest;
//Quest are missive or Scroll that the player can open with info on it, but no mini map or marker Also the map should be another scroll that is handdrawn, and the player can put marker and orient himself using landscape point of interest
// Other Struct
typedef struct {
int key[4];//should be the number of action in PLAYER_ACTION
union {
int key;
int pad;
int mouse;
} press;
Vector2 mouse_pos;
Vector2 mouse_delta;
//int mouse_pressed[2];
} Input;
typedef struct {
int state;
Player player;
Assets assets;
} Context;
# endif
#include <struct.h>
# ifndef ENGINE_PROTOTYPE
# define ENGINE_PROTOTYPE
@ -330,6 +14,10 @@ void UnloadPipeline();
void UserInterface(const Player *player);
//void Menu();
void EngineStateSwitch(ENGINE_STATE_E engine_state);
# endif
//other stuff here
#endif

129
include/enum.h Normal file
View File

@ -0,0 +1,129 @@
# ifndef ENGINE_ENUM
# define ENGINE_ENUM
typedef enum {
EVT_HUNGER_TICK,
EVT_DAMAGE_TAKEN,
EVT_ITEM_OBSERVED,
EVT_ORDER_RECEIVED,
EVT_MEMORY_TRIGGERED,
EVT_PLAYER_INPUT,
} EVENT_TYPE;
typedef enum {
ACT_IDLE,
ACT_WORKING,
ACT_FIGHTING,
ACT_FLEEING,
ACT_UNCONSCIOUS,
ACT_DEAD,
} ACTIVITY_STATE;
typedef enum {
PHYSICAL_DMG,
MAGICA_DMG,
} DAMAGE_TYPE;
typedef enum {
STATS_STRENGHT,
STATS_DEXTERITY,
STATS_WITHDOM,
STATS_INTELLIGENCE,
STATS_
} STATS_TYPE;
typedef enum {
LIMB_ARM,
LIMB_LEG,
LIMB_HAND,
LIMB_FOOT,
LIMB_HEAD,
LIMB_NECK,
} LIMB_TYPE;
typedef enum {
LIMB_DAMAGED,
LIMB_PARALIZED,
LIMB_CUT,
LIMB_MISSING,
LIMB_SEVERE,
LIMB_INTACT,
LIMB_OK,
LIMB_INVINCIBLE,
} LIMB_STATE;
typedef enum {
SKILL_NONE,
SKILL_PASSIF,
SKILL_MASTERY,
SKILL_ACTIF,
SKILL_LABOR,
SKILL_COMBAT,
SKILL_KNOWLEDGE,
SKILL_PROGRESSION,
SKILL_INATE,
} SKILL_TYPE;
typedef enum {
ENTITY_DEAD,
ENTITY_ALIVE,
ENTITY_UNCONCIOUS,
} ENTITY_STATE;
typedef enum {
CRITICAL_FAIL,
FAIL,
SUCCESS,
CRITICAL_SUCCESS,
} CHECK_STATE;
typedef enum {
ITEM_EQUIPABLE,
ITEM_CONSUMABLE,
ITEM_PLACEABLE,
ITEM_QUEST,
} ITEM_FLAGS;
typedef enum {
SPLASH_SCREEN,
GAMELOOP_SCREEN,
CREDIT_SCREEN,
GAMEOVER_SCREEN,
SERVER_SCREEN,
SECRET_SCREEN,
DEBUG_SCREEN,
} ENGINE_STATE_E;
typedef enum {
QUEST_SUCCESS,
QUEST_FAILURE,
QUEST_TAKEN,
QUEST_KNOW,
QUEST_UNKNOW,
QUEST_COMPLETE,
} QUEST_STATE;
typedef enum {
ACTION_FORWARD,
ACTION_BACKWARD,
ACTION_LEFT,
ACTION_RIGHT,
ACTION_PRIMARY,
ACTION_SECONDARY,
ACTION_USE,
ACTION_GRAB,
ACTION_JUMP,
ACTION_DASH,
ACTION_SKILL1,
ACTION_TOOLBAR1,
} PLAYER_ACTION;
typedef enum {
DENDRITIC_VOLTAGE,
LAZENBYCOMP_LIQUID,
LAZENBYCOMP_SMOOTH,
POTRA,
} FONTS_ENUM;
# endif

164
include/octree.h Normal file
View File

@ -0,0 +1,164 @@
#ifndef OCTREE_H
#define OCTREE_H
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
//This was vibecoded #FML
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
float x, y, z;
} oct_vec3;
typedef struct {
oct_vec3 min;
oct_vec3 max;
} oct_box;
typedef struct {
uint32_t first_child; // Index of first child in the pool, 0 if leaf
uint16_t count; // Number of items in this node
uint16_t data_offset; // Index into the data array
} oct_node;
typedef struct {
oct_node* nodes;
uint32_t* data; // Indices of your objects
uint32_t node_count;
uint32_t node_capacity;
uint32_t data_count;
uint32_t data_capacity;
oct_box bounds;
int max_depth;
} octree_t;
// --- Public API ---
void octree_init(octree_t* tree, oct_box bounds, int max_depth, uint32_t initial_cap);
void octree_free(octree_t* tree);
bool octree_insert(octree_t* tree, uint32_t item_id, oct_vec3 pos);
// Note: For thread safety, wrap insert in a mutex. Query can be lock-free if no inserts happen.
#ifdef __cplusplus
}
#endif
#endif // OCTREE_H
// --------------------------------------------------------------------------
#ifdef OCTREE_IMPLEMENTATION
static bool oct_box_contains(oct_box b, oct_vec3 p) {
return (p.x >= b.min.x && p.x <= b.max.x &&
p.y >= b.min.y && p.y <= b.max.y &&
p.z >= b.min.z && p.z <= b.max.z);
}
void octree_init(octree_t* tree, oct_box bounds, int max_depth, uint32_t initial_cap) {
tree->bounds = bounds;
tree->max_depth = max_depth;
tree->node_capacity = initial_cap;
tree->nodes = (oct_node*)calloc(initial_cap, sizeof(oct_node));
tree->node_count = 1; // Root is at index 0
tree->data_capacity = initial_cap * 4;
tree->data = (uint32_t*)malloc(tree->data_capacity * sizeof(uint32_t));
tree->data_count = 0;
}
void octree_free(octree_t* tree) {
free(tree->nodes);
free(tree->data);
}
// Internal: Splits a node into 8 children
static void oct_node_split(octree_t* tree, uint32_t node_idx, oct_box node_box) {
if (tree->node_count + 8 > tree->node_capacity) {
tree->node_capacity *= 2;
tree->nodes = (oct_node*)realloc(tree->nodes, tree->node_capacity * sizeof(oct_node));
}
tree->nodes[node_idx].first_child = tree->node_count;
tree->node_count += 8;
// Initialize children...
for(int i = 0; i < 8; ++i) {
tree->nodes[tree->nodes[node_idx].first_child + i] = (oct_node){0};
}
}
// Implementation of octree_insert would go here...
// It would traverse indices and check oct_box_contains.
// Internal helper to get the bounding box of a specific child
static oct_box oct_get_child_box(oct_box parent, int child_idx) {
oct_vec3 center = {
(parent.min.x + parent.max.x) * 0.5f,
(parent.min.y + parent.max.y) * 0.5f,
(parent.min.z + parent.max.z) * 0.5f
};
oct_box child = parent;
// Bit 0: X, Bit 1: Y, Bit 2: Z
if (child_idx & 1) child.min.x = center.x; else child.max.x = center.x;
if (child_idx & 2) child.min.y = center.y; else child.max.y = center.y;
if (child_idx & 4) child.min.z = center.z; else child.max.z = center.z;
return child;
}
// Recursive insert (Internal)
static bool oct_insert_internal(octree_t* tree, uint32_t node_idx, oct_box node_box, uint32_t item_id, oct_vec3 pos, int depth) {
// 1. If we are at max depth or it's a leaf with space, store it
// For simplicity, this version pushes everything to leaves:
if (depth >= tree->max_depth) {
// Handle data array resizing
if (tree->data_count >= tree->data_capacity) {
tree->data_capacity *= 2;
tree->data = (uint32_t*)realloc(tree->data, tree->data_capacity * sizeof(uint32_t));
}
// In a real STB-style, you'd link data to the node here
// For now, we'll just track that the node has data
tree->nodes[node_idx].count++;
tree->data[tree->data_count++] = item_id;
return true;
}
// 2. If leaf, split it
if (tree->nodes[node_idx].first_child == 0) {
oct_node_split(tree, node_idx, node_box);
}
// 3. Determine which child the point belongs to
oct_vec3 center = {
(node_box.min.x + node_box.max.x) * 0.5f,
(node_box.min.y + node_box.max.y) * 0.5f,
(node_box.min.z + node_box.max.z) * 0.5f
};
int child_idx = 0;
if (pos.x >= center.x) child_idx |= 1;
if (pos.y >= center.y) child_idx |= 2;
if (pos.z >= center.z) child_idx |= 4;
uint32_t next_node = tree->nodes[node_idx].first_child + child_idx;
oct_box next_box = oct_get_child_box(node_box, child_idx);
return oct_insert_internal(tree, next_node, next_box, item_id, pos, depth + 1);
}
bool octree_insert(octree_t* tree, uint32_t item_id, oct_vec3 pos) {
if (!oct_box_contains(tree->bounds, pos)) return false;
return oct_insert_internal(tree, 0, tree->bounds, item_id, pos, 0);
}
// Thread-safe query (No writes/allocations)
void octree_query_sphere(const octree_t* tree, oct_vec3 center, float radius, void (*callback)(uint32_t)) {
// This would implement a standard stack-based or recursive search
// checking if the sphere overlaps the node_box.
}
#endif // OCTREE_IMPLEMENTATION

120
include/queue.h Normal file
View File

@ -0,0 +1,120 @@
#ifndef QUEUE_H
#define QUEUE_H
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
//This was vibecoded #FML
typedef struct {
void *data;
size_t head;
size_t tail;
size_t count;
size_t capacity;
size_t stride; // Size of one element
bool is_dynamic;
} queue_t;
// Public API
void queue_init_static(queue_t *q, void *buffer, size_t capacity, size_t stride);
bool queue_init_dynamic(queue_t *q, size_t initial_capacity, size_t stride);
void queue_free(queue_t *q);
bool queue_push(queue_t *q, const void *val); // The "try_push" version
bool queue_pop(queue_t *q, void *out_val);
bool queue_peek(queue_t *q, void *out_val);
#define queue_is_empty(q) ((q)->count == 0)
#define queue_is_full(q) ((q)->count == (q)->capacity)
#ifdef QUEUE_IMPLEMENTATION
void queue_init_static(queue_t *q, void *buffer, size_t capacity, size_t stride) {
q->data = buffer;
q->head = 0;
q->tail = 0;
q->count = 0;
q->capacity = capacity;
q->stride = stride;
q->is_dynamic = false;
}
bool queue_init_dynamic(queue_t *q, size_t initial_capacity, size_t stride) {
q->capacity = (initial_capacity > 0) ? initial_capacity : 8;
q->stride = stride;
q->data = malloc(q->capacity * q->stride);
if (!q->data) return false;
q->head = 0;
q->tail = 0;
q->count = 0;
q->is_dynamic = true;
return true;
}
void queue_free(queue_t *q) {
if (q->is_dynamic && q->data) {
free(q->data);
}
q->data = NULL;
}
static bool _queue_grow(queue_t *q) {
size_t new_cap = q->capacity * 2;
void *new_data = malloc(new_cap * q->stride);
if (!new_data) return false;
// Copy data in order: from head to end, then from beginning to tail
for (size_t i = 0; i < q->count; ++i) {
size_t old_idx = (q->head + i) % q->capacity;
memcpy((char*)new_data + (i * q->stride),
(char*)q->data + (old_idx * q->stride),
q->stride);
}
if (q->is_dynamic) free(q->data);
q->data = new_data;
q->head = 0;
q->tail = q->count;
q->capacity = new_cap;
q->is_dynamic = true; // Even if it was static, it's dynamic now
return true;
}
bool queue_push(queue_t *q, const void *val) {
if (queue_is_full(q)) {
if (q->is_dynamic) {
if (!_queue_grow(q)) return false;
} else {
return false; // Static queue full
}
}
memcpy((char*)q->data + (q->tail * q->stride), val, q->stride);
q->tail = (q->tail + 1) % q->capacity;
q->count++;
return true;
}
bool queue_pop(queue_t *q, void *out_val) {
if (queue_is_empty(q)) return false;
if (out_val) {
memcpy(out_val, (char*)q->data + (q->head * q->stride), q->stride);
}
q->head = (q->head + 1) % q->capacity;
q->count--;
return true;
}
bool queue_peek(queue_t *q, void *out_val) {
if (queue_is_empty(q)) return false;
memcpy(out_val, (char*)q->data + (q->head * q->stride), q->stride);
return true;
}
#endif // QUEUE_IMPLEMENTATION
#endif // QUEUE_H

196
include/struct.h Normal file
View File

@ -0,0 +1,196 @@
#ifndef ENGINE_STRUCT
# define ENGINE_STRUCT
#include <core.h>
#include <enum.h>
typedef struct {
Font fonts[4];//
Texture textures;//
Model models;//
Sound sound;
} Assets;
// Render
typedef struct {
Shader gbuffer;
Shader deferred;
Shader filter;
} ShaderRD;
typedef struct {
unsigned int framebufferId;
unsigned int normal_tex_id;
unsigned int albedoSpec_tex_id;
unsigned int depth_tex_id;
} GBuffer;
typedef struct {
uint16_t height;
uint16_t width;
void* window;
//RenderTexture rendtex;
GBuffer gbuffer;
Camera3D camera3d;
Camera2D camera2d;
ShaderRD shader;
bool hud_on, debug_on;
} RenderCtx;
// Event
typedef struct {
EVENT_TYPE type;
int value;
double time;
char* info;
int initiator;
int actors;
int actions;
} Event;
//cities
//hideout
//tiles
//level
//npc
//clan
//army
//team
typedef struct {
} Damage;
typedef struct {
EVENT_TYPE trigger;
ACTIVITY_STATE required_state;
bool (*condition)(int e, Event ev);
void *(*effect)(int e, Event ev);
} virtualRule;
typedef struct {
EVENT_TYPE trigger;
ACTIVITY_STATE required_state;
bool (*condition)(int e, Event ev);
void *(*effect)(int e, Event ev);
} physicalRule;
typedef struct {
int strenght;
int agility;
int toughness;
int proprioception;
int earing;
int touch;
int eyesight;
} BodyStats;
typedef struct {
int intellect;
int fortitude;
int charisma;
int eloquence;
int perception;
} MentalStats;
typedef struct {
LIMB_TYPE type;
LIMB_STATE state;
} Limb;
typedef struct {
Limb limbs[10];
BodyStats body_stats;
MentalStats mental_stats;
int mass;
Vector3 pos;
Vector3 velocity;
int health;
} Body;
typedef struct {
Body body;
int faction;
ENTITY_STATE state;//can be multiple flag
} Entity;
typedef struct {
Entity entity;
void (*ai)(void);
} Mob;
// Item
typedef struct {
int number;
int description;//ref to item description table
int name;//ref to item name table
int rarity;
int flags;
int stack;
} Item;
/*
inventory could be a grid that have an item focused,
the item focused have a description and stats windows on the left,
the focused item is either the one under the mouse
or can be choosen using arrow keys (easier controller support)
*/
typedef struct {
int size;
int capacity;
Item storage[100];
} Inventory;
// Player
typedef struct {
char *name;
char *gender;
char *nickname;//can be changed, what npc refers to when talking to you, also npc do not know you until you interact with them
} Identity;
typedef struct {
} Skill;
typedef struct {
Entity entity;
Identity identity;
Skill skills[10];
Inventory inventory;
} Player;
//give more enphasis on the character than the item used (~60% ,~30%)
// Quest & Task
typedef struct {
int id;
int prerequisite;
int objectiv;
int status;//unknow, known, accepted, achieved, completed, unavailable
} Quest;
//Quest are missive or Scroll that the player can open with info on it, but no mini map or marker Also the map should be another scroll that is handdrawn, and the player can put marker and orient himself using landscape point of interest
// Other Struct
typedef struct {
int key[4];//should be the number of action in PLAYER_ACTION
union {
int key;
int pad;
int mouse;
} press;
Vector2 mouse_pos;
Vector2 mouse_delta;
//int mouse_pressed[2];
} Input;
typedef struct {
int state;
Player player;
Assets assets;
} Context;
# endif

25
source/client_assets.c Normal file
View File

@ -0,0 +1,25 @@
#include <engine.h>
Assets* LoadAssets() {
Assets *asset = (Assets *)calloc(sizeof(Assets), 1);
assert(asset);
//Font
asset->fonts[DENDRITIC_VOLTAGE] = LoadFont("assets/font/Dendritic_Voltage.ttf");
asset->fonts[LAZENBYCOMP_LIQUID] = LoadFont("assets/font/LazenbyCompLiquid.ttf");
asset->fonts[LAZENBYCOMP_SMOOTH] = LoadFont("assets/font/LazenbyCompSmooth.ttf");
asset->fonts[POTRA] = LoadFont("assets/font/Potra.ttf");
//Textures
//Models
//Sound
//Data
TraceLog(LOG_INFO, "Assets Loaded");
return (asset);
}
void UnloadAssets(Assets *asset) {
UnloadFont(asset->fonts[DENDRITIC_VOLTAGE]);
UnloadFont(asset->fonts[LAZENBYCOMP_LIQUID]);
UnloadFont(asset->fonts[LAZENBYCOMP_SMOOTH]);
UnloadFont(asset->fonts[POTRA]);
free(asset);
}

View File

@ -30,7 +30,7 @@ void DebugRender() {
/*
State Machine (Game over, Quest Complete, Reset, StartGame, Reload)
*/
void StateMachine(ENGINE_STATE *state) {
void StateMachine(ENGINE_STATE_E *state) {
(state);
}

64
source/client_gui.c Normal file
View File

@ -0,0 +1,64 @@
#include <engine.h>
/*
Audio
Video
Gameplay
Control
Accessibility
Filter
*/
void RenderOption() {
}
void RenderInventory() {
//DrawTextureRec();
}
void DebugInterface() {
DrawFPS(10, 10);
}
void UserInterface(const Player *player) {
//player stats
//player state and aliement
//health and other metric
//DrawTextureRec();
DrawText(player->entity.body.health, 0, 0, 16, RED);
}
void EngineStateSwitch(ENGINE_STATE_E engine_state) {
switch (engine_state) {
case(SPLASH_SCREEN): {
break;
}
case(GAMELOOP_SCREEN): {
break;
}
case(CREDIT_SCREEN): {
break;
}
case(GAMEOVER_SCREEN): {
break;
}
case(SERVER_SCREEN): {
break;
}
case(SECRET_SCREEN): {
break;
}
case(DEBUG_SCREEN): {
break;
}
default:
break;
}
}

17
source/client_input.c Normal file
View File

@ -0,0 +1,17 @@
#include <engine.h>
void UpdateInput() {
const Input input;
int key = GetKeyPressed();
Vector2 mouse_pos = GetMousePosition();
Vector2 mouse_delta = GetMouseDelta();
while (key) {
for (PLAYER_ACTION action = 0; action < 4; action++) {
if (input.key[action] == key) {
//emit("player_intent", action);
break;
}
}
key = GetKeyPressed();
}
}

26
source/client_main.c Normal file
View File

@ -0,0 +1,26 @@
#include <engine.h>
#include <rlgl.h>
#include <raymath.h>
//#define RAYGUI_IMPLEMENTATION
//#include <raygui.h>
int main(void) {
double tick_time = 0.4;
ENGINE_STATE_E engine_state = SPLASH_SCREEN;
SetTraceLogLevel(LOG_ALL);
LoadPipeline();
Assets *assets = LoadAssets();
SetExitKey(KEY_NULL);
while (!WindowShouldClose()) {
EngineStateSwitch(engine_state);
//UpdateInput();
//ComputeIntent();
//GameLoop(tick_time);
//Rendering();
}
UnloadAssets(assets);
assets = NULL;//to remember to not use it after
UnloadPipeline();
return (0);
}

View File

@ -1,213 +1,101 @@
#include <engine.h>
#include <rlgl.h>
#include <raymath.h>
//#define RAYGUI_IMPLEMENTATION
//#include <raygui.h>
Context g_ctx;
RenderCtx r_ctx;
/*
Audio
Video
Gameplay
Control
Accessibility
Filter
*/
void RenderOption() {
}
void RenderInventory() {
//DrawTextureRec();
}
void DebugInterface() {
DrawFPS(10, 10);
}
void UserInterface(const Player *player) {
//player stats
//player state and aliement
//health and other metric
//DrawTextureRec();
DrawText(player->entity.body.health, 0, 0, 16, RED);
}
void MainMenu() {
switch (g_ctx.state) {
case(0): {
break;
}
default:
break;
}
}
void LoadCameraMode(int mode) {
switch (mode) {
case(0): {
break;
}
default:
break;
}
}
void LoadPipeline() {
r_ctx.width = 800;
r_ctx.height = 480;
r_ctx.hud_on = true;
r_ctx.debug_on = true;
InitWindow(r_ctx.width, r_ctx.height, "GAME!!");
assert(IsWindowReady());
r_ctx.window = GetWindowHandle();
r_ctx.shader.deferred = LoadShader("source/shader/deferred.vs", "source/shader/deferred.fs");
r_ctx.shader.gbuffer = LoadShader("source/shader/gbuffer.vs", "source/shader/gbuffer.fs");
r_ctx.shader.filter = LoadShader("", "source/shader/Screen_filter.fs");
r_ctx.gbuffer.framebufferId = rlLoadFramebuffer();
assert(r_ctx.gbuffer.framebufferId);
rlEnableFramebuffer(r_ctx.gbuffer.framebufferId);
r_ctx.gbuffer.depth_tex_id = rlLoadTextureDepth(r_ctx.width, r_ctx.height, false);
// If Artefact appear on Normal, may need to change to RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32 and also need to be used in case of anti aliasing (MLAA or SMAA if needed)
r_ctx.gbuffer.normal_tex_id = rlLoadTexture(NULL, r_ctx.width, r_ctx.height, RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16, 1);
// The color in RGB, and the specular strength in the alpha channel
r_ctx.gbuffer.albedoSpec_tex_id = rlLoadTexture(NULL, r_ctx.width, r_ctx.height, RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, 1);
rlActiveDrawBuffers(3);
rlFramebufferAttach(r_ctx.gbuffer.framebufferId, r_ctx.gbuffer.depth_tex_id, RL_ATTACHMENT_DEPTH, RL_ATTACHMENT_TEXTURE2D, 0);
rlFramebufferAttach(r_ctx.gbuffer.framebufferId, r_ctx.gbuffer.normal_tex_id, RL_ATTACHMENT_COLOR_CHANNEL0, RL_ATTACHMENT_TEXTURE2D, 0);
rlFramebufferAttach(r_ctx.gbuffer.framebufferId, r_ctx.gbuffer.albedoSpec_tex_id, RL_ATTACHMENT_COLOR_CHANNEL1, RL_ATTACHMENT_TEXTURE2D, 0);
assert(rlFramebufferComplete(r_ctx.gbuffer.framebufferId));
rlEnableShader(r_ctx.shader.deferred.id);
int texUnitDepth = 0;
int texUnitNormal = 1;
int texUnitAlbedoSpec = 2;
SetShaderValue(r_ctx.shader.deferred, rlGetLocationUniform(r_ctx.shader.deferred.id, "gDepth"), &texUnitDepth, RL_SHADER_UNIFORM_SAMPLER2D);
SetShaderValue(r_ctx.shader.deferred, rlGetLocationUniform(r_ctx.shader.deferred.id, "gNormal"), &texUnitNormal, RL_SHADER_UNIFORM_SAMPLER2D);
SetShaderValue(r_ctx.shader.deferred, rlGetLocationUniform(r_ctx.shader.deferred.id, "gAlbedoSpec"), &texUnitAlbedoSpec, RL_SHADER_UNIFORM_SAMPLER2D);
rlDisableShader();
//now need to set this to things that use this Material, and add light used in the scene.
rlEnableDepthTest();
rlEnableBackfaceCulling();
TraceLog(LOG_INFO, "Render Pipeline Built");
SetTargetFPS(120);//may change
}
void UnloadPipeline() {
rlUnloadFramebuffer(r_ctx.gbuffer.framebufferId);
rlUnloadTexture(r_ctx.gbuffer.depth_tex_id);
rlUnloadTexture(r_ctx.gbuffer.normal_tex_id);
rlUnloadTexture(r_ctx.gbuffer.albedoSpec_tex_id);
UnloadShader(r_ctx.shader.deferred);
UnloadShader(r_ctx.shader.gbuffer);
UnloadShader(r_ctx.shader.filter);
CloseWindow();
}
void RenderingDeferred3D() {
BeginDrawing();
ClearBackground(BLACK);
rlEnableDepthMask();
rlEnableFramebuffer(r_ctx.gbuffer.framebufferId);
rlEnableShader(r_ctx.shader.gbuffer.id);
BeginMode3D(r_ctx.camera3d);
//MainGeamoetry;
EndMode3D();
rlDisableShader();
rlDisableFramebuffer();
rlDisableDepthMask();//may not be usefull
//rlDisableDepthTest();
//Light Pass and forward pass;
//I should build a shader that take every light in the scene and make a 3D heightmap of lighting then compute it once for all static light allowing to cheat computing everylight
//light is computed into a scalar field
//Light Pass
//Screen Filter Pass
BeginShaderMode(r_ctx.shader.filter);//may be good to have this disabled for accessibility
//DrawTextureRec();
EndShaderMode();
//render ui
EndDrawing();
}
Assets* LoadAssets() {
Assets *asset = (Assets *)calloc(sizeof(Assets), 1);
assert(asset);
//Font
asset->fonts[DENDRITIC_VOLTAGE] = LoadFont("assets/font/Dendritic_Voltage.ttf");
asset->fonts[LAZENBYCOMP_LIQUID] = LoadFont("assets/font/LazenbyCompLiquid.ttf");
asset->fonts[LAZENBYCOMP_SMOOTH] = LoadFont("assets/font/LazenbyCompSmooth.ttf");
asset->fonts[POTRA] = LoadFont("assets/font/Potra.ttf");
//Textures
//Models
//Sound
//Data
TraceLog(LOG_INFO, "Assets Loaded");
return (asset);
}
void UnloadAssets(Assets *asset) {
UnloadFont(asset->fonts[DENDRITIC_VOLTAGE]);
UnloadFont(asset->fonts[LAZENBYCOMP_LIQUID]);
UnloadFont(asset->fonts[LAZENBYCOMP_SMOOTH]);
UnloadFont(asset->fonts[POTRA]);
free(asset);
}
void UpdateInput() {
const Input input;
int key = GetKeyPressed();
Vector2 mouse_pos = GetMousePosition();
Vector2 mouse_delta = GetMouseDelta();
while (key) {
for (PLAYER_ACTION action = 0; action < 4; action++) {
if (input.key[action] == key) {
//emit("player_intent", action);
break;
}
}
key = GetKeyPressed();
}
}
//may be able to dispatch it
void GameLoop(const double tick_time) {
__thread static double time = 0;
time += GetFrameTime();
if (time >= tick_time) {
// interaction
// simulation
time = 0;
}
}
int main(void) {
double tick_time = 0.4;
SetTraceLogLevel(LOG_ALL);
LoadPipeline();
Assets *assets = LoadAssets();
SetExitKey(KEY_NULL);
while (!WindowShouldClose()) {
UpdateInput();
ComputeIntent();
GameLoop(tick_time);
Rendering();
}
UnloadAssets(assets);
assets = NULL;//to remember to not use it after
UnloadPipeline();
return (0);
}
#include <engine.h>
RenderCtx r_ctx;
void LoadPipeline() {
r_ctx.width = 800;
r_ctx.height = 480;
r_ctx.hud_on = true;
r_ctx.debug_on = true;
InitWindow(r_ctx.width, r_ctx.height, "GAME!!");
assert(IsWindowReady());
r_ctx.window = GetWindowHandle();
r_ctx.shader.deferred = LoadShader("source/shader/deferred.vs", "source/shader/deferred.fs");
r_ctx.shader.gbuffer = LoadShader("source/shader/gbuffer.vs", "source/shader/gbuffer.fs");
r_ctx.shader.filter = LoadShader("", "source/shader/Screen_filter.fs");
r_ctx.gbuffer.framebufferId = rlLoadFramebuffer();
assert(r_ctx.gbuffer.framebufferId);
rlEnableFramebuffer(r_ctx.gbuffer.framebufferId);
r_ctx.gbuffer.depth_tex_id = rlLoadTextureDepth(r_ctx.width, r_ctx.height, false);
// If Artefact appear on Normal, may need to change to RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32 and also need to be used in case of anti aliasing (MLAA or SMAA if needed)
r_ctx.gbuffer.normal_tex_id = rlLoadTexture(NULL, r_ctx.width, r_ctx.height, RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16, 1);
// The color in RGB, and the specular strength in the alpha channel
r_ctx.gbuffer.albedoSpec_tex_id = rlLoadTexture(NULL, r_ctx.width, r_ctx.height, RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, 1);
rlActiveDrawBuffers(3);
rlFramebufferAttach(r_ctx.gbuffer.framebufferId, r_ctx.gbuffer.depth_tex_id, RL_ATTACHMENT_DEPTH, RL_ATTACHMENT_TEXTURE2D, 0);
rlFramebufferAttach(r_ctx.gbuffer.framebufferId, r_ctx.gbuffer.normal_tex_id, RL_ATTACHMENT_COLOR_CHANNEL0, RL_ATTACHMENT_TEXTURE2D, 0);
rlFramebufferAttach(r_ctx.gbuffer.framebufferId, r_ctx.gbuffer.albedoSpec_tex_id, RL_ATTACHMENT_COLOR_CHANNEL1, RL_ATTACHMENT_TEXTURE2D, 0);
assert(rlFramebufferComplete(r_ctx.gbuffer.framebufferId));
rlEnableShader(r_ctx.shader.deferred.id);
int texUnitDepth = 0;
int texUnitNormal = 1;
int texUnitAlbedoSpec = 2;
SetShaderValue(r_ctx.shader.deferred, rlGetLocationUniform(r_ctx.shader.deferred.id, "gDepth"), &texUnitDepth, RL_SHADER_UNIFORM_SAMPLER2D);
SetShaderValue(r_ctx.shader.deferred, rlGetLocationUniform(r_ctx.shader.deferred.id, "gNormal"), &texUnitNormal, RL_SHADER_UNIFORM_SAMPLER2D);
SetShaderValue(r_ctx.shader.deferred, rlGetLocationUniform(r_ctx.shader.deferred.id, "gAlbedoSpec"), &texUnitAlbedoSpec, RL_SHADER_UNIFORM_SAMPLER2D);
rlDisableShader();
//now need to set this to things that use this Material, and add light used in the scene.
rlEnableDepthTest();
rlEnableBackfaceCulling();
TraceLog(LOG_INFO, "Render Pipeline Built");
SetTargetFPS(120);//may change
}
void UnloadPipeline() {
rlUnloadFramebuffer(r_ctx.gbuffer.framebufferId);
rlUnloadTexture(r_ctx.gbuffer.depth_tex_id);
rlUnloadTexture(r_ctx.gbuffer.normal_tex_id);
rlUnloadTexture(r_ctx.gbuffer.albedoSpec_tex_id);
UnloadShader(r_ctx.shader.deferred);
UnloadShader(r_ctx.shader.gbuffer);
UnloadShader(r_ctx.shader.filter);
CloseWindow();
}
void LoadCameraMode(int mode) {
switch (mode) {
case(0): {
break;
}
default:
break;
}
}
//need to work on a way to structurize my data for the scene to be rendered
void RenderingDeferred3D() {
BeginDrawing();
ClearBackground(BLACK);
rlEnableDepthMask();
rlEnableFramebuffer(r_ctx.gbuffer.framebufferId);
rlEnableShader(r_ctx.shader.gbuffer.id);
BeginMode3D(r_ctx.camera3d);
//MainGeamoetry;
EndMode3D();
rlDisableShader();
rlDisableFramebuffer();
rlDisableDepthMask();//may not be usefull
//rlDisableDepthTest();
//Light Pass and forward pass;
//I should build a shader that take every light in the scene and make a 3D heightmap of lighting then compute it once for all static light allowing to cheat computing everylight
//light is computed into a scalar field
//Light Pass
//Screen Filter Pass
BeginShaderMode(r_ctx.shader.filter);//may be good to have this disabled for accessibility
//DrawTextureRec();
EndShaderMode();
//render ui
EndDrawing();
}

View File

@ -1,7 +1,10 @@
#include <engine.h>
#include <core.h>
#define QUEUE_IMPLEMENTATION
#include <queue.h>
//#define OCTREE_IMPLEMENTATION
//#include <octree.h>
// Frame Allocator
__thread static char* frame_buffer = 0x00;
__thread static char* current_position = 0x00;
__thread static int buffer_size;
@ -38,6 +41,11 @@ void DeleteFrameAllocator() {
free(frame_buffer);
}
//should put my unitest here
int Unitest() {
}
// Ressource Allocator (PreComputed);
// Fast Allocator; when the fram allocator is too short lived

View File

@ -1,13 +1,13 @@
#include <engine.h>
#include <queue.h>
typedef uint32_t Entity;
#define ENTITY_INVALID 0
#define MAX_ENTITIES 4096
Entity entities[MAX_ENTITIES] = {0};
int spawn_queue = 0;
//lock queue when used
queue_t spawn_queue;
pthread_mutex_t qmtx;
int EntityUpdate(void) {
@ -24,10 +24,10 @@ void EntityManager(void) {
return;
}
void SpawnEntity() {
}
void SpawnVisualEffect() {
//spawn a timed entity used for a visuel effect
void EntitySpawn(Entity entity) {
while (pthread_mutex_trylock(&qmtx) != 0) {
usleep(20);
}
queue_push(&spawn_queue, &entity);
pthread_mutex_unlock(&qmtx);
}

64
source/core_event.c Normal file
View File

@ -0,0 +1,64 @@
#include <engine.h>
#include <queue.h>
//should have a event structure, and a system can subscribe to an event, then whenever the event is triggered by a system, subscriber system should receive a signal.
typedef struct {
void* (*callback)(Event);
EVENT_TYPE type;
} listener_t;
//static Event *queue;
static queue_t queue;
pthread_mutex_t qmtx;
#define MAX_LISTENER 100
#define QUEUE_SIZE 1000
listener_t listener[MAX_LISTENER];
static int current_listener = 0;
void EventInit(void) {
void* buffer = calloc(QUEUE_SIZE, sizeof(Event));
assert(buffer);
queue_init_static(&queue, buffer, QUEUE_SIZE, sizeof(Event));
assert(pthread_mutex_init(&qmtx, NULL));
}
void EventFree(void) {
free(queue.data);
pthread_mutex_destroy(qmtx);
queue_free(&queue);
}
void EventSubscribe(const int event_type, void (*callback)(Event)) {
//this should return an handle that allow to poll event that happen last frame
listener[current_listener].callback = callback;
listener[current_listener].type = event_type;
current_listener++;
}
void EventEmit(Event event) {
printf("Event Emited");
while (pthread_mutex_trylock(qmtx) != 0) {
usleep(20);
}
if (!queue_push(&queue, &event)) {
printf("EventQueue is Full !! add more space to it");
}
pthread_mutex_unlock(qmtx);
}
void EventUpdate() {
Event event;
//process all the queue each update
while (queue_pop(&queue, &event)) {
//notify each susbscriber of the event
for (int i = 0; i < MAX_LISTENER; i++) {
if (event.type == listener[i].type) {
//send to listener's
listener->callback(event);
}
}
printf("%lf, %s", event.time, event.info);//need to convert unix time to timestamp
}
}

28
source/core_terminal.c Normal file
View File

@ -0,0 +1,28 @@
#include <engine.h>
char buffer[4096];
int index;
void TermInput() {
int c = 0;
c = GetCharPressed();
while (c) {
//handle special char :
/*
Backslash
Enter
Esc
Ctrl +
Alt +
Maj +
Caps Lock
Space ?
arrow left and right
and cursor position
history ?
maybe could use readline
*/
buffer[index] = c;
c = GetCharPressed();
}
}

View File

@ -1,6 +1,8 @@
#define CR_HOST // required in the host only and before including cr.h
#include <extern/cr.h>
//not used for now
int main(int argc, char *argv[]) {
// the host application should initalize a plugin with a context, a plugin
cr_plugin ctx;

View File

@ -1,21 +0,0 @@
#include <engine.h>
//should have a event structure, and a system can subscribe to an event, then whenever the event is triggered by a system, subscriber system should receive a signal.
static Event *queue;
void EventCreate(void) {
queue = calloc(100, sizeof(Event));
}
void EventSubscribe(int event_type, void (*callback)(int)) {
//this should return an handle that allow to poll event that happen last frame
}
void EventEmit(Event event) {
printf("Event Emited");
}
void ConsoleUpdate() {
__thread static char *buffer[1024];
}

13
source/game_loop.c Normal file
View File

@ -0,0 +1,13 @@
#include <engine.h>
//may be able to dispatch it
void GameLoop(const double tick_time) {
__thread static double time = 0;
time += GetFrameTime();
if (time >= tick_time) {
// interaction
// simulation
time = 0;
}
}

View File

@ -1,14 +0,0 @@
#include <engine.h>
void ItemUsePrimary() {
}
void ItemUseSecondary() {
}
void ItemEquipe() {
}

View File

@ -1,3 +0,0 @@
#include <engine.h>
//write sandboxing api and mods manager

View File

@ -1,28 +0,0 @@
#include <engine.h>
/*
inventory is a grid that have an item focused,
the item focused have a description and stats windows on the left,
the focused item is either the one under the mouse
or can be choosen using arrow keys (easier controller support)
*/
void PlayerController2D() {
}
void PlayerController3D() {
}
void PlayerInventory() {
}
void PlayerUpdate() {
}
void PlayerStats() {
//
}

View File

@ -1,9 +0,0 @@
#include <engine.h>
void QuestFinish() {
}
void QuestSuccess() {
}

View File

@ -1,5 +1,7 @@
```c
#include <core.h>
#include <extern/tinycthread.h>
#include <pthread.h>
static bool done_flag = false;
static mtx_t done_mtx;
@ -90,3 +92,4 @@ void StopWorkerManager() {
running_flag = false;
mtx_unlock(&running_mtx);
}
```

0
tools/entity_creator.c Normal file
View File

0
tools/item_creator.c Normal file
View File