@@ -24,8 +24,8 @@ SomeNamespace::someLongFunctionName( | |||
``` C++ | |||
void someLongFunctionName( | |||
int first_argument, | |||
int second_argument) { | |||
int firstArgument, | |||
int secondArgument) { | |||
whatever; | |||
} | |||
``` | |||
@@ -34,9 +34,10 @@ void someLongFunctionName( | |||
* Classes and structs are PascalCase. | |||
* Methods and free functions are camelCase. | |||
* Local variables are snake_case. | |||
* Class member variables are snake_case_ (with the trailing underscore). | |||
* Struct member variables are snake_case (without the trailing underscore). | |||
* Local variables are camelCase. | |||
* Class member variables are camelCase\_ (with the trailing underscore). | |||
* Struct member variables are camelCase (without the trailing underscore). | |||
* Constants are UPPER\_SNAKE\_CASE (no trailing underscore) everywhere. | |||
## Structure | |||
@@ -4,11 +4,11 @@ | |||
#include "entities/PlayerEntity.h" | |||
static int grassLevel(const siv::PerlinNoise &perlin, int x) { | |||
static int getGrassLevel(const siv::PerlinNoise &perlin, int x) { | |||
return (int)(perlin.noise(x / 50.0, 0) * 13); | |||
} | |||
static int stoneLevel(const siv::PerlinNoise &perlin, int x) { | |||
static int getStoneLevel(const siv::PerlinNoise &perlin, int x) { | |||
return (int)(perlin.noise(x / 50.0, 10) * 10) + 10; | |||
} | |||
@@ -43,18 +43,18 @@ SDL_Color DefaultWorldGen::backgroundColor(Swan::Vec2 pos) { | |||
} | |||
Swan::Tile::ID DefaultWorldGen::genTile(Swan::TilePos pos) { | |||
int grass_level = grassLevel(perlin_, pos.x); | |||
int stone_level = stoneLevel(perlin_, pos.x); | |||
int grassLevel = getGrassLevel(perlin_, pos.x); | |||
int stoneLevel = getStoneLevel(perlin_, pos.x); | |||
// Caves | |||
if (pos.y > grass_level + 7 && perlin_.noise(pos.x / 43.37, pos.y / 16.37) > 0.2) | |||
if (pos.y > grassLevel + 7 && perlin_.noise(pos.x / 43.37, pos.y / 16.37) > 0.2) | |||
return tAir_; | |||
if (pos.y > stone_level) | |||
if (pos.y > stoneLevel) | |||
return tStone_; | |||
else if (pos.y > grass_level) | |||
else if (pos.y > grassLevel) | |||
return tDirt_; | |||
else if (pos.y == grass_level) | |||
else if (pos.y == grassLevel) | |||
return tGrass_; | |||
else | |||
return tAir_; | |||
@@ -77,5 +77,5 @@ void DefaultWorldGen::genChunk(Swan::WorldPlane &plane, Swan::Chunk &chunk) { | |||
Swan::EntityRef DefaultWorldGen::spawnPlayer(const Swan::Context &ctx) { | |||
int x = 0; | |||
return ctx.plane.spawnEntity<PlayerEntity>( | |||
ctx, Swan::Vec2{ (float)x, (float)grassLevel(perlin_, x) - 4 }); | |||
ctx, Swan::Vec2{ (float)x, (float)getGrassLevel(perlin_, x) - 4 }); | |||
} |
@@ -34,8 +34,8 @@ void ItemStackEntity::update(const Swan::Context &ctx, float dt) { | |||
} | |||
void ItemStackEntity::tick(const Swan::Context &ctx, float dt) { | |||
despawn_timer_ -= dt; | |||
if (despawn_timer_ <= 0) | |||
despawnTimer_ -= dt; | |||
if (despawnTimer_ <= 0) | |||
despawn(ctx); | |||
} | |||
@@ -21,6 +21,6 @@ private: | |||
ItemStackEntity(): PhysicsEntity(SIZE) {} | |||
float despawn_timer_ = DESPAWN_TIME; | |||
float despawnTimer_ = DESPAWN_TIME; | |||
Swan::Item *item_ = NULL; | |||
}; |
@@ -23,19 +23,19 @@ void PlayerEntity::update(const Swan::Context &ctx, float dt) { | |||
State oldState = state_; | |||
state_ = State::IDLE; | |||
mouse_tile_ = ctx.game.getMouseTile(); | |||
ctx.plane.debugBox(mouse_tile_); | |||
jump_timer_.tick(dt); | |||
place_timer_.tick(dt); | |||
mouseTile_ = ctx.game.getMouseTile(); | |||
ctx.plane.debugBox(mouseTile_); | |||
jumpTimer_.tick(dt); | |||
placeTimer_.tick(dt); | |||
// Break block | |||
if (ctx.game.isMousePressed(SDL_BUTTON_LEFT)) | |||
ctx.plane.breakTile(mouse_tile_); | |||
ctx.plane.breakTile(mouseTile_); | |||
// Place block | |||
if (ctx.game.isMousePressed(SDL_BUTTON_RIGHT) && place_timer_.periodic(0.50)) { | |||
if (ctx.plane.getTileID(mouse_tile_) == ctx.world.getTileID("@::air")) { | |||
ctx.plane.setTile(mouse_tile_, "core::torch"); | |||
if (ctx.game.isMousePressed(SDL_BUTTON_RIGHT) && placeTimer_.periodic(0.50)) { | |||
if (ctx.plane.getTileID(mouseTile_) == ctx.world.getTileID("@::air")) { | |||
ctx.plane.setTile(mouseTile_, "core::torch"); | |||
} | |||
} | |||
@@ -54,15 +54,15 @@ void PlayerEntity::update(const Swan::Context &ctx, float dt) { | |||
state_ = State::RUNNING_R; | |||
} | |||
bool jump_pressed = ctx.game.isKeyPressed(SDL_SCANCODE_SPACE); | |||
bool jumpPressed = ctx.game.isKeyPressed(SDL_SCANCODE_SPACE); | |||
// Jump | |||
if (physics_.on_ground && jump_pressed && jump_timer_.periodic(0.5)) { | |||
if (physics_.onGround && jumpPressed && jumpTimer_.periodic(0.5)) { | |||
physics_.vel.y = -JUMP_VEL; | |||
} | |||
// Fall down faster than we went up | |||
if (!physics_.on_ground && (!jump_pressed || physics_.vel.y > 0)) | |||
if (!physics_.on_ground && (!jumpPressed || physics_.vel.y > 0)) | |||
physics_.force += Swan::Vec2(0, DOWN_FORCE); | |||
if (state_ != oldState) | |||
@@ -74,14 +74,14 @@ void PlayerEntity::update(const Swan::Context &ctx, float dt) { | |||
// Do this after moving so that it's not behind | |||
Swan::Vec2 headPos = body_.topMid() + Swan::Vec2(0, 0.5); | |||
Swan::TilePos tilePos = Swan::Vec2i(floor(headPos.x), floor(headPos.y)); | |||
if (!placed_light_) { | |||
if (!placedLight_) { | |||
ctx.plane.addLight(tilePos, LIGHT_LEVEL); | |||
placed_light_ = true; | |||
light_tile_ = tilePos; | |||
} else if (tilePos != light_tile_) { | |||
ctx.plane.removeLight(light_tile_, LIGHT_LEVEL); | |||
placedLight_ = true; | |||
lightTile_ = tilePos; | |||
} else if (tilePos != lightTile_) { | |||
ctx.plane.removeLight(lightTile_, LIGHT_LEVEL); | |||
ctx.plane.addLight(tilePos, LIGHT_LEVEL); | |||
light_tile_ = tilePos; | |||
lightTile_ = tilePos; | |||
} | |||
} | |||
@@ -46,12 +46,12 @@ private: | |||
State state_ = State::IDLE; | |||
std::array<Swan::Animation, (int)State::COUNT> anims_; | |||
Swan::Clock jump_timer_; | |||
Swan::Clock place_timer_; | |||
Swan::TilePos mouse_tile_; | |||
Swan::Clock jumpTimer_; | |||
Swan::Clock placeTimer_; | |||
Swan::TilePos mouseTile_; | |||
Swan::TilePos light_tile_; | |||
bool placed_light_ = false; | |||
Swan::TilePos lightTile_; | |||
bool placedLight_ = false; | |||
BasicInventory inventory_{INVENTORY_SIZE}; | |||
}; |
@@ -7,7 +7,7 @@ | |||
class CoreMod: public Swan::Mod { | |||
public: | |||
CoreMod(Swan::World &world): Swan::Mod("core") { | |||
break_listener_ = world.evt_tile_break_.subscribe( | |||
breakListener_ = world.evtTileBreak_.subscribe( | |||
std::bind_front(&CoreMod::onTileBreak, this)); | |||
registerImage("tile/stone"); | |||
@@ -75,13 +75,13 @@ public: | |||
} | |||
void onTileBreak(const Swan::Context &ctx, Swan::TilePos pos, Swan::Tile &tile) { | |||
if (tile.dropped_item_) { | |||
if (tile.droppedItem_) { | |||
ctx.plane.spawnEntity<ItemStackEntity>( | |||
ctx, (Swan::Vec2)pos + Swan::Vec2{0.5, 0.5}, *tile.dropped_item_); | |||
ctx, (Swan::Vec2)pos + Swan::Vec2{0.5, 0.5}, *tile.droppedItem_); | |||
} | |||
} | |||
Swan::EventListener break_listener_; | |||
Swan::EventListener breakListener_; | |||
}; | |||
extern "C" Swan::Mod *mod_create(Swan::World &world) { |
@@ -73,24 +73,24 @@ private: | |||
std::unique_ptr<RendererState> state_; | |||
std::vector<DrawChunk> draw_chunks_; | |||
std::vector<DrawSprite> draw_sprites_; | |||
std::vector<DrawChunk> drawChunks_; | |||
std::vector<DrawSprite> drawSprites_; | |||
}; | |||
inline void Renderer::drawChunk(RenderChunk chunk, SwanCommon::Vec2 pos) { | |||
draw_chunks_.emplace_back(pos, chunk); | |||
drawChunks_.emplace_back(pos, chunk); | |||
} | |||
inline void Renderer::drawSprite(RenderSprite sprite, Mat3gf mat, int frame) { | |||
draw_sprites_.emplace_back(mat, frame, sprite); | |||
drawSprites_.emplace_back(mat, frame, sprite); | |||
} | |||
inline void Renderer::drawSprite(RenderSprite sprite, SwanCommon::Vec2 pos, int frame) { | |||
draw_sprites_.emplace_back(Mat3gf{}.translate(pos), frame, sprite); | |||
drawSprites_.emplace_back(Mat3gf{}.translate(pos), frame, sprite); | |||
} | |||
inline void Renderer::drawSpriteFlipped(RenderSprite sprite, SwanCommon::Vec2 pos, int frame) { | |||
draw_sprites_.emplace_back(Mat3gf{}.translate(pos).scale({ -1, 1 }), frame, sprite); | |||
drawSprites_.emplace_back(Mat3gf{}.translate(pos).scale({ -1, 1 }), frame, sprite); | |||
} | |||
} |
@@ -33,7 +33,7 @@ public: | |||
private: | |||
Renderer &rnd_; | |||
std::unordered_map<std::string, RenderSprite> sprites_; | |||
std::vector<ResourceTileAnimation> tile_anims_; | |||
std::vector<ResourceTileAnimation> tileAnims_; | |||
TileAtlas atlas_; | |||
friend ResourceManager; | |||
@@ -52,7 +52,7 @@ private: | |||
Renderer &rnd_; | |||
std::unordered_map<std::string, RenderSprite> sprites_; | |||
std::unordered_map<std::string, RenderTile> tiles_; | |||
std::vector<ResourceTileAnimation> tile_anims_; | |||
std::vector<ResourceTileAnimation> tileAnims_; | |||
}; | |||
inline RenderSprite ResourceBuilder::addSprite( | |||
@@ -79,7 +79,7 @@ inline void ResourceBuilder::addTile(uint16_t id, void *data, int frames) { | |||
inline void ResourceBuilder::addTile(Renderer::TileID id, std::unique_ptr<unsigned char[]> data, int frames) { | |||
atlas_.addTile(id, data.get()); | |||
if (frames > 1) { | |||
tile_anims_.push_back({ | |||
tileAnims_.push_back({ | |||
.id = id, | |||
.frames = frames, | |||
.index = 0, |
@@ -170,14 +170,14 @@ void Renderer::draw(const RenderCamera &cam) { | |||
glCheck(); | |||
glActiveTexture(GL_TEXTURE1); | |||
for (auto [pos, chunk]: draw_chunks_) { | |||
for (auto [pos, chunk]: drawChunks_) { | |||
glUniform2f(chunkProg.pos, pos.x, pos.y); | |||
glBindTexture(GL_TEXTURE_2D, chunk.tex); | |||
glDrawArrays(GL_TRIANGLES, 0, 6); | |||
glCheck(); | |||
} | |||
draw_chunks_.clear(); | |||
drawChunks_.clear(); | |||
chunkProg.disable(); | |||
} | |||
@@ -187,7 +187,7 @@ void Renderer::draw(const RenderCamera &cam) { | |||
glCheck(); | |||
glActiveTexture(GL_TEXTURE0); | |||
for (auto [mat, frame, sprite]: draw_sprites_) { | |||
for (auto [mat, frame, sprite]: drawSprites_) { | |||
mat.scale(sprite.scale); | |||
glUniformMatrix3fv(spriteProg.transform, 1, GL_TRUE, mat.data()); | |||
glUniform3f(spriteProg.frameInfo, sprite.scale.y, sprite.frameCount, frame); | |||
@@ -196,7 +196,7 @@ void Renderer::draw(const RenderCamera &cam) { | |||
glCheck(); | |||
} | |||
draw_sprites_.clear(); | |||
drawSprites_.clear(); | |||
spriteProg.disable(); | |||
} | |||
} |
@@ -4,7 +4,7 @@ namespace Cygnet { | |||
ResourceManager::ResourceManager(ResourceBuilder &&builder): | |||
rnd_(builder.rnd_), sprites_(std::move(builder.sprites_)), | |||
tile_anims_(std::move(builder.tile_anims_)) { | |||
tileAnims_(std::move(builder.tileAnims_)) { | |||
size_t width, height; | |||
const unsigned char *data = builder.atlas_.getImage(&width, &height); | |||
rnd_.uploadTileAtlas(data, width, height); | |||
@@ -18,7 +18,7 @@ ResourceManager::~ResourceManager() { | |||
void ResourceManager::tick() { | |||
// TODO: Maybe do a GPU->GPU copy instead of an upload from the CPU? | |||
for (auto &anim: tile_anims_) { | |||
for (auto &anim: tileAnims_) { | |||
anim.index = (anim.index + 1) % anim.frames; | |||
unsigned char *data = anim.data.get() + | |||
SwanCommon::TILE_SIZE * SwanCommon::TILE_SIZE * 4 * anim.index; |
@@ -49,12 +49,12 @@ public: | |||
void setTileID(RelPos pos, Tile::ID id, SDL_Texture *tex) { | |||
getTileData()[pos.y * CHUNK_WIDTH + pos.x] = id; | |||
draw_list_.push_back({ pos, tex }); | |||
drawList_.push_back({ pos, tex }); | |||
} | |||
void setTileData(RelPos pos, Tile::ID id) { | |||
getTileData()[pos.y * CHUNK_WIDTH + pos.x] = id; | |||
need_render_ = true; | |||
needRender_ = true; | |||
} | |||
uint8_t getLightLevel(RelPos pos) { | |||
@@ -63,7 +63,7 @@ public: | |||
void setLightData(const uint8_t *data) { | |||
memcpy(getLightData(), data, CHUNK_WIDTH * CHUNK_HEIGHT); | |||
need_light_render_ = true; | |||
needLightRender_ = true; | |||
} | |||
void render(const Context &ctx, SDL_Renderer *rnd); | |||
@@ -74,9 +74,9 @@ public: | |||
void draw(const Context &ctx, Win &win); | |||
TickAction tick(float dt); | |||
bool isActive() { return deactivate_timer_ > 0; } | |||
bool isActive() { return deactivateTimer_ > 0; } | |||
void keepActive(); | |||
void markModified() { is_modified_ = true; } | |||
void markModified() { isModified_ = true; } | |||
ChunkPos pos_; | |||
@@ -85,19 +85,19 @@ private: | |||
void renderList(SDL_Renderer *rnd); | |||
bool isCompressed() { return compressed_size_ != -1; } | |||
bool isCompressed() { return compressedSize_ != -1; } | |||
std::unique_ptr<uint8_t[]> data_; | |||
std::vector<std::pair<RelPos, SDL_Texture *>> draw_list_; | |||
std::vector<std::pair<RelPos, SDL_Texture *>> drawList_; | |||
ssize_t compressed_size_ = -1; // -1 if not compressed, a positive number if compressed | |||
bool need_render_ = false; | |||
bool need_light_render_ = false; | |||
float deactivate_timer_ = DEACTIVATE_INTERVAL; | |||
bool is_modified_ = false; | |||
ssize_t compressedSize_ = -1; // -1 if not compressed, a positive number if compressed | |||
bool needRender_ = false; | |||
bool needLightRender_ = false; | |||
float deactivateTimer_ = DEACTIVATE_INTERVAL; | |||
bool isModified_ = false; | |||
CPtr<SDL_Texture, SDL_DestroyTexture> texture_; | |||
CPtr<SDL_Texture, SDL_DestroyTexture> light_texture_; | |||
CPtr<SDL_Texture, SDL_DestroyTexture> lightTexture_; | |||
}; | |||
} |
@@ -146,7 +146,7 @@ inline EntityRef EntityCollection::spawn(Args&&... args) { | |||
template<typename Ent> | |||
inline Entity *EntityCollectionImpl<Ent>::get(size_t idx, size_t generation) { | |||
if (idx >=entities_.size()) | |||
if (idx >= entities_.size()) | |||
return nullptr; | |||
auto &e = entities_[idx]; |
@@ -17,49 +17,49 @@ class Game { | |||
public: | |||
Game(Win &win): | |||
win_(win), | |||
mouse_pos_(0, 0) {} | |||
mousePos_(0, 0) {} | |||
std::optional<ModWrapper> loadMod(std::string path, World &world); | |||
void createWorld(const std::string &worldgen, const std::vector<std::string> &mods); | |||
void onKeyDown(SDL_Keysym sym) { | |||
pressed_keys_[sym.scancode] = true; | |||
did_press_keys_[sym.scancode] = true; | |||
pressedKeys_[sym.scancode] = true; | |||
didPressKeys_[sym.scancode] = true; | |||
} | |||
void onKeyUp(SDL_Keysym sym) { | |||
pressed_keys_[sym.scancode] = false; | |||
did_release_keys_[sym.scancode] = true; | |||
pressedKeys_[sym.scancode] = false; | |||
didReleaseKeys_[sym.scancode] = true; | |||
} | |||
void onMouseMove(Sint32 x, Sint32 y) { | |||
mouse_pos_ = { x, y }; | |||
mousePos_ = { x, y }; | |||
} | |||
void onMouseDown(Sint32 x, Sint32 y, Uint8 button) { | |||
mouse_pos_ = { x, y }; | |||
pressed_buttons_[button] = true; | |||
did_press_buttons_[button] = true; | |||
mousePos_ = { x, y }; | |||
pressedButtons_[button] = true; | |||
didPressButtons_[button] = true; | |||
} | |||
void onMouseUp(Sint32 x, Sint32 y, Uint8 button) { | |||
mouse_pos_ = { x, y }; | |||
pressed_buttons_[button] = false; | |||
did_release_buttons_[button] = true; | |||
mousePos_ = { x, y }; | |||
pressedButtons_[button] = false; | |||
didReleaseButtons_[button] = true; | |||
} | |||
void onScrollWheel(Sint32 y) { | |||
did_scroll_ = (y > 0 ? 1 : -1 ); | |||
didScroll_ = (y > 0 ? 1 : -1 ); | |||
} | |||
bool isKeyPressed(SDL_Scancode code) { return pressed_keys_[code]; } | |||
bool wasKeyPressed(SDL_Scancode code) { return did_press_keys_[code]; } | |||
bool wasKeyReleased(SDL_Scancode code) { return did_release_keys_[code]; } | |||
Vec2i getMousePos() { return mouse_pos_; } | |||
bool isMousePressed(Uint8 button) { return pressed_buttons_[button]; } | |||
bool wasMousePressed(Uint8 button) { return did_press_buttons_[button]; } | |||
bool wasMouseReleased(Uint8 button) { return did_release_buttons_[button]; } | |||
int wasWheelScrolled() { return did_scroll_; } | |||
bool isKeyPressed(SDL_Scancode code) { return pressedKeys_[code]; } | |||
bool wasKeyPressed(SDL_Scancode code) { return didPressKeys_[code]; } | |||
bool wasKeyReleased(SDL_Scancode code) { return didReleaseKeys_[code]; } | |||
Vec2i getMousePos() { return mousePos_; } | |||
bool isMousePressed(Uint8 button) { return pressedButtons_[button]; } | |||
bool wasMousePressed(Uint8 button) { return didPressButtons_[button]; } | |||
bool wasMouseReleased(Uint8 button) { return didReleaseButtons_[button]; } | |||
int wasWheelScrolled() { return didScroll_; } | |||
TilePos getMouseTile(); | |||
@@ -69,22 +69,22 @@ public: | |||
void tick(float dt); | |||
std::unique_ptr<World> world_ = NULL; | |||
std::unique_ptr<ImageResource> invalid_image_ = NULL; | |||
std::unique_ptr<Tile> invalid_tile_ = NULL; | |||
std::unique_ptr<Item> invalid_item_ = NULL; | |||
std::unique_ptr<ImageResource> invalidImage_ = NULL; | |||
std::unique_ptr<Tile> invalidTile_ = NULL; | |||
std::unique_ptr<Item> invalidItem_ = NULL; | |||
Win &win_; | |||
private: | |||
std::bitset<SDL_NUM_SCANCODES> pressed_keys_; | |||
std::bitset<SDL_NUM_SCANCODES> did_press_keys_; | |||
std::bitset<SDL_NUM_SCANCODES> did_release_keys_; | |||
std::bitset<SDL_NUM_SCANCODES> pressedKeys_; | |||
std::bitset<SDL_NUM_SCANCODES> didPressKeys_; | |||
std::bitset<SDL_NUM_SCANCODES> didReleaseKeys_; | |||
Vec2i mouse_pos_; | |||
std::bitset<SDL_BUTTON_X2> pressed_buttons_; | |||
std::bitset<SDL_BUTTON_X2> did_press_buttons_; | |||
std::bitset<SDL_BUTTON_X2> did_release_buttons_; | |||
Vec2i mousePos_; | |||
std::bitset<SDL_BUTTON_X2> pressedButtons_; | |||
std::bitset<SDL_BUTTON_X2> didPressButtons_; | |||
std::bitset<SDL_BUTTON_X2> didReleaseButtons_; | |||
int did_scroll_ = 0; | |||
int didScroll_ = 0; | |||
}; | |||
} |
@@ -6,22 +6,21 @@ | |||
namespace Swan { | |||
// TODO: Switch to struct | |||
class Item { | |||
public: | |||
struct Builder { | |||
std::string name; | |||
std::string image; | |||
int max_stack = 64; | |||
int maxStack = 64; | |||
}; | |||
Item(const ResourceManager &resources, const Builder &builder): | |||
name_(builder.name), image_(resources.getImage(builder.image)), | |||
max_stack_(builder.max_stack) {} | |||
name(builder.name), image(resources.getImage(builder.image)), | |||
maxStack(builder.maxStack) {} | |||
const std::string name_; | |||
const ImageResource &image_; | |||
const int max_stack_; | |||
const std::string name; | |||
const ImageResource ℑ | |||
const int maxStack; | |||
static std::unique_ptr<Item> createInvalid(Context &ctx); | |||
@@ -32,8 +31,8 @@ public: | |||
// a complete ImageResource for a headless server, but for now, this will suffice. | |||
protected: | |||
Item(const Builder &builder): | |||
name_(builder.name), image_(*(ImageResource *)this), | |||
max_stack_(builder.max_stack) {} | |||
name(builder.name), image(*(ImageResource *)this), | |||
maxStack(builder.maxStack) {} | |||
}; | |||
} |
@@ -14,7 +14,7 @@ namespace Swan { | |||
struct NewLightChunk { | |||
std::bitset<CHUNK_WIDTH * CHUNK_HEIGHT> blocks; | |||
std::map<std::pair<int, int>, float> light_sources; | |||
std::map<std::pair<int, int>, float> lightSources; | |||
}; | |||
struct LightChunk { | |||
@@ -22,16 +22,16 @@ struct LightChunk { | |||
LightChunk(NewLightChunk &&ch); | |||
std::bitset<CHUNK_WIDTH * CHUNK_HEIGHT> blocks; | |||
uint8_t light_levels[CHUNK_WIDTH * CHUNK_HEIGHT] = { 0 }; | |||
float light_buffers[CHUNK_WIDTH * CHUNK_HEIGHT * 2] = { 0 }; | |||
uint8_t lightLevels[CHUNK_WIDTH * CHUNK_HEIGHT] = { 0 }; | |||
float lightBuffers[CHUNK_WIDTH * CHUNK_HEIGHT * 2] = { 0 }; | |||
int buffer = 0; | |||
uint8_t blocks_line[CHUNK_WIDTH] = { 0 }; | |||
std::map<std::pair<int, int>, float> light_sources; | |||
uint8_t blocksLine[CHUNK_WIDTH] = { 0 }; | |||
std::map<std::pair<int, int>, float> lightSources; | |||
std::vector<std::pair<TilePos, float>> bounces; | |||
float *light_buffer() { return light_buffers + CHUNK_WIDTH * CHUNK_HEIGHT * buffer; } | |||
float *lightBuffer() { return lightBuffers + CHUNK_WIDTH * CHUNK_HEIGHT * buffer; } | |||
bool was_updated = false; | |||
bool wasUpdated = false; | |||
}; | |||
class LightCallback { | |||
@@ -85,13 +85,13 @@ private: | |||
LightCallback &cb_; | |||
bool running_ = true; | |||
std::map<std::pair<int, int>, LightChunk> chunks_; | |||
std::set<std::pair<int, int>> updated_chunks_; | |||
LightChunk *cached_chunk_ = nullptr; | |||
Vec2i cached_chunk_pos_; | |||
std::set<std::pair<int, int>> updatedChunks_; | |||
LightChunk *cachedChunk_ = nullptr; | |||
Vec2i cachedChunkPos_; | |||
int buffer_ = 0; | |||
std::vector<Event> buffers_[2] = { {}, {} }; | |||
std::vector<NewLightChunk> new_chunk_buffers_[2] = { {}, {} }; | |||
std::vector<NewLightChunk> newChunkBuffers_[2] = { {}, {} }; | |||
std::thread thread_; | |||
std::condition_variable cond_; | |||
std::mutex mut_; | |||
@@ -124,8 +124,8 @@ inline void LightServer::onLightRemoved(TilePos pos, float level) { | |||
inline void LightServer::onChunkAdded(Vec2i pos, NewLightChunk &&chunk) { | |||
std::lock_guard<std::mutex> lock(mut_); | |||
buffers_[buffer_].push_back({ Event::Tag::CHUNK_ADDED, pos, | |||
{ .i = (int)new_chunk_buffers_[buffer_].size() } }); | |||
new_chunk_buffers_[buffer_].push_back(std::move(chunk)); | |||
{ .i = (int)newChunkBuffers_[buffer_].size() } }); | |||
newChunkBuffers_[buffer_].push_back(std::move(chunk)); | |||
cond_.notify_one(); | |||
} | |||
@@ -10,29 +10,28 @@ | |||
namespace Swan { | |||
// TODO: Switch to struct | |||
class Tile { | |||
struct Tile { | |||
public: | |||
using ID = uint16_t; | |||
struct Builder { | |||
std::string name; | |||
std::string image; | |||
bool is_solid = true; | |||
float light_level = 0; | |||
std::optional<std::string> dropped_item = std::nullopt; | |||
bool isSolid = true; | |||
float lightLevel = 0; | |||
std::optional<std::string> droppedItem = std::nullopt; | |||
}; | |||
Tile(const ResourceManager &resources, const Builder &builder): | |||
name_(builder.name), image_(resources.getImage(builder.image)), | |||
is_solid_(builder.is_solid), light_level_(builder.light_level), | |||
dropped_item_(builder.dropped_item) {} | |||
const std::string name_; | |||
const ImageResource &image_; | |||
const bool is_solid_; | |||
const float light_level_; | |||
const std::optional<std::string> dropped_item_; | |||
name(builder.name), image(resources.getImage(builder.image)), | |||
isSolid(builder.isSolid), lightLevel(builder.lightLevel), | |||
droppedItem(builder.droppedItem) {} | |||
const std::string name; | |||
const ImageResource ℑ | |||
const bool isSolid; | |||
const float lightLevel; | |||
const std::optional<std::string> droppedItem; | |||
static std::unique_ptr<Tile> createInvalid(const ResourceManager &ctx); | |||
static std::unique_ptr<Tile> createAir(const ResourceManager &ctx); |
@@ -31,7 +31,7 @@ public: | |||
void setCurrentPlane(WorldPlane &plane); | |||
WorldPlane &addPlane(const std::string &gen); | |||
WorldPlane &addPlane() { return addPlane(default_world_gen_); } | |||
WorldPlane &addPlane() { return addPlane(defaultWorldGen_); } | |||
Tile &getTileByID(Tile::ID id) { return *tiles_[id]; } | |||
Tile::ID getTileID(const std::string &name); | |||
@@ -45,19 +45,19 @@ public: | |||
// Event emitters | |||
EventEmitter<const Context &, TilePos, Tile &> | |||
evt_tile_break_; | |||
evtTileBreak_; | |||
// World owns all mods | |||
std::vector<ModWrapper> mods_; | |||
// World owns tiles and items, the mod just has Builder objects | |||
std::vector<std::unique_ptr<Tile>> tiles_; | |||
std::unordered_map<std::string, Tile::ID> tiles_map_; | |||
std::unordered_map<std::string, Tile::ID> tilesMap_; | |||
std::unordered_map<std::string, std::unique_ptr<Item>> items_; | |||
// Mods give us factories to create new world gens and new entity collections | |||
std::unordered_map<std::string, WorldGen::Factory> worldgen_factories_; | |||
std::vector<EntityCollection::Factory> ent_coll_factories_; | |||
std::unordered_map<std::string, WorldGen::Factory> worldgenFactories_; | |||
std::vector<EntityCollection::Factory> entCollFactories_; | |||
BodyTrait::Body *player_; | |||
Game *game_; | |||
@@ -71,10 +71,10 @@ private: | |||
void tick(WorldPlane &plane, ChunkPos abspos); | |||
}; | |||
ChunkRenderer chunk_renderer_; | |||
WorldPlane::ID current_plane_; | |||
ChunkRenderer chunkRenderer_; | |||
WorldPlane::ID currentPlane_; | |||
std::vector<std::unique_ptr<WorldPlane>> planes_; | |||
std::string default_world_gen_; | |||
std::string defaultWorldGen_; | |||
}; | |||
} |
@@ -91,14 +91,14 @@ private: | |||
std::unique_ptr<LightServer> lighting_; | |||
std::map<std::pair<int, int>, Chunk> chunks_; | |||
std::vector<Chunk *> active_chunks_; | |||
std::vector<std::pair<ChunkPos, Chunk *>> tick_chunks_; | |||
std::vector<std::unique_ptr<EntityCollection>> ent_colls_; | |||
std::unordered_map<std::type_index, EntityCollection *> ent_colls_by_type_; | |||
std::unordered_map<std::string, EntityCollection *> ent_colls_by_name_; | |||
std::deque<Chunk *> chunk_init_list_; | |||
std::vector<TilePos> debug_boxes_; | |||
std::vector<Chunk *> activeChunks_; | |||
std::vector<std::pair<ChunkPos, Chunk *>> tickChunks_; | |||
std::vector<std::unique_ptr<EntityCollection>> entColls_; | |||
std::unordered_map<std::type_index, EntityCollection *> entCollsByType_; | |||
std::unordered_map<std::string, EntityCollection *> entCollsByName_; | |||
std::deque<Chunk *> chunkInitList_; | |||
std::vector<TilePos> debugBoxes_; | |||
}; | |||
/* | |||
@@ -112,15 +112,15 @@ inline EntityRef WorldPlane::spawnEntity(Args&&... args) { | |||
template<typename Ent> | |||
inline EntityCollection &WorldPlane::getCollectionOf() { | |||
return *ent_colls_by_type_.at(typeid(Ent)); | |||
return *entCollsByType_.at(typeid(Ent)); | |||
} | |||
inline EntityCollection &WorldPlane::getCollectionOf(std::string name) { | |||
return *ent_colls_by_name_.at(name); | |||
return *entCollsByName_.at(name); | |||
} | |||
inline EntityCollection &WorldPlane::getCollectionOf(std::type_index type) { | |||
return *ent_colls_by_type_.at(type); | |||
return *entCollsByType_.at(type); | |||
} | |||
} |
@@ -74,17 +74,17 @@ private: | |||
class RenderTarget: NonCopyable { | |||
public: | |||
RenderTarget(SDL_Renderer *rnd, SDL_Texture *tex): rnd_(rnd) { | |||
prev_target_ = SDL_GetRenderTarget(rnd_); | |||
prevTarget_ = SDL_GetRenderTarget(rnd_); | |||
SDL_SetRenderTarget(rnd_, tex); | |||
} | |||
~RenderTarget() { | |||
SDL_SetRenderTarget(rnd_, prev_target_); | |||
SDL_SetRenderTarget(rnd_, prevTarget_); | |||
} | |||
private: | |||
SDL_Renderer *rnd_; | |||
SDL_Texture *prev_target_; | |||
SDL_Texture *prevTarget_; | |||
}; | |||
class TexLock: NonCopyable { |
@@ -26,11 +26,11 @@ public: | |||
}; | |||
Logger(std::ostream &os, std::string name, bool use_color = false, std::string color = ""): | |||
os_(os), name_(std::move(name)), use_color_(use_color), color_(std::move(color)) {} | |||
os_(os), name_(std::move(name)), useColor_(use_color), color_(std::move(color)) {} | |||
template<typename T> | |||
NewlineStream operator<<(const T &val) { | |||
if (use_color_) | |||
if (useColor_) | |||
os_ << color_ << name_ << "\033[0m: " << val; | |||
else | |||
os_ << name_ << ": " << val; | |||
@@ -40,7 +40,7 @@ public: | |||
private: | |||
std::ostream &os_; | |||
std::string name_; | |||
bool use_color_; | |||
bool useColor_; | |||
std::string color_; | |||
}; | |||
@@ -19,7 +19,7 @@ struct PhysicsTrait { | |||
struct Physics { | |||
Vec2 vel{}; | |||
Vec2 force{}; | |||
bool on_ground = false; | |||
bool onGround = false; | |||
void friction(Vec2 coef = Vec2(400, 50)); | |||
void gravity(float mass, Vec2 g = Vec2(0, 20)); |
@@ -33,7 +33,7 @@ void Chunk::compress() { | |||
memcpy(data_.get(), dest, destlen); | |||
texture_.reset(); | |||
compressed_size_ = destlen; | |||
compressedSize_ = destlen; | |||
info | |||
<< "Compressed chunk " << pos_ << " from " | |||
@@ -56,7 +56,7 @@ void Chunk::decompress() { | |||
uLongf destlen = DATA_SIZE; | |||
int ret = uncompress( | |||
dest.get(), &destlen, | |||
(Bytef *)data_.get(), compressed_size_); | |||
(Bytef *)data_.get(), compressedSize_); | |||
if (ret != Z_OK) { | |||
panic << "Decompressing chunk failed: " << ret; | |||
@@ -64,24 +64,24 @@ void Chunk::decompress() { | |||
} | |||
data_ = std::move(dest); | |||
need_render_ = true; | |||
needRender_ = true; | |||
info | |||
<< "Decompressed chunk " << pos_ << " from " | |||
<< compressed_size_ << " bytes to " | |||
<< compressedSize_ << " bytes to " | |||
<< DATA_SIZE << " bytes."; | |||
compressed_size_ = -1; | |||
compressedSize_ = -1; | |||
} | |||
void Chunk::renderLight(const Context &ctx, SDL_Renderer *rnd) { | |||
std::optional<RenderTarget> target; | |||
// The texture might not be created yet | |||
if (!light_texture_) { | |||
light_texture_.reset(SDL_CreateTexture( | |||
if (!lightTexture_) { | |||
lightTexture_.reset(SDL_CreateTexture( | |||
ctx.game.win_.renderer_, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, | |||
CHUNK_WIDTH, CHUNK_HEIGHT)); | |||
SDL_SetTextureBlendMode(light_texture_.get(), SDL_BLENDMODE_BLEND); | |||
SDL_SetTextureBlendMode(lightTexture_.get(), SDL_BLENDMODE_BLEND); | |||
target.emplace(rnd, texture_.get()); | |||
} else { | |||
@@ -89,7 +89,7 @@ void Chunk::renderLight(const Context &ctx, SDL_Renderer *rnd) { | |||
} | |||
// Fill light texture | |||
target.emplace(rnd, light_texture_.get()); | |||
target.emplace(rnd, lightTexture_.get()); | |||
RenderBlendMode mode(rnd, SDL_BLENDMODE_NONE); | |||
RenderDrawColor color(rnd, 0, 0, 0, 0); | |||
for (int y = 0; y < CHUNK_HEIGHT; ++y) { | |||
@@ -101,7 +101,7 @@ void Chunk::renderLight(const Context &ctx, SDL_Renderer *rnd) { | |||
} | |||
} | |||
need_light_render_ = false; | |||
needLightRender_ = false; | |||
} | |||
void Chunk::render(const Context &ctx, SDL_Renderer *rnd) { | |||
@@ -125,7 +125,7 @@ void Chunk::render(const Context &ctx, SDL_Renderer *rnd) { | |||
// We're caching tiles so we don't have to world.getTileByID() every time | |||
Tile::ID prevID = Tile::INVALID_ID; | |||
Tile *tile = ctx.game.invalid_tile_.get(); | |||
Tile *tile = ctx.game.invalidTile_.get(); | |||
// Fill tile texture | |||
for (int y = 0; y < CHUNK_HEIGHT; ++y) { | |||
@@ -137,11 +137,11 @@ void Chunk::render(const Context &ctx, SDL_Renderer *rnd) { | |||
} | |||
SDL_Rect dest{x * TILE_SIZE, y * TILE_SIZE, TILE_SIZE, TILE_SIZE}; | |||
SDL_RenderCopy(rnd, tile->image_.texture_.get(), nullptr, &dest); | |||
SDL_RenderCopy(rnd, tile->image.texture_.get(), nullptr, &dest); | |||
} | |||
} | |||
need_render_ = false; | |||
needRender_ = false; | |||
renderLight(ctx, rnd); | |||
} | |||
@@ -158,7 +158,7 @@ void Chunk::renderList(SDL_Renderer *rnd) { | |||
// When we FillRect, we must fill transparency. | |||
RenderDrawColor color(rnd, 0, 0, 0, 0); | |||
for (auto &[pos, tex]: draw_list_) { | |||
for (auto &[pos, tex]: drawList_) { | |||
SDL_Rect dest{pos.x * TILE_SIZE, pos.y * TILE_SIZE, TILE_SIZE, TILE_SIZE}; | |||
SDL_RenderFillRect(rnd, &dest); | |||
SDL_RenderCopy(rnd, tex, nullptr, &dest); | |||
@@ -170,16 +170,16 @@ void Chunk::draw(const Context &ctx, Win &win) { | |||
return; | |||
// The world plane is responsible for managing initial renders | |||
if (need_render_) | |||
if (needRender_) | |||
return; | |||
// We're responsible for the light level rendering though | |||
if (need_light_render_) | |||
if (needLightRender_) | |||
renderLight(ctx, win.renderer_); | |||
if (draw_list_.size() > 0) { | |||
if (drawList_.size() > 0) { | |||
renderList(win.renderer_); | |||
draw_list_.clear(); | |||
drawList_.clear(); | |||
} | |||
auto chunkpos = pos_ * Vec2i(CHUNK_WIDTH, CHUNK_HEIGHT); | |||
@@ -187,15 +187,15 @@ void Chunk::draw(const Context &ctx, Win &win) { | |||
win.showTexture(chunkpos, texture_.get(), &rect); | |||
SDL_Rect texrect{ 0, 0, CHUNK_WIDTH, CHUNK_HEIGHT }; | |||
win.showTexture(chunkpos, light_texture_.get(), &texrect, &rect); | |||
win.showTexture(chunkpos, lightTexture_.get(), &texrect, &rect); | |||
} | |||
Chunk::TickAction Chunk::tick(float dt) { | |||
assert(isActive()); | |||
deactivate_timer_ -= dt; | |||
if (deactivate_timer_ <= 0) { | |||
if (is_modified_) | |||
deactivateTimer_ -= dt; | |||
if (deactivateTimer_ <= 0) { | |||
if (isModified_) | |||
return TickAction::DEACTIVATE; | |||
else | |||
return TickAction::DELETE; | |||
@@ -205,7 +205,7 @@ Chunk::TickAction Chunk::tick(float dt) { | |||
} | |||
void Chunk::keepActive() { | |||
deactivate_timer_ = DEACTIVATE_INTERVAL; | |||
deactivateTimer_ = DEACTIVATE_INTERVAL; | |||
decompress(); | |||
} | |||
@@ -63,11 +63,11 @@ void Game::update(float dt) { | |||
else if (win_.zoom_ < 0.3) | |||
win_.zoom_ = 0.3; | |||
did_scroll_ = 0; | |||
did_press_keys_.reset(); | |||
did_release_keys_.reset(); | |||
did_press_buttons_.reset(); | |||
did_release_buttons_.reset(); | |||
didScroll_ = 0; | |||
didPressKeys_.reset(); | |||
didReleaseKeys_.reset(); | |||
didPressButtons_.reset(); | |||
didReleaseButtons_.reset(); | |||
} | |||
void Game::tick(float dt) { |
@@ -21,9 +21,9 @@ ItemStack ItemStack::insert(ItemStack st) { | |||
// Merge | |||
count_ += st.count_; | |||
if (count_ > item_->max_stack_) { | |||
st.count_ = count_ - item_->max_stack_; | |||
count_ = item_->max_stack_; | |||
if (count_ > item_->maxStack) { | |||
st.count_ = count_ - item_->maxStack; | |||
count_ = item_->maxStack; | |||
} else { | |||
st.count_ = 0; | |||
st.item_ = nullptr; |
@@ -48,11 +48,11 @@ static float attenuateSquared(float squareDist) { | |||
} | |||
LightChunk::LightChunk(NewLightChunk &&ch): | |||
blocks(std::move(ch.blocks)), light_sources(std::move(ch.light_sources)) { | |||
blocks(std::move(ch.blocks)), lightSources(std::move(ch.lightSources)) { | |||
for (int y = 0; y < CHUNK_HEIGHT; ++y) { | |||
for (int x = 0; x < CHUNK_WIDTH; ++x) { | |||
if (blocks[y * CHUNK_WIDTH + x]) { | |||
blocks_line[x] += 1; | |||
blocksLine[x] += 1; | |||
} | |||
} | |||
} | |||
@@ -79,14 +79,14 @@ bool LightServer::tileIsSolid(TilePos pos) { | |||
} | |||
LightChunk *LightServer::getChunk(ChunkPos cpos) { | |||
if (cached_chunk_ && cached_chunk_pos_ == cpos) { | |||
return cached_chunk_; | |||
if (cachedChunk_ && cachedChunkPos_ == cpos) { | |||
return cachedChunk_; | |||
} | |||
auto it = chunks_.find(cpos); | |||
if (it != chunks_.end()) { | |||
cached_chunk_ = &it->second; | |||
cached_chunk_pos_ = cpos; | |||
cachedChunk_ = &it->second; | |||
cachedChunkPos_ = cpos; | |||
return &it->second; | |||
} | |||
@@ -97,21 +97,21 @@ void LightServer::processEvent(const Event &evt, std::vector<NewLightChunk> &new | |||
auto markAdjacentChunksModified = [&](ChunkPos cpos) { | |||
for (int y = -1; y <= 1; ++y) { | |||
for (int x = -1; x <= 1; ++x) { | |||
updated_chunks_.insert(cpos + Vec2i(x, y)); | |||
updatedChunks_.insert(cpos + Vec2i(x, y)); | |||
} | |||
} | |||
}; | |||
auto markChunks = [&](ChunkPos cpos, Vec2i rpos, bool l, bool r, bool t, bool b) { | |||
updated_chunks_.insert(cpos); | |||
if (l) updated_chunks_.insert(cpos + Vec2i(-1, 0)); | |||
if (r) updated_chunks_.insert(cpos + Vec2i(1, 0)); | |||
if (t) updated_chunks_.insert(cpos + Vec2i(0, -1)); | |||
if (b) updated_chunks_.insert(cpos + Vec2i(0, 1)); | |||
if (l && t) updated_chunks_.insert(cpos + Vec2i(-1, -1)); | |||
if (r && t) updated_chunks_.insert(cpos + Vec2i(1, -1)); | |||
if (l && b) updated_chunks_.insert(cpos + Vec2i(-1, 1)); | |||
if (r && b) updated_chunks_.insert(cpos + Vec2i(1, 1)); | |||
updatedChunks_.insert(cpos); | |||
if (l) updatedChunks_.insert(cpos + Vec2i(-1, 0)); | |||
if (r) updatedChunks_.insert(cpos + Vec2i(1, 0)); | |||
if (t) updatedChunks_.insert(cpos + Vec2i(0, -1)); | |||
if (b) updatedChunks_.insert(cpos + Vec2i(0, 1)); | |||
if (l && t) updatedChunks_.insert(cpos + Vec2i(-1, -1)); | |||
if (r && t) updatedChunks_.insert(cpos + Vec2i(1, -1)); | |||
if (l && b) updatedChunks_.insert(cpos + Vec2i(-1, 1)); | |||
if (r && b) updatedChunks_.insert(cpos + Vec2i(1, 1)); | |||
}; | |||
auto markChunksModified = [&](ChunkPos cpos, Vec2i rpos, float light) { | |||
@@ -150,28 +150,28 @@ void LightServer::processEvent(const Event &evt, std::vector<NewLightChunk> &new | |||
switch (evt.tag) { | |||
case Event::Tag::BLOCK_ADDED: | |||
ch->blocks.set(rpos.y * CHUNK_WIDTH + rpos.x, true); | |||
ch->blocks_line[rpos.x] += 1; | |||
ch->blocksLine[rpos.x] += 1; | |||
markChunksModifiedRange(cpos, rpos, LIGHT_CUTOFF_DIST); | |||
break; | |||
case Event::Tag::BLOCK_REMOVED: | |||
ch->blocks.set(rpos.y * CHUNK_WIDTH + rpos.x, false); | |||
ch->blocks_line[rpos.x] -= 1; | |||
ch->blocksLine[rpos.x] -= 1; | |||
markChunksModifiedRange(cpos, rpos, LIGHT_CUTOFF_DIST); | |||
break; | |||
case Event::Tag::LIGHT_ADDED: | |||
info << cpos << ": Add " << evt.f << " light to " << rpos; | |||
ch->light_sources[rpos] += evt.f; | |||
markChunksModified(cpos, rpos, ch->light_sources[rpos]); | |||
ch->lightSources[rpos] += evt.f; | |||
markChunksModified(cpos, rpos, ch->lightSources[rpos]); | |||
break; | |||
case Event::Tag::LIGHT_REMOVED: | |||
info << cpos << ": Remove " << evt.f << " light to " << rpos; | |||
markChunksModified(cpos, rpos, ch->light_sources[rpos]); | |||
ch->light_sources[rpos] -= evt.f; | |||
if (ch->light_sources[rpos] < LIGHT_CUTOFF) { | |||
ch->light_sources.erase(rpos); | |||
markChunksModified(cpos, rpos, ch->lightSources[rpos]); | |||
ch->lightSources[rpos] -= evt.f; | |||
if (ch->lightSources[rpos] < LIGHT_CUTOFF) { | |||
ch->lightSources.erase(rpos); | |||
} | |||
break; | |||
@@ -319,14 +319,14 @@ void LightServer::processChunkSun(LightChunk &chunk, ChunkPos cpos) { | |||
} | |||
for (int rx = 0; rx < CHUNK_WIDTH; ++rx) { | |||
bool lit = light > 0 && tc && tc->blocks_line[rx] == 0 && !line[rx]; | |||
bool lit = light > 0 && tc && tc->blocksLine[rx] == 0 && !line[rx]; | |||
if (lit) { | |||
chunk.light_buffer()[ry * CHUNK_WIDTH + rx] = light; | |||
chunk.lightBuffer()[ry * CHUNK_WIDTH + rx] = light; | |||
if (chunk.blocks[ry * CHUNK_WIDTH + rx]) { | |||
line[rx] = true; | |||
} | |||
} else { | |||
chunk.light_buffer()[ry * CHUNK_WIDTH + rx] = 0; | |||
chunk.lightBuffer()[ry * CHUNK_WIDTH + rx] = 0; | |||
} | |||
} | |||
} | |||
@@ -336,7 +336,7 @@ void LightServer::processChunkLights(LightChunk &chunk, ChunkPos cpos) { | |||
TilePos base = cpos * Vec2i(CHUNK_WIDTH, CHUNK_HEIGHT); | |||
std::vector<std::pair<TilePos, float>> lights; | |||
for (auto &[pos, level]: chunk.light_sources) { | |||
for (auto &[pos, level]: chunk.lightSources) { | |||
lights.emplace_back(Vec2i(pos) + base, level); | |||
} | |||
@@ -346,7 +346,7 @@ void LightServer::processChunkLights(LightChunk &chunk, ChunkPos cpos) { | |||
} | |||
TilePos b = base + Vec2i(dx * CHUNK_WIDTH, dy * CHUNK_HEIGHT); | |||
for (auto &[pos, level]: chunk->light_sources) { | |||
for (auto &[pos, level]: chunk->lightSources) { | |||
lights.emplace_back(TilePos(pos) + b, level); | |||
} | |||
}; | |||
@@ -362,7 +362,7 @@ void LightServer::processChunkLights(LightChunk &chunk, ChunkPos cpos) { | |||
for (int y = 0; y < CHUNK_HEIGHT; ++y) { | |||
for (int x = 0; x < CHUNK_WIDTH; ++x) { | |||
float light = recalcTile(chunk, cpos, Vec2i(x, y), base, lights); | |||
chunk.light_buffer()[y * CHUNK_WIDTH + x] += light; | |||
chunk.lightBuffer()[y * CHUNK_WIDTH + x] += light; | |||
if (light > 0 && chunk.blocks[y * CHUNK_WIDTH + x]) { | |||
chunk.bounces.emplace_back(base + Vec2i(x, y), light * 0.1); | |||
@@ -399,8 +399,8 @@ void LightServer::processChunkBounces(LightChunk &chunk, ChunkPos cpos) { | |||
for (int y = 0; y < CHUNK_HEIGHT; ++y) { | |||
for (int x = 0; x < CHUNK_WIDTH; ++x) { | |||
float light = recalcTile(chunk, cpos, Vec2i(x, y), base, lights); | |||
float sum = chunk.light_buffer()[y * CHUNK_WIDTH + x] + light; | |||
chunk.light_buffer()[y * CHUNK_WIDTH + x] = sum; | |||
float sum = chunk.lightBuffer()[y * CHUNK_WIDTH + x] + light; | |||
chunk.lightBuffer()[y * CHUNK_WIDTH + x] = sum; | |||
} | |||
} | |||
} | |||
@@ -412,18 +412,18 @@ void LightServer::processChunkSmoothing(LightChunk &chunk, ChunkPos cpos) { | |||
LightChunk *rc = getChunk(cpos + Vec2i(1, 0)); | |||
auto getLight = [&](LightChunk &chunk, int x, int y) { | |||
return chunk.light_buffer()[y * CHUNK_WIDTH + x]; | |||
return chunk.lightBuffer()[y * CHUNK_WIDTH + x]; | |||
}; | |||
auto calc = [&](int x1, int x2, int y1, int y2, auto tf, auto bf, auto lf, auto rf) { | |||
float *dest = chunk.light_buffers + CHUNK_WIDTH * CHUNK_HEIGHT * ((chunk.buffer + 1) % 2); | |||
float *dest = chunk.lightBuffers + CHUNK_WIDTH * CHUNK_HEIGHT * ((chunk.buffer + 1) % 2); | |||
for (int y = y1; y < y2; ++y) { | |||
for (int x = x1; x < x2; ++x) { | |||
float t = tf(x, y); | |||
float b = bf(x, y); | |||
float l = lf(x, y); | |||
float r = rf(x, y); | |||
float light = chunk.light_buffer()[y * CHUNK_WIDTH + x]; | |||
float light = chunk.lightBuffer()[y * CHUNK_WIDTH + x]; | |||
int count = 1; | |||
if (t > light) { light += t; count += 1; } | |||
if (b > light) { light += b; count += 1; } | |||
@@ -443,7 +443,7 @@ void LightServer::processChunkSmoothing(LightChunk &chunk, ChunkPos cpos) { | |||
if (tc) { | |||
calc(1, CHUNK_WIDTH - 1, 0, 1, | |||
[&](int x, int y) { return tc->light_buffer()[(CHUNK_HEIGHT - 1) * CHUNK_WIDTH + x]; }, | |||
[&](int x, int y) { return tc->lightBuffer()[(CHUNK_HEIGHT - 1) * CHUNK_WIDTH + x]; }, | |||
[&](int x, int y) { return getLight(chunk, x, y + 1); }, | |||
[&](int x, int y) { return getLight(chunk, x - 1, y); }, | |||
[&](int x, int y) { return getLight(chunk, x + 1, y); }); | |||
@@ -452,7 +452,7 @@ void LightServer::processChunkSmoothing(LightChunk &chunk, ChunkPos cpos) { | |||
if (bc) { | |||
calc(1, CHUNK_WIDTH - 1, CHUNK_HEIGHT - 1, CHUNK_HEIGHT, | |||
[&](int x, int y) { return getLight(chunk, x, y - 1); }, | |||
[&](int x, int y) { return bc->light_buffer()[x]; }, | |||
[&](int x, int y) { return bc->lightBuffer()[x]; }, | |||
[&](int x, int y) { return getLight(chunk, x - 1, y); }, | |||
[&](int x, int y) { return getLight(chunk, x + 1, y); }); | |||
} | |||
@@ -461,7 +461,7 @@ void LightServer::processChunkSmoothing(LightChunk &chunk, ChunkPos cpos) { | |||
calc(0, 1, 1, CHUNK_HEIGHT - 1, | |||
[&](int x, int y) { return getLight(chunk, x, y - 1); }, | |||
[&](int x, int y) { return getLight(chunk, x, y + 1); }, | |||
[&](int x, int y) { return lc->light_buffer()[y * CHUNK_WIDTH + CHUNK_WIDTH - 1]; }, | |||
[&](int x, int y) { return lc->lightBuffer()[y * CHUNK_WIDTH + CHUNK_WIDTH - 1]; }, | |||
[&](int x, int y) { return getLight(chunk, x + 1, y); }); | |||
} | |||
@@ -470,47 +470,47 @@ void LightServer::processChunkSmoothing(LightChunk &chunk, ChunkPos cpos) { | |||
[&](int x, int y) { return getLight(chunk, x, y - 1); }, | |||
[&](int x, int y) { return getLight(chunk, x, y + 1); }, | |||
[&](int x, int y) { return getLight(chunk, x - 1, y); }, | |||
[&](int x, int y) { return rc->light_buffer()[y * CHUNK_WIDTH]; }); | |||
[&](int x, int y) { return rc->lightBuffer()[y * CHUNK_WIDTH]; }); | |||
} | |||
if (tc && lc) { | |||
calc(0, 1, 0, 1, | |||
[&](int x, int y) { return tc->light_buffer()[(CHUNK_HEIGHT - 1) * CHUNK_WIDTH + x]; }, | |||
[&](int x, int y) { return tc->lightBuffer()[(CHUNK_HEIGHT - 1) * CHUNK_WIDTH + x]; }, | |||
[&](int x, int y) { return getLight(chunk, x, y + 1); }, | |||
[&](int x, int y) { return lc->light_buffer()[y * CHUNK_WIDTH + CHUNK_WIDTH - 1]; }, | |||
[&](int x, int y) { return lc->lightBuffer()[y * CHUNK_WIDTH + CHUNK_WIDTH - 1]; }, | |||
[&](int x, int y) { return getLight(chunk, x + 1, y); }); | |||
} | |||
if (tc && rc) { | |||
calc(CHUNK_WIDTH - 1, CHUNK_WIDTH, 0, 1, | |||
[&](int x, int y) { return tc->light_buffer()[(CHUNK_HEIGHT - 1) * CHUNK_WIDTH + x]; }, | |||
[&](int x, int y) { return tc->lightBuffer()[(CHUNK_HEIGHT - 1) * CHUNK_WIDTH + x]; }, | |||
[&](int x, int y) { return getLight(chunk, x, y + 1); }, | |||
[&](int x, int y) { return getLight(chunk, x - 1, y); }, | |||
[&](int x, int y) { return rc->light_buffer()[y * CHUNK_WIDTH]; }); | |||
[&](int x, int y) { return rc->lightBuffer()[y * CHUNK_WIDTH]; }); | |||
} | |||
if (bc && lc) { | |||
calc(0, 1, CHUNK_HEIGHT - 1, CHUNK_HEIGHT, | |||
[&](int x, int y) { return getLight(chunk, x, y - 1); }, | |||
[&](int x, int y) { return bc->light_buffer()[x]; }, | |||
[&](int x, int y) { return lc->light_buffer()[y * CHUNK_WIDTH + CHUNK_WIDTH - 1]; }, | |||
[&](int x, int y) { return bc->lightBuffer()[x]; }, | |||
[&](int x, int y) { return lc->lightBuffer()[y * CHUNK_WIDTH + CHUNK_WIDTH - 1]; }, | |||
[&](int x, int y) { return getLight(chunk, x + 1, y); }); | |||
} | |||
if (bc && rc) { | |||
calc(CHUNK_WIDTH - 1, CHUNK_WIDTH, CHUNK_HEIGHT - 1, CHUNK_HEIGHT, | |||
[&](int x, int y) { return getLight(chunk, x, y - 1); }, | |||
[&](int x, int y) { return bc->light_buffer()[x]; }, | |||
[&](int x, int y) { return bc->lightBuffer()[x]; }, | |||
[&](int x, int y) { return getLight(chunk, x - 1, y); }, | |||
[&](int x, int y) { return rc->light_buffer()[y * CHUNK_WIDTH]; }); | |||
[&](int x, int y) { return rc->lightBuffer()[y * CHUNK_WIDTH]; }); | |||
} | |||
} | |||
void LightServer::finalizeChunk(LightChunk &chunk) { | |||
for (int y = 0; y < CHUNK_HEIGHT; ++y) { | |||
for (int x = 0; x < CHUNK_WIDTH; ++x) { | |||
chunk.light_levels[y * CHUNK_WIDTH + x] = | |||
linToSRGB(chunk.light_buffer()[y * CHUNK_HEIGHT + x]); | |||
chunk.lightLevels[y * CHUNK_WIDTH + x] = | |||
linToSRGB(chunk.lightBuffer()[y * CHUNK_HEIGHT + x]); | |||
} | |||
} | |||
} | |||
@@ -522,11 +522,11 @@ void LightServer::run() { | |||
cond_.wait(lock, [&] { return buffers_[buffer_].size() > 0 || !running_; }); | |||
std::vector<Event> &buf = buffers_[buffer_]; | |||
std::vector<NewLightChunk> &newChunks = new_chunk_buffers_[buffer_]; | |||
std::vector<NewLightChunk> &newChunks = newChunkBuffers_[buffer_]; | |||
buffer_ = (buffer_ + 1) % 2; | |||
lock.unlock(); | |||
updated_chunks_.clear(); | |||
updatedChunks_.clear(); | |||
for (auto &evt: buf) { | |||
processEvent(evt, newChunks); | |||
} | |||
@@ -536,21 +536,21 @@ void LightServer::run() { | |||
auto start = std::chrono::steady_clock::now(); | |||
for (auto &pos: updated_chunks_) { | |||
for (auto &pos: updatedChunks_) { | |||
auto ch = chunks_.find(pos); | |||
if (ch != chunks_.end()) { | |||
processChunkSun(ch->second, ChunkPos(pos.first, pos.second)); | |||
} | |||
} | |||
for (auto &pos: updated_chunks_) { | |||
for (auto &pos: updatedChunks_) { | |||
auto ch = chunks_.find(pos); | |||
if (ch != chunks_.end()) { | |||
processChunkLights(ch->second, ChunkPos(pos.first, pos.second)); | |||
} | |||
} | |||
for (auto &pos: updated_chunks_) { | |||
for (auto &pos: updatedChunks_) { | |||
auto ch = chunks_.find(pos); | |||
if (ch != chunks_.end()) { | |||
processChunkBounces(ch->second, ChunkPos(pos.first, pos.second)); | |||
@@ -558,7 +558,7 @@ void LightServer::run() { | |||
} | |||
for (int i = 0; i < 4; ++i) { | |||
for (auto &pos: updated_chunks_) { | |||
for (auto &pos: updatedChunks_) { | |||
auto ch = chunks_.find(pos); | |||
if (ch != chunks_.end()) { | |||
processChunkSmoothing(ch->second, ChunkPos(pos.first, pos.second)); | |||
@@ -567,7 +567,7 @@ void LightServer::run() { | |||
} | |||
} | |||
for (auto &pos: updated_chunks_) { | |||
for (auto &pos: updatedChunks_) { | |||
auto ch = chunks_.find(pos); | |||
if (ch != chunks_.end()) { | |||
finalizeChunk(ch->second); | |||
@@ -576,10 +576,10 @@ void LightServer::run() { | |||
auto end = std::chrono::steady_clock::now(); | |||
auto dur = std::chrono::duration<double, std::milli>(end - start); | |||
info << "Generating light for " << updated_chunks_.size() | |||
info << "Generating light for " << updatedChunks_.size() | |||
<< " chunks took " << dur.count() << "ms"; | |||
for (auto &pos: updated_chunks_) { | |||
for (auto &pos: updatedChunks_) { | |||
auto ch = chunks_.find(pos); | |||
if (ch != chunks_.end()) { | |||
cb_.onLightChunkUpdated(ch->second, pos); |
@@ -18,7 +18,7 @@ std::unique_ptr<Tile> Tile::createAir(const ResourceManager &resources) { | |||
return std::make_unique<Tile>(resources, Builder{ | |||
.name = "@::air", | |||
.image = "@::air", | |||
.is_solid = false, | |||
.isSolid = false, | |||
}); | |||
} | |||
@@ -19,17 +19,16 @@ static void chunkLine(int l, WorldPlane &plane, ChunkPos &abspos, const Vec2i &d | |||
World::World(Game *game, unsigned long rand_seed): | |||
game_(game), random_(rand_seed), resources_(game->win_) { | |||
std::unique_ptr<Tile> invalid_tile = Tile::createInvalid(resources_); | |||
tiles_map_[invalid_tile->name_] = 0; | |||
std::unique_ptr<Tile> invalidTile = Tile::createInvalid(resources_); | |||
tilesMap_[invalidTile->name] = 0; | |||
// tiles_ is empty, so pushing back now will ensure invalid_tile | |||
// ends up at location 0 | |||
tiles_.push_back(std::move(invalid_tile)); | |||
tiles_.push_back(std::move(invalidTile)); | |||
// We're also going to need an air tile at location 1 | |||
tiles_.push_back(Tile::createAir(resources_)); | |||
tiles_map_["@::air"] = 1; | |||
tilesMap_["@::air"] = 1; | |||
} | |||
void World::ChunkRenderer::tick(WorldPlane &plane, ChunkPos abspos) { | |||
@@ -56,52 +55,52 @@ void World::addMod(ModWrapper &&mod) { | |||
for (auto t: mod.buildTiles(resources_)) { | |||
Tile::ID id = tiles_.size(); | |||
tiles_map_[t->name_] = id; | |||
tilesMap_[t->name] = id; | |||
tiles_.push_back(std::move(t)); | |||
} | |||
for (auto i: mod.buildItems(resources_)) { | |||
items_[i->name_] = std::move(i); | |||
items_[i->name] = std::move(i); | |||
} | |||
for (auto fact: mod.getWorldGens()) { | |||
worldgen_factories_.emplace( | |||
worldgenFactories_.emplace( | |||
std::piecewise_construct, | |||
std::forward_as_tuple(fact.name), | |||
std::forward_as_tuple(fact)); | |||
} | |||
for (auto fact: mod.getEntities()) { | |||
ent_coll_factories_.push_back(fact); | |||
entCollFactories_.push_back(fact); | |||
} | |||
mods_.push_back(std::move(mod)); | |||
} | |||
void World::setWorldGen(std::string gen) { | |||
default_world_gen_ = std::move(gen); | |||
defaultWorldGen_ = std::move(gen); | |||
} | |||
void World::spawnPlayer() { | |||
player_ = &((dynamic_cast<BodyTrait *>( | |||
planes_[current_plane_]->spawnPlayer().get()))->get(BodyTrait::Tag{})); | |||
planes_[currentPlane_]->spawnPlayer().get()))->get(BodyTrait::Tag{})); | |||
} | |||
void World::setCurrentPlane(WorldPlane &plane) { | |||
current_plane_ = plane.id_; | |||
currentPlane_ = plane.id_; | |||
} | |||
WorldPlane &World::addPlane(const std::string &gen) { | |||
WorldPlane::ID id = planes_.size(); | |||
auto it = worldgen_factories_.find(gen); | |||
if (it == worldgen_factories_.end()) { | |||
auto it = worldgenFactories_.find(gen); | |||
if (it == worldgenFactories_.end()) { | |||
panic << "Tried to add plane with non-existant world gen " << gen << "!"; | |||
abort(); | |||
} | |||
std::vector<std::unique_ptr<EntityCollection>> colls; | |||
colls.reserve(ent_coll_factories_.size()); | |||
for (auto &fact: ent_coll_factories_) { | |||
colls.reserve(entCollFactories_.size()); | |||
for (auto &fact: entCollFactories_) { | |||
colls.emplace_back(fact.create(fact.name)); | |||
} | |||
@@ -116,15 +115,15 @@ Item &World::getItem(const std::string &name) { | |||
auto iter = items_.find(name); | |||
if (iter == items_.end()) { | |||
warn << "Tried to get non-existant item " << name << "!"; | |||
return *game_->invalid_item_; | |||
return *game_->invalidItem_; | |||
} | |||
return *iter->second; | |||
} | |||
Tile::ID World::getTileID(const std::string &name) { | |||
auto iter = tiles_map_.find(name); | |||
if (iter == tiles_map_.end()) { | |||
auto iter = tilesMap_.find(name); | |||
if (iter == tilesMap_.end()) { | |||
warn << "Tried to get non-existant item " << name << "!"; | |||
return Tile::INVALID_ID; | |||
} | |||
@@ -138,13 +137,13 @@ Tile &World::getTile(const std::string &name) { | |||
} | |||
SDL_Color World::backgroundColor() { | |||
return planes_[current_plane_]->backgroundColor(); | |||
return planes_[currentPlane_]->backgroundColor(); | |||
} | |||
void World::draw(Win &win) { | |||
ZoneScopedN("World draw"); | |||
win.cam_ = player_->pos - (win.getSize() / 2) + (player_->size / 2); | |||
planes_[current_plane_]->draw(win); | |||
planes_[currentPlane_]->draw(win); | |||
} | |||
void World::update(float dt) { | |||
@@ -158,8 +157,8 @@ void World::tick(float dt) { | |||
for (auto &plane: planes_) | |||
plane->tick(dt); | |||
chunk_renderer_.tick( | |||
*planes_[current_plane_], | |||
chunkRenderer_.tick( | |||
*planes_[currentPlane_], | |||
ChunkPos((int)player_->pos.x / CHUNK_WIDTH, (int)player_->pos.y / CHUNK_HEIGHT)); | |||
} | |||
@@ -47,16 +47,16 @@ WorldPlane::WorldPlane( | |||
std::vector<std::unique_ptr<EntityCollection>> &&colls): | |||
id_(id), world_(world), gen_(std::move(gen)), | |||
lighting_(std::make_unique<LightServer>(*this)), | |||
ent_colls_(std::move(colls)) { | |||
entColls_(std::move(colls)) { | |||
for (auto &coll: ent_colls_) { | |||
ent_colls_by_type_[coll->type()] = coll.get(); | |||
ent_colls_by_name_[coll->name()] = coll.get(); | |||
for (auto &coll: entColls_) { | |||
entCollsByType_[coll->type()] = coll.get(); | |||
entCollsByName_[coll->name()] = coll.get(); | |||
} | |||
} | |||
EntityRef WorldPlane::spawnEntity(const std::string &name, const Entity::PackObject &obj) { | |||
return ent_colls_by_name_.at(name)->spawn(getContext(), obj); | |||
return entCollsByName_.at(name)->spawn(getContext(), obj); | |||
} | |||
bool WorldPlane::hasChunk(ChunkPos pos) { | |||
@@ -66,13 +66,13 @@ bool WorldPlane::hasChunk(ChunkPos pos) { | |||
// This function will be a bit weird because it's a really fucking hot function. | |||
Chunk &WorldPlane::getChunk(ChunkPos pos) { | |||
// First, look through all chunks which have been in use this tick | |||
for (auto [chpos, chunk]: tick_chunks_) { | |||
for (auto [chpos, chunk]: tickChunks_) { | |||
if (chpos == pos) | |||
return *chunk; | |||
} | |||
Chunk &chunk = slowGetChunk(pos); | |||
tick_chunks_.push_back({ pos, &chunk }); | |||
tickChunks_.push_back({ pos, &chunk }); | |||
return chunk; | |||
} | |||
@@ -86,8 +86,8 @@ Chunk &WorldPlane::slowGetChunk(ChunkPos pos) { | |||
Chunk &chunk = iter->second; | |||
gen_->genChunk(*this, chunk); | |||
active_chunks_.push_back(&chunk); | |||
chunk_init_list_.push_back(&chunk); | |||
activeChunks_.push_back(&chunk); | |||
chunkInitList_.push_back(&chunk); | |||
// Need to tell the light engine too | |||
NewLightChunk lc; | |||
@@ -95,11 +95,11 @@ Chunk &WorldPlane::slowGetChunk(ChunkPos pos) { | |||
for (int x = 0; x < CHUNK_WIDTH; ++x) { | |||
Tile::ID id = chunk.getTileID({ x, y }); | |||
Tile &tile = world_->getTileByID(id); | |||
if (tile.is_solid_) { | |||
if (tile.isSolid) { | |||
lc.blocks[y * CHUNK_HEIGHT + x] = true; | |||
} | |||
if (tile.light_level_ > 0) { | |||
lc.light_sources[{ x, y }] = tile.light_level_; | |||
if (tile.lightLevel > 0) { | |||
lc.lightSources[{ x, y }] = tile.lightLevel; | |||
} | |||
} | |||
} | |||
@@ -109,8 +109,8 @@ Chunk &WorldPlane::slowGetChunk(ChunkPos pos) { | |||
// Otherwise, it might not be active, so let's activate it | |||
} else if (!iter->second.isActive()) { | |||
iter->second.keepActive(); | |||
active_chunks_.push_back(&iter->second); | |||
chunk_init_list_.push_back(&iter->second); | |||
activeChunks_.push_back(&iter->second); | |||
chunkInitList_.push_back(&iter->second); | |||
} | |||
return iter->second; | |||
@@ -124,22 +124,22 @@ void WorldPlane::setTileID(TilePos pos, Tile::ID id) { | |||
if (id != old) { | |||
Tile &newTile = world_->getTileByID(id); | |||
Tile &oldTile = world_->getTileByID(old); | |||
chunk.setTileID(rp, id, newTile.image_.texture_.get()); | |||
chunk.setTileID(rp, id, newTile.image.texture_.get()); | |||
chunk.markModified(); | |||
if (!oldTile.is_solid_ && newTile.is_solid_) { | |||
if (!oldTile.isSolid && newTile.isSolid) { | |||
lighting_->onSolidBlockAdded(pos); | |||
} else if (oldTile.is_solid_ && !newTile.is_solid_) { | |||
} else if (oldTile.isSolid && !newTile.isSolid) { | |||
lighting_->onSolidBlockRemoved(pos); | |||
} | |||
if (newTile.light_level_ != oldTile.light_level_) { | |||
if (oldTile.light_level_ > 0) { | |||
removeLight(pos, oldTile.light_level_); | |||
if (newTile.lightLevel != oldTile.lightLevel) { | |||
if (oldTile.lightLevel > 0) { | |||
removeLight(pos, oldTile.lightLevel); | |||
} | |||
if (newTile.light_level_ > 0) { | |||
addLight(pos, newTile.light_level_); | |||
if (newTile.lightLevel > 0) { | |||
addLight(pos, newTile.lightLevel); | |||
} | |||
} | |||
} | |||
@@ -196,7 +196,7 @@ void WorldPlane::breakTile(TilePos pos) { | |||
// Change tile to air and emit event | |||
setTileID(pos, air); | |||
world_->evt_tile_break_.emit(getContext(), pos, world_->getTileByID(id)); | |||
world_->evtTileBreak_.emit(getContext(), pos, world_->getTileByID(id)); | |||
} | |||
SDL_Color WorldPlane::backgroundColor() { | |||
@@ -216,9 +216,9 @@ void WorldPlane::draw(Win &win) { | |||
(int)floor(pbody.pos.y / CHUNK_HEIGHT)); | |||
// Just init one chunk per frame | |||
if (chunk_init_list_.size() > 0) { | |||
Chunk *chunk = chunk_init_list_.front(); | |||
chunk_init_list_.pop_front(); | |||
if (chunkInitList_.size() > 0) { | |||
Chunk *chunk = chunkInitList_.front(); | |||
chunkInitList_.pop_front(); | |||
chunk->render(ctx, win.renderer_); | |||
} | |||
@@ -230,11 +230,11 @@ void WorldPlane::draw(Win &win) { | |||
} | |||
} | |||
for (auto &coll: ent_colls_) | |||
for (auto &coll: entColls_) | |||
coll->draw(ctx, win); | |||
if (debug_boxes_.size() > 0) { | |||
for (auto &pos: debug_boxes_) { | |||
if (debugBoxes_.size() > 0) { | |||
for (auto &pos: debugBoxes_) { | |||
win.drawRect(pos, Vec2(1, 1)); | |||
} | |||
} | |||
@@ -244,9 +244,9 @@ void WorldPlane::update(float dt) { | |||
ZoneScopedN("WorldPlane update"); | |||
std::lock_guard<std::mutex> lock(mut_); | |||
auto ctx = getContext(); | |||
debug_boxes_.clear(); | |||
debugBoxes_.clear(); | |||
for (auto &coll: ent_colls_) | |||
for (auto &coll: entColls_) | |||
coll->update(ctx, dt); | |||
} | |||
@@ -256,16 +256,16 @@ void WorldPlane::tick(float dt) { | |||
auto ctx = getContext(); | |||
// Any chunk which has been in use since last tick should be kept alive | |||
for (std::pair<ChunkPos, Chunk *> &ch: tick_chunks_) | |||
for (std::pair<ChunkPos, Chunk *> &ch: tickChunks_) | |||
ch.second->keepActive(); | |||
tick_chunks_.clear(); | |||
tickChunks_.clear(); | |||
for (auto &coll: ent_colls_) | |||
for (auto &coll: entColls_) | |||
coll->tick(ctx, dt); | |||
// Tick all chunks, figure out if any of them should be deleted or compressed | |||
auto iter = active_chunks_.begin(); | |||
auto last = active_chunks_.end(); | |||
auto iter = activeChunks_.begin(); | |||
auto last = activeChunks_.end(); | |||
while (iter != last) { | |||
auto &chunk = *iter; | |||
auto action = chunk->tick(dt); | |||
@@ -274,14 +274,14 @@ void WorldPlane::tick(float dt) { | |||
case Chunk::TickAction::DEACTIVATE: | |||
info << "Compressing inactive modified chunk " << chunk->pos_; | |||
chunk->compress(); | |||
iter = active_chunks_.erase(iter); | |||
last = active_chunks_.end(); | |||
iter = activeChunks_.erase(iter); | |||
last = activeChunks_.end(); | |||
break; | |||
case Chunk::TickAction::DELETE: | |||
info << "Deleting inactive unmodified chunk " << chunk->pos_; | |||
chunks_.erase(chunk->pos_); | |||
iter = active_chunks_.erase(iter); | |||
last = active_chunks_.end(); | |||
iter = activeChunks_.erase(iter); | |||
last = activeChunks_.end(); | |||
break; | |||
case Chunk::TickAction::NOTHING: | |||
++iter; | |||
@@ -291,7 +291,7 @@ void WorldPlane::tick(float dt) { | |||
} | |||
void WorldPlane::debugBox(TilePos pos) { | |||
debug_boxes_.push_back(pos); | |||
debugBoxes_.push_back(pos); | |||
} | |||
void WorldPlane::addLight(TilePos pos, float level) { | |||
@@ -307,7 +307,7 @@ void WorldPlane::removeLight(TilePos pos, float level) { | |||
void WorldPlane::onLightChunkUpdated(const LightChunk &chunk, ChunkPos pos) { | |||
std::lock_guard<std::mutex> lock(mut_); | |||
Chunk &realChunk = getChunk(pos); | |||
realChunk.setLightData(chunk.light_levels); | |||
realChunk.setLightData(chunk.lightLevels); | |||
} | |||
} |
@@ -15,7 +15,7 @@ static void collideX( | |||
for (int y = (int)floor(body.top() + epsilon); y <= (int)floor(body.bottom() - epsilon); ++y) { | |||
int lx = (int)floor(body.left() + epsilon); | |||
Tile &left = plane.getTile({ lx, y }); | |||
if (left.is_solid_) { | |||
if (left.isSolid) { | |||
body.pos.x = (float)lx + 1.0; | |||
collided = true; | |||
break; | |||
@@ -23,7 +23,7 @@ static void collideX( | |||
int rx = (int)floor(body.right() - epsilon); | |||
Tile &right = plane.getTile({ rx, y }); | |||
if (right.is_solid_) { | |||
if (right.isSolid) { | |||
body.pos.x = (float)rx - body.size.x; | |||
collided = true; | |||
break; | |||
@@ -41,12 +41,12 @@ static void collideY( | |||
PhysicsTrait::Physics &phys, BodyTrait::Body &body, | |||
WorldPlane &plane, const PhysicsTrait::PhysicsProps &props) { | |||
bool collided = false; | |||
phys.on_ground = false; | |||
phys.onGround = false; | |||
for (int x = (int)floor(body.left() + epsilon); x <= (int)floor(body.right() - epsilon); ++x) { | |||
int ty = (int)floor(body.top() + epsilon); | |||
Tile &top = plane.getTile({ x, ty }); | |||
if (top.is_solid_) { | |||
if (top.isSolid) { | |||
body.pos.y = (float)ty + 1.0; | |||
collided = true; | |||
break; | |||
@@ -54,10 +54,10 @@ static void collideY( | |||
int by = (int)floor(body.bottom() - epsilon); | |||
Tile &bottom = plane.getTile({ x, by }); | |||
if (bottom.is_solid_) { | |||
if (bottom.isSolid) { | |||
body.pos.y = (float)by - body.size.y; | |||
collided = true; | |||
phys.on_ground = true; | |||
phys.onGround = true; | |||
break; | |||
} | |||
} |
@@ -40,12 +40,12 @@ test("Insert never overflows") { | |||
Swan::ItemStack s2(&item1, 40); | |||
s2 = s1.insert(s2); | |||
expecteq(s1.count(), item1.max_stack_); | |||
expecteq(s2.count(), 80 - item1.max_stack_); | |||
expecteq(s1.count(), item1.maxStack_); | |||
expecteq(s2.count(), 80 - item1.maxStack_); | |||
} | |||
test("Insert respects max_stack_") { | |||
MockItem item1({ .name = "item1", .image = "no", .max_stack = 20 }); | |||
MockItem item1({ .name = "item1", .image = "no", .maxStack = 20 }); | |||
Swan::ItemStack s1(&item1, 15); | |||
Swan::ItemStack s2(&item1, 19); |
@@ -9,17 +9,17 @@ | |||
namespace testlib { | |||
static const std::string color_reset = "\033[0m"; | |||
static const std::string color_highlight = "\033[1m"; | |||
static const std::string color_testing = color_highlight; | |||
static const std::string color_desc = "\033[33m"; | |||
static const std::string color_maybe = "\033[35m"; | |||
static const std::string color_success = "\033[32m"; | |||
static const std::string color_fail = "\033[31m"; | |||
static const std::string color_errormsg = "\033[95m"; | |||
static const std::string COLOR_RESET = "\033[0m"; | |||
static const std::string COLOR_HIGHLIGHT = "\033[1m"; | |||
static const std::string COLOR_TESTING = COLOR_HIGHLIGHT; | |||
static const std::string COLOR_DESC = "\033[33m"; | |||
static const std::string COLOR_MAYBE = "\033[35m"; | |||
static const std::string COLOR_SUCCESS = "\033[32m"; | |||
static const std::string COLOR_FAIL = "\033[31m"; | |||
static const std::string COLOR_ERRORMSG = "\033[95m"; | |||
std::string color(const std::string &color, std::string_view str) { | |||
return std::string(color) + std::string(str) + std::string(color_reset); | |||
return std::string(color) + std::string(str) + std::string(COLOR_RESET); | |||
} | |||
struct TestCase { | |||
@@ -57,8 +57,8 @@ void addTestCase(TestSpec *testcase) { | |||
static std::stringstream printFailure(const std::string &msg) { | |||
std::stringstream str; | |||
str | |||
<< "\r" << color(color_highlight + color_fail, "✕ ") | |||
<< color(color_fail, "Failed: ") << "\n" | |||
<< "\r" << color(COLOR_HIGHLIGHT + COLOR_FAIL, "✕ ") | |||
<< color(COLOR_FAIL, "Failed: ") << "\n" | |||
<< " " << msg << "\n"; | |||
return str; | |||
} | |||
@@ -91,13 +91,13 @@ int main() { | |||
if (currfile != testcase.filename) { | |||
currfile = testcase.filename; | |||
size_t lastslash = currfile.find_last_of('/'); | |||
std::cout << '\n' << color(color_testing, currfile.substr(lastslash + 1)) << ":\n"; | |||
std::cout << '\n' << color(COLOR_TESTING, currfile.substr(lastslash + 1)) << ":\n"; | |||
} | |||
std::cout | |||
<< color(color_highlight + color_maybe, "? ") | |||
<< color(color_maybe, "Testing: ") | |||
<< color(color_desc, testcase.description) << " " << std::flush; | |||
<< color(COLOR_HIGHLIGHT + COLOR_MAYBE, "? ") | |||
<< color(COLOR_MAYBE, "Testing: ") | |||
<< color(COLOR_DESC, testcase.description) << " " << std::flush; | |||
bool casefailed = false; | |||
@@ -105,9 +105,9 @@ int main() { | |||
totaltests += 1; | |||
testcase.func(); | |||
std::cout | |||
<< "\r" << color(color_highlight + color_success, "✓ ") | |||
<< color(color_success, "Success: ") | |||
<< color(color_desc, testcase.description) << "\n"; | |||
<< "\r" << color(COLOR_HIGHLIGHT + COLOR_SUCCESS, "✓ ") | |||
<< color(COLOR_SUCCESS, "Success: ") | |||
<< color(COLOR_DESC, testcase.description) << "\n"; | |||
totalsuccess += 1; | |||
} catch (const TestFailure &failure) { | |||
casefailed = true; |
@@ -54,7 +54,7 @@ int main() { | |||
png::image<png::rgb_pixel> image(Swan::CHUNK_WIDTH, Swan::CHUNK_HEIGHT); | |||
for (int y = 0; y < Swan::CHUNK_HEIGHT; ++y) { | |||
for (int x = 0; x < Swan::CHUNK_WIDTH; ++x) { | |||
uint8_t light = cb.chunk_.light_levels[y * Swan::CHUNK_WIDTH + x]; | |||
uint8_t light = cb.chunk_.lightLevels[y * Swan::CHUNK_WIDTH + x]; | |||
bool block = false; | |||
if (cb.chunk_.blocks[y * Swan::CHUNK_WIDTH + x]) { | |||
block = true; |
@@ -45,24 +45,24 @@ int sdlButtonToImGuiButton(uint8_t button) { | |||
} | |||
int main(int argc, char **argv) { | |||
uint32_t winflags = SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI; | |||
uint32_t renderflags = SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC; | |||
float gui_scale = 1; | |||
uint32_t winFlags = SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI; | |||
uint32_t renderFlags = SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC; | |||
float guiScale = 1; | |||
for (int i = 1; i < argc; ++i) { | |||
if (strcmp(argv[i], "--lodpi") == 0) { | |||
winflags &= ~SDL_WINDOW_ALLOW_HIGHDPI; | |||
winFlags &= ~SDL_WINDOW_ALLOW_HIGHDPI; | |||
} else if (strcmp(argv[i], "--fullscreen") == 0) { | |||
winflags |= SDL_WINDOW_FULLSCREEN_DESKTOP; | |||
winFlags |= SDL_WINDOW_FULLSCREEN_DESKTOP; | |||
} else if (strcmp(argv[i], "--no-vsync") == 0) { | |||
renderflags &= ~SDL_RENDERER_PRESENTVSYNC; | |||
renderFlags &= ~SDL_RENDERER_PRESENTVSYNC; | |||
} else if (strcmp(argv[i], "--vulkan") == 0) { | |||
winflags |= SDL_WINDOW_VULKAN; | |||
winFlags |= SDL_WINDOW_VULKAN; | |||
} else if (strcmp(argv[i], "--sw-render") == 0) { | |||
renderflags &= ~SDL_RENDERER_ACCELERATED; | |||
renderflags |= SDL_RENDERER_SOFTWARE; | |||
renderFlags &= ~SDL_RENDERER_ACCELERATED; | |||
renderFlags |= SDL_RENDERER_SOFTWARE; | |||
} else if (strcmp(argv[i], "--2x") == 0) { | |||
gui_scale = 2; | |||
guiScale = 2; | |||
} else if (strcmp(argv[i], "--gles") == 0) { | |||
SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengles2"); | |||
} else { | |||
@@ -73,16 +73,16 @@ int main(int argc, char **argv) { | |||
sdlassert(SDL_Init(SDL_INIT_VIDEO) >= 0, "Could not initialize SDL"); | |||
Deferred<SDL_Quit> sdl; | |||
int imgflags = IMG_INIT_PNG; | |||
imgassert(IMG_Init(imgflags) == imgflags, "Could not initialize SDL_Image"); | |||
Deferred<IMG_Quit> sdl_image; | |||
int imgFlags = IMG_INIT_PNG; | |||
imgassert(IMG_Init(imgFlags) == imgFlags, "Could not initialize SDL_Image"); | |||
Deferred<IMG_Quit> sdlImage; | |||
// Create the window | |||
CPtr<SDL_Window, SDL_DestroyWindow> window( | |||
SDL_CreateWindow( | |||
"Project: SWAN", | |||
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, | |||
(int)(640 * gui_scale), (int)(480 * gui_scale), winflags)); | |||
(int)(640 * guiScale), (int)(480 * guiScale), winFlags)); | |||
// Load and display application icon | |||
CPtr<SDL_Surface, SDL_FreeSurface> icon( | |||
@@ -91,40 +91,40 @@ int main(int argc, char **argv) { | |||
SDL_SetWindowIcon(window.get(), icon.get()); | |||
CPtr<SDL_Renderer, SDL_DestroyRenderer> renderer( | |||
SDL_CreateRenderer(window.get(), -1, renderflags)); | |||
SDL_CreateRenderer(window.get(), -1, renderFlags)); | |||
sdlassert(renderer, "Could not create renderer"); | |||
SDL_SetRenderDrawBlendMode(renderer.get(), SDL_BLENDMODE_BLEND); | |||
SDL_SetRenderDrawColor(renderer.get(), 0, 0, 0, 255); | |||
Win win(window.get(), renderer.get(), gui_scale); | |||
Win win(window.get(), renderer.get(), guiScale); | |||
// Init ImGUI and ImGUI_SDL | |||
IMGUI_CHECKVERSION(); | |||
CPtr<ImGuiContext, ImGui::DestroyContext> context( | |||
ImGui::CreateContext()); | |||
ImGuiSDL::Initialize(renderer.get(), (int)win.getPixSize().x, (int)win.getPixSize().y); | |||
Deferred<ImGuiSDL::Deinitialize> imgui_sdl; | |||
Deferred<ImGuiSDL::Deinitialize> imguiSDL; | |||
info << "Initialized with window size " << win.getPixSize(); | |||
// ImGuiIO is to glue SDL and ImGUI together | |||
ImGuiIO& imgui_io = ImGui::GetIO(); | |||
imgui_io.BackendPlatformName = "imgui_sdl + Project: SWAN"; | |||
ImGuiIO& imguiIO = ImGui::GetIO(); | |||
imguiIO.BackendPlatformName = "imgui_sdl + Project: SWAN"; | |||
// Create a world | |||
Game game(win); | |||
std::vector<std::string> mods{ "core.mod" }; | |||
game.createWorld("core::default", mods); | |||
auto prev_time = std::chrono::steady_clock::now(); | |||
auto prevTime = std::chrono::steady_clock::now(); | |||
float fps_acc = 0; | |||
float tick_acc = 0; | |||
float fpsAcc = 0; | |||
float tickAcc = 0; | |||
int fcount = 0; | |||
int slow_frames = 0; | |||
int fCount = 0; | |||
int slowFrames = 0; | |||
while (1) { | |||
ZoneScopedN("game loop"); | |||
RTClock total_time_clock; | |||
RTClock totalTimeClock; | |||
SDL_Event evt; | |||
while (SDL_PollEvent(&evt)) { | |||
@@ -135,8 +135,8 @@ int main(int argc, char **argv) { | |||
case SDL_WINDOWEVENT: | |||
if (evt.window.event == SDL_WINDOWEVENT_RESIZED) { | |||
imgui_io.DisplaySize.x = (float)evt.window.data1; | |||
imgui_io.DisplaySize.y = (float)evt.window.data2; | |||
imguiIO.DisplaySize.x = (float)evt.window.data1; | |||
imguiIO.DisplaySize.y = (float)evt.window.data2; | |||
win.onResize(evt.window.data1, evt.window.data2); | |||
} | |||
break; | |||
@@ -150,64 +150,64 @@ int main(int argc, char **argv) { | |||
break; | |||
case SDL_MOUSEMOTION: | |||
imgui_io.MousePos.x = (float)evt.motion.x; | |||
imgui_io.MousePos.y = (float)evt.motion.y; | |||
if (!imgui_io.WantCaptureMouse) | |||
imguiIO.MousePos.x = (float)evt.motion.x; | |||
imguiIO.MousePos.y = (float)evt.motion.y; | |||
if (!imguiIO.WantCaptureMouse) | |||
game.onMouseMove(evt.motion.x, evt.motion.y); | |||
break; | |||
case SDL_MOUSEBUTTONDOWN: | |||
imgui_io.MouseDown[sdlButtonToImGuiButton(evt.button.button)] = true; | |||
if (!imgui_io.WantCaptureMouse) | |||
imguiIO.MouseDown[sdlButtonToImGuiButton(evt.button.button)] = true; | |||
if (!imguiIO.WantCaptureMouse) | |||
game.onMouseDown(evt.button.x, evt.button.y, evt.button.button); | |||
break; | |||
case SDL_MOUSEBUTTONUP: | |||
imgui_io.MouseDown[sdlButtonToImGuiButton(evt.button.button)] = false; | |||
if (!imgui_io.WantCaptureMouse) | |||
imguiIO.MouseDown[sdlButtonToImGuiButton(evt.button.button)] = false; | |||
if (!imguiIO.WantCaptureMouse) | |||
game.onMouseUp(evt.button.x, evt.button.y, evt.button.button); | |||
break; | |||
case SDL_MOUSEWHEEL: | |||
imgui_io.MouseWheel += (float)evt.wheel.y; | |||
if (!imgui_io.WantCaptureMouse) | |||
imguiIO.MouseWheel += (float)evt.wheel.y; | |||
if (!imguiIO.WantCaptureMouse) | |||
game.onScrollWheel(evt.wheel.y); | |||
break; | |||
} | |||
} | |||
auto now = std::chrono::steady_clock::now(); | |||
std::chrono::duration<float> dur(now - prev_time); | |||
prev_time = now; | |||
std::chrono::duration<float> dur(now - prevTime); | |||
prevTime = now; | |||
float dt = dur.count(); | |||
// Display FPS | |||
fps_acc += dt; | |||
fcount += 1; | |||
if (fps_acc >= 4) { | |||
info << "FPS: " << fcount / 4.0; | |||
fps_acc -= 4; | |||
fcount = 0; | |||
fpsAcc += dt; | |||
fCount += 1; | |||
if (fpsAcc >= 4) { | |||
info << "FPS: " << fCount / 4.0; | |||
fpsAcc -= 4; | |||
fCount = 0; | |||
} | |||
// We want to warn if one frame takes over 0.1 seconds... | |||
if (dt > 0.1) { | |||
if (slow_frames == 0) | |||
if (slowFrames == 0) | |||
warn << "Delta time too high! (" << dt << "s)"; | |||
slow_frames += 1; | |||
slowFrames += 1; | |||
// And we never want to do physics as if our one frame is greater than | |||
// 0.5 seconds. | |||
if (dt > 0.5) | |||
dt = 0.5; | |||
} else if (slow_frames > 0) { | |||
if (slow_frames > 1) | |||
warn << slow_frames << " consecutive slow frames."; | |||
slow_frames = 0; | |||
} else if (slowFrames > 0) { | |||
if (slowFrames > 1) | |||
warn << slowFrames << " consecutive slow frames."; | |||
slowFrames = 0; | |||
} | |||
// Simple case: we can keep up, only need one physics update | |||
RTClock update_clock; | |||
RTClock updateClock; | |||
if (dt <= 1 / 25.0) { | |||
ZoneScopedN("game update"); | |||
game.update(dt); | |||
@@ -226,10 +226,10 @@ int main(int argc, char **argv) { | |||
} | |||
// Tick at a consistent TICK_RATE | |||
tick_acc += dt; | |||
while (tick_acc >= 1.0 / TICK_RATE) { | |||
tickAcc += dt; | |||
while (tickAcc >= 1.0 / TICK_RATE) { | |||
ZoneScopedN("game tick"); | |||
tick_acc -= 1.0 / TICK_RATE; | |||
tickAcc -= 1.0 / TICK_RATE; | |||
RTClock tick_clock; | |||
game.tick(1.0 / TICK_RATE); | |||
} | |||
@@ -241,12 +241,12 @@ int main(int argc, char **argv) { | |||
} | |||
// ImGUI | |||
imgui_io.DeltaTime = dt; | |||
imguiIO.DeltaTime = dt; | |||
ImGui::NewFrame(); | |||
{ | |||
ZoneScopedN("game draw"); | |||
RTClock draw_clock; | |||
RTClock drawClock; | |||
game.draw(); | |||
} | |||
@@ -257,7 +257,7 @@ int main(int argc, char **argv) { | |||
ImGuiSDL::Render(ImGui::GetDrawData()); | |||
} | |||
RTClock present_clock; | |||
RTClock presentClock; | |||
{ | |||
ZoneScopedN("render present"); | |||
SDL_RenderPresent(renderer.get()); |
@@ -3,11 +3,11 @@ | |||
#include <PerlinNoise/PerlinNoise.hpp> | |||
#include <png++/png.hpp> | |||
static int grassLevel(const siv::PerlinNoise &perlin, int x) { | |||
static int getGrassLevel(const siv::PerlinNoise &perlin, int x) { | |||
return (int)(perlin.noise(x / 50.0, 0) * 13); | |||
} | |||
static int stoneLevel(const siv::PerlinNoise &perlin, int x) { | |||
static int getStoneLevel(const siv::PerlinNoise &perlin, int x) { | |||
return (int)(perlin.noise(x / 50.0, 10) * 10) + 10; | |||
} | |||
@@ -24,25 +24,25 @@ int main() { | |||
for (int x = x1; x <= x2; ++x) { | |||
int px = x - x1; | |||
int grass_level = grassLevel(perlin, x); | |||
int stone_level = stoneLevel(perlin, x); | |||
int grassLevel = getGrassLevel(perlin, x); | |||
int stoneLevel = getStoneLevel(perlin, x); | |||
for (int y = y1; y <= y2; ++y) { | |||
int py = y - y1; | |||
if (y > grass_level + 10) { | |||
if (y > grassLevel + 10) { | |||
double l = perlin.noise(x / 41.37, y / 16.37); | |||
if (l > 0.2) | |||
image[py][px] = 255; | |||
else | |||
image[py][px] = 0; | |||
} else if (y >= grass_level) { | |||
} else if (y >= grassLevel) { | |||
image[py][px] = 0; | |||
} else { | |||
image[py][px] = 255; | |||
} | |||
if (y == grass_level) { | |||
if (y == grassLevel) { | |||
image[py][px] = 128; | |||
} | |||
} |