Broken state NewAllObj
Christian Immanuel · 2025-02-03 11:20 · eea4011bbba8a1e3e7abc8afde0f1ada870bfde5
CMakeLists.txt | 10 +++--
camera.c | 14 +++----
camera.h | 5 ++-
character.c | 22 +++++-----
character.h | 17 ++------
collectable.c | 11 +++++
collectable.h | 18 +++++++++
main.c | 60 ++++++++++++++++++---------
map.c | 89 +++++++++++++++++++++++++---------------
map.h | 18 +++++----
object.c | 126 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
object.h | 32 +++++++++++++++
render.c | 95 ++++++++++++++++++++++++++++++++++++-------
render.h | 4 +-
14 files changed, 407 insertions(+), 114 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6c2fd98..df4b55b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -6,11 +6,13 @@ project(FestivalGame C)
# Define source files
set(SOURCES
- main.c
- map.c
- character.c
- render.c
camera.c
+ character.c
+ collectable.c
+ main.c
+ map.c
+ object.c
+ render.c
)
# Include directories
diff --git a/camera.c b/camera.c
index 65299c1..5702528 100644
--- a/camera.c
+++ b/camera.c
@@ -2,24 +2,20 @@
extern int MAP_WIDTH;
extern int MAP_HEIGHT;
-extern float MAP_CENTER_X;
-extern float MAP_CENTER_Y;
-extern float WINDOW_WIDTH;
-extern float WINDOW_HEIGHT;
extern const int TILE_SIZE;
void setCamera(Camera* camera) {
// Calculate camera offset
- camera->offset_x = MAP_CENTER_X - (WINDOW_WIDTH / 2);
- camera->offset_y = MAP_CENTER_Y - (WINDOW_HEIGHT / 2);
+ camera->offset_x = camera->center_x - (camera->view_w / 2);
+ camera->offset_y = camera->center_y - (camera->view_h / 2);
- // Calculate window bounds in terms of tiles
+ // Calculate bounds in terms of tiles
camera->min_x = (int)(camera->offset_x / TILE_SIZE);
- camera->max_x = (int)((camera->offset_x + WINDOW_WIDTH) / TILE_SIZE);
+ camera->max_x = (int)((camera->offset_x + camera->view_w) / TILE_SIZE);
camera->min_y = (int)(camera->offset_y / TILE_SIZE);
- camera->max_y = (int)((camera->offset_y + WINDOW_HEIGHT) / TILE_SIZE);
+ camera->max_y = (int)((camera->offset_y + camera->view_h) / TILE_SIZE);
// Ensure bounds are within map limits
camera->min_x = (camera->min_x < 0) ? 0 : camera->min_x;
diff --git a/camera.h b/camera.h
index 2624d8d..2989a6a 100644
--- a/camera.h
+++ b/camera.h
@@ -5,14 +5,17 @@ typedef struct {
// Calculate the camera offset once
float offset_x;
float offset_y;
+ float center_x;
+ float center_y;
// Calculate the window bounds in terms of tiles
int min_x;
int max_x;
int min_y;
int max_y;
+ float view_w, view_h;
-
+ void* render_object;
} Camera;
void setCamera(Camera* camera);
diff --git a/character.c b/character.c
index 40d3235..8624410 100644
--- a/character.c
+++ b/character.c
@@ -10,62 +10,60 @@ char* strdup(const char* s);
// Function to create a new character
-Character Character_create(const char *name, int energy, int friendliness, int creativity, Position pos) {
+Character Character_create(const char *name, int energy, int friendliness, int creativity) {
Character c;
c.name = strdup(name);
c.energy = energy;
c.friendliness = friendliness;
c.creativity = creativity;
- c.position = pos;
+ c.object = (Object*)malloc(sizeof(Object));
return c;
}
// Function to create characters with constant values and return the array
-Character* Character_creates(int* size) {
+Character* Character_creates(Object* object_first, int* size) {
*size = 4; // Set the number of characters
Character* characters = malloc(sizeof(Character) * (*size)); // Allocate memory for the characters
+ for (int i = 0; i < *size; i++) {
+ characters[i].object = Object_create_pos(0,0,20,30);
+ Object_add(object_first, characters[i].object);
+ characters[i].object->parent_type = Object_Character;
+ characters[i].object->parent = (void*)&characters[i];
+ }
// Initialize each character with constant values
characters[0].name = "Bob";
- characters[0].dimension = (Dimension){20,30};
characters[0].color = (Color){0, 0, 255, 255};
characters[0].energy = 50;
characters[0].friendliness = 80;
characters[0].creativity = 70;
characters[0].role = "Organizer";
characters[0].preferences = "Music, Dance";
- characters[0].position = (Position){0, 0};
characters[1].name = "Alice";
- characters[1].dimension = (Dimension){20,30};
characters[1].color = (Color){255, 0, 255, 255};
characters[1].energy = 40;
characters[1].friendliness = 60;
characters[1].creativity = 90;
characters[1].role = "Performer";
characters[1].preferences = "Singing, Acting";
- characters[1].position = (Position){0, 0};
characters[2].name = "Charlie";
- characters[2].dimension = (Dimension){20,30};
characters[2].color = (Color){255, 0, 255, 255};
characters[2].energy = 70;
characters[2].friendliness = 85;
characters[2].creativity = 60;
characters[2].role = "Technician";
characters[2].preferences = "Sound, Lighting";
- characters[2].position = (Position){0, 0};
characters[3].name = "Diana";
- characters[3].dimension = (Dimension){20,30};
characters[3].color = (Color){255, 0, 255, 255};
characters[3].energy = 55;
characters[3].friendliness = 75;
characters[3].creativity = 80;
characters[3].role = "Volunteer";
characters[3].preferences = "Logistics, Helping";
- characters[3].position = (Position){0, 0};
return characters;
}
@@ -74,7 +72,7 @@ Character* Character_creates(int* size) {
// Function to print character details
void Character_log(const Character* character) {
printf("╔════════════════════════════════════════════╗\n");
- printf("║ Character Info ║\n");
+ printf("║ %3.0f/%3.0f Character Info ║\n", character->object->x, character->object->y);
printf("╠════════════════════════════════════════════╣\n");
printf("║ Name : %-29s ║\n", character->name);
printf("║ Role : %-29s ║\n", character->role);
diff --git a/character.h b/character.h
index 06cfda2..8901d8a 100644
--- a/character.h
+++ b/character.h
@@ -2,15 +2,7 @@
#define CHARACTER_H
#include "color.h"
-
-typedef struct {
- double x, y;
-} Position;
-
-typedef struct {
- double w, h;
-} Dimension;
-
+#include "object.h"
typedef struct {
char* name;
@@ -19,13 +11,12 @@ typedef struct {
int creativity;
char* role;
char* preferences;
- Position position;
Color color;
- Dimension dimension;
+ Object* object;
} Character;
-Character Character_create(const char *name, int energy, int friendliness, int creativity, Position pos);
-Character* Character_creates(int* size);
+Character Character_create(const char *name, int energy, int friendliness, int creativity);
+Character* Character_creates(Object* object_first, int* size);
void Character_log(const Character* character);
diff --git a/collectable.c b/collectable.c
new file mode 100644
index 0000000..1f4ba3a
--- /dev/null
+++ b/collectable.c
@@ -0,0 +1,11 @@
+#include "stdlib.h"
+#include "stdio.h"
+
+#include "collectable.h"
+
+Collectable* Collectable_create() {
+ Collectable* t = (Collectable*)malloc(sizeof(Collectable));
+ if (!t)
+ fprintf(stderr, "Failled to allocate memory: Collectable_create();");
+ return t;
+}
diff --git a/collectable.h b/collectable.h
new file mode 100644
index 0000000..8d115a6
--- /dev/null
+++ b/collectable.h
@@ -0,0 +1,18 @@
+#ifndef COLLECTABLE_H
+#define COLLECTABLE_H
+
+#include "object.h"
+
+
+typedef enum {
+ Collectable_Default
+} CollectableType;
+
+typedef struct {
+ CollectableType type;
+ Object* object;
+} Collectable;
+
+Collectable* Collectable_create();
+
+#endif
diff --git a/main.c b/main.c
index 301ddbd..d1326de 100644
--- a/main.c
+++ b/main.c
@@ -1,6 +1,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
+#include <float.h>
#include <SDL3/SDL.h>
#include <SDL3/SDL_init.h>
#include <SDL3_ttf/SDL_ttf.h>
@@ -12,24 +13,23 @@
#define MOVEMENT_SPEED 100.0f
TileType** map;
-ObjectType*** map_objects;
+MapObjectType*** map_objects;
unsigned char** map_objects_count;
int MAP_WIDTH = 0;
int MAP_HEIGHT = 0;
-float MAP_CENTER_X = 0;
-float MAP_CENTER_Y = 0;
-float WINDOW_WIDTH = 960;
-float WINDOW_HEIGHT = 620;
const int TILE_SIZE = 32;
int characters_size;
Character* characters;
Character* character;
+Object* object_first;
int main() {
Camera camera;
+ camera.view_w = 960;
+ camera.view_h = 620;
if (!SDL_Init(SDL_INIT_VIDEO)) {
fprintf(stderr, "SDL_Init Error: %s\n", SDL_GetError());
@@ -43,12 +43,12 @@ int main() {
}
SDL_Window* window = SDL_CreateWindow("Entropie",
- WINDOW_WIDTH, WINDOW_HEIGHT,
+ camera.view_w, camera.view_h,
0);
// Initialize the camera to be centered on the window initially
- MAP_CENTER_X = WINDOW_WIDTH / 2;
- MAP_CENTER_Y = WINDOW_HEIGHT / 2;
+ camera.center_x = camera.view_w / 2;
+ camera.center_y = camera.view_h / 2;
if (!window) {
fprintf(stderr, "SDL_CreateWindow Error: %s\n", SDL_GetError());
@@ -75,17 +75,30 @@ int main() {
srand(42);
- characters = Character_creates(&characters_size);
+
+ object_first = Object_create_pos(FLT_MIN,FLT_MIN,0,0);
+
+ characters = Character_creates(object_first, &characters_size);
int character_active_id = 0;
character = &characters[character_active_id];
printf("\n\n### %d %d %d\n", character->color.r, character->color.g, character->color.b);
+ printf("\n\n### %f %f %f %f\n", character->object->x, character->object->y, character->object->w, character->object->h);
// Load the map and assign character positions
- if (Map_load("map.txt", characters, characters_size) != 0) {
+ if (Map_load("hof.map", characters, characters_size, object_first) != 0) {
fprintf(stderr, "Failed to load map\n");
return 1;
}
printf("MAP: %d %d\n", MAP_WIDTH, MAP_HEIGHT);
+ printf("\n\n### %f %f %f %f\n", character->object->x, character->object->y, character->object->w, character->object->h);
+
+
+
+ Object* obj = object_first;
+ while (obj->next) {
+ object_log(obj->next);
+ obj = obj->next;
+ }
int running = 1;
@@ -138,20 +151,26 @@ int main() {
}
// Calculate the new position
- float new_x = character->position.x + move_x * MOVEMENT_SPEED * delta_time;
- float new_y = character->position.y + move_y * MOVEMENT_SPEED * delta_time;
+ float new_x = character->object->x + move_x * MOVEMENT_SPEED * delta_time;
+ float new_y = character->object->y + move_y * MOVEMENT_SPEED * delta_time;
// Check collisions
- if (Map_isPassable(new_x, character->position.y, character->dimension.w, character->dimension.h)) {
- character->position.x = new_x;
+ if (Map_isPassable(new_x, character->object->y, character->object->w, character->object->h)) {
+ character->object->x = new_x;
}
- if (Map_isPassable(character->position.x, new_y, character->dimension.w, character->dimension.h)) {
- character->position.y = new_y;
+ if (Map_isPassable(character->object->x, new_y, character->object->w, character->object->h)) {
+ character->object->y = new_y;
}
// Center camera
- MAP_CENTER_X = character->position.x;
- MAP_CENTER_Y = character->position.y;
+ camera.center_x = character->object->x;
+ camera.center_y = character->object->y;
+ Object* ro = character->object;
+ while (ro->prev && Object_is_visible(ro, &camera))
+ ro = ro->prev;
+ if (ro->prev)
+ ro = ro->next;
+ camera.render_object = (void*)ro;
setCamera(&camera);
@@ -163,15 +182,16 @@ int main() {
// Render stuff
- Render_map(renderer, camera);
+ Render_map(renderer, camera, character->object);
Render_characterInfo(renderer, font, character);
- //Render_rect(renderer, MAP_CENTER_X - 2, MAP_CENTER_Y - 2, 4, 4, 255, 255, 0, 255);
+ //Render_rect(renderer, camera.center_x - 2, camera.center_y - 2, 4, 4, 255, 255, 0, 255);
SDL_RenderPresent(renderer);
}
Character_free(characters, characters_size);
Map_free();
+ Objects_free(object_first);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
diff --git a/map.c b/map.c
index 6f6a2d8..ec14b42 100644
--- a/map.c
+++ b/map.c
@@ -4,6 +4,14 @@
#include <ctype.h>
#include "map.h"
+#include "collectable.h"
+
+Tile* Tile_create() {
+ Tile* t = (Tile*)malloc(sizeof(Tile));
+ if (!t)
+ fprintf(stderr, "Failled to allocate memory: Tile_create();");
+ return t;
+}
void Map_log(void) {
@@ -19,7 +27,7 @@ void Map_log(void) {
printf("OBJECT [%d|%d] %d: %d\n", y, x, map_objects_count[y][x], map_objects[y][x][i]);
}
-int Map_load(const char* filename, Character* characters, int characters_size) {
+int Map_load(const char* filename, Character* characters, int characters_size, Object* object_first) {
FILE* file = fopen(filename, "r");
if (!file) {
fprintf(stderr, "Error opening map file\n");
@@ -53,7 +61,7 @@ int Map_load(const char* filename, Character* characters, int characters_size) {
// Dynamically allocate memory for the map
map = (TileType**)malloc(map_height * sizeof(TileType*));
- map_objects = (ObjectType***)malloc(map_height * sizeof(ObjectType**));
+ map_objects = (MapObjectType***)malloc(map_height * sizeof(MapObjectType**));
map_objects_count = (unsigned char**)malloc(map_height * sizeof(unsigned char*));
if (!map || !map_objects) {
fclose(file);
@@ -63,7 +71,7 @@ int Map_load(const char* filename, Character* characters, int characters_size) {
for (int i = 0; i < map_height; i++) {
map[i] = (TileType*)malloc(map_width * sizeof(TileType));
- map_objects[i] = (ObjectType**)malloc(map_width * sizeof(ObjectType*));
+ map_objects[i] = (MapObjectType**)malloc(map_width * sizeof(MapObjectType*));
map_objects_count[i] = (unsigned char*)malloc(map_width * sizeof(unsigned char));
if (!map[i] || !map_objects[i]) {
fclose(file);
@@ -73,6 +81,7 @@ int Map_load(const char* filename, Character* characters, int characters_size) {
}
// Now load the map data
+ Object* prev = object_first;
int y = 0;
while (fgets(line, sizeof(line), file)) {
int x = 0;
@@ -80,59 +89,75 @@ int Map_load(const char* filename, Character* characters, int characters_size) {
// Split the line into words and map them to tile types
char* token = strtok(line, " \n");
while (token != NULL) {
- map_objects[y][x] = (ObjectType*)malloc(sizeof(ObjectType));
- map_objects_count[y][x] = 0;
+ Object* active = Object_create();
+ active->x = x*TILE_SIZE;
+ active->y = y*TILE_SIZE;
+ active->w = TILE_SIZE;
+ active->h = TILE_SIZE;
// Map the string (word) to the appropriate tile type
+#define TILE_CREATE(t) \
+ Tile* tile = Tile_create(); \
+ active->parent_type = Object_Tile; \
+ active->parent = (void*)tile; \
+ map[y][x] = t; \
+ tile->type = t;
if (strcmp(token, "..") == 0) {
- map[y][x] = TILE_EMPTY;
+ TILE_CREATE(TILE_EMPTY)
} else if (strcmp(token, "##") == 0) {
- map[y][x] = TILE_WALL;
+ TILE_CREATE(TILE_WALL)
} else if (strcmp(token, "==") == 0) {
- map[y][x] = TILE_HOUSE;
+ TILE_CREATE(TILE_HOUSE)
} else if (strcmp(token, "~~") == 0) {
- map[y][x] = TILE_WATER;
+ TILE_CREATE(TILE_WATER)
} else if (strcmp(token, "__") == 0) {
- map[y][x] = TILE_WAY;
+ TILE_CREATE(TILE_WAY)
} else if (strcmp(token, "++") == 0) {
- map[y][x] = TILE_ROAD;
+ TILE_CREATE(TILE_ROAD)
} else if (strcmp(token, "––") == 0) {
- map[y][x] = TILE_TRACK;
+ TILE_CREATE(TILE_TRACK)
} else if (strcmp(token, ";;") == 0) {
- map[y][x] = TILE_GRAVEL;
+ TILE_CREATE(TILE_GRAVEL)
} else if (strcmp(token, "DD") == 0) {
- map[y][x] = TILE_DIRT;
+ TILE_CREATE(TILE_DIRT)
} else if (strcmp(token, "WW") == 0) {
- map[y][x] = TILE_GRASS;
+ TILE_CREATE(TILE_GRASS)
} else if (strcmp(token, "TT") == 0) {
- map[y][x] = TILE_TREE;
+ TILE_CREATE(TILE_TREE)
} else if (strcmp(token, "PP") == 0) {
- map[y][x] = TILE_PLAYER_SPAWN;
+ TILE_CREATE(TILE_PLAYER_SPAWN)
} else if (strcmp(token, "CC") == 0) {
- map[y][x] = TILE_CHARACTER_SPAWN;
+ TILE_CREATE(TILE_CHARACTER_SPAWN)
} else if (strcmp(token, "oo") == 0) {
- map[y][x] = TILE_COLLECTABLE;
+ TILE_CREATE(TILE_COLLECTABLE)
+#undef TILE_CREATE
+
} else if (token[0] == 'o' && isdigit(token[1])) {
+ map[y][x] = TILE_COLLECTABLE;
int collectable_index = atoi(&token[1]);
- if (collectable_index >= 0 && collectable_index < COLLECTABLE_MAX-COLLECTABLE_0) {
- map_objects[y][x][0] = (ObjectType)(COLLECTABLE_0 + collectable_index);
- map_objects_count[y][x] = 1;
- printf("Set position of object %d %d %d\n", x, y, collectable_index);
- }
+ printf("Set position of object %d %d %d\n", x, y, collectable_index);
+ Collectable* collectable = Collectable_create();
+ collectable->object = active;
+ active->parent_type = Object_Collectable;
+ active->parent = (void*)collectable;
+
} else if (token[0] == 'C' && isdigit(token[1])) {
- int char_index = atoi(&token[1]);
- if (char_index >= 0 && char_index < characters_size) {
- characters[char_index].position.x = x * TILE_SIZE;
- characters[char_index].position.y = y * TILE_SIZE;
- printf("Set position of character %d to (%d, %d)\n", char_index, x * TILE_SIZE, y * TILE_SIZE);
- }
- map_objects[y][x][0] = (ObjectType)(CHARACTER_0 + char_index);
- map_objects_count[y][x] = 1;
+ free(active);
map[y][x] = TILE_CHARACTER_SPAWN;
+ int char_index = atoi(&token[1]);
+ Character* character = &characters[char_index];
+ printf("Set position of character %d to (%d, %d)\n%p || %d\n", char_index, x * TILE_SIZE, y * TILE_SIZE, character, character->object->parent_type);
+ active = character->object;
+ active->x = x*TILE_SIZE;
+ active->y = y*TILE_SIZE;
} else {
map[y][x] = TILE_EMPTY;
+ active->parent_type = Object_Undefined;;
+ active->parent = NULL;
}
+ Object_add(prev, active);
x++;
+ prev = active;
token = strtok(NULL, " \n");
}
diff --git a/map.h b/map.h
index 8940e6c..2c1f16d 100644
--- a/map.h
+++ b/map.h
@@ -7,10 +7,6 @@
extern int MAP_WIDTH;
extern int MAP_HEIGHT;
-extern float MAP_CENTER_X;
-extern float MAP_CENTER_Y;
-extern float WINDOW_WIDTH;
-extern float WINDOW_HEIGHT;
extern const int TILE_SIZE;
typedef enum {
@@ -42,15 +38,23 @@ typedef enum {
COLLECTABLE_2,
COLLECTABLE_3,
COLLECTABLE_MAX,
-} ObjectType;
+} MapObjectType;
+
+typedef struct {
+ TileType type;
+ Object* object;
+} Tile;
extern TileType** map;
-extern ObjectType*** map_objects;
+extern MapObjectType*** map_objects;
extern unsigned char** map_objects_count;
+
+Tile* Tile_create();
+
void Map_log(void);
-int Map_load(const char* filename, Character* characters, int characters_size);
+int Map_load(const char* filename, Character* characters, int characters_size, Object*);
int Map_isPassable(float x, float y, float w, float h);
void Map_free();
diff --git a/object.c b/object.c
new file mode 100644
index 0000000..a0a8998
--- /dev/null
+++ b/object.c
@@ -0,0 +1,126 @@
+#include "object.h"
+#include "camera.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+
+
+void object_log(const Object* obj) {
+ if (!obj) {
+ printf("Object: NULL\n");
+ return;
+ }
+
+ printf("Object Debug Info:\n");
+ printf(" Type: %d\n", obj->parent_type);
+ printf(" Position: (%.2f, %.2f)\n", obj->x, obj->y);
+ printf(" Size: %.2fx%.2f\n", obj->w, obj->h);
+ printf(" Parent Pointer: %p\n", obj->parent);
+ printf(" Prev: %p | Next: %p\n", (void*)obj->prev, (void*)obj->next);
+}
+
+Object* Object_create() {
+ Object* obj = (Object*)malloc(sizeof(Object));
+ if (!obj) fprintf(stderr, "Failed allocate Object_create()");
+ obj->prev = NULL;
+ obj->next = NULL;
+ return obj;
+}
+Object* Object_create_pos(float x, float y, float w, float h) {
+ Object* o = Object_create();
+ o->x = x;
+ o->y = y;
+ o->w = w;
+ o->h = h;
+ o->prev = NULL;
+ o->next = NULL;
+ return o;
+}
+
+char Object_is_visible(Object* obj, Camera* camera) {
+ if (!obj || !camera) return 0;
+
+ float obj_left = obj->x;
+ float obj_right = obj->x + obj->w;
+ float obj_top = obj->y;
+ float obj_bottom = obj->y + obj->h;
+
+ float cam_left = camera->offset_x;
+ float cam_right = camera->offset_x + camera->view_w;
+ float cam_top = camera->offset_y;
+ float cam_bottom = camera->offset_y + camera->view_h;
+
+ return !(obj_right < cam_left || // Object is left of the view
+ obj_left > cam_right || // Object is right of the view
+ obj_bottom < cam_top || // Object is above the view
+ obj_top > cam_bottom); // Object is below the view
+}
+
+
+// Helper function: compute the z-index of an object (e.g., bottom edge)
+static inline float get_z_index(const Object *obj) {
+ return obj->y + (obj->parent_type == Object_Tile ? 0 : obj->h );
+}
+
+// Insertion function: insert obj_new into the doubly linked list starting at reference.
+// This function will traverse backward or forward from the reference to find the proper spot.
+// After insertion, obj_new is correctly linked into the list.
+Object* Object_add(Object *reference, Object *obj_new) {
+ if (!obj_new) {
+ fprintf(stderr, "NULL passed in Object_add()\n");
+ return NULL;
+ }
+
+ // Unlink from doubly linked list
+ if (obj_new->prev) {
+ obj_new->prev->next = obj_new->next;
+ }
+ if (obj_new->next) {
+ obj_new->next->prev = obj_new->prev;
+ }
+ // Initialize the new object's pointers
+ obj_new->prev = NULL;
+ obj_new->next = NULL;
+
+ // Calculate the new object's z-index
+ float new_z = get_z_index(obj_new);
+
+ // Start from the reference node
+ Object *current = reference;
+ float current_z = get_z_index(current);
+
+ if (new_z < current_z) {
+ // We need to move backwards: find the first node whose z-index is less than or equal to new_z
+ while (current->prev != NULL && get_z_index(current->prev) > new_z) {
+ current = current->prev;
+ }
+ // Insert obj_new before current
+ obj_new->next = current;
+ obj_new->prev = current->prev;
+ if (current->prev != NULL) {
+ current->prev->next = obj_new;
+ }
+ current->prev = obj_new;
+ } else {
+ // new_z is greater than or equal to current_z; move forward until we find a node with a greater z-index
+ while (current->next != NULL && get_z_index(current->next) <= new_z) {
+ current = current->next;
+ }
+ // Insert obj_new after current
+ obj_new->prev = current;
+ obj_new->next = current->next;
+ if (current->next != NULL) {
+ current->next->prev = obj_new;
+ }
+ current->next = obj_new;
+ }
+ return obj_new;
+}
+
+void Objects_free(Object* first) {
+ while (first) {
+ Object* next = first->next;
+ free(first);
+ first = next;
+ }
+}
diff --git a/object.h b/object.h
new file mode 100644
index 0000000..9ea7cb9
--- /dev/null
+++ b/object.h
@@ -0,0 +1,32 @@
+#ifndef OBJECT_H
+#define OBJECT_H
+
+#include "camera.h"
+
+typedef enum {
+ Object_Undefined,
+ Object_Tile,
+ Object_Character,
+ Object_Collectable,
+} ObjectType;
+
+
+typedef struct Object_s {
+ struct Object_s* prev,* next;
+ ObjectType parent_type;
+ void* parent;
+ float x, y;
+ float w, h;
+} Object;
+
+
+void object_log(const Object* obj);
+
+Object* Object_create ();
+Object* Object_create_pos(float x, float y, float w, float h);
+
+char Object_is_visible(Object* obj, Camera* camera);
+Object* Object_add (Object* reference, Object* obj_new);
+void Objects_free (Object* first);
+
+#endif
diff --git a/render.c b/render.c
index f9fc093..62a4679 100644
--- a/render.c
+++ b/render.c
@@ -2,16 +2,13 @@
#include <SDL3_ttf/SDL_ttf.h>
#include "color.h"
+#include "object.h"
#include "render.h"
#include "character.h"
#include "map.h"
extern int MAP_WIDTH;
extern int MAP_HEIGHT;
-extern float MAP_CENTER_X;
-extern float MAP_CENTER_Y;
-extern float WINDOW_WIDTH;
-extern float WINDOW_HEIGHT;
extern const int TILE_SIZE;
extern int characters_size;
@@ -72,7 +69,7 @@ void Render_characterInfo(SDL_Renderer *renderer, TTF_Font* font, const Characte
Render_text(renderer, font, stats, margin_left, (text_height * 3) + margin_top, textColor);
}
-void Render_character(SDL_Renderer* renderer, Character* character) {
+void Render_character(SDL_Renderer* renderer, Camera camera, Character* character) {
// Set the drawing color for the character (e.g., blue)
Color c = character->color;
@@ -80,18 +77,88 @@ void Render_character(SDL_Renderer* renderer, Character* character) {
// Define the rectangle
SDL_FRect rect = {
- character->position.x - MAP_CENTER_X + (WINDOW_WIDTH / 2), // Adjust for camera position
- character->position.y - MAP_CENTER_Y + (WINDOW_HEIGHT / 2), // Adjust for camera position
- character->dimension.w,
- character->dimension.h
+ character->object->x - camera.center_x + (camera.view_w / 2), // Adjust for camera position
+ character->object->y - camera.center_y + (camera.view_h / 2), // Adjust for camera position
+ character->object->w,
+ character->object->h
};
// Render the filled rectangle
SDL_RenderFillRect(renderer, &rect);
}
+void Render_object(SDL_Renderer* renderer, Camera camera, Object* object) {
+ printf("## %f %f %p\n", object->x, object->y, object);
+ if (object->parent_type == Object_Character) {
+ Character* character = (Character*)object->parent;
+ Color co = character->color;
+ SDL_SetRenderDrawColor(renderer, co.r, co.g, co.b, co.a);
+ } else if (object->parent_type == Object_Tile) {
+ Tile* tile = (Tile*)object->parent;
+ switch (tile->type) {
+ case TILE_TREE:
+ SDL_SetRenderDrawColor(renderer, 34, 139, 34, 255); // Forest Green for trees
+ break;
+ case TILE_GRASS:
+ SDL_SetRenderDrawColor(renderer, 50, 205, 50, 255); // Lime Green for grass
+ break;
+ case TILE_DIRT:
+ SDL_SetRenderDrawColor(renderer, 139, 69, 19, 255); // Saddle Brown for dirt
+ break;
+ case TILE_WATER:
+ SDL_SetRenderDrawColor(renderer, 70, 130, 180, 255); // Steel Blue for water
+ break;
+ case TILE_WAY:
+ SDL_SetRenderDrawColor(renderer, 255, 223, 186, 255); // Peach for pathways
+ break;
+ case TILE_ROAD:
+ SDL_SetRenderDrawColor(renderer, 128, 128, 128, 255); // Gray for roads
+ break;
+ case TILE_TRACK:
+ SDL_SetRenderDrawColor(renderer, 139, 69, 19, 255); // Saddle Brown for tracks
+ break;
+ case TILE_GRAVEL:
+ SDL_SetRenderDrawColor(renderer, 169, 169, 169, 255); // Light Gray for gravel
+ break;
+ case TILE_WALL:
+ SDL_SetRenderDrawColor(renderer, 105, 105, 105, 255); // Dim Gray for walls
+ break;
+ case TILE_EMPTY:
+ SDL_SetRenderDrawColor(renderer, 240, 248, 255, 255); // Alice Blue for empty tiles
+ break;
+ case TILE_PLAYER_SPAWN:
+ SDL_SetRenderDrawColor(renderer, 255, 223, 0, 255); // Golden Yellow for player spawn
+ break;
+ case TILE_CHARACTER_SPAWN:
+ SDL_SetRenderDrawColor(renderer, 255, 105, 180, 255); // Hot Pink for character spawn
+ break;
+ case TILE_HOUSE:
+ SDL_SetRenderDrawColor(renderer, 178, 34, 34, 255); // Firebrick for houses
+ break;
+ case TILE_COLLECTABLE:
+ SDL_SetRenderDrawColor(renderer, 255, 215, 0, 255); // Gold for collectibles
+ break;
+ default:
+ SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); // Black for unknown types
+ break;
+ }
+ } else {
+ return;
+ }
+
+ SDL_FRect tileRect = { object->x - camera.offset_x, object->y - camera.offset_y, object->w, object->h };
+ SDL_RenderFillRect(renderer, &tileRect);
+}
-void Render_map(SDL_Renderer* renderer, Camera camera) {
+void Render_map(SDL_Renderer* renderer, Camera camera, Object* object) {
+ Object* next = camera.render_object;
+ printf("*_* %p %f %f\n", next, next->x, next->y);
+ while (next->next && Object_is_visible(next, &camera)) {
+ Render_object(renderer, camera, next);
+ next = next->next;
+ }
+}
+void Render_map_OLD(SDL_Renderer* renderer, Camera camera, Object* object) {
// printf("MIN %d\n", camera.min_y);
// Render only the tiles within the visible window area
for (int y = camera.min_y; y <= camera.max_y; y++) {
@@ -157,10 +224,10 @@ void Render_map(SDL_Renderer* renderer, Camera camera) {
float pos_x = tile_x, pos_y = tile_y;
int char_id = map_objects[y][x][i] - CHARACTER_0;
if (char_id >= 0 && char_id < CHARACTER_MAX-CHARACTER_0) {
- w = characters[char_id].dimension.w;
- h = characters[char_id].dimension.h;
- pos_x = characters[char_id].position.x - MAP_CENTER_X + (WINDOW_WIDTH / 2);
- pos_y = characters[char_id].position.y - MAP_CENTER_Y + (WINDOW_HEIGHT / 2);
+ w = characters[char_id].object->w;
+ h = characters[char_id].object->h;
+ pos_x = characters[char_id].object->x - camera.center_x + (camera.view_w / 2);
+ pos_y = characters[char_id].object->y - camera.center_y + (camera.view_h / 2);
if (char_id == 0) {
printf("REND_CAR %d %f %f\n", char_id, pos_x, tile_x);
printf("MIN %d %d %d %d\n", camera.min_y, camera.min_x, camera.max_y, camera.max_x);
diff --git a/render.h b/render.h
index 555db43..be4eed9 100644
--- a/render.h
+++ b/render.h
@@ -15,8 +15,8 @@ void Render_text(SDL_Renderer* renderer, TTF_Font* font, const char* text, int x
// Function to print character details to the SDL window
void Render_characterInfo(SDL_Renderer *renderer, TTF_Font* font, const Character* character);
-void Render_character(SDL_Renderer* renderer, Character* character);
+void Render_character(SDL_Renderer* renderer, Camera camera, Character* character);
-void Render_map(SDL_Renderer* renderer, Camera camera);
+void Render_map(SDL_Renderer* renderer, Camera camera, Object* object);
#endif