@@ -4,7 +4,6 @@ class DefaultWorldGen: public Swan::WorldGen { | |||
public: | |||
class Factory: public Swan::WorldGen::Factory { | |||
public: | |||
Factory(): Swan::WorldGen::Factory("Default") {} | |||
WorldGen *create(Swan::TileMap &tmap) { return new DefaultWorldGen(tmap); } | |||
}; | |||
@@ -26,13 +25,12 @@ public: | |||
extern "C" void mod_init(Swan::Mod &mod) { | |||
mod.init("core"); | |||
mod.registerTile("air", "assets/tiles/air.png", Swan::Tile::Opts() | |||
.solid(false)); | |||
mod.registerTile("stone", "assets/tiles/stone.png", Swan::Tile::Opts()); | |||
mod.registerTile("dirt", "assets/tiles/dirt.png", Swan::Tile::Opts()); | |||
mod.registerTile("grass", "assets/tiles/grass.png", Swan::Tile::Opts()); | |||
mod.registerTile("air", (new Swan::Tile("assets/tiles/air.png"))->solid(false)); | |||
mod.registerTile("stone", (new Swan::Tile("assets/tiles/stone.png"))); | |||
mod.registerTile("dirt", (new Swan::Tile("assets/tiles/dirt.png"))); | |||
mod.registerTile("grass", (new Swan::Tile("assets/tiles/grass.png"))); | |||
mod.registerWorldGen(new DefaultWorldGen::Factory()); | |||
mod.registerWorldGen("Default", new DefaultWorldGen::Factory()); | |||
} | |||
int main() { |
@@ -11,34 +11,36 @@ namespace Swan { | |||
class Chunk { | |||
public: | |||
int x_; | |||
int y_; | |||
using ChunkPos = Vector2<int>; | |||
using RelPos = Vector2<int>; | |||
ChunkPos pos_; | |||
bool dirty_ = false; | |||
Tile::ID tiles_[CHUNK_WIDTH][CHUNK_HEIGHT]; | |||
sf::Texture texture_; | |||
sf::Sprite sprite_; | |||
Chunk(int x, int y): x_(x), y_(y) { | |||
Chunk(ChunkPos pos): pos_(pos) { | |||
texture_.create(CHUNK_WIDTH * TILE_SIZE, CHUNK_HEIGHT * TILE_SIZE); | |||
sprite_ = sf::Sprite(texture_); | |||
} | |||
void setTileID(TileMap &tmap, int x, int y, Tile::ID id) { | |||
tiles_[x][y] = id; | |||
drawBlock(tmap, x, y, id); | |||
void setTileID(TileMap &tmap, RelPos pos, Tile::ID id) { | |||
tiles_[pos.x_][pos.y_] = id; | |||
drawBlock(tmap, pos, id); | |||
} | |||
Tile &getTile(TileMap &tmap, int x, int y) { | |||
return tmap.get(tiles_[x][y]); | |||
Tile &getTile(TileMap &tmap, RelPos pos) { | |||
return tmap.get(tiles_[pos.x_][pos.y_]); | |||
} | |||
void drawBlock(int x, int y, const Tile &t) { | |||
texture_.update(t.image_, x * TILE_SIZE, y * TILE_SIZE); | |||
void drawBlock(RelPos pos, const Tile &t) { | |||
texture_.update(t.image_, pos.x_ * TILE_SIZE, pos.y_ * TILE_SIZE); | |||
dirty_ = true; | |||
} | |||
void drawBlock(TileMap &tmap, int x, int y, Tile::ID id) { | |||
drawBlock(x, y, tmap.get(id)); | |||
void drawBlock(TileMap &tmap, RelPos pos, Tile::ID id) { | |||
drawBlock(pos, tmap.get(id)); | |||
} | |||
void redraw(TileMap &tmap); |
@@ -21,8 +21,8 @@ public: | |||
bool inited_ = false; | |||
void init(const std::string &name); | |||
void registerTile(const std::string &name, const std::string &asset, const Tile::Opts &opts); | |||
void registerWorldGen(WorldGen::Factory *gen); | |||
void registerTile(const std::string &name, Tile *tile); | |||
void registerWorldGen(const std::string &name, WorldGen::Factory *gen); | |||
}; | |||
} |
@@ -10,14 +10,15 @@ class Tile { | |||
public: | |||
using ID = uint16_t; | |||
struct Opts { | |||
bool solid_ = true; | |||
Opts &solid(bool b) { solid_ = b; return *this; } | |||
}; | |||
std::string path_; | |||
std::string name_; | |||
sf::Image image_; | |||
Opts opts_; | |||
bool is_solid_ = true; | |||
Tile(std::string path): path_(path) {} | |||
Tile *solid(bool b) { is_solid_ = b; return this; } | |||
static sf::Image invalid_image; | |||
static Tile invalid_tile; |
@@ -73,6 +73,12 @@ public: | |||
y_ /= num; | |||
return *this; | |||
} | |||
bool operator<(const Vector2<T> &vec) const { | |||
if (x_ < vec.x_) return true; | |||
if (vec.x_ < x_) return false; | |||
return y_ < vec.y_; | |||
} | |||
}; | |||
using Vec2 = Vector2<float>; |
@@ -14,7 +14,6 @@ public: | |||
class Factory { | |||
public: | |||
std::string name_; | |||
Factory(const std::string &name): name_(name) {} | |||
virtual WorldGen *create(TileMap &tmap) = 0; | |||
}; | |||
@@ -17,9 +17,8 @@ class World; | |||
class WorldPlane { | |||
public: | |||
using ID = uint16_t; | |||
using Coord = std::pair<int, int>; | |||
std::map<Coord, Chunk> chunks_; | |||
std::map<Chunk::ChunkPos, Chunk> chunks_; | |||
ID id_; | |||
World *world_; | |||
std::shared_ptr<WorldGen> gen_; |
@@ -17,7 +17,7 @@ void Body::collide(WorldPlane &plane) { | |||
int y = (int)(pos_.y_ + size_.y_); | |||
for (int x = startx; x <= endx; ++x) { | |||
Tile &tile = plane.getTile(x, y); | |||
if (tile.opts_.solid_) { | |||
if (tile.is_solid_) { | |||
pos_.y_ = y - size_.y_; | |||
vel_.y_ = 0; | |||
break; |
@@ -11,22 +11,21 @@ void Mod::init(const std::string &name) { | |||
fprintf(stderr, "Mod initing: %s\n", name_.c_str()); | |||
} | |||
void Mod::registerTile(const std::string &name, const std::string &asset, const Tile::Opts &opts) { | |||
Tile *t = new Tile(); | |||
t->name_ = name_ + "::" + name; | |||
t->opts_ = opts; | |||
fprintf(stderr, "Adding tile: %s\n", t->name_.c_str()); | |||
std::string asset_path = path_ + "/" + asset; | |||
if (!t->image_.loadFromFile(asset_path)) { | |||
fprintf(stderr, "Tile %s: Failed to load image %s\n", t->name_.c_str(), asset_path.c_str()); | |||
t->image_ = Tile::invalid_image; | |||
void Mod::registerTile(const std::string &name, Tile *tile) { | |||
tile->name_ = name_ + "::" + name; | |||
fprintf(stderr, "Adding tile: %s\n", tile->name_.c_str()); | |||
std::string asset_path = path_ + "/" + tile->path_; | |||
if (!tile->image_.loadFromFile(asset_path)) { | |||
fprintf(stderr, "Tile %s: Failed to load image %s\n", tile->name_.c_str(), asset_path.c_str()); | |||
tile->image_ = Tile::invalid_image; | |||
} | |||
tiles_.push_back(std::shared_ptr<Tile>(t)); | |||
tiles_.push_back(std::shared_ptr<Tile>(tile)); | |||
} | |||
void Mod::registerWorldGen(WorldGen::Factory *gen) { | |||
void Mod::registerWorldGen(const std::string &name, WorldGen::Factory *gen) { | |||
gen->name_ = name; | |||
worldgens_.push_back(std::shared_ptr<WorldGen::Factory>(gen)); | |||
} | |||
@@ -4,13 +4,13 @@ | |||
namespace Swan { | |||
sf::Image Tile::invalid_image; | |||
Tile Tile::invalid_tile; | |||
Tile Tile::invalid_tile(""); | |||
void Tile::initInvalid() { | |||
invalid_image.create((int)TILE_SIZE, (int)TILE_SIZE, sf::Color(245, 66, 242)); | |||
invalid_tile.name_ = "INVALID"; | |||
invalid_tile.image_ = invalid_image; | |||
invalid_tile.opts_ = Opts().solid(false); | |||
invalid_tile.is_solid_ = false; | |||
} | |||
} |
@@ -4,13 +4,25 @@ | |||
namespace Swan { | |||
static Chunk::ChunkPos chunkPos(int x, int y) { | |||
return Chunk::ChunkPos( | |||
(x >= 0 ? x : x - CHUNK_WIDTH) / CHUNK_WIDTH, | |||
(y >= 0 ? y : y - CHUNK_HEIGHT) / CHUNK_HEIGHT); | |||
} | |||
static Chunk::RelPos relPos(int x, int y) { | |||
return Chunk::ChunkPos( | |||
(x >= 0 ? x : x + CHUNK_WIDTH) % CHUNK_WIDTH, | |||
(y >= 0 ? y : y + CHUNK_HEIGHT) % CHUNK_HEIGHT); | |||
} | |||
Chunk &WorldPlane::getChunk(int x, int y) { | |||
auto coord = Coord(x / CHUNK_WIDTH, y / CHUNK_HEIGHT); | |||
auto it = chunks_.find(coord); | |||
Chunk::ChunkPos pos = chunkPos(x, y); | |||
auto it = chunks_.find(pos); | |||
if (it == chunks_.end()) { | |||
it = chunks_.emplace(coord, Chunk(coord.first, coord.second)).first; | |||
gen_->genChunk(it->second, coord.first, coord.second); | |||
it = chunks_.emplace(pos, Chunk(pos)).first; | |||
gen_->genChunk(it->second, pos.x_, pos.y_); | |||
it->second.redraw(world_->tile_map_); | |||
} | |||
@@ -18,11 +30,11 @@ Chunk &WorldPlane::getChunk(int x, int y) { | |||
} | |||
void WorldPlane::setTileID(int x, int y, Tile::ID id) { | |||
getChunk(x, y).setTileID(world_->tile_map_, x % CHUNK_WIDTH, y % CHUNK_HEIGHT, id); | |||
getChunk(x, y).setTileID(world_->tile_map_, relPos(x, y), id); | |||
} | |||
Tile &WorldPlane::getTile(int x, int y) { | |||
return getChunk(x, y).getTile(world_->tile_map_, x % CHUNK_WIDTH, y % CHUNK_HEIGHT); | |||
return getChunk(x, y).getTile(world_->tile_map_, relPos(x, y)); | |||
} | |||
void WorldPlane::draw(Win &win) { |