/* This file is part of Minitrem. Minitrem is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. Minitrem is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Minitrem. If not, see . */ #include "game.hpp" namespace game { using namespace world; static void add_entity(uint8_t tile_type, world_t *world, state_t *game, v2f_t x) { float noise, noise_nest, noise_spider; deco_t *deco; deco_type_t type; v2f_t center, offset; noise = world->perlin.get(x, 0.53213f) + world->perlin.get(x, 0.12994f); noise = fabs(noise / 2); offset[0] = world->perlin.get(x, 0.17331f); offset[1] = world->perlin.get(x, 0.19571f); center = x + v2f_t(0.5f, 0.5f) + offset.norm() * 0.1; switch (tile_type) { case TILE_DIRT: noise_nest = 0.40f; noise_spider = 0.38f; break; case TILE_DIRT_RED: noise_nest = 0.45f; noise_spider = 0.41f; break; case TILE_GRAVEL: noise_nest = 0.34f; noise_spider = 0.32f; break; default: goto just_decos; } if (noise > noise_nest) { unit_nest_t *nest = new unit_nest_t(game); nest->place(world, center); return; } else if (noise > noise_spider) { unit_spider_t *spider = new unit_spider_t(game); spider->place(world, center); return; } just_decos: switch (tile_type) { case TILE_DIRT_RED: if (noise > 0.21) type = DECO_EYETHING; else if (noise > 0.08) type = DECO_WART; else return; break; case TILE_DIRT: if (noise > 0.34) type = DECO_CRYSTAL; else if (noise > 0.33) type = DECO_CRYSTAL_BROKEN; else if (noise > 0.32) type = DECO_STONE; else if (noise > 0.26) type = DECO_SPIKE; else if (noise > 0.20) type = DECO_SPIKE_SMALL; else if (noise > 0.16) type = DECO_STONE_SMALL; else return; break; case TILE_GRAVEL: if (noise > 0.26) type = DECO_CRYSTAL; else if (noise > 0.25) type = DECO_STONE; else if (noise > 0.13) type = DECO_STONE_SMALL; else return; break; default: return; } deco = new deco_t(game, type); deco->phase_shift = offset[0] * 500.0; deco->place(world, center); } void worldgen(world_t *world, sector_index_t index, sector_t *sector, bool gen_tiles, bool gen_decos, void *data) { state_t *game = (game::state_t*)data; if (!gen_tiles) goto decos; for (coord_t ly = 0; ly < SECTOR_SIZE; ly++) for (coord_t lx = 0; lx < SECTOR_SIZE; lx++) { tile_t *tile = sector->tiles + ly * SECTOR_SIZE + lx; tile_index_t tile_index(index[0] * SECTOR_SIZE + lx, index[1] * SECTOR_SIZE + ly); v2f_t x; float biome, waterlevel, height; x = v2f_t(index) * SECTOR_SIZE + v2f_t(lx, ly); waterlevel = world->perlin.get(x, 1000.0f) * 0.3f + world->perlin.get(x, 500.0f) * 0.1f; biome = world->perlin.get(-x + v2f_t(-60, 120), 160.0f) * 0.4f + world->perlin.get(x, 30.0f) * 0.2f + world->perlin.get(x, 8.0f) * 0.03f; height = world->perlin.get(x, 40.0f) * 0.6f + world->perlin.get(x, 20.0f) * 0.25f + world->perlin.get(x, 10.0f) * 0.2f + world->perlin.get(x, 4.0f) * 0.1f + world->perlin.get(x, 1.0f) * 0.05f; if (biome < 0.0f) { if (height < waterlevel) tile->type = TILE_WATER; else if (height < waterlevel + 0.12) tile->type = TILE_DIRT; else if (world->perlin.get(x, 4.0f) > 0.0f) tile->type = TILE_STONE; else tile->type = TILE_DIRT; } else if (biome < 0.1f) { if (height < waterlevel - 0.07f) tile->type = TILE_STONE; else tile->type = TILE_GRAVEL; } else { if (height < waterlevel) tile->type = TILE_DIRT_RED; else if (world->perlin.get(x, 3.0f) > 0.0f) tile->type = TILE_STONE_RED; else tile->type = TILE_DIRT_RED; } } decos: if (!gen_decos) return; for (coord_t ly = 0; ly < SECTOR_SIZE; ly++) for (coord_t lx = 0; lx < SECTOR_SIZE; lx++) { tile_t *tile = sector->tiles + ly * SECTOR_SIZE + lx; tile_index_t tile_index(index[0] * SECTOR_SIZE + lx, index[1] * SECTOR_SIZE + ly); v2f_t x; x = v2f_t(index) * SECTOR_SIZE + v2f_t(lx, ly); add_entity(tile->type, world, game, x); } } }