first commit with full source

This commit is contained in:
Emilia(SleepeeSoftware) 2026-01-31 18:35:26 +01:00
parent 2acd32c592
commit 05d38d7b69
35 changed files with 36685 additions and 9 deletions

5
.gitignore vendored
View File

@ -8,3 +8,8 @@ obj
.cache
assets
asset
include/extern/cglm
include/extern/glad
include/extern/GLFW
include/extern/win
include/extern/rpmalloc-1.4.5.zip

View File

@ -4,7 +4,7 @@ SRC := $(wildcard source/*.c)
OBJ := $(SRC:source/%.c=obj/%.o)
CC := gcc
CFLAG := -ggdb -Wall -Wextra -Werror -Wpedantic -I include -O0
CFLAG := -ggdb -Wall -Wextra -Werror -Wpedantic -I include -O0 -std=c99
LFLAG := -lraylib -lGL -lm -lpthread -ldl -lrt -lX11
all: $(NAME)

View File

@ -26,7 +26,6 @@ MODDING API
EVENT ENTITY ITEM WORLD
Map movement are tour par tour.
TODO:
@ -59,17 +58,38 @@ Like having the player be able to have a wide swing action, a piercing one, anot
Skill based xp, if player train against a dummy or using a simple method, he while unlock bad or flawed Style and be very clumsy. and allow to correct them through real experience when failing ? or having critical success ?
Xp and other currency should be a way to tell the player that i want him to do something to make it meaningfull
Things that need to be in a table:
## Things that need to be in a database:
- Item Name and Description
- Dialogue and Static Text
- Experience, Skills, Level, Scaling, Database
Data Category,Suggested Format,Access Method
Item Metadata,JSON / Dictionary,GetItemByID(string id)
Dialogue Trees,Directed Acyclic Graph (DAG),Node-based traversal
Inventory,Array or Linked List,Index-based (slots)
Quest Progress,Bitmask or Boolean Map,CheckFlag(flag_name)
World Persistence,SQL (SQLite) or Save File,Serialized Object Binary
| Data Category | Suggested Format | Access Method |
| ----------- | ----------- | ----------- |
| Item Metadata | TOML / Dictionary | GetItemByID(string id) |
| Dialogue Trees | Directed Acyclic Graph (DAG) | Node-based traversal |
| Inventory | Array or Linked List | Index-based (slots) |
| Quest Progress | Bitmask or Boolean Map | CheckFlag(flag_name) |
| World Persistence | SQL (SQLite) or Save File | Serialized Object Binary |
"I finally realized: I'm not sick, I was never sick. I just live in a sick society, where someone's individual worth is measured only by the raw productive output they can spit out before getting chewed up by the gears"
The Player Should'nt be special (Chosen one) but should become by is action. either become a hero or becoming a demon king
The Time Should Flow to make the world feel alive when the player isn't in a place (make things happen)
A lot of things should be hidden to the player, the player shouldn't know everything.
# Good Idea and ressources:
- [RPG Myths by Timothy Cain](https://www.youtube.com/watch?v=x-438XTmFBE)
- [paper by Eric Chan Mit](https://people.csail.mit.edu/ericchan/papers/)
# Quote i like:
```
“The most amazing achievement of the computer software industry is its continuing cancellation of the steady and staggering gains made by the computer hardware industry.”
-Henry Petroski
```

22
compile_commands.json Normal file
View File

@ -0,0 +1,22 @@
[
{
"arguments": [
"/usr/bin/gcc",
"-ggdb",
"-std=c99",
"-Wall",
"-Wextra",
"-Werror",
"-Wpedantic",
"-I",
"include",
"-c",
"-o",
"obj/entity.o",
"source/entity.c"
],
"directory": "/home/emilia/Desktop/game",
"file": "/home/emilia/Desktop/game/source/entity.c",
"output": "/home/emilia/Desktop/game/obj/entity.o"
}
]

20
cr_host.cpp Normal file
View File

@ -0,0 +1,20 @@
#define CR_HOST // required in the host only and before including cr.h
#include <extern/cr.h>
int main(int argc, char *argv[]) {
// the host application should initalize a plugin with a context, a plugin
cr_plugin ctx;
// the full path to the live-reloadable application
cr_plugin_open(ctx, "c:/path/to/build/game.dll");
// call the update function at any frequency matters to you, this will give
// the real application a chance to run
while (!cr_plugin_update(ctx)) {
// do anything you need to do on host side (ie. windowing and input stuff?)
}
// at the end do not forget to cleanup the plugin context
cr_plugin_close(ctx);
return 0;
}

21
include/core.h Normal file
View File

@ -0,0 +1,21 @@
#ifndef CORE_H
# define CORE_H
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <assert.h>
#include <stdio.h>
//#include <stdarg.h>
#include <stdlib.h>
#include <complex.h>
#include <math.h>
#include <raylib.h>
#include <extern/toml.h>
#include <extern/FastNoiseLite.h>
#endif

301
include/engine.h Normal file
View File

@ -0,0 +1,301 @@
#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;
# endif
#ifndef ENGINE_STRUCT
# define ENGINE_STRUCT
// 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 camera;
ShaderRD shader;
bool hud_on, debug_on;
} RenderCtx;
// Event
typedef struct {
EVENT_TYPE type;
int value;
} Event;
typedef struct {
} Damage;
// Storage
typedef struct {
} Inventory;
// Entity
typedef struct {
int id;
} virtualEntity;
typedef struct {
int id;
} physicalEntity;
typedef struct {
EVENT_TYPE trigger;
ACTIVITY_STATE required_state;
bool (*condition)(virtualEntity e, Event ev);
void *(*effect)(virtualEntity e, Event ev);
} virtualRule;
typedef struct {
EVENT_TYPE trigger;
ACTIVITY_STATE required_state;
bool (*condition)(physicalEntity e, Event ev);
void *(*effect)(physicalEntity 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];
} Body;
typedef struct {
Body body;
BodyStats body_stats;
MentalStats mental_stats;
ENTITY_STATE state;//can be multiple flag
} Entity;
// 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;
} Inventory;
// Player
typedef struct {
char *name;
char *gender;
char *nickname;//can be changed, what npc refers to, also npc do not know you until you interact with them
} Identity;
typedef struct {
} Skill;
typedef struct {
Entity entity;
Identity identity;
Skill skills[10];
} 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 enum {
ACTION_FORWARD,
ACTION_BACKWARD,
ACTION_LEFT,
ACTION_RIGHT,
} PLAYER_ACTION;
typedef struct {
int key[4];//should be the number of action in PLAYER_ACTION
int button;
int mbutton;
Vector2 mouse_pos;
Vector2 mouse_delta;
//int mouse_pressed[2];
} Input;
# endif
# ifndef ENGINE_PROTOTYPE
# define ENGINE_PROTOTYPE
//Render
void LoadPipeline();
void UnloadPipeline();
void Rendering();
void LoadAssets();
void UnloadAssets();
//UI
void UserInterface();
void Menu();
# endif
#endif

2433
include/extern/FastNoiseLite.h vendored Normal file

File diff suppressed because it is too large Load Diff

2083
include/extern/cr.h vendored Normal file

File diff suppressed because it is too large Load Diff

6170
include/extern/enet.h vendored Normal file

File diff suppressed because it is too large Load Diff

22120
include/extern/librg.h vendored Normal file

File diff suppressed because it is too large Load Diff

2392
include/extern/toml.c vendored Normal file

File diff suppressed because it is too large Load Diff

175
include/extern/toml.h vendored Normal file
View File

@ -0,0 +1,175 @@
/*
MIT License
Copyright (c) CK Tan
https://github.com/cktan/tomlc99
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef TOML_H
#define TOML_H
#ifdef _MSC_VER
#pragma warning(disable : 4996)
#endif
#include <stdint.h>
#include <stdio.h>
#ifdef __cplusplus
#define TOML_EXTERN extern "C"
#else
#define TOML_EXTERN extern
#endif
typedef struct toml_timestamp_t toml_timestamp_t;
typedef struct toml_table_t toml_table_t;
typedef struct toml_array_t toml_array_t;
typedef struct toml_datum_t toml_datum_t;
/* Parse a file. Return a table on success, or 0 otherwise.
* Caller must toml_free(the-return-value) after use.
*/
TOML_EXTERN toml_table_t *toml_parse_file(FILE *fp, char *errbuf, int errbufsz);
/* Parse a string containing the full config.
* Return a table on success, or 0 otherwise.
* Caller must toml_free(the-return-value) after use.
*/
TOML_EXTERN toml_table_t *toml_parse(char *conf, /* NUL terminated, please. */
char *errbuf, int errbufsz);
/* Free the table returned by toml_parse() or toml_parse_file(). Once
* this function is called, any handles accessed through this tab
* directly or indirectly are no longer valid.
*/
TOML_EXTERN void toml_free(toml_table_t *tab);
/* Timestamp types. The year, month, day, hour, minute, second, z
* fields may be NULL if they are not relevant. e.g. In a DATE
* type, the hour, minute, second and z fields will be NULLs.
*/
struct toml_timestamp_t {
struct { /* internal. do not use. */
int year, month, day;
int hour, minute, second, millisec;
char z[10];
} __buffer;
int *year, *month, *day;
int *hour, *minute, *second, *millisec;
char *z;
};
/*-----------------------------------------------------------------
* Enhanced access methods
*/
struct toml_datum_t {
int ok;
union {
toml_timestamp_t *ts; /* ts must be freed after use */
char *s; /* string value. s must be freed after use */
int b; /* bool value */
int64_t i; /* int value */
double d; /* double value */
} u;
};
/* on arrays: */
/* ... retrieve size of array. */
TOML_EXTERN int toml_array_nelem(const toml_array_t *arr);
/* ... retrieve values using index. */
TOML_EXTERN toml_datum_t toml_string_at(const toml_array_t *arr, int idx);
TOML_EXTERN toml_datum_t toml_bool_at(const toml_array_t *arr, int idx);
TOML_EXTERN toml_datum_t toml_int_at(const toml_array_t *arr, int idx);
TOML_EXTERN toml_datum_t toml_double_at(const toml_array_t *arr, int idx);
TOML_EXTERN toml_datum_t toml_timestamp_at(const toml_array_t *arr, int idx);
/* ... retrieve array or table using index. */
TOML_EXTERN toml_array_t *toml_array_at(const toml_array_t *arr, int idx);
TOML_EXTERN toml_table_t *toml_table_at(const toml_array_t *arr, int idx);
/* on tables: */
/* ... retrieve the key in table at keyidx. Return 0 if out of range. */
TOML_EXTERN const char *toml_key_in(const toml_table_t *tab, int keyidx);
/* ... returns 1 if key exists in tab, 0 otherwise */
TOML_EXTERN int toml_key_exists(const toml_table_t *tab, const char *key);
/* ... retrieve values using key. */
TOML_EXTERN toml_datum_t toml_string_in(const toml_table_t *arr,
const char *key);
TOML_EXTERN toml_datum_t toml_bool_in(const toml_table_t *arr, const char *key);
TOML_EXTERN toml_datum_t toml_int_in(const toml_table_t *arr, const char *key);
TOML_EXTERN toml_datum_t toml_double_in(const toml_table_t *arr,
const char *key);
TOML_EXTERN toml_datum_t toml_timestamp_in(const toml_table_t *arr,
const char *key);
/* .. retrieve array or table using key. */
TOML_EXTERN toml_array_t *toml_array_in(const toml_table_t *tab,
const char *key);
TOML_EXTERN toml_table_t *toml_table_in(const toml_table_t *tab,
const char *key);
/*-----------------------------------------------------------------
* lesser used
*/
/* Return the array kind: 't'able, 'a'rray, 'v'alue, 'm'ixed */
TOML_EXTERN char toml_array_kind(const toml_array_t *arr);
/* For array kind 'v'alue, return the type of values
i:int, d:double, b:bool, s:string, t:time, D:date, T:timestamp, 'm'ixed
0 if unknown
*/
TOML_EXTERN char toml_array_type(const toml_array_t *arr);
/* Return the key of an array */
TOML_EXTERN const char *toml_array_key(const toml_array_t *arr);
/* Return the number of key-values in a table */
TOML_EXTERN int toml_table_nkval(const toml_table_t *tab);
/* Return the number of arrays in a table */
TOML_EXTERN int toml_table_narr(const toml_table_t *tab);
/* Return the number of sub-tables in a table */
TOML_EXTERN int toml_table_ntab(const toml_table_t *tab);
/* Return the key of a table*/
TOML_EXTERN const char *toml_table_key(const toml_table_t *tab);
/*--------------------------------------------------------------
* misc
*/
TOML_EXTERN int toml_utf8_to_ucs(const char *orig, int len, int64_t *ret);
TOML_EXTERN int toml_ucs_to_utf8(int64_t code, char buf[6]);
TOML_EXTERN void toml_set_memutil(void *(*xxmalloc)(size_t),
void (*xxfree)(void *));
/*--------------------------------------------------------------
* deprecated
*/
/* A raw value, must be processed by toml_rto* before using. */
typedef const char *toml_raw_t;
TOML_EXTERN toml_raw_t toml_raw_in(const toml_table_t *tab, const char *key);
TOML_EXTERN toml_raw_t toml_raw_at(const toml_array_t *arr, int idx);
TOML_EXTERN int toml_rtos(toml_raw_t s, char **ret);
TOML_EXTERN int toml_rtob(toml_raw_t s, int *ret);
TOML_EXTERN int toml_rtoi(toml_raw_t s, int64_t *ret);
TOML_EXTERN int toml_rtod(toml_raw_t s, double *ret);
TOML_EXTERN int toml_rtod_ex(toml_raw_t s, double *ret, char *buf, int buflen);
TOML_EXTERN int toml_rtots(toml_raw_t s, toml_timestamp_t *ret);
#endif /* TOML_H */

21
source/core_data.c Normal file
View File

@ -0,0 +1,21 @@
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdlib.h>
#include <math.h>
//List
//DAG
//BinaryTree
//QuadTree
//OcTree
//K-Tree
//HashMap

43
source/core_memory.c Normal file
View File

@ -0,0 +1,43 @@
#include <core.h>
// Frame Allocator
__thread static char* frame_buffer = 0x00;
__thread static char* current_position = 0x00;
__thread static int buffer_size;
void* MemSet(void *dst, const char data, const size_t length) {
for (size_t i = 0; i < length; i++) {
*((char *)dst + i) = data;
}
return (dst);
}
void InitFrameAllocator(size_t n) {
frame_buffer = malloc(n);
current_position = frame_buffer;
}
void *FrameAlloc(size_t n) {
void* ret = 0x00;
if (current_position - frame_buffer + n < buffer_size) {
}
ret = current_position;
current_position += n;
return (ret);
}
void FrameReset() {
current_position = frame_buffer;
MemSet(frame_buffer, 0, buffer_size);
}
void DeleteFrameAllocator() {
current_position = NULL;
free(frame_buffer);
}
// Ressource Allocator (PreComputed);
// Fast Allocator; when the fram allocator is too short lived

5
source/core_sorting.c Normal file
View File

@ -0,0 +1,5 @@
#include <core.h>
//QuickSort
//RadixSort
//DepthSort used for transparancy in the scene

51
source/debug.c Normal file
View File

@ -0,0 +1,51 @@
#include <engine.h>
#include <pthread.h>
/*
Time Manipulation
// base tick = 0.4;
// *2 = 0.2;
// *0.5 = 0.8;
*/
#define BASE_TICK 0.4
void TimeManipulation(float *tick) {
if (1) {
*tick = BASE_TICK;
}
if (2) {
*tick = BASE_TICK * 2;
}
if (3) {
*tick = BASE_TICK * 0.5;
}
}
/*
Toggle Show Debug (hitbox, scanray, scan cone, vision cone, interactrion range, overlay)
*/
void DebugRender() {
}
/*
State Machine (Game over, Quest Complete, Reset, StartGame, Reload)
*/
void StateMachine(ENGINE_STATE *state) {
(state);
}
/*
Live Data Inspector (UI Panel)
current state of a selected NPC or Item
*/
void DataInspector() {
}
/*
Debug Console
*/
void DebugConsol() {
__thread static char user_input[256];//need to be allocated for thread safety
}

28
source/entity.c Normal file
View File

@ -0,0 +1,28 @@
#include <engine.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
int EntityUpdate(void) {
}
void EntityManager(void) {
bool close_signal = false;
while(!close_signal) {
//update all entity data
//spawn newentity from queue
//cull entity
}
return;
}
void SpawnVisualEffect() {
//spawn a timed entity used for a visuel effect
}

17
source/event.c Normal file
View File

@ -0,0 +1,17 @@
#include <engine.h>
void create(void) {
}
void subscribe(void) {
//this should return an handle that allow to poll event that happen last frame
}
void emit(void) {
double currentTime = GetTime();
int event_type = 0;
char* Information = "tmp";
int initiator = 0;
int actors = 0;
int action = 0;
}

57
source/gamemode.c Normal file
View File

@ -0,0 +1,57 @@
#include <engine.h>
/*
Roll Dice between 1 and max_value role_number times and return either the average if avrg flag is set or the best of the roll
*/
void RollDice(int max_value, int role_number, bool avrg) {
GetRandomValue(1, max_value);
}
/*
Gather Loot Table and roll dice to generate loot
*/
void Loot() {
}
void BaseBuild() {
}
void BaseDefense() {
}
void BaseAssault() {
}
void Diplomacy() {
}
void Dungeon() {
}
void Fighting() {
}
void Dungeon() {
}
void Crafting() {
}
void Fishing() {
}
void Mining() {
}
void WoodCutting() {
}
void Harvesting() {
}
void Gathering() {
}
void World_Exploration() {
}

3
source/item.c Normal file
View File

@ -0,0 +1,3 @@
#include <engine.h>

78
source/main.c Normal file
View File

@ -0,0 +1,78 @@
#include <engine.h>
/*
// Input-related functions: keyboard
bool IsKeyPressed(int key); // Check if a key has been pressed once
bool IsKeyPressedRepeat(int key); // Check if a key has been pressed again
bool IsKeyDown(int key); // Check if a key is being pressed
bool IsKeyReleased(int key); // Check if a key has been released once
bool IsKeyUp(int key); // Check if a key is NOT being pressed
int GetKeyPressed(void); // Get key pressed (keycode), call it multiple times for keys queued, returns 0 when the queue is empty
int GetCharPressed(void); // Get char pressed (unicode), call it multiple times for chars queued, returns 0 when the queue is empty
void SetExitKey(int key); // Set a custom key to exit program (default is ESC)
// Input-related functions: mouse
bool IsMouseButtonPressed(int button); // Check if a mouse button has been pressed once
bool IsMouseButtonDown(int button); // Check if a mouse button is being pressed
bool IsMouseButtonReleased(int button); // Check if a mouse button has been released once
bool IsMouseButtonUp(int button); // Check if a mouse button is NOT being pressed
int GetMouseX(void); // Get mouse position X
int GetMouseY(void); // Get mouse position Y
Vector2 GetMousePosition(void); // Get mouse position XY
Vector2 GetMouseDelta(void); // Get mouse delta between frames
void SetMousePosition(int x, int y); // Set mouse position XY
void SetMouseOffset(int offsetX, int offsetY); // Set mouse offset
void SetMouseScale(float scaleX, float scaleY); // Set mouse scaling
float GetMouseWheelMove(void); // Get mouse wheel movement for X or Y, whichever is larger
Vector2 GetMouseWheelMoveV(void); // Get mouse wheel movement for both X and Y
void SetMouseCursor(int cursor); // Set mouse cursor
*/
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)l
break;
}
}
key = GetKeyPressed();
}
}
void GameLoop(const double tick_time) {
static double time = 0;
time += GetFrameTime();
if (time >= tick_time) {
// interaction
// simulation
//dispatch all thread then
//wait all thread end
time = 0;
}
}
int main(void) {
double tick_time = 0.4;
SetTraceLogLevel(LOG_ALL);
LoadPipeline();
LoadAssets();
SetExitKey(KEY_NULL);
while (!WindowShouldClose()) {
UpdateInput();
//DispatchWorker
ComputeIntent();
GameLoop(tick_time);
//joinWorker
Rendering();
}
UnloadAssets();
UnloadPipeline();
return (0);
}

View File

@ -0,0 +1,92 @@
#include <core.h>
#include <extern/tinycthread.h>
static bool done_flag = false;
static mtx_t done_mtx;
static bool running_flag = false;
static mtx_t running_mtx;
static thrd_t *worker_queue;
static int worker_size;
// Create Thread Pool (Workers)
// Queue Task
// Return Result
void WorkerManager() {
bool running = true;
while (running) {
assert(thrd_sleep(10, 0) == 0);
switch (mtx_trylock(&running_mtx)) {
case (thrd_success): {
running = running_flag;
mtx_unlock(&running_mtx);
break;
}
case (thrd_error): {
thrd_exit(-1);
break;
}
default: {
TraceLog(LOG_DEBUG, "running mutex busy");
break;
}
}
//process worker queue
}
for (int i = 0; i < worker_size; i++) {
thrd_join(&worker_queue[i], NULL);
}
free(worker_queue);
thrd_exit(0);
}
void StartWorkerManager(int worker_number) {
thrd_t worker_mgr_thrd;
switch (thrd_create(&worker_mgr_thrd, WorkerManager, NULL)) {
case (thrd_error): {
TraceLog(LOG_ERROR, "WorkerManager Start Was Unsuccessful");
//launch the engine in no thread mods;
break;
}
case (thrd_nomem): {
TraceLog(LOG_ERROR, "WorkerManager Start Was Unsuccessful: no memory could get allocated for new thread");
assert(false);
break;
}
default: {
TraceLog(LOG_DEBUG, "WorkerManager Start Was Successful");
break;
}
}
worker_queue = malloc(sizeof(thrd_t) * worker_number);
worker_size = worker_number;
assert(worker_queue);
for (int i = 0; i < worker_number; i++) {
switch (thrd_create(&worker_queue[i], WorkerManager, NULL)) {
case (thrd_error): {
TraceLog(LOG_ERROR, "Worker No.%i Start Was Unsuccessful", i);
assert(false);
break;
}
case (thrd_nomem): {
TraceLog(LOG_ERROR, "Worker No.%i Start Was Unsuccessful: no memory could get allocated for new thread", i);
assert(false);
break;
}
default: {
TraceLog(LOG_DEBUG, "Worker No.%i Start Was Successful", i);
break;
}
}
}
}
void StopWorkerManager() {
while (mtx_trylock(&running_mtx) != thrd_success) {
thrd_sleep(11, 0);
}
running_flag = false;
mtx_unlock(&running_mtx);
}

8
source/player.c Normal file
View File

@ -0,0 +1,8 @@
#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)
*/

155
source/render.c Normal file
View File

@ -0,0 +1,155 @@
#include <engine.h>
#include <rlgl.h>
#include <raymath.h>
//#define RAYGUI_IMPLEMENTATION
//#include <raygui.h>
RenderCtx ctx;
/*
Audio
Video
Gameplay
Control
Accessibility
Filter
*/
void RenderOption() {
}
void RenderInventory() {
//DrawTextureRec();
}
void DebugInterface() {
DrawFPS(10, 10);
}
void UserInterface() {
}
void MainMenu() {
int current_state;
switch (current_state) {
case(0): {
break;
}
default:
break;
}
}
void LoadCameraMode(int mode) {
switch (mode) {
case(0): {
break;
}
default:
break;
}
}
void LoadPipeline() {
ctx.width = 800;
ctx.height = 480;
ctx.hud_on = true;
ctx.debug_on = true;
InitWindow(ctx.width, ctx.height, "GAME!!");
assert(IsWindowReady());
ctx.window = GetWindowHandle();
ctx.shader.deferred = LoadShader("source/shader/deferred.vs", "source/shader/deferred.fs");
ctx.shader.gbuffer = LoadShader("source/shader/gbuffer.vs", "source/shader/gbuffer.fs");
ctx.shader.filter = LoadShader("", "source/shader/Screen_filter.fs");
ctx.gbuffer.framebufferId = rlLoadFramebuffer();
assert(ctx.gbuffer.framebufferId);
rlEnableFramebuffer(ctx.gbuffer.framebufferId);
ctx.gbuffer.depth_tex_id = rlLoadTextureDepth(ctx.width, ctx.height, false);
// If Artefact appear on Normal, may need to change to RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32
ctx.gbuffer.normal_tex_id = rlLoadTexture(NULL, ctx.width, ctx.height, RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16, 1);
// The color in RGB, and the specular strength in the alpha channel
ctx.gbuffer.albedoSpec_tex_id = rlLoadTexture(NULL, ctx.width, ctx.height, RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, 1);
rlActiveDrawBuffers(3);
rlFramebufferAttach(ctx.gbuffer.framebufferId, ctx.gbuffer.depth_tex_id, RL_ATTACHMENT_DEPTH, RL_ATTACHMENT_TEXTURE2D, 0);
rlFramebufferAttach(ctx.gbuffer.framebufferId, ctx.gbuffer.normal_tex_id, RL_ATTACHMENT_COLOR_CHANNEL0, RL_ATTACHMENT_TEXTURE2D, 0);
rlFramebufferAttach(ctx.gbuffer.framebufferId, ctx.gbuffer.albedoSpec_tex_id, RL_ATTACHMENT_COLOR_CHANNEL1, RL_ATTACHMENT_TEXTURE2D, 0);
assert(rlFramebufferComplete(ctx.gbuffer.framebufferId));
rlEnableShader(ctx.shader.deferred.id);
int texUnitDepth = 0;
int texUnitNormal = 1;
int texUnitAlbedoSpec = 2;
SetShaderValue(ctx.shader.deferred, rlGetLocationUniform(ctx.shader.deferred.id, "gDepth"), &texUnitDepth, RL_SHADER_UNIFORM_SAMPLER2D);
SetShaderValue(ctx.shader.deferred, rlGetLocationUniform(ctx.shader.deferred.id, "gNormal"), &texUnitNormal, RL_SHADER_UNIFORM_SAMPLER2D);
SetShaderValue(ctx.shader.deferred, rlGetLocationUniform(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(240);//may change
}
void UnloadPipeline() {
rlUnloadFramebuffer(ctx.gbuffer.framebufferId);
rlUnloadTexture(ctx.gbuffer.depth_tex_id);
rlUnloadTexture(ctx.gbuffer.normal_tex_id);
rlUnloadTexture(ctx.gbuffer.albedoSpec_tex_id);
UnloadShader(ctx.shader.deferred);
UnloadShader(ctx.shader.gbuffer);
UnloadShader(ctx.shader.filter);
CloseWindow();
}
void Rendering() {
BeginDrawing();
ClearBackground(BLACK);
rlEnableDepthMask();
rlEnableFramebuffer(ctx.gbuffer.framebufferId);
rlEnableShader(ctx.shader.gbuffer.id);
BeginMode3D(ctx.camera);
//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
BeginShaderMode(ctx.shader.filter);
//DrawTextureRec();
EndShaderMode();
//render ui
//if (ctx.hud_on) {
// UserInterface();
//}
//if (ctx.debug_on) {
// DebugInterface();
//}
EndDrawing();
}
void LoadAssets() {
//Font
//Textures
//Models
//Sound
//Data
TraceLog(LOG_INFO, "Assets Loaded");
}
void UnloadAssets() {
}

3
source/sandbox.c Normal file
View File

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

48
source/serialization.c Normal file
View File

@ -0,0 +1,48 @@
#include <engine.h>
#include <extern/toml.h>
//load setting.toml to memory
void SettingLoad(const char *name) {
FILE *file;
file = fopen(name, "rb");
fclose(file);
}
//write setting in memory to setting.toml
void SettingSave(const char *name) {
FILE *file;
file = fopen(name, "wb");
fclose(file);
}
//apply change made by the player to setting in memory and write to setting.toml
void SettingUpdate() {
SettingSave("setting.toml");
}
void CharacterLoad(const char *name) {
FILE *file;
file = fopen(name, "wb");
fclose(file);
}
void CharacterSave(const char *name) {
FILE *file;
file = fopen(name, "wb");
fclose(file);
}
void WorldLoad(const char *name) {
FILE *file;
file = fopen(name, "wb");
fclose(file);
}
void WorldSave(const char *name) {
FILE *file;
file = fopen(name, "wb");
fclose(file);
}

31
source/shader/crt.fs Normal file
View File

@ -0,0 +1,31 @@
#version 330
uniform sampler2D texture0;
uniform vec2 resolution;
uniform float time;
in vec2 fragTexCoord;
out vec4 fragColor;
void main() {
vec2 uv = fragTexCoord;
// // Subtle horizontal distortion (small, smooth)
// float wave = 0.003 * sin(uv.y * 80.0 + time * 2.0);
// uv.x += wave;
//
// // Very light vertical distortion
// uv.y += 0.002 * sin(uv.x * 50.0 + time * 2.5);
// RGB slight chromatic aberration
float r = texture(texture0, uv + vec2(0.0015, 0.0)).r;
float g = texture(texture0, uv).g;
float b = texture(texture0, uv - vec2(0.0015, 0.0)).b;
vec3 color = vec3(r, g, b);
// Very light scanlines
float scanline = 0.96 + 0.04 * sin(uv.y * resolution.y * 2.5);
fragColor = vec4(color * scanline, 1.0);
}

54
source/shader/deferred.fs Normal file
View File

@ -0,0 +1,54 @@
#version 330 core
out vec4 finalColor;
in vec2 texCoord;
in vec2 texCoord2;
uniform sampler2D gPosition;
uniform sampler2D gNormal;
uniform sampler2D gAlbedoSpec;
struct Light {
int enabled;
int type; // Unused in this demo
vec3 position;
vec3 target; // Unused in this demo
vec4 color;
};
const int NR_LIGHTS = 4;
uniform Light lights[NR_LIGHTS];
uniform vec3 viewPosition;
const float QUADRATIC = 0.032;
const float LINEAR = 0.09;
void main() {
vec3 fragPosition = texture(gPosition, texCoord).rgb;
vec3 normal = texture(gNormal, texCoord).rgb;
vec3 albedo = texture(gAlbedoSpec, texCoord).rgb;
float specular = texture(gAlbedoSpec, texCoord).a;
vec3 ambient = albedo*vec3(0.1f);
vec3 viewDirection = normalize(viewPosition - fragPosition);
for (int i = 0; i < NR_LIGHTS; ++i)
{
if (lights[i].enabled == 0) continue;
vec3 lightDirection = lights[i].position - fragPosition;
vec3 diffuse = max(dot(normal, lightDirection), 0.0)*albedo*lights[i].color.xyz;
vec3 halfwayDirection = normalize(lightDirection + viewDirection);
float spec = pow(max(dot(normal, halfwayDirection), 0.0), 32.0);
vec3 specular = specular*spec*lights[i].color.xyz;
// Attenuation
float distance = length(lights[i].position - fragPosition);
float attenuation = 1.0/(1.0 + LINEAR*distance + QUADRATIC*distance*distance);
diffuse *= attenuation;
specular *= attenuation;
ambient += diffuse + specular;
}
finalColor = vec4(ambient, 1.0);
}

11
source/shader/deferred.vs Normal file
View File

@ -0,0 +1,11 @@
#version 330 core
layout (location = 0) in vec3 vertexPosition;
layout (location = 1) in vec2 vertexTexCoord;
out vec2 texCoord;
void main() {
gl_Position = vec4(vertexPosition, 1.0);
texCoord = vertexTexCoord;
}

95
source/shader/fog.fs Normal file
View File

@ -0,0 +1,95 @@
#version 330
// Input vertex attributes (from vertex shader)
in vec2 fragTexCoord;
in vec4 fragColor;
in vec3 fragPosition;
in vec3 fragNormal;
// Input uniform values
uniform sampler2D texture0;
uniform vec4 colDiffuse;
// Output fragment color
out vec4 finalColor;
// NOTE: Add your custom variables here
#define MAX_LIGHTS 4
#define LIGHT_DIRECTIONAL 0
#define LIGHT_POINT 1
struct MaterialProperty {
vec3 color;
int useSampler;
sampler2D sampler;
};
struct Light {
int enabled;
int type;
vec3 position;
vec3 target;
vec4 color;
};
// Input lighting values
uniform Light lights[MAX_LIGHTS];
uniform vec4 ambient;
uniform vec3 viewPos;
uniform float fogDensity;
void main()
{
// Texel color fetching from texture sampler
vec4 texelColor = texture(texture0, fragTexCoord);
vec3 lightDot = vec3(0.0);
vec3 normal = normalize(fragNormal);
vec3 viewD = normalize(viewPos - fragPosition);
vec3 specular = vec3(0.0);
// NOTE: Implement here your fragment shader code
for (int i = 0; i < MAX_LIGHTS; i++)
{
if (lights[i].enabled == 1)
{
vec3 light = vec3(0.0);
if (lights[i].type == LIGHT_DIRECTIONAL) light = -normalize(lights[i].target - lights[i].position);
if (lights[i].type == LIGHT_POINT) light = normalize(lights[i].position - fragPosition);
float NdotL = max(dot(normal, light), 0.0);
lightDot += lights[i].color.rgb*NdotL;
float specCo = 0.0;
if (NdotL > 0.0) specCo = pow(max(0.0, dot(viewD, reflect(-(light), normal))), 16.0); // Shine: 16.0
specular += specCo;
}
}
finalColor = (texelColor*((colDiffuse + vec4(specular,1))*vec4(lightDot, 1.0)));
finalColor += texelColor*(ambient/10.0);
// Gamma correction
finalColor = pow(finalColor, vec4(1.0/2.2));
// Fog calculation
float dist = length(viewPos - fragPosition);
// these could be parameters...
const vec4 fogColor = vec4(0.5, 0.5, 0.5, 1.0);
//const float fogDensity = 0.16;
// Exponential fog
float fogFactor = 1.0/exp((dist*fogDensity)*(dist*fogDensity));
// Linear fog (less nice)
//const float fogStart = 2.0;
//const float fogEnd = 10.0;
//float fogFactor = (fogEnd - dist)/(fogEnd - fogStart);
fogFactor = clamp(fogFactor, 0.0, 1.0);
finalColor = mix(fogColor, finalColor, fogFactor);
}

22
source/shader/gbuffer.fs Normal file
View File

@ -0,0 +1,22 @@
#version 330 core
layout (location = 0) out vec3 gPosition;
layout (location = 1) out vec3 gNormal;
layout (location = 2) out vec4 gAlbedoSpec;
in vec3 fragPosition;
in vec2 fragTexCoord;
in vec3 fragNormal;
uniform sampler2D diffuseTexture;
uniform sampler2D specularTexture;
void main() {
// store the fragment position vector in the first gbuffer texture
gPosition = fragPosition;
// also store the per-fragment normals into the gbuffer
gNormal = normalize(fragNormal);
// and the diffuse per-fragment color
gAlbedoSpec.rgb = texture(diffuseTexture, fragTexCoord).rgb;
// store specular intensity in gAlbedoSpec's alpha component
gAlbedoSpec.a = texture(specularTexture, fragTexCoord).r;
}

24
source/shader/gbuffer.vs Normal file
View File

@ -0,0 +1,24 @@
#version 330 core
layout (location = 0) in vec3 vertexPosition;
layout (location = 1) in vec2 vertexTexCoord;
layout (location = 2) in vec3 vertexNormal;
out vec3 fragPosition;
out vec2 fragTexCoord;
out vec3 fragNormal;
uniform mat4 matModel;
uniform mat4 matView;
uniform mat4 matProjection;
void main()
{
vec4 worldPos = matModel*vec4(vertexPosition, 1.0);
fragPosition = worldPos.xyz;
fragTexCoord = vertexTexCoord;
mat3 normalMatrix = transpose(inverse(mat3(matModel)));
fragNormal = normalMatrix*vertexNormal;
gl_Position = matProjection*matView*worldPos;
}

35
source/shader/outline.fs Normal file
View File

@ -0,0 +1,35 @@
#version 330
// Input vertex attributes (from vertex shader)
in vec2 fragTexCoord;
in vec4 fragColor;
// Input uniform values
uniform sampler2D texture0;
uniform vec4 colDiffuse;
uniform vec2 textureSize;
uniform float outlineSize;
uniform vec4 outlineColor;
// Output fragment color
out vec4 finalColor;
void main()
{
vec4 texel = texture(texture0, fragTexCoord); // Get texel color
vec2 texelScale = vec2(0.0);
texelScale.x = outlineSize/textureSize.x;
texelScale.y = outlineSize/textureSize.y;
// We sample four corner texels, but only for the alpha channel (this is for the outline)
vec4 corners = vec4(0.0);
corners.x = texture(texture0, fragTexCoord + vec2(texelScale.x, texelScale.y)).a;
corners.y = texture(texture0, fragTexCoord + vec2(texelScale.x, -texelScale.y)).a;
corners.z = texture(texture0, fragTexCoord + vec2(-texelScale.x, texelScale.y)).a;
corners.w = texture(texture0, fragTexCoord + vec2(-texelScale.x, -texelScale.y)).a;
float outline = min(dot(corners, vec4(1.0)), 1.0);
vec4 color = mix(vec4(0.0), outlineColor, outline);
finalColor = mix(color, texel, texel.a);
}

View File

@ -0,0 +1,33 @@
#version 330
// Input vertex attributes (from vertex shader)
in vec2 fragTexCoord;
in vec4 fragColor;
// Input uniform values
uniform sampler2D texture0;
uniform vec4 colDiffuse;
// Output fragment color
out vec4 finalColor;
// NOTE: Add your custom variables here
// NOTE: Render size values must be passed from code
const float renderWidth = 800;
const float renderHeight = 450;
uniform float pixelWidth = 5.0;
uniform float pixelHeight = 5.0;
void main()
{
float dx = pixelWidth*(1.0/renderWidth);
float dy = pixelHeight*(1.0/renderHeight);
vec2 coord = vec2(dx*floor(fragTexCoord.x/dx), dy*floor(fragTexCoord.y/dy));
vec3 tc = texture(texture0, coord).rgb;
finalColor = vec4(tc, 1.0);
}