2021-01-11 16:20:12 +00:00
|
|
|
#include "world.h"
|
|
|
|
#include "blocks.h"
|
2021-01-11 17:30:47 +00:00
|
|
|
#include "perlin.h"
|
2021-01-11 16:20:12 +00:00
|
|
|
#include "zpl.h"
|
|
|
|
|
2021-01-11 16:49:00 +00:00
|
|
|
#include <math.h>
|
|
|
|
|
2021-01-11 17:15:11 +00:00
|
|
|
#define WORLD_BLOCK_OBSERVER(name) uint32_t name(uint32_t id, uint32_t block_idx)
|
|
|
|
typedef WORLD_BLOCK_OBSERVER(world_block_observer_proc);
|
|
|
|
|
2021-01-11 17:30:47 +00:00
|
|
|
#define WORLD_PERLIN_FREQ 1.0
|
|
|
|
#define WORLD_PERLIN_OCTAVES 1
|
|
|
|
|
2021-01-11 17:15:11 +00:00
|
|
|
static void world_fill_rect(uint32_t id, uint32_t x, uint32_t y, uint32_t w, uint32_t h, world_block_observer_proc *proc) {
|
2021-01-11 16:20:12 +00:00
|
|
|
for (uint32_t cy=y; cy<y+h; cy++) {
|
|
|
|
for (uint32_t cx=x; cx<x+w; cx++) {
|
2021-01-11 17:15:11 +00:00
|
|
|
if (cx < 0 || cx >= world_width) continue;
|
|
|
|
if (cy < 0 || cy >= world_height) continue;
|
2021-01-11 16:49:00 +00:00
|
|
|
uint32_t i = (cy*world_width) + cx;
|
2021-01-11 17:15:11 +00:00
|
|
|
|
|
|
|
if (proc) {
|
|
|
|
uint32_t new_id = (*proc)(id, i);
|
2021-01-11 17:30:47 +00:00
|
|
|
if (new_id != BLOCK_INVALID) {
|
|
|
|
id = new_id;
|
|
|
|
}
|
|
|
|
else continue;
|
2021-01-11 17:15:11 +00:00
|
|
|
}
|
|
|
|
|
2021-01-11 16:20:12 +00:00
|
|
|
world[i] = id;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-11 17:15:11 +00:00
|
|
|
static void world_fill_rect_anchor(uint32_t id, uint32_t x, uint32_t y, uint32_t w, uint32_t h, float ax, float ay, world_block_observer_proc *proc) {
|
|
|
|
uint32_t w2 = (uint32_t)floorf(w*ax);
|
|
|
|
uint32_t h2 = (uint32_t)floorf(h*ay);
|
|
|
|
world_fill_rect(id, x-w2, y-h2, w, h, proc);
|
|
|
|
}
|
|
|
|
|
|
|
|
static WORLD_BLOCK_OBSERVER(shaper) {
|
|
|
|
uint32_t biome = blocks_get_biome(id);
|
|
|
|
uint32_t kind = blocks_get_kind(id);
|
|
|
|
uint32_t old_biome = blocks_get_biome(world[block_idx]);
|
|
|
|
uint32_t old_kind = blocks_get_kind(world[block_idx]);
|
|
|
|
|
|
|
|
if (biome == old_biome) {
|
|
|
|
if (kind == BLOCK_KIND_WALL && kind == old_kind) {
|
|
|
|
return blocks_find(biome, BLOCK_KIND_HILL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return id;
|
2021-01-11 16:49:00 +00:00
|
|
|
}
|
|
|
|
|
2021-01-11 17:30:47 +00:00
|
|
|
static WORLD_BLOCK_OBSERVER(shaper_noise80) {
|
|
|
|
uint32_t x = block_idx % world_width;
|
|
|
|
uint32_t y = block_idx / world_width;
|
|
|
|
|
2021-01-11 17:33:27 +00:00
|
|
|
if (perlin_fbm(world_seed, x, y, WORLD_PERLIN_FREQ, WORLD_PERLIN_OCTAVES) < 0.80)
|
|
|
|
return shaper(id, block_idx);
|
|
|
|
else
|
|
|
|
return BLOCK_INVALID;
|
|
|
|
}
|
|
|
|
|
|
|
|
static WORLD_BLOCK_OBSERVER(shaper_noise50) {
|
|
|
|
uint32_t x = block_idx % world_width;
|
|
|
|
uint32_t y = block_idx / world_width;
|
|
|
|
|
|
|
|
if (perlin_fbm(world_seed, x, y, WORLD_PERLIN_FREQ, WORLD_PERLIN_OCTAVES) < 0.50)
|
|
|
|
return shaper(id, block_idx);
|
|
|
|
else
|
|
|
|
return BLOCK_INVALID;
|
|
|
|
}
|
|
|
|
|
|
|
|
static WORLD_BLOCK_OBSERVER(shaper_noise33) {
|
|
|
|
uint32_t x = block_idx % world_width;
|
|
|
|
uint32_t y = block_idx / world_width;
|
|
|
|
|
|
|
|
if (perlin_fbm(world_seed, x, y, WORLD_PERLIN_FREQ, WORLD_PERLIN_OCTAVES) < 0.33)
|
2021-01-11 17:30:47 +00:00
|
|
|
return shaper(id, block_idx);
|
|
|
|
else
|
|
|
|
return BLOCK_INVALID;
|
|
|
|
}
|
|
|
|
|
|
|
|
int32_t world_gen() {
|
2021-01-11 16:20:12 +00:00
|
|
|
// TODO: perform world gen
|
|
|
|
// atm, we will fill the world with ground and surround it by walls
|
|
|
|
uint32_t wall_id = blocks_find(BLOCK_BIOME_DEV, BLOCK_KIND_WALL);
|
|
|
|
uint32_t grnd_id = blocks_find(BLOCK_BIOME_DEV, BLOCK_KIND_GROUND);
|
|
|
|
uint32_t watr_id = blocks_find(BLOCK_BIOME_DEV, BLOCK_KIND_WATER);
|
|
|
|
|
|
|
|
// walls
|
2021-01-11 17:15:11 +00:00
|
|
|
world_fill_rect(wall_id, 0, 0, world_width, world_height, NULL);
|
2021-01-11 16:20:12 +00:00
|
|
|
|
|
|
|
// ground
|
2021-01-11 17:15:11 +00:00
|
|
|
world_fill_rect(grnd_id, 1, 1, world_width-2, world_height-2, NULL);
|
2021-01-11 16:20:12 +00:00
|
|
|
|
|
|
|
// water
|
2021-01-11 17:15:11 +00:00
|
|
|
world_fill_rect_anchor(watr_id, 8, 8, 4, 4, 0.5f, 0.5f, NULL);
|
|
|
|
|
|
|
|
// hills
|
2021-01-11 17:30:47 +00:00
|
|
|
world_fill_rect_anchor(wall_id, 14, 21, 8, 8, 0.5f, 0.5f, shaper_noise80);
|
2021-01-11 17:33:27 +00:00
|
|
|
world_fill_rect_anchor(wall_id, 14, 21, 4, 4, 0.5f, 0.5f, shaper_noise50);
|
2021-01-11 17:15:11 +00:00
|
|
|
|
2021-01-11 16:20:12 +00:00
|
|
|
|
|
|
|
return WORLD_ERROR_NONE;
|
|
|
|
}
|