| @@ -3,6 +3,7 @@ core_mod = shared_library('mod', | |||
| 'src/DefaultWorldGen.cc', | |||
| 'src/entities/PlayerEntity.cc', | |||
| 'src/entities/ItemStackEntity.cc', | |||
| 'src/world/tree.cc', | |||
| name_prefix: '', | |||
| name_suffix: 'so', | |||
| install: true, | |||
| @@ -1,6 +1,7 @@ | |||
| #include "DefaultWorldGen.h" | |||
| #include <algorithm> | |||
| #include <cstdint> | |||
| #include "entities/PlayerEntity.h" | |||
| @@ -54,6 +55,25 @@ Swan::Tile::ID DefaultWorldGen::genTile(Swan::TilePos pos) { | |||
| if (pos.y > grassLevel + 7 && perlin_.noise(pos.x / 43.37, pos.y / 16.37) > 0.2) | |||
| return tAir_; | |||
| // Trees | |||
| if (pos.y == grassLevel - 1) { | |||
| constexpr int treeProb = 4; | |||
| bool spawnTree = Swan::random(pos.x) % treeProb == 0; | |||
| if (spawnTree) { | |||
| // Avoid trees which are too close | |||
| for (int rx = 1; rx <= 5; ++rx) { | |||
| if (Swan::random(pos.x + rx) % treeProb == 0) { | |||
| spawnTree = false; | |||
| break; | |||
| } | |||
| } | |||
| if (spawnTree) { | |||
| return tTreeSeeder_; | |||
| } | |||
| } | |||
| } | |||
| if (pos.y > stoneLevel) | |||
| return tStone_; | |||
| else if (pos.y > grassLevel) | |||
| @@ -10,9 +10,8 @@ public: | |||
| tGrass_(world.getTileID("core::grass")), | |||
| tDirt_(world.getTileID("core::dirt")), | |||
| tStone_(world.getTileID("core::stone")), | |||
| tTreeSeeder_(world.getTileID("core::tree-seeder")), | |||
| tAir_(world.getTileID("@::air")), | |||
| tTreeTrunk_(world.getTileID("core::tree-trunk")), | |||
| tLeaves_(world.getTileID("core::leaves")), | |||
| bgCave_(world.getSprite("core::misc/background-cave")) {} | |||
| void drawBackground( | |||
| @@ -23,7 +22,9 @@ public: | |||
| private: | |||
| Swan::Tile::ID genTile(Swan::TilePos pos); | |||
| Swan::Tile::ID tGrass_, tDirt_, tStone_, tAir_, tTreeTrunk_, tLeaves_; | |||
| const uint32_t seed_ = 100; | |||
| Swan::Tile::ID tGrass_, tDirt_, tStone_, tTreeSeeder_, tAir_; | |||
| Cygnet::RenderSprite bgCave_; | |||
| siv::PerlinNoise perlin_ = siv::PerlinNoise(100); | |||
| siv::PerlinNoise perlin_{seed_}; | |||
| }; | |||
| @@ -3,6 +3,7 @@ | |||
| #include "DefaultWorldGen.h" | |||
| #include "entities/PlayerEntity.h" | |||
| #include "entities/ItemStackEntity.h" | |||
| #include "world/tree.h" | |||
| #include <functional> | |||
| @@ -34,11 +35,18 @@ public: | |||
| registerTile({ | |||
| .name = "tree-trunk", | |||
| .image = "core::tile/tree-trunk", | |||
| .isSolid = false, | |||
| .droppedItem = "core::tree-trunk", | |||
| }); | |||
| registerTile({ | |||
| .name = "leaves", | |||
| .name = "tree-leaves", | |||
| .image = "core::tile/leaves", | |||
| .isSolid = false, | |||
| }); | |||
| registerTile({ | |||
| .name = "tree-seeder", | |||
| .image = "core::tile/leaves", | |||
| .onSpawn = spawnTree, | |||
| }); | |||
| registerTile({ | |||
| .name = "torch", | |||
| @@ -0,0 +1,31 @@ | |||
| #include "tree.h" | |||
| #include <algorithm> | |||
| void spawnTree(const Swan::Context &ctx, Swan::TilePos pos) { | |||
| Swan::Tile::ID logID = ctx.world.getTileID("core::tree-trunk"); | |||
| Swan::Tile::ID leavesID = ctx.world.getTileID("core::tree-leaves"); | |||
| int height = 4 + Swan::random(pos.x) % 3; | |||
| for (int y = pos.y; y >= pos.y - height; --y) { | |||
| ctx.plane.setTileID({pos.x, y}, logID); | |||
| } | |||
| int radius = 2 + Swan::random(pos.x) % 2; | |||
| int radius2 = radius * radius; | |||
| Swan::TilePos top = pos - Swan::Vec2i{0, height}; | |||
| for (int ry = -radius; ry <= radius + 2; ++ry) { | |||
| for (int rx = -radius; rx <= radius; ++rx) { | |||
| if (rx == 0 && ry <= -radius / 2) { | |||
| continue; | |||
| } | |||
| int d2 = std::max( | |||
| ry * ry + rx * rx, | |||
| (ry + 1) * (ry + 1) + rx * rx); | |||
| if (d2 <= radius2) { | |||
| ctx.plane.setTileID(top - Swan::Vec2i{rx, ry}, leavesID); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,5 @@ | |||
| #pragma once | |||
| #include "swan/swan.h" | |||
| void spawnTree(const Swan::Context &ctx, Swan::TilePos pos); | |||