Added Sand, Water, Lava Tiles physics.

This commit is contained in:
2024-12-31 00:41:08 -05:00
parent 534ae32f36
commit e3b8901bcd
7 changed files with 183 additions and 27 deletions

View File

@@ -29,7 +29,6 @@ namespace CaveGame::Core
~Chunk()
{
}
/// Constructs a chunk with empty (air) tiles, located at the given chunk-cell.
@@ -53,7 +52,18 @@ namespace CaveGame::Core
}
TileID GetTile(int x, int y) const;
void SetTile(int x, int y, TileID t);
void SetTile(int x, int y, TileID t, bool trigger_tile_updates = true);
void SetTileSilent(int x, int y, TileID t)
{ SetTile(x, y, t, false); }
bool GetTileUpdateFlag(int x, int y) const {
return tagged_for_update[x][y];
}
void SetTileUpdateFlag(int x, int y, bool flag = true) {
tagged_for_update[x][y] = flag;
}
[[nodiscard]] Vector2 GetChunkCell() const;
[[nodiscard]] Vector2 GetChunkRealCoordinates() const;
@@ -101,6 +111,7 @@ namespace CaveGame::Core
protected:
Vector2 cell;
TileID tiles[ChunkSize][ChunkSize];
bool tagged_for_update[ChunkSize][ChunkSize];
};
}

View File

@@ -12,21 +12,15 @@ namespace CaveGame::Core
public:
virtual TileID GetTile(int x, int y) const = 0;
virtual void SetTile(int x, int y, TileID tile) = 0;
virtual bool GetTileUpdateFlag(int x, int y) = 0;
virtual void SetTileUpdateFlag(int x, int y, bool flag = true) = 0;
virtual TileState GetTileState(int x, int y) const = 0;
virtual void SetTileState(int x, int y, TileState state) = 0;
bool GrassSpreadable(int x, int y) const;
bool IsNonSolidTile(int x, int y) const;
bool GrassShouldSuffocate(int x, int y) const;
bool IsSolidTile(int x, int y) const;
bool HasAdjacentOrDiagonalAirBlock(int x, int y) const;
bool HasAdjacentAirBlock(int x, int y) const;
};
}

View File

@@ -135,6 +135,7 @@ namespace CaveGame::Core
[[nodiscard]] std::string MnemonicID() const;
std::string Name() const { return mnemonic_id; }
virtual bool DoesRandomTicc() const { return false; }
virtual bool DoesForcedTicc() const { return false;}
virtual bool Solid() const { return false;}
virtual void ForcedTicc(ITileMap* world, TileState state, int x, int y) {}
virtual void RandomTicc(ITileMap* world, TileState state, int x, int y) {}
@@ -152,6 +153,39 @@ namespace CaveGame::Core
LiquidTile(TileID id, const std::string& name, const Color4& color, const std::vector<Color4>& pallet);
LiquidTile(TileID numeric, const std::string& name, Color4 color);
bool Solid() const override { return true;}
bool DoesForcedTicc() const override { return true;}
void ForcedTicc(ITileMap *world, TileState state, int x, int y) override {
if (world->GetTile(x, y+1) == TileID::AIR) {
world->SetTile(x, y+1, numeric_id);
world->SetTile(x, y, TileID::AIR);
return;
}
if (world->GetTile(x+1, y+1) == TileID::AIR) {
world->SetTile(x+1, y+1, numeric_id);
world->SetTile(x, y, TileID::AIR);
return;
}
if (world->GetTile(x-1, y+1) == TileID::AIR) {
world->SetTile(x-1, y+1, numeric_id);
world->SetTile(x, y, TileID::AIR);
return;
}
if (world->GetTile(x-1, y) == TileID::AIR) {
world->SetTile(x-1, y, numeric_id);
world->SetTile(x, y, TileID::AIR);
return;
}
if (world->GetTile(x+1, y) == TileID::AIR) {
world->SetTile(x+1, y, numeric_id);
world->SetTile(x, y, TileID::AIR);
return;
}
}
};
class SoilTile : public Tile
@@ -181,9 +215,7 @@ namespace CaveGame::Core
class MossyTile : public SoilTile {
public:
MossyTile();
MossyTile(TileID id, const std::string& name, const Color4& color, TileID decays_target);
MossyTile(TileID numeric, const std::string &name, Color4 color, TileID decays_target);
MossyTile(TileID id, const std::string &name, const Color4 &color, const std::vector<Color4> &pallet);
MossyTile(TileID numeric, const std::string &name, Color4 color);
void RandomTicc(ITileMap *world, TileState state, int x, int y) override;
@@ -192,21 +224,46 @@ namespace CaveGame::Core
class VineTile : public Tile {
public:
VineTile();
VineTile(TileID id, const std::string& name, const Color4& color);
VineTile(TileID id, const std::string& name, const Color4& color, const std::vector<Color4>& pallet);
bool Solid() const override { return true;}
bool DoesRandomTicc() const override { return true; }
void ForcedTicc(ITileMap* world, TileState state, int x, int y) override;
void RandomTicc(ITileMap* world, TileState state, int x, int y) override;
bool DecayCheck(ITileMap* world, TileState state, int x, int y, TileID decays_to) override;
bool ShouldSpread(ITileMap* world, int x, int y, TileID spreads_to) const override;
bool SpreadCheck(ITileMap* world, TileState state, int x, int y, TileID spreads_to) override;
};
class GravityTile : public Tile {
public:
GravityTile();
GravityTile(TileID id, const std::string& name, const Color4& color);
GravityTile(TileID id, const std::string& name, const Color4& color, const std::vector<Color4>& pallet);
bool DoesForcedTicc() const override { return true;}
void ForcedTicc(ITileMap *world, TileState state, int x, int y) override {
if (world->GetTile(x, y+1) == TileID::AIR) {
world->SetTile(x, y+1, numeric_id);
world->SetTile(x, y, TileID::AIR);
return;
}
if (world->GetTile(x+1, y+2) == TileID::AIR) {
world->SetTile(x+1, y+2, numeric_id);
world->SetTile(x, y, TileID::AIR);
return;
}
if (world->GetTile(x-1, y+2) == TileID::AIR) {
world->SetTile(x-1, y+2, numeric_id);
world->SetTile(x, y, TileID::AIR);
return;
}
}
};
class SaplingTile : public Tile {
public:
@@ -234,10 +291,10 @@ namespace CaveGame::Core
static const Tile Limestone {ID::LIMESTONE, "Limestone", Colors::Yellows::PaleGoldenrod};
static const Tile Basalt {ID::BASALT, "Basalt", Colors::Grays::DimGray};
static const Tile Cobblestone {ID::COBBLESTONE, "Cobblestone", Colors::Grays::Gainsboro};
static const SoilTile RedMoss {ID::RED_MOSS, "Red Moss ", Colors::Reds::Crimson, ID::STONE};
static const SoilTile BrownMoss {ID::BROWN_MOSS, "Brown Moss", Colors::Browns::Brown, ID::STONE};
static const SoilTile GreenMoss {ID::GREEN_MOSS, "Green Moss", Colors::Greens::LimeGreen, ID::STONE};
static const SoilTile LavaMoss {ID::LAVA_MOSS, "Lava Moss", Colors::Reds::LightCoral, ID::STONE};
static const MossyTile RedMoss {ID::RED_MOSS, "Red Moss ", Colors::Reds::Crimson, ID::STONE};
static const MossyTile BrownMoss {ID::BROWN_MOSS, "Brown Moss", Colors::Browns::Brown, ID::STONE};
static const MossyTile GreenMoss {ID::GREEN_MOSS, "Green Moss", Colors::Greens::LimeGreen, ID::STONE};
static const MossyTile LavaMoss {ID::LAVA_MOSS, "Lava Moss", Colors::Reds::LightCoral, ID::STONE};
static const Tile Granite {ID::GRANITE, "Granite", Colors::Whites::AntiqueWhite};
static const Tile Marble {ID::MARBLE, "Marble", Colors::Whites::GhostWhite};
static const GrassyTile Grass {ID::GRASS, "Grass", Colors::Greens::LawnGreen,
@@ -246,7 +303,7 @@ namespace CaveGame::Core
static const VineTile Vine {ID::VINE, "Vine", Colors::Greens::ForestGreen};
static const Tile Sand {ID::SAND, "Sand", Colors::Yellows::PaleGoldenrod, {{238, 232, 170}, {232, 238, 160}, {218, 212, 175}}};
static const GravityTile Sand {ID::SAND, "Sand", Colors::Yellows::PaleGoldenrod, {{238, 232, 170}, {232, 238, 160}, {218, 212, 175}}};
static const Tile WhiteSand {ID::WHITE_SAND, "White Sand", Colors::Whites::SeaShell};
static const Tile RedSand {ID::RED_SAND, "Red Sand", Colors::Reds::Firebrick};

View File

@@ -47,7 +47,11 @@ namespace CaveGame::Core
TileState GetTileState(int x, int y) const override { return 0; /* TODO: Implement tile state field */ }
void SetTileState(int x, int y, TileState state) { /* TODO: Implement tile state field */ }
void SetTileState(int x, int y, TileState state) override { /* TODO: Implement tile state field */ }
void SetTileUpdateFlag(int x, int y, bool flag) override;
bool GetTileUpdateFlag(int x, int y) override;
// TODO: Doesn't really belong here.
Vector2 ToUnitDirection(float rotation);
@@ -62,6 +66,8 @@ namespace CaveGame::Core
virtual void RefreshAll();
void DoForcedTileTicks();
virtual void AutoSaveAsync() { }
virtual void AutoSave();

View File

@@ -6,7 +6,7 @@
namespace CaveGame::Core
{
void Chunk::SetTile(int x, int y, TileID t) {
void Chunk::SetTile(int x, int y, TileID t, bool trigger_tile_updates) {
if (!(0 <= x && x < ChunkSize && 0 <= y && y < ChunkSize))
assert("Out of bounds!");
@@ -14,6 +14,10 @@ namespace CaveGame::Core
{
tiles[x][y] = t;
touched = true;
if (trigger_tile_updates)
SetTileUpdateFlag(x, y);
}
}

View File

@@ -138,10 +138,7 @@ namespace CaveGame::Core
MossyTile::MossyTile(): SoilTile()
{}
MossyTile::MossyTile(TileID id, const std::string& name, const Color4& color, TileID decays_target): SoilTile(id, name, color, decays_target)
{}
MossyTile::MossyTile(TileID numeric, const std::string &name, Color4 color, TileID decays_target): SoilTile(numeric, name, color, decays_target) { }
MossyTile::MossyTile(TileID id, const std::string& name, const Color4& color, TileID decays_target): SoilTile(id, name, color, decays_target) { }
MossyTile::MossyTile(TileID id, const std::string &name, const Color4 &color, const std::vector<Color4> &pallet): SoilTile(id,name, color,pallet, TileID::STONE) { }
@@ -157,9 +154,24 @@ namespace CaveGame::Core
}
GravityTile::GravityTile(): Tile()
{
//does_forced_ticc = true;
}
GravityTile::GravityTile(TileID id, const std::string& name, const Color4& color): Tile(id, name, color)
{
//does_forced_ticc = true;
}
GravityTile::GravityTile(TileID id, const std::string& name, const Color4& color, const std::vector<Color4>& pallet):Tile(id, name, color, pallet)
{
//does_forced_ticc = true;
}
VineTile::VineTile(): Tile()
{
does_random_ticc = true;
//does_forced_ticc = true;
}
VineTile::VineTile(TileID id, const std::string& name, const Color4& color): Tile(id, name, color)

View File

@@ -25,6 +25,7 @@ namespace CaveGame::Core
}
DoRandomTileTicks();
DoForcedTileTicks();
for (auto* entity : entities) {
entity->Update(elapsed);
@@ -98,6 +99,46 @@ namespace CaveGame::Core
std::unordered_map<Vector2, Chunk> World::GetChunkList() { return loaded_chunks; }
void World::SetTileUpdateFlag(int x, int y, bool flag) {
float chunkX = Math::Floor((float)x / Chunk::ChunkSize);
float chunkY = Math::Floor((float)y / Chunk::ChunkSize);
float tileX = Math::Mod(x, Chunk::ChunkSize);
float tileY = Math::Mod(y, Chunk::ChunkSize);
if (tileX < 0)
tileX = Chunk::ChunkSize + tileX;
if (tileY < 0)
tileY = Chunk::ChunkSize + tileY;
const Vector2 coords = Vector2(chunkX, chunkY);
if (HasChunkAtCell(coords))
loaded_chunks.at(coords).SetTileUpdateFlag(tileX, tileY, flag);
}
bool World::GetTileUpdateFlag(int x, int y) {
float chunkX = Math::Floor((float)x / Chunk::ChunkSize);
float chunkY = Math::Floor((float)y / Chunk::ChunkSize);
float tileX = Math::Mod(x, Chunk::ChunkSize);
float tileY = Math::Mod(y, Chunk::ChunkSize);
if (tileX < 0)
tileX = Chunk::ChunkSize + tileX;
if (tileY < 0)
tileY = Chunk::ChunkSize + tileY;
Vector2 coords = Vector2(chunkX, chunkY);
if (HasChunkAtCell(coords))
return loaded_chunks.at(coords).GetTileUpdateFlag(tileX, tileY);
return false;
}
Vector2 World::ToUnitDirection(float rotation) {
return {std::cos(rotation), std::cos(rotation)};
}
@@ -210,6 +251,37 @@ namespace CaveGame::Core
}
void World::DoForcedTileTicks() {
Tile* tile = nullptr;
for (auto [coords, chunk] : loaded_chunks) {
for (int x = 0; x < Core::Chunk::ChunkSize; x++) {
for (int y = 0; y < Core::Chunk::ChunkSize; y++) {
int wx = coords.x*Chunk::ChunkSize + x;
int wy = coords.y*Chunk::ChunkSize + y;
if (!chunk.GetTileUpdateFlag(x, y))
continue;
TileID at = chunk.GetTile(x, y);
if (at == TileID::AIR)
continue;
tile = GetByNumeric(at);
if (tile != nullptr) {
if (tile->DoesForcedTicc()) {
tile->ForcedTicc(this, 0, wx, wy);
chunk.SetTileUpdateFlag(x, y, false);
}
}
}
}
}
}
void World::DoRandomTileTicks() {
// Every frame, In each loaded chunk, perform a RandomTileTick on N tiles.