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;
 | |
| }
 |