// // Created by bruno on 4/24/25. // #include #include "tile.h" #include "../player/player.h" #include "furnace.h" #include "../util/atlas.h" #include "../util/font.h" #include "miner.h" #include "turret.h" #include "../util/perlin.h" #include "../util/button.h" #include "../util/audio.h" #include "ammoCrafter.h" #include "wiredrawer.h" #include "core.h" MiniRect enemySpawn; MiniRect playerCore; SDL_Rect viewport; uint16_t DISPLAY_MAP_WIDTH = 30; uint16_t DISPLAY_MAP_HEIGHT = 16; uint16_t DISPLAY_WIDTH = 30 * TILE_SIZE; uint16_t DISPLAY_HEIGHT = 16 * TILE_SIZE; void setTileView(uint16_t w, uint16_t h) { DISPLAY_MAP_WIDTH = w; DISPLAY_MAP_HEIGHT = h; DISPLAY_WIDTH = DISPLAY_MAP_WIDTH * TILE_SIZE; DISPLAY_HEIGHT = DISPLAY_MAP_HEIGHT * TILE_SIZE; screenRect.x = 0; screenRect.y = 0; screenRect.w = DISPLAY_WIDTH; screenRect.h = DISPLAY_HEIGHT; SDL_RenderSetLogicalSize(mainRenderer, DISPLAY_WIDTH, DISPLAY_HEIGHT); SDL_SetWindowSize(window, DISPLAY_WIDTH, DISPLAY_HEIGHT); viewport = screenRect; SDL_RenderSetViewport(mainRenderer, &viewport); SDL_SetWindowPosition(window, 0, 0); audioData.maxPanDistance = DISPLAY_WIDTH / 2; SDL_DestroyTexture(hudTexture); SDL_DestroyTexture(entityTexture); SDL_DestroyTexture(itemsTexture); SDL_DestroyTexture(tilesTexture); SDL_DestroyTexture(backgroundTexture); hudTexture = SDL_CreateTexture(mainRenderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, screenRect.w, screenRect.h); entityTexture = SDL_CreateTexture(mainRenderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, screenRect.w, screenRect.h); SDL_SetTextureBlendMode(entityTexture, SDL_BLENDMODE_BLEND); SDL_SetTextureBlendMode(hudTexture, SDL_BLENDMODE_BLEND); itemsTexture = SDL_CreateTexture(mainRenderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, screenRect.w, screenRect.h); tilesTexture = SDL_CreateTexture(mainRenderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, screenRect.w, screenRect.h); SDL_SetTextureBlendMode(tilesTexture, SDL_BLENDMODE_BLEND); SDL_SetTextureBlendMode(itemsTexture, SDL_BLENDMODE_BLEND); backgroundTexture = SDL_CreateTexture(mainRenderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, screenRect.w, screenRect.h); PlayerRect.x = (DISPLAY_WIDTH / 2) - (PlayerRect.w / 2); PlayerRect.y = (DISPLAY_HEIGHT / 2) - (PlayerRect.h / 2); initButtons(); } int scrollFrame = 0; unsigned long beltFrames = 0; TileArray neededUpdates; int add_tile(TileArray *arr, MiniRect t) { if (arr->activeCount >= MAX_TILES) return 0; arr->tiles[arr->activeCount] = t; arr->activeCount++; return arr->activeCount - 1; } void remove_tile(TileArray *arr, int index) { if (index < 0 || index >= arr->activeCount) return; arr->activeCount--; arr->tiles[index] = arr->tiles[arr->activeCount]; // swap with last active } SDL_Texture *backgroundTexture; SDL_Texture *tilesTexture; SDL_Texture *itemsTexture; Tile tileMap[MAP_HEIGHT][MAP_WIDTH]; BackgroundTile backgroundMap[MAP_HEIGHT][MAP_WIDTH]; uint16_t tileTypeIndex = 0; uint16_t backgroundTileTypeIndex = 0; TileTypeReg TileRegistry[TILEREGISTRY_SIZE]; BackgroundTileType BackgroundTileRegistry[TILEREGISTRY_SIZE]; void generateTestMap() { for (int y = 0; y < DISPLAY_MAP_HEIGHT; y++) { for (int x = 0; x < DISPLAY_MAP_WIDTH; x++) { Tile tile = {0}; tile.rect.x = x; tile.rect.y = y; tileMap[y][x] = tile; } } for (int x = 0; x < MAP_WIDTH; x += 1) { for (int y = 0; y < MAP_HEIGHT; y += 1) { tileMap[y][x].type = TYPE_BELT; tileMap[y][x].miscVal = 0; //tileMap[y][x].direction = ((x + y) % 4 * 2) + 1; //tileMap[y][x].direction = 5; tileMap[y][x].direction = (rand() % 4 * 2) + 1; } } uint8_t type = 0; for (int x = 142; x < 154; x += 3) { for (int y = 80; y < 94; y += 3) { putItem(x, y, type++ % ITEMREGISTRY_SIZE, 0); } } } void registerTile(char fname[20], SDL_Renderer *renderer) { char name[21]; // Load animation frames int frame = 0; ItemType indexTile = 0; char texturePath[80]; if (sscanf(fname, "%d_%20[^_]_%d.png", &indexTile, name, &frame) == 3) { // Success: you now have index, fname, and frame } else { fprintf(stderr, "Invalid format: %s\n", fname); } strcpy(TileRegistry[indexTile].name, name); snprintf(texturePath, sizeof(texturePath), "./assets/tiles/%s", fname); SDL_Texture *texture = IMG_LoadTexture(renderer, texturePath); if (!texture) { // Stop loading frames if the first one fails, or after all valid ones are added if (frame == 0) { fprintf(stderr, "Failed to load tile texture %s: %s\n", texturePath, IMG_GetError()); } } for (int o = 0; o < ORIENT_DIRECTION_COUNT; o++) { SDL_Texture *textures[ORIENT_DIRECTION_COUNT] = { NULL, texture, NULL, createRotatedTexture(renderer, texture, 90), NULL, createFlippedTexture(renderer, texture, SDL_FLIP_HORIZONTAL), NULL, createRotatedTexture(renderer, texture, 270) }; // printf("Bound %s to %d orient %s\n", fname, indexTile, OrientStrings[o]); SDL_SetTextureBlendMode(textures[o], SDL_BLENDMODE_BLEND); TileRegistry[indexTile].animation.atlasRects[o][frame] = allocate_32x32(textures[o], renderer); } //printf("Bound %s to %d\n", fname, indexTile); TileRegistry[indexTile].type = indexTile; TileRegistry[indexTile].maxHealth = 200; TileRegistry[indexTile].animation.frameCount = frame + 1; TileRegistry[indexTile].animation.divisor = 1; TileRegistry[indexTile].type = tileTypeIndex; TileRegistry[indexTile].breakTime = 15; TileRegistry[indexTile].itemMoves = false; TileRegistry[indexTile].walkable = false; TileRegistry[indexTile].needsTicks = false; TileRegistry[indexTile].updateTileCallback = NULL; if (indexTile + 1 > tileTypeIndex) { tileTypeIndex = indexTile + 1; } } void registerBackgroundTile(char fname[20], SDL_Renderer *renderer) { char name[21]; // Load animation frames int frame = 0; int indexBgTile = 0; char texturePath[80]; if (sscanf(fname, "%d_%20[^_]_%d.png", &indexBgTile, name, &frame) == 3) { // Success: you now have index, fname, and frame } else { fprintf(stderr, "Invalid format: %s\n", fname); } strcpy(BackgroundTileRegistry[indexBgTile].name, name); snprintf(texturePath, sizeof(texturePath), "./assets/backgrounds/%s", fname); SDL_Texture *texture = IMG_LoadTexture(renderer, texturePath); if (!texture) { if (frame == 0) { fprintf(stderr, "Failed to load background texture %s: %s\n", texturePath, IMG_GetError()); } } SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_NONE); //printf("Bound %s to %d\n", fname, indexBgTile); BackgroundTileRegistry[indexBgTile].animation.atlasRects[frame] = allocate_32x32(texture, renderer); BackgroundTileRegistry[indexBgTile].type = indexBgTile; BackgroundTileRegistry[indexBgTile].animation.frameCount = frame + 1; BackgroundTileRegistry[indexBgTile].animation.divisor = 1; BackgroundTileRegistry[indexBgTile].walkable = true; if (indexBgTile + 1 > backgroundTileTypeIndex) { backgroundTileTypeIndex = indexBgTile + 1; } } void loadTiles(SDL_Renderer *renderer) { DIR *dir = opendir("./assets/tiles"); if (!dir) { perror("Failed to open tiles directory"); return; } char *baseNames[MAX_BASE_NAMES]; int baseNameCount = 0; struct dirent *entry; while ((entry = readdir(dir))) { char *dot = strrchr(entry->d_name, '.'); if (!dot || strcmp(dot, ".png") != 0) continue; // Check if baseName already stored int found = 0; for (int i = 0; i < baseNameCount; ++i) { if (strcmp(baseNames[i], entry->d_name) == 0) { found = 1; break; } } if (!found && baseNameCount < MAX_BASE_NAMES) { baseNames[baseNameCount++] = strdup(entry->d_name); // Only store base, not full file name } } closedir(dir); qsort(baseNames, baseNameCount, sizeof(char *), compareStrings); // Call registerTile on each base name for (int i = 0; i < baseNameCount; ++i) { char fileName[64]; snprintf(fileName, sizeof(fileName), "%s", baseNames[i]); registerTile(fileName, renderer); free(baseNames[i]); } generateBeltFrames(renderer); } void loadBackgroundTiles(SDL_Renderer *renderer) { DIR *dir = opendir("./assets/backgrounds"); if (!dir) { perror("Failed to open backgrounds directory"); return; } char *baseNames[MAX_BASE_NAMES]; int baseNameCount = 0; struct dirent *entry; while ((entry = readdir(dir))) { char *dot = strrchr(entry->d_name, '.'); if (!dot || strcmp(dot, ".png") != 0) continue; // Check if baseName already stored int found = 0; for (int i = 0; i < baseNameCount; ++i) { if (strcmp(baseNames[i], entry->d_name) == 0) { found = 1; break; } } if (!found && baseNameCount < MAX_BASE_NAMES) { baseNames[baseNameCount++] = strdup(entry->d_name); // Only store base, not full file name } } closedir(dir); qsort(baseNames, baseNameCount, sizeof(char *), compareStrings); // Call registerBackgroundTile on each base name for (int i = 0; i < baseNameCount; ++i) { char fileName[64]; snprintf(fileName, sizeof(fileName), "%s", baseNames[i]); registerBackgroundTile(fileName, renderer); free(baseNames[i]); } } void preSetupTiles() { TileRegistry[TYPE_MINER].animation.startFrame = 1; TileRegistry[TYPE_FURNACE].animation.divisor = 8; TileRegistry[TYPE_WIRECRAFTER].animation.divisor = 8; TileRegistry[TYPE_SPLITTER].animation.divisor = 8; TileRegistry[TYPE_AMMOCRAFTER].animation.divisor = 8; TileRegistry[TYPE_CORE].animation.divisor = 8; BackgroundTileRegistry[BGType_WATER_DEEP].animation.divisor = 16; BackgroundTileRegistry[BGType_ENEMY_FLOOR].animation.divisor = 16; BackgroundTileRegistry[BGType_WATER_SHALLOW].animation.divisor = 12; BackgroundTileRegistry[BGType_GRASS_FLOWER0].animation.divisor = 16; BackgroundTileRegistry[BGType_GRASS_FLOWER1].animation.divisor = 16; BackgroundTileRegistry[BGType_GRASS_FLOWER2].animation.divisor = 16; } void setupTiles() { TileRegistry[TYPE_AIR].breakTime = 0; TileRegistry[TYPE_BELT].itemMoves = true; for (uint16_t i = 0; i < ItemSlotCount; i++) { TileRegistry[TYPE_BELT].outputLane[i] = true; } for (uint16_t l = 0; l < 2; l++) { for (ItemType i = 0; i < itemRegistryIndex; i++) { TileRegistry[TYPE_BELT].allowedInItems[l][i] = true; } } for (ItemType i = 0; i < itemRegistryIndex; i++) { TileRegistry[TYPE_SPLITTER].allowedInItems[0][i] = true; } TileRegistry[TYPE_SPLITTER].outputLane[0] = true; TileRegistry[TYPE_SPLITTER].needsTicks = true; TileRegistry[TYPE_SPLITTER].walkable = true; TileRegistry[TYPE_SPLITTER].allDir = true; TileRegistry[TYPE_FURNACE].outputLane[FURNACE_OUTPUT_SLOT] = 1; TileRegistry[TYPE_FURNACE].animation.startFrame = 1; TileRegistry[TYPE_FURNACE].needsTicks = true; TileRegistry[TYPE_BELT].needsTicks = true; TileRegistry[TYPE_BELT].walkable = true; TileRegistry[TYPE_MINER].needsTicks = true; TileRegistry[TYPE_MINER].outputLane[MINER_OUTPUT_SLOT] = 1; TileRegistry[TYPE_AIR].walkable = true; TileRegistry[TYPE_TURRET].needsTicks = true; for (ItemType i = 0; i < ITEMREGISTRY_SIZE; i++) { if (AmmoDamages[i] > 0) TileRegistry[TYPE_TURRET].allowedInItems[TURRET_AMMO_INPUT_SLOT][i] = true; } BackgroundTileRegistry[BGType_WATER_SHALLOW].walkable = false; BackgroundTileRegistry[BGType_WATER_DEEP].walkable = false; initFurnaceTile(); initWireDrawerTile(); initAmmoCrafterTile(); initCoreTile(); } uint16_t getBreakTime(int type) { if (type >= tileTypeIndex) { return 0; } return TileRegistry[type].breakTime; } void initTiles() { itemsTexture = SDL_CreateTexture(mainRenderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, screenRect.w, screenRect.h); tilesTexture = SDL_CreateTexture(mainRenderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, screenRect.w, screenRect.h); backgroundTexture = SDL_CreateTexture(mainRenderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, screenRect.w, screenRect.h); SDL_SetTextureBlendMode(itemsTexture, SDL_BLENDMODE_BLEND); SDL_SetTextureBlendMode(tilesTexture, SDL_BLENDMODE_BLEND); } void renderAllTiles(SDL_Renderer *renderer, SDL_Rect playerRect) { SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0); SDL_Texture *oldTarget = SDL_GetRenderTarget(renderer); int tileSize = TILE_SIZE; int minTileX = (playerRect.x / TILE_SIZE) - (DISPLAY_MAP_WIDTH / 2) - 1; int maxTileX = (playerRect.x / TILE_SIZE) + (DISPLAY_MAP_WIDTH / 2) + 1; int minTileY = (playerRect.y / TILE_SIZE) - (DISPLAY_MAP_HEIGHT / 2) - 1; int maxTileY = (playerRect.y / TILE_SIZE) + (DISPLAY_MAP_HEIGHT / 2) + 1; int scrollSpeed = 1; // pixels per step int scrollDelay = 1; // frames between steps if (beltFrames++ % scrollDelay == 0) { scrollFrame += scrollSpeed; } // --- Render background tiles --- SDL_SetRenderTarget(renderer, backgroundTexture); SDL_RenderClear(renderer); for (int y = minTileY; y < maxTileY; y++) { if (y < 0 || y >= MAP_HEIGHT) continue; for (int x = minTileX; x < maxTileX; x++) { if (x < 0 || x >= MAP_WIDTH) continue; SDL_Rect dstRect = { .x = x * TILE_SIZE, .y = y * TILE_SIZE, .w = TILE_SIZE, .h = TILE_SIZE }; adjustRect(&dstRect, playerRect); BackgroundTile bt = backgroundMap[y][x]; if (bt.type > BGType_END) { SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255); SDL_RenderFillRect(renderer, &dstRect); printf("Error on tile %d, %d\n", x, y); backgroundMap[y][x].type = BGType_PLATINUM_ORE; } else { SDL_Rect atlRect = BackgroundTileRegistry[bt.type].animation.atlasRects[ (animationStep / BackgroundTileRegistry[bt.type].animation.divisor) % BackgroundTileRegistry[bt.type].animation.frameCount]; if (atlRect.w != 0 && atlRect.h != 0) { SDL_RenderCopy(renderer, atlasTexture, &atlRect, &dstRect); //SDL_RenderCopy(renderer, tex, NULL, &dstRect); } } } } SDL_SetRenderTarget(renderer, tilesTexture); SDL_RenderClear(renderer); for (int y = minTileY; y < maxTileY; y++) { if (y < 0 || y >= MAP_HEIGHT) continue; for (int x = minTileX; x < maxTileX; x++) { if (x < 0 || x >= MAP_WIDTH) continue; SDL_Rect dstRect = { .x = x * TILE_SIZE, .y = y * TILE_SIZE, .w = TILE_SIZE, .h = TILE_SIZE }; adjustRect(&dstRect, playerRect); Tile t = tileMap[y][x]; switch (t.type) { case TYPE_AIR: break; case TYPE_BELT: renderBelt(x, y, tileSize, tileSize, t.direction, playerRect, renderer); break; default: { char animationFrame = ((animationStep / TileRegistry[t.type].animation.divisor) % (TileRegistry[t.type].animation.frameCount - TileRegistry[t.type].animation.startFrame)) + TileRegistry[t.type].animation.startFrame; if (t.fixedFrame > 0) { animationFrame = t.fixedFrame - 1; } SDL_Rect atlRect = TileRegistry[t.type].animation.atlasRects[t.direction][animationFrame]; if (atlRect.w == 0 || atlRect.h == 0) { atlRect = TileRegistry[t.type].animation.atlasRects[ORIENT_LEFT][ animationFrame]; } if (atlRect.w != 0 && atlRect.h != 0) { SDL_RenderCopy(renderer, atlasTexture, &atlRect, &dstRect); if (t.health < TileRegistry[t.type].maxHealth) { char healthStr[12]; snprintf(healthStr, 12, "%d/%d", t.health, TileRegistry[t.type].maxHealth); renderText(renderer, fonts[3], healthStr, dstRect.x, dstRect.y); } // if (t.health < TileRegistry[t.type].maxHealth) { // SDL_Color tileHealthColor = {(t.health / TileRegistry[t.type].maxHealth ) * 255, (TileRegistry[t.type].maxHealth / t.health) * 255, 0, 255}; // renderBar(mainRenderer, x * TILE_SIZE, (y * TILE_SIZE) + (TILE_SIZE / 2), TILE_SIZE, 8, // TileRegistry[t.type].maxHealth, t.health, tileHealthColor, 4); // } } } } } } SDL_SetRenderTarget(renderer, itemsTexture); SDL_RenderClear(renderer); for (int y = minTileY; y < maxTileY; y++) { if (y < 0 || y >= MAP_HEIGHT) continue; for (int x = minTileX; x < maxTileX; x++) { if (x < 0 || x >= MAP_WIDTH) continue; Tile t = tileMap[y][x]; if (debugMode) { char locChar[20]; sprintf(locChar, "X:%d\nY:%d", x, y); SDL_Rect dstRect = { .x = x * TILE_SIZE, .y = y * TILE_SIZE, .w = TILE_SIZE, .h = TILE_SIZE }; adjustRect(&dstRect, playerRect); renderText(renderer, fonts[4], locChar, dstRect.x, dstRect.y); } if (t.type == TYPE_BELT || itemViewing) { for (uint8_t lane = 0; lane < ItemSlotCount; lane++) { if (t.items[lane].type != 0) { renderItem(t.items[lane], renderer, lane, playerRect); } } } } } SDL_SetRenderTarget(renderer, oldTarget); } bool isWalkable(MiniRect tileCoords) { if (tileCoords.x < 0 || tileCoords.x >= MAP_WIDTH || tileCoords.y < 0 || tileCoords.y >= MAP_HEIGHT) { return false; } BackgroundTileType bgt = BackgroundTileRegistry[backgroundMap[tileCoords.y][tileCoords.x].type]; TileTypeReg fgt = TileRegistry[tileMap[tileCoords.y][tileCoords.x].type]; return bgt.walkable && fgt.walkable; } void updateTiles() { } // Main generator: void genInitMap() { const double terrainScale = 2; const double humidityScale = 1; const double oreScale = 2; const int terrainOct = 4; const int humidityOct = 4; const int oreOct = 4; int seedX = rand(); int seedY = rand(); int seedN = rand(); // Min/max trackers double terrainMin = 1e9, terrainMax = -1e9; double humidityMin = 1e9, humidityMax = -1e9; double oreNrmMin = 1e9, oreNrmMax = -1e9; for (uint16_t y = 0; y < MAP_HEIGHT; y++) { for (uint16_t x = 0; x < MAP_WIDTH; x++) { double terrain = pnoise2d(x + 1000 + seedX, y + 1000 + seedY, terrainScale, terrainOct, seedN); double humidity = pnoise2d(x + seedX, y + seedY, humidityScale, humidityOct, seedN); double oreNrm = pnoise2d(x + 9999 + seedX, y + 1111 + seedY, oreScale, oreOct, seedN); // Track min/max if (terrain < terrainMin) terrainMin = terrain; if (terrain > terrainMax) terrainMax = terrain; if (humidity < humidityMin) humidityMin = humidity; if (humidity > humidityMax) humidityMax = humidity; if (oreNrm < oreNrmMin) oreNrmMin = oreNrm; if (oreNrm > oreNrmMax) oreNrmMax = oreNrm; // [Same as your original terrain generation logic...] BackgroundType baseType = BGType_COBBLE0; if (terrain < 0.30) { baseType = (humidity < 0.5) ? BGType_WATER_SHALLOW : BGType_WATER_DEEP; } else if (terrain < 0.35) { if (humidity < 0.3) baseType = BGType_SAND4; else if (humidity < 0.6) baseType = BGType_SAND2; else baseType = BGType_SAND7; } else if (terrain < 0.7) { double grassVal = (terrain - 0.35) / (0.70 - 0.35); int idx = (int) (grassVal * 3.0); if (idx >= 4) idx = 3; if (humidity > 0.6 && ((rand() & 0xFF) < 10)) { int flowerIdx = rand() % 4; baseType = (BackgroundType) (BGType_GRASS_FLOWER0 + flowerIdx); } else { baseType = (BackgroundType) (BGType_GRASS0 + idx); } } else if (terrain < 0.85) { int idx = rand() % 4; baseType = (BackgroundType) (BGType_COBBLE0 + idx); } else { int idx = rand() % 4; baseType = (BackgroundType) (BGType_TILES0 + idx); } BackgroundType finalType = baseType; if (baseType != BGType_WATER_SHALLOW && baseType != BGType_WATER_DEEP) { if (oreNrm > 0.86) { double sub = (oreNrm - 0.86) / (1.0 - 0.86); if (sub < 0.25) finalType = BGType_IRON_ORE; else if (sub < 0.50) finalType = BGType_SILVER_ORE; else if (sub < 0.80) finalType = BGType_GOLD_ORE; else finalType = BGType_PLATINUM_ORE; } } if (finalType > BGType_END) { finalType = BGType_COBBLE0; } backgroundMap[y][x].type = finalType; } enemySpawn.x = MAP_WIDTH - 10; enemySpawn.y = 10; for (int enX = enemySpawn.x - 5; enX < enemySpawn.x + 6; enX++) { for (int enY = enemySpawn.y - 5; enY < enemySpawn.y + 6; enY++) { backgroundMap[enY][enX].type = BGType_ENEMY_FLOOR; } } playerCore.x = 8; playerCore.y = MAP_HEIGHT - 10; for (int plX = playerCore.x - 5; plX < playerCore.x + 6; plX++) { for (int plY = playerCore.y - 5; plY < playerCore.y + 6; plY++) { backgroundMap[plY][plX].type = BGType_TILES0; } } tileMap[playerCore.y][playerCore.x].type = TYPE_CORE; tileMap[playerCore.y][playerCore.x].direction = ORIENT_LEFT; tileMap[playerCore.y][playerCore.x].health = TileRegistry[TYPE_CORE].maxHealth; tileMap[playerCore.y][playerCore.x].fixedFrame = 0; tileMap[playerCore.y][playerCore.x].rect = playerCore; } // Debug printout printf("Terrain Noise: min = %f, max = %f\n", terrainMin, terrainMax); printf("Humidity Noise: min = %f, max = %f\n", humidityMin, humidityMax); printf("Ore Normalized: min = %f, max = %f\n", oreNrmMin, oreNrmMax); }