@@ -7,12 +7,12 @@ | |||
extern "C" void mod_init(Swan::Mod &mod) { | |||
mod.init("core"); | |||
mod.registerImage("air", "tiles/air.png"); | |||
mod.registerImage("stone", "tiles/stone.png"); | |||
mod.registerImage("dirt", "tiles/dirt.png"); | |||
mod.registerImage("grass", "tiles/grass.png"); | |||
mod.registerImage("player-running", "entities/player-running.png"); | |||
mod.registerImage("player-still", "entities/player-still.png"); | |||
mod.registerImage({ "air", "tiles/air.png" }); | |||
mod.registerImage({ "stone", "tiles/stone.png" }); | |||
mod.registerImage({ "dirt", "tiles/dirt.png" }); | |||
mod.registerImage({ "grass", "tiles/grass.png" }); | |||
mod.registerImage({ "player-running", "entities/player-running.png" }); | |||
mod.registerImage({ "player-still", "entities/player-still.png" }); | |||
mod.registerTile({ | |||
.name = "air", |
@@ -5,6 +5,7 @@ | |||
#include <string> | |||
#include "common.h" | |||
#include "Resource.h" | |||
#include "Mod.h" | |||
#include "World.h" | |||
@@ -17,17 +17,17 @@ namespace Swan { | |||
class Mod { | |||
public: | |||
Mod(const std::string &path, SDL_Renderer *renderer): path_(path), renderer_(renderer) {} | |||
Mod(const std::string &path): path_(path) {} | |||
void init(const std::string &name); | |||
void registerImage(const std::string &name, const std::string &path, int frame_height = -1); | |||
void registerImage(ImageResource::Builder image); | |||
void registerTile(Tile::Builder tile); | |||
void registerItem(Item::Builder item); | |||
void registerWorldGen(const std::string &name, std::unique_ptr<WorldGen::Factory> gen); | |||
void registerEntity(const std::string &name, std::unique_ptr<Entity::Factory> ent); | |||
Iter<std::unique_ptr<ImageResource>> buildImages(SDL_Renderer *renderer); | |||
Iter<std::unique_ptr<Tile>> buildTiles(const ResourceManager &resources); | |||
Iter<std::unique_ptr<Item>> buildItems(const ResourceManager &resources); | |||
Iter<WorldGen::Factory *> getWorldGens(); | |||
@@ -36,14 +36,13 @@ public: | |||
std::string name_ = "@uninitialized"; | |||
private: | |||
std::vector<std::unique_ptr<ImageResource>> images_; | |||
std::vector<ImageResource::Builder> images_; | |||
std::vector<Tile::Builder> tiles_; | |||
std::vector<Item::Builder> items_; | |||
std::vector<std::unique_ptr<WorldGen::Factory>> worldgens_; | |||
std::vector<std::unique_ptr<Entity::Factory>> entities_; | |||
std::string path_; | |||
SDL_Renderer *renderer_; | |||
bool inited_ = false; | |||
}; | |||
@@ -12,9 +12,14 @@ namespace Swan { | |||
class ImageResource { | |||
public: | |||
ImageResource( | |||
SDL_Renderer *renderer, const std::string &name, | |||
const std::string &path, int frame_height = -1); | |||
struct Builder { | |||
std::string name; | |||
std::string path; | |||
int frame_height = -1; | |||
std::string modpath = ""; | |||
}; | |||
ImageResource(SDL_Renderer *renderer, const Builder &builder); | |||
ImageResource( | |||
SDL_Renderer *renderer, const std::string &name, | |||
int w, int h, uint8_t r, uint8_t g, uint8_t b); | |||
@@ -42,7 +47,7 @@ public: | |||
void tick(float dt); | |||
ImageResource &getImage(const std::string &name) const; | |||
void addImage(std::string name, std::unique_ptr<ImageResource> img); | |||
void addImage(std::unique_ptr<ImageResource> img) { images_[img->name_] = std::move(img); } | |||
std::unique_ptr<ImageResource> invalid_image_; | |||
@@ -24,7 +24,11 @@ public: | |||
} | |||
void showTexture(const Vec2 &pos, SDL_Texture *tex, SDL_Rect *srcrect) { | |||
SDL_Rect destrect{ (int)pos.x, (int)pos.y, srcrect->w, srcrect->h }; | |||
SDL_Rect destrect{ | |||
(int)pos.x * TILE_SIZE, (int)pos.y * TILE_SIZE, | |||
srcrect->w, srcrect->h, | |||
}; | |||
if (SDL_RenderCopy(renderer_, tex, srcrect, &destrect) < 0) { | |||
panic << "RenderCopy failed: " << SDL_GetError(); | |||
abort(); |
@@ -45,8 +45,8 @@ private: | |||
}; | |||
static std::ostream &logstream = std::clog; | |||
static Logger info(std::clog, "info", OS::isTTY(stderr), "\033[36m"); | |||
static Logger warn(std::clog, "warning", OS::isTTY(stderr), "\033[33m"); | |||
static Logger panic(std::clog, "panic", OS::isTTY(stderr), "\033[1m\033[31m"); | |||
static Logger info(logstream, "info", OS::isTTY(stderr), "\033[36m"); | |||
static Logger warn(logstream, "warning", OS::isTTY(stderr), "\033[33m"); | |||
static Logger panic(logstream, "panic", OS::isTTY(stderr), "\033[1m\033[31m"); | |||
} |
@@ -102,6 +102,10 @@ void Chunk::render(const Context &ctx) { | |||
CHUNK_WIDTH * TILE_SIZE, CHUNK_HEIGHT * TILE_SIZE)); | |||
} | |||
if (pos_ != ChunkPos(0, 0)) | |||
return; | |||
info << "Rendering chunk " << pos_; | |||
Tile::ID prevID = Tile::INVALID_ID; | |||
Tile *tile = ctx.game.invalid_tile_.get(); | |||
@@ -114,8 +118,8 @@ void Chunk::render(const Context &ctx) { | |||
} | |||
auto lock = makeDeferred([this] { SDL_UnlockTexture(visuals_->texture_.get()); }); | |||
for (int x = 0; x < CHUNK_WIDTH; ++x) { | |||
for (int y = 0; y < CHUNK_HEIGHT; ++y) { | |||
for (int y = 0; y < CHUNK_HEIGHT; ++y) { | |||
for (int x = 0; x < CHUNK_WIDTH; ++x) { | |||
Tile::ID id = getTileID(RelPos(x, y)); | |||
if (id != prevID) { | |||
prevID = id; | |||
@@ -126,7 +130,9 @@ void Chunk::render(const Context &ctx) { | |||
for (int imgy = 0; imgy < TILE_SIZE; ++imgy) { | |||
uint8_t *tilepix = (uint8_t *)tilesurf->pixels + imgy * tilesurf->pitch; | |||
uint8_t *destpix = pixels + y * pitch + (x * TILE_SIZE) * 4; | |||
uint8_t *destpix = pixels + | |||
((y * TILE_SIZE + imgy) * pitch) + | |||
(x * TILE_SIZE) * 4; | |||
memcpy(destpix, tilepix, TILE_SIZE * 4); | |||
} | |||
} | |||
@@ -150,8 +156,9 @@ void Chunk::draw(const Context &ctx, Win &win) { | |||
} | |||
SDL_Rect rect{ 0, 0, CHUNK_WIDTH * TILE_SIZE, CHUNK_HEIGHT * TILE_SIZE }; | |||
win.showTexture(pos_, visuals_->texture_.get(), &rect); | |||
//win.draw(visuals_->sprite_); | |||
win.showTexture( | |||
pos_ * Vec2i(CHUNK_WIDTH, CHUNK_HEIGHT), | |||
visuals_->texture_.get(), &rect); | |||
} | |||
void Chunk::tick(float dt) { |
@@ -20,7 +20,7 @@ std::unique_ptr<Mod> Game::loadMod(const std::string &path) { | |||
return NULL; | |||
} | |||
std::unique_ptr<Mod> mod = std::make_unique<Mod>(path, win_.renderer_); | |||
std::unique_ptr<Mod> mod = std::make_unique<Mod>(path); | |||
init(*mod); | |||
return mod; | |||
} |
@@ -15,10 +15,11 @@ void Mod::init(const std::string &name) { | |||
info << "Mod initing: " << name_; | |||
} | |||
void Mod::registerImage(const std::string &name, const std::string &path, int frame_height) { | |||
images_.push_back(std::make_unique<ImageResource>( | |||
renderer_, name_ + "::" + name, path_ + "/assets/" + path, frame_height)); | |||
info << " Adding image: " << name_ << "::" << name << " (" << path << ')'; | |||
void Mod::registerImage(ImageResource::Builder image) { | |||
image.name = name_ + "::" + image.name; | |||
image.modpath = path_; | |||
images_.push_back(image); | |||
info << " Adding image: " << image.name << " (" << image.path << ')'; | |||
} | |||
void Mod::registerTile(Tile::Builder tile) { | |||
@@ -45,6 +46,12 @@ void Mod::registerEntity(const std::string &name, std::unique_ptr<Entity::Factor | |||
entities_.push_back(std::move(ent)); | |||
} | |||
Iter<std::unique_ptr<ImageResource>> Mod::buildImages(SDL_Renderer *renderer) { | |||
return map(begin(images_), end(images_), [&](const ImageResource::Builder &builder) { | |||
return std::make_unique<ImageResource>(renderer, builder); | |||
}); | |||
} | |||
Iter<std::unique_ptr<Tile>> Mod::buildTiles(const ResourceManager &resources) { | |||
return map(begin(tiles_), end(tiles_), [&](const Tile::Builder &builder) { | |||
return std::make_unique<Tile>(resources, builder); |
@@ -10,13 +10,10 @@ | |||
namespace Swan { | |||
ImageResource::ImageResource( | |||
SDL_Renderer *renderer, const std::string &name, | |||
const std::string &path, int frame_height) { | |||
surface_.reset(IMG_Load(path.c_str())); | |||
ImageResource::ImageResource(SDL_Renderer *renderer, const Builder &builder) { | |||
surface_.reset(IMG_Load((builder.modpath + "/assets/" + builder.path).c_str())); | |||
if (surface_ == nullptr) { | |||
warn << "Loading " << path << " failed: " << SDL_GetError(); | |||
warn << "Loading image " << builder.name << " failed: " << SDL_GetError(); | |||
surface_.reset(SDL_CreateRGBSurface( | |||
0, TILE_SIZE, TILE_SIZE, 32, 0, 0, 0, 0)); | |||
@@ -25,16 +22,16 @@ ImageResource::ImageResource( | |||
PLACEHOLDER_RED, PLACEHOLDER_GREEN, PLACEHOLDER_BLUE)); | |||
} | |||
if (frame_height < 0) | |||
frame_height = surface_->h; | |||
frame_height_ = builder.frame_height; | |||
if (frame_height_ < 0) | |||
frame_height_ = surface_->h; | |||
texture_.reset(SDL_CreateTexture( | |||
renderer, surface_->format->format, SDL_TEXTUREACCESS_STATIC, | |||
surface_->w, frame_height)); | |||
renderer, surface_->format->format, SDL_TEXTUREACCESS_STATIC, | |||
surface_->w, frame_height_)); | |||
frame_height_ = frame_height; | |||
num_frames_ = surface_->h / frame_height_; | |||
name_ = name; | |||
name_ = builder.name; | |||
} | |||
ImageResource::ImageResource( | |||
@@ -44,6 +41,7 @@ ImageResource::ImageResource( | |||
surface_.reset(SDL_CreateRGBSurface( | |||
0, TILE_SIZE, TILE_SIZE, 32, 0, 0, 0, 0)); | |||
SDL_FillRect(surface_.get(), NULL, SDL_MapRGB(surface_->format, r, g, b)); | |||
texture_.reset(SDL_CreateTexture( | |||
renderer, surface_->format->format, SDL_TEXTUREACCESS_STATIC, w, h)); | |||
@@ -80,8 +78,10 @@ void ResourceManager::tick(float dt) { | |||
ImageResource &ResourceManager::getImage(const std::string &name) const { | |||
auto it = images_.find(name); | |||
if (it == end(images_)) | |||
if (it == end(images_)) { | |||
warn << "Couldn't find image " << name << "!"; | |||
return *invalid_image_; | |||
} | |||
return *it->second; | |||
} | |||
@@ -49,6 +49,10 @@ void World::ChunkRenderer::tick(WorldPlane &plane, ChunkPos abspos) { | |||
void World::addMod(std::unique_ptr<Mod> mod) { | |||
info << "World: adding mod " << mod->name_; | |||
for (auto i: mod->buildImages(game_->win_.renderer_)) { | |||
resources_.addImage(std::move(i)); | |||
} | |||
for (auto t: mod->buildTiles(resources_)) { | |||
Tile::ID id = tiles_.size(); | |||
tiles_map_[t->name_] = id; |