#include "common.hpp" #include namespace world { sector_index_t sector_index_at(v2f_t x) { return sector_index_t((x / SECTOR_SIZE).floor()); } tile_index_t tile_index_at(v2f_t x) { return sector_index_t(x.floor()); } world_t::world_t(void) { prng.seed(125); perlin.generate(&prng, 32); } void world_t::generate_tile(tile_t *tile, tile_index_t x) { float waterlevel, height; waterlevel = perlin.get(x, 1000.0f) * 0.3f + perlin.get(x, 500.0f) * 0.1f; height = perlin.get(x, 40.0f) * 0.6f + perlin.get(x, 20.0f) * 0.25f + perlin.get(x, 10.0f) * 0.2f + perlin.get(x, 4.0f) * 0.1f + perlin.get(x, 1.0f) * 0.05f; if (height < waterlevel - 0.2f) tile->type = -1; else if (height < waterlevel) tile->type = 0; else if (height < waterlevel + 0.05f) tile->type = 1; else { if (perlin.get(x, 5.0f) > 0.0f) tile->type = 3; else tile->type = 2; if (height > waterlevel + 0.1f && perlin.get(x, 2.0f) > 0.3f) tile->type = 4; } } void world_t::generate(sector_t *sector, sector_index_t index) { sector->index = index; sector->bounds.v[0] = (v2f_t)index * SECTOR_SIZE; sector->bounds.v[1] = sector->bounds.v[0] + v2f_t(SECTOR_SIZE, SECTOR_SIZE); std::cout << "generating " << index << "\n"; for (ssize_t ly = 0; ly < SECTOR_SIZE; ly++) for (ssize_t lx = 0; lx < SECTOR_SIZE; lx++) generate_tile(sector->tiles + ly * SECTOR_SIZE + lx, tile_index_t(index[0] * SECTOR_SIZE + lx, index[1] * SECTOR_SIZE + ly)); sector->empty = false; } bool world_t::find_path(v2f_t src, v2f_t dst, rectf_t size, std::list *path) { path_finder_t finder; finder.setup_nodes(src, dst); for (size_t y = 0; y < finder.height; y++) for (size_t x = 0; x < finder.width; x++) { path_node_t *node = finder.nodes + y * finder.width + x; tile_index_t index; index = finder.base + tile_index_t(x, y); node->accessible = (get_tile(index)->type >= 1 && get_tile(index)->type <= 3); } if (!finder.find()) return false; finder.export_path(path); return true; } sector_t *world_t::get_sector(sector_index_t index) { sector_t *sector; sector = §ors[index]; if (sector->empty) generate(sector, index); return sector; } tile_t *world_t::get_tile(tile_index_t index) { sector_index_t sector_index; sector_t *sector; int64_t tx, ty; sector_index[0] = divide_rmi(index[0], (int64_t)SECTOR_SIZE, &tx); sector_index[1] = divide_rmi(index[1], (int64_t)SECTOR_SIZE, &ty); sector = get_sector(sector_index); return sector->tiles + ty * SECTOR_SIZE + tx; } std::list world_t::get_sectors(rectf_t rect) { sector_index_t base, upper; std::list list; base = sector_index_at(rect.v[0]); upper = sector_index_at(rect.v[1]); for (int64_t y = base[1]; y <= upper[1]; y++) for (int64_t x = base[0]; x <= upper[0]; x++) { sector_index_t index(x, y); list.push_back(get_sector(index)); } return list; } std::list world_t::get_entities(rectf_t rect) { static size_t cookie = 0; std::list list; cookie++; for (sector_t *sector : get_sectors(rect)) for (entity_t *ent : sector->ents) { if (ent->cookie == cookie) continue; if (!rect.intersects(ent->bounds)) continue; ent->cookie = cookie; list.push_back(ent); } return list; } std::list world_t::get_render_entities(rectf_t rect) { static size_t cookie = 0; std::list list; cookie++; for (sector_t *sector : get_sectors(rect)) for (entity_t *ent : sector->ents) { if (ent->cookie == cookie) continue; if (!rect.intersects(ent->render_bounds)) continue; ent->cookie = cookie; list.push_back(ent); } return list; } void world_t::debug_point(sf::Vector2f point) { sector_index_t index = sector_index_at(point); printf("sector (%zd, %zd)\n", index[0], index[1]); } void entity_t::link_to_sector(sector_t *sector) { parents.push_back(sector); sector->ents.insert(this); } void entity_t::link(world_t *world) { rectf_t total_bounds; float fx, fy; sector_index_t base; float xlip, ylip; size_t xsecs, ysecs; total_bounds = bounds + render_bounds; fx = floor(total_bounds[0][0]); fy = floor(total_bounds[0][1]); base = sector_index_at(v2f_t(fx, fy)); xlip = total_bounds[1][0] - (base[0] + 1) * SECTOR_SIZE; ylip = total_bounds[1][1] - (base[1] + 1) * SECTOR_SIZE; if (xlip > 0.0f) xsecs = ceil(xlip / SECTOR_SIZE) + 1; else xsecs = 1; if (ylip > 0.0f) ysecs = ceil(ylip / SECTOR_SIZE) + 1; else ysecs = 1; for (int64_t y = 0; y < (int64_t)ysecs; y++) for (int64_t x = 0; x < (int64_t)xsecs; x++) { sector_index_t index = base + sector_index_t(x, y); sector_t *sector; sector = world->get_sector(index); link_to_sector(sector); } } void entity_t::unlink(void) { for (sector_t *sector : parents) { if (sector->ents.find(this) == sector->ents.end()) { printf("entity_t::unlink: %p should belong to %p (%" PRIi64", %" PRIi64") but it doesn't\n", this, sector, sector->index[0], sector->index[1]); continue; } sector->ents.erase(sector->ents.find(this)); } parents.clear(); parent_world = nullptr; } } // namespace world