#include "common.hpp" namespace world { sector_index_t::sector_index_t () { } sector_index_t::sector_index_t (int64_t x_, int64_t y_) { x = x_; y = y_; } sector_index_t::sector_index_t (float x_, float y_) { x = (int64_t)floor(x_ / SECTOR_SIZE); y = (int64_t)floor(y_ / SECTOR_SIZE); } bool sector_index_t::operator<(sector_index_t B) const { if (x < B.x) return true; if (x > B.x) return false; if (y < B.y) return true; return false; } world_t::world_t(void) { prng.seed(124); perlin.generate(&prng, 32); } void world_t::generate_tile(ssize_t x, ssize_t y, tile_t *tile) { float waterlevel, height; waterlevel = perlin.get(x, y, 100.0f) * 0.3f + perlin.get(x, y, 50.0f) * 0.1f; height = perlin.get(x, y, 30.0f) * 0.6f + perlin.get(x, y, 15.0f) * 0.25f + perlin.get(x, y, 7.0f) * 0.1f + perlin.get(x, y, 3.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, y, 5.0f) > 0.0f) tile->type = 3; else tile->type = 2; } } void world_t::generate(sector_t *sector, sector_index_t index) { sector->index = index; sector->bounds.left = index.x * SECTOR_SIZE; sector->bounds.top = index.y * SECTOR_SIZE; sector->bounds.width = SECTOR_SIZE; sector->bounds.height = SECTOR_SIZE; std::cout << "generating (" << index.x << ", " << index.y << ")\n"; for (ssize_t ly = 0; ly < SECTOR_SIZE; ly++) for (ssize_t lx = 0; lx < SECTOR_SIZE; lx++) generate_tile(index.x * SECTOR_SIZE + lx, index.y * SECTOR_SIZE + ly, sector->tiles + ly * SECTOR_SIZE + lx); sector->empty = false; } 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(ssize_t x, ssize_t y) { sector_index_t index; sector_t *sector; ssize_t tx, ty; index.x = divide_rmi(x, (ssize_t)SECTOR_SIZE, &tx); index.y = divide_rmi(y, (ssize_t)SECTOR_SIZE, &ty); sector = get_sector(index); return sector->tiles + ty * SECTOR_SIZE + tx; } std::list world_t::get_sectors(sf::FloatRect rect) { sector_index_t base(rect.left, rect.top), upper(rect.left + rect.width, rect.top + rect.height); std::list list; for (int64_t y = base.y; y <= upper.y; y++) for (int64_t x = base.x; x <= upper.x; x++) { sector_index_t index(x, y); list.push_back(get_sector(index)); } return list; } std::list world_t::get_entities(sf::FloatRect 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; ent->cookie = cookie; list.push_back(ent); } return list; } void world_t::debug_point(sf::Vector2f point) { sector_index_t index(point.x, point.y); printf("sector (%zd, %zd)\n", index.x, index.y); } void entity_t::link_to_sector(sector_t *sector) { parents.push_back(sector); sector->ents.insert(this); } void entity_t::link(world_t *world) { float fx, fy; sector_index_t base; float xlip, ylip; size_t xsecs, ysecs; fx = floor(bounds.left); fy = floor(bounds.top); base = sector_index_t(fx, fy); xlip = bounds.left + bounds.width - (base.x + 1) * SECTOR_SIZE; ylip = bounds.top + bounds.height - (base.y + 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.x + x, base.y + y); sector_t *sector; sector = world->get_sector(index); link_to_sector(sector); } } void entity_t::unlink(void) { for (sector_t *sector : parents) sector->ents.erase(sector->ents.find(this)); parents.clear(); parent_world = nullptr; } } // namespace world