/* 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.25) type = DECO_CRYSTAL; else if (noise > 0.21) type = DECO_STONE; else if (noise > 0.12) 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 waterlevel, height, biome; 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; 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 (height > waterlevel + 0.12f) { float noise1, noise2; noise1 = world->perlin.get(x, 2.6f) + world->perlin.get(x, 7.0f); noise2 = world->perlin.get(x, 10.0f); if (height > waterlevel + 0.18f + noise1 * 0.16f || noise2 > 0.3f) tile->type = TILE_GRAVEL; else tile->type = TILE_STONE; } else if (height > waterlevel) tile->type = TILE_DIRT; else tile->type = TILE_WATER; biome = world->perlin.get(x, 60.0f) * 0.6f + world->perlin.get(x, 30.0f) * 0.25f + world->perlin.get(x, 15.0f) * 0.2f + world->perlin.get(x, 7.0f) * 0.1f + world->perlin.get(x, 3.0f) * 0.05f; if (biome > 0.2f) switch (tile->type) { case TILE_DIRT: tile->type = TILE_DIRT_RED; break; case TILE_STONE: tile->type = TILE_STONE_RED; break; } } 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); } } }