Entropie git · main
git clone https://git.christianimmanuel.de/games/Entropie.gitwget https://git.christianimmanuel.de/games/Entropie/archive/Entropie.tar.gzmap.c raw
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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) {
for (int i= 0; i < MAP_HEIGHT; i++) {
printf("\n");
for (int j= 0; j < MAP_WIDTH; j++) {
printf("%d", map[i][j]);
}
}
for (int y = 0; y < MAP_HEIGHT; y++)
for (int x = 0; x < MAP_WIDTH; x++)
for (int i = 0; i < map_objects_count[y][x]; i++)
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, Object* object_first) {
FILE* file = fopen(filename, "r");
if (!file) {
fprintf(stderr, "Error opening map file\n");
return -1;
}
int map_width = 0;
int map_height = 0;
char line[1024]; // Buffer to hold each line
// First, determine the width and height of the map by reading the file line by line
while (fgets(line, sizeof(line), file)) {
map_height++; // Increment height for each line
int line_width = 0;
// Split the line into words and count them
char* token = strtok(line, " \n");
while (token != NULL) {
line_width++;
token = strtok(NULL, " \n");
}
// Track the maximum width of any row to determine the map width
if (line_width > map_width) {
map_width = line_width;
}
}
// Rewind the file pointer to start reading the map data
rewind(file);
// Dynamically allocate memory for the map
map = (TileType**)malloc(map_height * sizeof(TileType*));
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);
fprintf(stderr, "Memory allocation for map failed\n");
return -1;
}
for (int i = 0; i < map_height; i++) {
map[i] = (TileType*)malloc(map_width * sizeof(TileType));
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);
fprintf(stderr, "Memory allocation for map row failed\n");
return -1;
}
}
// Now load the map data
Object* prev = object_first;
int y = 0;
while (fgets(line, sizeof(line), file)) {
int x = 0;
// Split the line into words and map them to tile types
char* token = strtok(line, " \n");
while (token != NULL) {
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) {
TILE_CREATE(TILE_EMPTY)
} else if (strcmp(token, "##") == 0) {
TILE_CREATE(TILE_WALL)
} else if (strcmp(token, "==") == 0) {
TILE_CREATE(TILE_HOUSE)
} else if (strcmp(token, "~~") == 0) {
TILE_CREATE(TILE_WATER)
} else if (strcmp(token, "__") == 0) {
TILE_CREATE(TILE_WAY)
} else if (strcmp(token, "++") == 0) {
TILE_CREATE(TILE_ROAD)
} else if (strcmp(token, "––") == 0) {
TILE_CREATE(TILE_TRACK)
} else if (strcmp(token, ";;") == 0) {
TILE_CREATE(TILE_GRAVEL)
} else if (strcmp(token, "DD") == 0) {
TILE_CREATE(TILE_DIRT)
} else if (strcmp(token, "WW") == 0) {
TILE_CREATE(TILE_GRASS)
} else if (strcmp(token, "TT") == 0) {
TILE_CREATE(TILE_TREE)
} else if (strcmp(token, "PP") == 0) {
TILE_CREATE(TILE_PLAYER_SPAWN)
} else if (strcmp(token, "CC") == 0) {
TILE_CREATE(TILE_CHARACTER_SPAWN)
} else if (strcmp(token, "oo") == 0) {
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]);
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])) {
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");
}
y++;
}
fclose(file);
// Update global map dimensions
MAP_WIDTH = map_width;
MAP_HEIGHT = map_height;
return 0;
}
// Check if the position is within the map and if the tile is passable
int Map_isPassable(float x, float y, float w, float h) {
int tile_x_start = (int)(x / TILE_SIZE);
int tile_y_start = (int)(y / TILE_SIZE);
int tile_x_end = (int)((x + w) / TILE_SIZE);
int tile_y_end = (int)((y + h) / TILE_SIZE);
for (int ty = tile_y_start; ty <= tile_y_end; ty++) {
for (int tx = tile_x_start; tx <= tile_x_end; tx++) {
if (tx < 0 || tx >= MAP_WIDTH || ty < 0 || ty >= MAP_HEIGHT) {
return 0; // Out of bounds
}
TileType tile = map[ty][tx];
if (tile == TILE_WALL || tile == TILE_HOUSE || tile == TILE_TREE) {
return 0; // Early exit on collision
}
}
}
return 1;
}
void Map_free() {
for (int y = 0; y < MAP_HEIGHT; y++) {
for (int x = 0; x < MAP_WIDTH; x++)
free(map_objects[y][x]);
free(map[y]);
free(map_objects_count[y]);
}
free(map);
free(map_objects_count);
}