Entity system, generate some trees around player, etc

This commit is contained in:
2025-06-03 19:29:36 +02:00
parent c6377f1233
commit c5370a4614
21 changed files with 229 additions and 72 deletions
+4 -4
View File
@@ -1,11 +1,11 @@
SRC=src/main.c src/program.c src/resources.c src/camera.c src/chunk/chunk.c \
src/chunk/mesh.c src/flags.c src/texture.c src/chunk/manager.c \
src/event/manager.c src/event/handlers.c src/state.c src/graphics.c \
src/entity/meshes.c src/entity/manager.c
src/entity/meshes.c src/entity/manager.c src/entity/templates.c
OBJ=$(SRC:.c=.o)
CFLAGS=-pg -Werror -Wextra -Wall `pkg-config --cflags sdl3 sdl3-image cglm gl glib-2.0`
LDFLAGS=`pkg-config --libs sdl3 sdl3-image cglm gl glib-2.0` -lm
CFLAGS=-g -pg -Werror -Wextra -Wall `pkg-config --cflags sdl3 sdl3-image cglm gl glib-2.0`
LDFLAGS=-g -pg -lm `pkg-config --libs sdl3 sdl3-image cglm gl glib-2.0`
TARGET=wschod
CC=gcc
LD=gcc
@@ -21,4 +21,4 @@ $(TARGET): $(OBJ)
$(CC) -c $^ -o $@ $(CFLAGS)
clean:
$(RM) $(TARGET) $(OBJ)
$(RM) gmon.out $(TARGET) $(OBJ)
+2 -1
View File
@@ -4,8 +4,9 @@ attribute vec4 position;
uniform mat4 view;
uniform mat4 projection;
uniform mat4 model;
void main ()
{
gl_Position = projection * view * position;
gl_Position = projection * view * model * position;
}
-1
View File
@@ -18,6 +18,5 @@ void main ()
result = mix (result, texture2D (materials[3], f_uv), f_material[2]);
result = mix (result, texture2D (materials[4], f_uv), f_material[3]);
result = result * (f_height / 5.0);
gl_FragColor = result;
}
+1 -1
View File
@@ -8,7 +8,7 @@ varying vec2 f_uv;
void main ()
{
if(texture2D (texture, f_uv).a < 0.1)
if(texture2D (texture, f_uv).a < 0.2)
{
discard;
}
+2 -1
View File
@@ -5,11 +5,12 @@ attribute vec2 uv;
uniform mat4 view;
uniform mat4 projection;
uniform mat4 model;
varying vec2 f_uv;
void main ()
{
f_uv = uv;
gl_Position = projection * view * position;
gl_Position = projection * view * model * position;
}
+29 -1
View File
@@ -2,6 +2,9 @@
#include <math.h>
extern GHashTable *entity_templates;
extern GSequence *entity_manager;
Chunk *
Chunk_new ()
{
@@ -11,6 +14,13 @@ Chunk_new ()
return chunk;
}
/* Example function for a tick for an entity. */
void
tree_grow (Entity *entity)
{
entity->scale[1] += 0.01;
}
void
Chunk_random (Chunk *chunk, int xoffset, int zoffset)
{
@@ -20,10 +30,28 @@ Chunk_random (Chunk *chunk, int xoffset, int zoffset)
{
chunk->heightmap[INDEX (x, z)] =
(glm_perlin_vec2
((vec2) { (x + xoffset + 0.5) / 10.0, (z + zoffset + 0.5) / 10.0 }) + 0.6) * 5;
((vec2) { (x + xoffset + 0.5) / 10.0, (z + zoffset + 0.5) / 10.0 }) + 0.6) * 10;
chunk->materialmap[INDEX (x, z)] = (int)
(glm_perlin_vec2 ((vec2) { (x + xoffset + 0.5) / 20.0, (z + zoffset + 0.5) / 20.0 }) + 0.6 * 5) % 5;
if (rand() % 100 < 2)
{
Entity *tree = malloc (sizeof (Entity));
*tree = (Entity) {
.type = ENTITY_SOLID,
.mesh_type = ENTITY_MESH_X,
.origin = ENTITY_BOTTOM,
.position = { (float) x + xoffset, chunk->heightmap[INDEX (x, z)], (float) z + zoffset },
.scale = { 3.0, 10.0, 3.0 },
.rotation = (rand () % 180) * (M_PI / 180.0),
.texture = "tree0",
.on_tick = tree_grow
};
EM_ENTADD (tree);
}
}
}
}
+4
View File
@@ -2,9 +2,13 @@
#include <stdlib.h>
#include <glib-2.0/glib.h>
#include <cglm/cglm.h>
#include <cglm/noise.h>
#include "../util.h"
#include "../entity/templates.h"
#include "../entity/manager.h"
#define CHUNK_DIM 32
#define CHUNK_SIZE (CHUNK_DIM*CHUNK_DIM)
+3
View File
@@ -43,6 +43,9 @@ ChunkManager_init ()
chunk_manager.chunk_meshes = g_hash_table_new_full (cm_ivec2_hash, cm_ivec2_equal, free, (GDestroyNotify) Chunk_free);
}
/* TODO: Update the chunks only if the player has moved into another
chunk, to save frame time. */
void
ChunkManager_update (vec3 camera_position)
{
+25
View File
@@ -0,0 +1,25 @@
#include "templates.h"
GHashTable *entity_templates;
void
EntityTemplates_init ()
{
entity_templates = g_hash_table_new (g_str_hash, g_str_equal);
Entity *tree = malloc (sizeof (Entity));
*tree = (Entity) {
.type = ENTITY_SOLID,
.mesh_type = ENTITY_MESH_X,
.origin = ENTITY_BOTTOM,
.position = { 0.0, 0.0, 0.0 },
.scale = { 1.0, 3.0, 1.0 },
.rotation = 0.0,
.texture = "tree0"
};
ET_ENTADD ("tree", tree);
}
/* To avoid confusion with EM_ENTADD. */
#undef ET_ENTADD
+1
View File
@@ -0,0 +1 @@
emssej@Komputer-Ze-Smieci.2233:1748755544
+9 -11
View File
@@ -1,18 +1,16 @@
#pragma once
typedef enum EntityMeshType
{
ENTITY_MESH_BILLBOARD,
ENTITY_MESH_X
} EntityMeshType;
typedef struct Entity
{
enum { ENTITY_DEFAULT, ENTITY_SOLID } type;
enum { ENTITY_MESH_BILLBOARD, ENTITY_MESH_X } mesh_type;
enum { ENTITY_CENTER, ENTITY_BOTTOM } origin;
void *userdata;
void (*on_tick) (struct Entity *self);
vec3 position;
vec3 rotation; /* Unused for now. */
float rotation;
vec3 scale; /* Unused for now. */
int texture;
EntityMeshType type;
char *texture;
} Entity;
Entity *Entity_new (vec3 position, int texture, EntityMeshType type);
+58 -2
View File
@@ -1,9 +1,14 @@
#include "manager.h"
GSequence *entity_manager;
/* TODO: Sort entities by mesh type AS WELL AS distance. Binding
buffers is very performance-sensitive, thus to conserve speed one
type should be rendered in one go, then the other type, etc. */
GSequence *entity_manager;
EntityMesh mesh_billboard, mesh_x;
extern Resources resources;
void
EntityManager_init ()
{
@@ -12,14 +17,65 @@ EntityManager_init ()
mesh_x = EntityMesh_make_x ();
}
void
em_tick_internal (gpointer data, gpointer userdata)
{
UNUSED (userdata);
Entity *entity = data;
if (entity->on_tick)
{
entity->on_tick (entity);
}
}
void
EntityManager_tick ()
{
g_sequence_foreach (entity_manager, em_tick_internal, NULL);
}
void
em_render_internal (gpointer data, gpointer userdata)
{
UNUSED (userdata);
Entity *entity = data;
EntityMesh to_render;
unsigned int program;
switch (entity->mesh_type)
{
case ENTITY_MESH_X:
program = R_PRGGET ("default");
to_render = mesh_x;
break;
default:
program = R_PRGGET ("billboard");
to_render = mesh_billboard;
break;
}
mat4 model = GLM_MAT4_IDENTITY_INIT;
glm_translate (model, entity->position);
if (entity->origin == ENTITY_BOTTOM)
{
glm_translate (model, (vec3) { 0.0, entity->scale[1], 0.0 });
}
glm_scale (model, entity->scale);
program_use (program);
program_set_mat4 (program, "model", model);
glActiveTexture (GL_TEXTURE0);
glBindTexture (GL_TEXTURE_2D, R_TEXGET (entity->texture));
EntityMesh_render (&to_render);
}
void
EntityManager_render ()
{
g_sequence_foreach (entity_manager, em_render_internal, NULL);
}
+3 -3
View File
@@ -5,10 +5,10 @@
#include "entity.h"
#include "meshes.h"
#include "../util.h"
#include "../resources.h"
/* TODO: Sort entities by mesh type AS WELL AS distance. Binding
buffers is very performance-sensitive, thus to conserve speed one
type should be rendered in one go, then the other type, etc. */
#define EM_ENTADD(entity) (g_sequence_append (entity_manager, entity));
void EntityManager_init ();
void EntityManager_tick ();
+2 -6
View File
@@ -1,11 +1,11 @@
#include "meshes.h"
/* TODO: add back faces. */
/* TODO: Split binding/rendering */
extern GameFlags game_flags;
void
EntityMesh_bind (EntityMesh *mesh)
EntityMesh_render (EntityMesh *mesh)
{
glBindBuffer (GL_ARRAY_BUFFER, mesh->pbo);
glEnableVertexAttribArray (0);
@@ -16,11 +16,7 @@ EntityMesh_bind (EntityMesh *mesh)
glVertexAttribPointer (1, 2, GL_FLOAT, GL_FALSE, sizeof (float) * 2, 0);
glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, mesh->ebo);
}
void
EntityMesh_render (EntityMesh *mesh)
{
if (game_flags.wireframe_enabled)
{
glDrawElements (GL_LINES, mesh->indices_len, GL_UNSIGNED_INT, 0);
-1
View File
@@ -13,7 +13,6 @@ typedef struct EntityMesh
unsigned int ebo;
} EntityMesh;
void EntityMesh_bind (EntityMesh *mesh);
void EntityMesh_render (EntityMesh *mesh);
EntityMesh EntityMesh_make_billboard ();
EntityMesh EntityMesh_make_x ();
+32
View File
@@ -0,0 +1,32 @@
#include "templates.h"
GHashTable *entity_templates;
void
EntityTemplates_init ()
{
entity_templates = g_hash_table_new (g_str_hash, g_str_equal);
Entity *tree = malloc (sizeof (Entity));
*tree = (Entity) {
.type = ENTITY_SOLID,
.mesh_type = ENTITY_MESH_X,
.origin = ENTITY_BOTTOM,
.position = { 0.0, 0.0, 0.0 },
.scale = { 1.0, 3.0, 1.0 },
.rotation = 0.0,
.texture = "tree0"
};
ET_ENTADD ("tree", tree);
}
/* Example function for a tick for an entity. */
void
example_entity_tick (Entity *entity)
{
entity->scale[1] += 0.0000001;
}
/* To avoid confusion with EM_ENTADD. */
#undef ET_ENTADD
+13
View File
@@ -0,0 +1,13 @@
#pragma once
#include <stdlib.h>
#include <glib-2.0/glib.h>
#include <cglm/cglm.h>
#include "entity.h"
#define ET_ENTGET(key) ((Entity *) g_hash_table_lookup (entity_templates, key))
#define ET_ENTADD(key, entity) (g_hash_table_insert (entity_templates, key, entity))
void EntityTemplates_init ();
+20 -22
View File
@@ -6,9 +6,6 @@ extern ChunkManager chunk_manager;
extern GameState game_state;
extern Resources resources;
extern EntityMesh mesh_billboard;
extern EntityMesh mesh_x;
void
GraphicsContext_init ()
{
@@ -60,32 +57,33 @@ GraphicsContext_render ()
mat4 projection, view;
Camera_get_projection (&game_state.camera, 640.0 / 480.0, projection);
Camera_get_view (&game_state.camera, view);
program_use (_RGP ("chunk"));
program_set_mat4 (_RGP ("chunk"), "projection", projection);
program_set_mat4 (_RGP ("chunk"), "view", view);
/* Set views and projections in all programs. TODO: make this dynamic*/
program_use (R_PRGGET ("billboard"));
program_set_mat4 (R_PRGGET ("billboard"), "projection", projection);
program_set_mat4 (R_PRGGET ("billboard"), "view", view);
program_use (R_PRGGET ("default"));
program_set_mat4 (R_PRGGET ("default"), "projection", projection);
program_set_mat4 (R_PRGGET ("default"), "view", view);
program_use (R_PRGGET ("chunk"));
program_set_mat4 (R_PRGGET ("chunk"), "projection", projection);
program_set_mat4 (R_PRGGET ("chunk"), "view", view);
glActiveTexture (GL_TEXTURE0);
glBindTexture (GL_TEXTURE_2D, _RGT ("terrain0"));
glBindTexture (GL_TEXTURE_2D, R_TEXGET ("terrain0"));
glActiveTexture (GL_TEXTURE1);
glBindTexture (GL_TEXTURE_2D, _RGT ("terrain1"));
glBindTexture (GL_TEXTURE_2D, R_TEXGET ("terrain1"));
glActiveTexture (GL_TEXTURE2);
glBindTexture (GL_TEXTURE_2D, _RGT ("terrain2"));
glBindTexture (GL_TEXTURE_2D, R_TEXGET ("terrain2"));
glActiveTexture (GL_TEXTURE3);
glBindTexture (GL_TEXTURE_2D, _RGT ("terrain3"));
glBindTexture (GL_TEXTURE_2D, R_TEXGET ("terrain3"));
glActiveTexture (GL_TEXTURE4);
glBindTexture (GL_TEXTURE_2D, _RGT ("terrain4"));
glBindTexture (GL_TEXTURE_2D, R_TEXGET ("terrain4"));
ChunkManager_render (game_state.camera.position, _RGP ("chunk"));
program_use (_RGP ("default"));
program_set_mat4 (_RGP ("default"), "projection", projection);
program_set_mat4 (_RGP ("default"), "view", view);
glActiveTexture (GL_TEXTURE0);
glBindTexture (GL_TEXTURE_2D, _RGT ("tree0"));
EntityMesh_bind (&mesh_x);
EntityMesh_render (&mesh_x);
ChunkManager_render (game_state.camera.position, R_PRGGET ("chunk"));
EntityManager_render ();
SDL_GL_SwapWindow (gfx.window);
}
+4 -1
View File
@@ -6,6 +6,7 @@
#include "event/manager.h"
#include "event/handlers.h"
#include "chunk/manager.h"
#include "entity/templates.h"
#include "state.h"
#include "resources.h"
#include "graphics.h"
@@ -24,6 +25,7 @@ SDL_AppInit (void **appstate, int argc, char **argv)
Resources_init ();
ChunkManager_init ();
EntityManager_init ();
EntityTemplates_init ();
GameState_init (SDL_GetTicks ());
/* Set some basic game flags for testing. */
game_flags.can_free_look = 1;
@@ -51,8 +53,9 @@ SDL_AppIterate (void *appstate)
{
UNUSED (appstate);
ChunkManager_update (game_state.camera.position);
GameState_tick (SDL_GetTicks ());
EntityManager_tick ();
ChunkManager_update (game_state.camera.position);
GraphicsContext_render ();
return SDL_APP_CONTINUE;
+11 -11
View File
@@ -8,20 +8,20 @@ Resources_init ()
resources.programs = g_hash_table_new (g_str_hash, g_str_equal);
resources.textures = g_hash_table_new (g_str_hash, g_str_equal);
_RAP ("default", _RLP ("res/shaders/default.vert", "res/shaders/default.frag"));
_RAP ("billboard", _RLP ("res/shaders/billboard.vert", "res/shaders/billboard.frag"));
_RAP ("chunk", _RLP ("res/shaders/chunk.vert", "res/shaders/chunk.frag"));
R_PRGADD ("default", R_PRGLOAD ("res/shaders/default.vert", "res/shaders/default.frag"));
R_PRGADD ("billboard", R_PRGLOAD ("res/shaders/billboard.vert", "res/shaders/billboard.frag"));
R_PRGADD ("chunk", R_PRGLOAD ("res/shaders/chunk.vert", "res/shaders/chunk.frag"));
program_use (_RGP ("chunk"));
program_set_int_array (_RGP ("chunk"), "materials", 5, (int[5]) { 0, 1, 2, 3, 4 });
program_use (R_PRGGET ("chunk"));
program_set_int_array (R_PRGGET ("chunk"), "materials", 5, (int[5]) { 0, 1, 2, 3, 4 });
_RAT ("terrain0", _RLT ("res/textures/dirt.png"));
_RAT ("terrain1", _RLT ("res/textures/drygrass.png"));
_RAT ("terrain2", _RLT ("res/textures/grass.png"));
_RAT ("terrain3", _RLT ("res/textures/rock_cement.png"));
_RAT ("terrain4", _RLT ("res/textures/asphalt_gravel.png"));
R_TEXADD ("terrain0", R_TEXLOAD ("res/textures/dirt.png"));
R_TEXADD ("terrain1", R_TEXLOAD ("res/textures/drygrass.png"));
R_TEXADD ("terrain2", R_TEXLOAD ("res/textures/grass.png"));
R_TEXADD ("terrain3", R_TEXLOAD ("res/textures/rock_cement.png"));
R_TEXADD ("terrain4", R_TEXLOAD ("res/textures/asphalt_gravel.png"));
_RAT ("tree0", _RLT ("res/textures/tree.png"));
R_TEXADD ("tree0", R_TEXLOAD ("res/textures/tree.png"));
}
unsigned int
+6 -6
View File
@@ -6,12 +6,12 @@
#include "program.h"
#include "texture.h"
#define _RAP(key, program) (g_hash_table_insert (resources.programs, key, GINT_TO_POINTER (program)))
#define _RAT(key, texture) (g_hash_table_insert (resources.textures, key, GINT_TO_POINTER (texture)))
#define _RLP(v_path, f_path) (Resources_load_program (v_path, f_path))
#define _RLT(path) (Resources_load_texture (path))
#define _RGP(key) (GPOINTER_TO_INT (g_hash_table_lookup (resources.programs, key)))
#define _RGT(key) (GPOINTER_TO_INT (g_hash_table_lookup (resources.textures, key)))
#define R_PRGADD(key, program) (g_hash_table_insert (resources.programs, key, GINT_TO_POINTER (program)))
#define R_TEXADD(key, texture) (g_hash_table_insert (resources.textures, key, GINT_TO_POINTER (texture)))
#define R_PRGLOAD(v_path, f_path) (Resources_load_program (v_path, f_path))
#define R_TEXLOAD(path) (Resources_load_texture (path))
#define R_PRGGET(key) (GPOINTER_TO_INT (g_hash_table_lookup (resources.programs, key)))
#define R_TEXGET(key) (GPOINTER_TO_INT (g_hash_table_lookup (resources.textures, key)))
typedef struct Resources {
GHashTable *programs;