#include <string> | #include <string> | ||||
#include <optional> | #include <optional> | ||||
#include "common.h" | |||||
namespace Swan { | namespace Swan { | ||||
struct Tile { | struct Tile { | ||||
std::string name; | std::string name; | ||||
std::string image; | std::string image; | ||||
bool isSolid = true; | bool isSolid = true; | ||||
bool isOpaque = isSolid; | |||||
float lightLevel = 0; | float lightLevel = 0; | ||||
std::optional<std::string> droppedItem = std::nullopt; | std::optional<std::string> droppedItem = std::nullopt; | ||||
void (*onSpawn)(const Context &ctx, TilePos pos) = nullptr; | |||||
}; | }; | ||||
const ID id; | const ID id; | ||||
const std::string name; | const std::string name; | ||||
const bool isSolid; | const bool isSolid; | ||||
const bool isOpaque; | |||||
const float lightLevel; | const float lightLevel; | ||||
const std::optional<std::string> droppedItem; | const std::optional<std::string> droppedItem; | ||||
void (*const onSpawn)(const Context &ctx, TilePos pos); | |||||
Tile(ID id, std::string name, const Builder &builder): | Tile(ID id, std::string name, const Builder &builder): | ||||
id(id), name(name), | id(id), name(name), | ||||
isSolid(builder.isSolid), lightLevel(builder.lightLevel), | |||||
droppedItem(builder.droppedItem) {} | |||||
isSolid(builder.isSolid), isOpaque(builder.isOpaque), | |||||
lightLevel(builder.lightLevel), | |||||
droppedItem(builder.droppedItem), onSpawn(builder.onSpawn) {} | |||||
}; | }; | ||||
} | } |
// These things get initialized in the ctor. | // These things get initialized in the ctor. | ||||
// the above members must be initialized before these. | // the above members must be initialized before these. | ||||
Game *game_; // TODO: reference, not pointer | |||||
Game *game_; | |||||
std::mt19937 random_; | std::mt19937 random_; | ||||
std::vector<ModWrapper> mods_; | std::vector<ModWrapper> mods_; | ||||
Cygnet::ResourceManager resources_; | Cygnet::ResourceManager resources_; |
#include <chrono> | #include <chrono> | ||||
#include <type_traits> | #include <type_traits> | ||||
#include <string> | #include <string> | ||||
#include <stddef.h> | |||||
#include <cstddef> | |||||
#include <cstdint> | |||||
namespace Swan { | namespace Swan { | ||||
inline uint32_t random(uint32_t x) { | |||||
x ^= 0x55555555u; | |||||
x = ((x >> 16u) ^ x) * 0x45d9f3bu; | |||||
x = ((x >> 16u) ^ x) * 0x45d9f3bu; | |||||
x = (x >> 16u) ^ x; | |||||
return x; | |||||
} | |||||
// Inherit from this class to make a class non-copyable | // Inherit from this class to make a class non-copyable | ||||
class NonCopyable { | class NonCopyable { | ||||
public: | public: |
for (int x = 0; x < CHUNK_WIDTH; ++x) { | for (int x = 0; x < CHUNK_WIDTH; ++x) { | ||||
Tile::ID id = chunk.getTileID({ x, y }); | Tile::ID id = chunk.getTileID({ x, y }); | ||||
Tile &tile = world_->getTileByID(id); | Tile &tile = world_->getTileByID(id); | ||||
if (tile.isSolid) { | |||||
if (tile.isOpaque) { | |||||
lc.blocks[y * CHUNK_HEIGHT + x] = true; | lc.blocks[y * CHUNK_HEIGHT + x] = true; | ||||
} | } | ||||
if (tile.lightLevel > 0) { | if (tile.lightLevel > 0) { | ||||
Tile &oldTile = world_->getTileByID(old); | Tile &oldTile = world_->getTileByID(old); | ||||
chunk.setTileID(rp, id); | chunk.setTileID(rp, id); | ||||
if (!oldTile.isSolid && newTile.isSolid) { | |||||
if (!oldTile.isOpaque && newTile.isOpaque) { | |||||
lighting_->onSolidBlockAdded(pos); | lighting_->onSolidBlockAdded(pos); | ||||
} else if (oldTile.isSolid && !newTile.isSolid) { | |||||
} else if (oldTile.isOpaque && !newTile.isOpaque) { | |||||
lighting_->onSolidBlockRemoved(pos); | lighting_->onSolidBlockRemoved(pos); | ||||
} | } | ||||
addLight(pos, newTile.lightLevel); | addLight(pos, newTile.lightLevel); | ||||
} | } | ||||
} | } | ||||
if (newTile.onSpawn) { | |||||
newTile.onSpawn(getContext(), pos); | |||||
} | |||||
} | } | ||||
} | } | ||||
(int)floor(pbody.pos.x / CHUNK_WIDTH), | (int)floor(pbody.pos.x / CHUNK_WIDTH), | ||||
(int)floor(pbody.pos.y / CHUNK_HEIGHT)); | (int)floor(pbody.pos.y / CHUNK_HEIGHT)); | ||||
// Just init one chunk per frame | |||||
if (chunkInitList_.size() > 0) { | |||||
/* | |||||
Chunk *chunk = chunkInitList_.front(); | |||||
chunkInitList_.pop_front(); | |||||
chunk->render(ctx, win.renderer_); | |||||
TODO */ | |||||
} | |||||
for (int x = -1; x <= 1; ++x) { | for (int x = -1; x <= 1; ++x) { | ||||
for (int y = -1; y <= 1; ++y) { | for (int y = -1; y <= 1; ++y) { | ||||
auto iter = chunks_.find(pcpos + ChunkPos(x, y)); | auto iter = chunks_.find(pcpos + ChunkPos(x, y)); | ||||
auto ctx = getContext(); | auto ctx = getContext(); | ||||
debugBoxes_.clear(); | debugBoxes_.clear(); | ||||
// Just init one chunk per frame | |||||
if (chunkInitList_.size() > 0) { | |||||
Chunk *chunk = chunkInitList_.front(); | |||||
chunkInitList_.pop_front(); | |||||
TilePos base = chunk->pos_ * Vec2i{CHUNK_WIDTH, CHUNK_HEIGHT}; | |||||
for (int y = 0; y < CHUNK_HEIGHT; ++y) { | |||||
for (int x = 0; x < CHUNK_WIDTH; ++x) { | |||||
Tile::ID id = chunk->getTileID({x, y}); | |||||
Tile &tile = world_->getTileByID(id); | |||||
if (tile.onSpawn) { | |||||
tile.onSpawn(getContext(), base + Vec2i{x, y}); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
for (auto &coll: entColls_) | for (auto &coll: entColls_) | ||||
coll->update(ctx, dt); | coll->update(ctx, dt); | ||||
} | } |