finally passed my mental block
This commit is contained in:
parent
1f79497145
commit
cb6c5ac0c6
4
Makefile
4
Makefile
@ -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)
|
||||
|
||||
@ -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
|
||||
|
||||
322
include/engine.h
322
include/engine.h
@ -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
129
include/enum.h
Normal 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
164
include/octree.h
Normal 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
120
include/queue.h
Normal 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
196
include/struct.h
Normal 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
25
source/client_assets.c
Normal 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);
|
||||
}
|
||||
@ -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
64
source/client_gui.c
Normal 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
17
source/client_input.c
Normal 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
26
source/client_main.c
Normal 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);
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -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
|
||||
@ -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
64
source/core_event.c
Normal 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
28
source/core_terminal.c
Normal 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();
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
@ -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
13
source/game_loop.c
Normal 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;
|
||||
}
|
||||
}
|
||||
@ -1,14 +0,0 @@
|
||||
#include <engine.h>
|
||||
|
||||
void ItemUsePrimary() {
|
||||
|
||||
}
|
||||
|
||||
void ItemUseSecondary() {
|
||||
|
||||
}
|
||||
|
||||
void ItemEquipe() {
|
||||
|
||||
}
|
||||
|
||||
@ -1,3 +0,0 @@
|
||||
#include <engine.h>
|
||||
|
||||
//write sandboxing api and mods manager
|
||||
@ -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() {
|
||||
//
|
||||
}
|
||||
@ -1,9 +0,0 @@
|
||||
#include <engine.h>
|
||||
|
||||
void QuestFinish() {
|
||||
|
||||
}
|
||||
|
||||
void QuestSuccess() {
|
||||
|
||||
}
|
||||
@ -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
0
tools/entity_creator.c
Normal file
0
tools/item_creator.c
Normal file
0
tools/item_creator.c
Normal file
Loading…
x
Reference in New Issue
Block a user