174 lines
4.8 KiB
C
174 lines
4.8 KiB
C
#include "map.h"
|
|
#include "tile.h"
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h> // printf
|
|
|
|
/*
|
|
================================
|
|
struct Map *newMap(int width, int height)
|
|
|
|
This function allocates memory for a 2D array of Tile pointers. Calls nullMap before returning the newly allocated Map.
|
|
|
|
Returns: NULL on malloc failure for: map, map->tiles, map->tiles[x]
|
|
|
|
TODO: Map->tiles could be fragmented - figure out a way to use one malloc call for both x and y.
|
|
================================
|
|
*/
|
|
struct Map *newMap(int width, int height, int depth) {
|
|
struct Map *map = malloc(sizeof(struct Map));
|
|
if (map == NULL) {
|
|
// TODO: ERROR: could not allocate memory for Map
|
|
return NULL;
|
|
}
|
|
map->width = width;
|
|
map->height = height;
|
|
map->depth = depth;
|
|
|
|
map->tiles = malloc(width * sizeof(struct Tile ***));
|
|
if (map->tiles == NULL) {
|
|
free(map);
|
|
printf("ERR: malloc width failed\n");
|
|
return NULL;
|
|
}
|
|
int i,j;
|
|
// TODO: error check
|
|
for(i=0;i<width;i++) {
|
|
map->tiles[i] = malloc(height * sizeof(struct Tile **));
|
|
if (map->tiles[i] == NULL) {
|
|
printf("ERR: malloc height failed\n");
|
|
return NULL;
|
|
}
|
|
for(j=0;j<height;j++) {
|
|
map->tiles[i][j] = malloc(depth * sizeof(struct Tile*));
|
|
if (map->tiles[i][j] == NULL) {
|
|
printf("ERR: malloc depth failed\n");
|
|
return NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
nullMap(map);
|
|
return map;
|
|
}
|
|
/*
|
|
================================
|
|
nullMap(struct Map *map)
|
|
|
|
This function takes a fully allocated Map and sets all Tile pointers to NULL.
|
|
================================
|
|
*/
|
|
int nullMap(struct Map *map) {
|
|
if (map == NULL) {
|
|
// TODO: ERROR: zeroMap passed NULL map
|
|
return 1;
|
|
}
|
|
int i, j, k;
|
|
for(i=0;i < map->width;i++) {
|
|
for(j=0;j < map->height;j++) {
|
|
for(k=0;k < map->depth;k++) {
|
|
map->tiles[i][j][k] = NULL;
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
================================
|
|
freeMap(struct Map *map, int flags)
|
|
|
|
This function frees the given map. If flags contains MAP_FREE_TILES, then the Tiles themselves are also freed.
|
|
================================
|
|
*/
|
|
#define MAP_FREE_TILES 1
|
|
void freeMap(struct Map *map, int flags) {
|
|
if (map == NULL)
|
|
return;
|
|
int i, j, k;
|
|
for(i=0;i < map->width;i++) {
|
|
for(j=0;j < map->height;j++) {
|
|
for(k=0;k < map->depth;k++) {
|
|
if (flags & MAP_FREE_TILES) {
|
|
//freeTile(map->tiles[i][j][k]);
|
|
}
|
|
//free(map->tiles[i][j][k]);
|
|
}
|
|
free(map->tiles[i][j]);
|
|
}
|
|
free(map->tiles[i]);
|
|
}
|
|
free(map->tiles);
|
|
free(map);
|
|
}
|
|
|
|
/* Tile -> Map interaction */
|
|
int moveTile(struct Map *map, struct Tile *tile, float x, float y, float z) {
|
|
//printf("request to move %fx%fx%f distance from %fx%fx%f\n", x, y, z, tile->x, tile->y, tile->z);
|
|
float target_x = tile->x + x;
|
|
float target_y = tile->y + y;
|
|
float target_z = tile->z + z;
|
|
//printf("absolute new pos %fx%fx%f\n", target_x, target_y, target_z);
|
|
int tile_x = (int)target_x;
|
|
int tile_y = (int)target_y;
|
|
int tile_z = (int)target_z;
|
|
//float leftover_x = target_x - tile_x;
|
|
//float leftover_y = target_y - tile_y;
|
|
//float leftover_z = target_z - tile_z;
|
|
//printf("move to %dx%dx%d with %fx%fx%f leftover\n", tile_x, tile_y, tile_z, leftover_x, leftover_y, leftover_z);
|
|
//printf(" MAP: %dx%dx%d vs %fx%fx%f\n", map->width, map->height, map->depth, target_x, target_y, target_z);
|
|
if (target_x < -0.5f || target_y < -0.5f || target_z < -0.5f || target_x >= map->width || target_y >= map->height || target_z >= map->depth) {
|
|
return 1;
|
|
}
|
|
if (tile_x != (int)tile->x || tile_y != (int)tile->y || tile_z != (int)tile->z) {
|
|
if (map->tiles[tile_x][tile_y][tile_z] == NULL) {
|
|
map->tiles[tile_x][tile_y][tile_z] = tile;
|
|
//return 2;
|
|
} else {
|
|
removeTile(tile); // remove from current position
|
|
appendTile(map->tiles[tile_x][tile_y][tile_z], tile);
|
|
}
|
|
}
|
|
tile->x = target_x;
|
|
tile->y = target_y;
|
|
tile->z = target_z;
|
|
return 0;
|
|
}
|
|
|
|
int addTileToMap(struct Map *map, struct Tile *tile, float x, float y, float z) {
|
|
if (map == NULL)
|
|
return -1;
|
|
if (tile == NULL)
|
|
return -2;
|
|
int tile_x = (int)x;
|
|
int tile_y = (int)y;
|
|
int tile_z = (int)z;
|
|
// if out of bounds, add to nearest cell
|
|
if (tile_x >= map->width) {
|
|
tile_x = map->width-1;
|
|
} else if (tile_x < 0) {
|
|
tile_x = 0;
|
|
}
|
|
if (tile_y >= map->height) {
|
|
tile_y = map->height-1;
|
|
} else if (tile_y < 0) {
|
|
tile_y = 0;
|
|
}
|
|
if (tile_z >= map->depth) {
|
|
tile_z = map->depth-1;
|
|
} else if (tile_z < 0) {
|
|
tile_z = 0;
|
|
}
|
|
// set tile's x, y, and z params
|
|
tile->x = tile_x;
|
|
tile->y = tile_y;
|
|
tile->z = tile_z;
|
|
if (map->tiles[tile_x][tile_y][tile_z] == NULL) {
|
|
map->tiles[tile_x][tile_y][tile_z] = tile;
|
|
return 0;
|
|
}
|
|
// if existing, append to tile linked list there
|
|
appendTile(map->tiles[tile_x][tile_y][tile_z], tile);
|
|
return 0;
|
|
}
|