@@ -18,6 +18,11 @@ else() | |||
message(FATAL_ERROR "CMAKE_BUILD_TYPE must be Debug or Release.") | |||
endif() | |||
# We want to be able to use C++20 designated initializers, | |||
# but Clang doesn't support them yet. | |||
# Remove once Clang 9.1 or something comes out. | |||
add_compile_options(-Wno-c99-extensions) | |||
include_directories( | |||
${PROJECT_SOURCE_DIR}/libswan/include | |||
${PROJECT_SOURCE_DIR}/third_party) |
@@ -22,5 +22,5 @@ void WGDefault::genChunk(Swan::WorldPlane &plane, Swan::Chunk &chunk) { | |||
} | |||
Swan::Entity &WGDefault::spawnPlayer(Swan::WorldPlane &plane) { | |||
return plane.spawnEntity("core::player", Swan::Vec2(0, 0)); | |||
return plane.spawnEntity("core::player", Swan::SRFFloatArray{0, 0}); | |||
} |
@@ -1,7 +1,10 @@ | |||
#include "EntPlayer.h" | |||
EntPlayer::EntPlayer(const Swan::Context &ctx, const Swan::Vec2 &pos): | |||
body_(pos, SIZE, MASS) { | |||
EntPlayer::EntPlayer(const Swan::Context &ctx, const Swan::SRF ¶ms): | |||
body_(SIZE, MASS) { | |||
readSRF(params); | |||
anims_[(int)State::IDLE].init(32, 64, 0.8, | |||
ctx.world.getAsset("core::player-still")); | |||
anims_[(int)State::RUNNING_R].init(32, 64, 1, | |||
@@ -58,3 +61,12 @@ void EntPlayer::update(const Swan::Context &ctx, float dt) { | |||
body_.update(dt); | |||
body_.collide(ctx.plane); | |||
} | |||
void EntPlayer::readSRF(const Swan::SRF &srf) { | |||
auto pos = dynamic_cast<const Swan::SRFFloatArray &>(srf); | |||
body_.pos_.set(pos.val[0], pos.val[1]); | |||
} | |||
Swan::SRF *EntPlayer::writeSRF() { | |||
return new Swan::SRFFloatArray{ body_.pos_.x_, body_.pos_.y_ }; | |||
} |
@@ -6,17 +6,19 @@ class EntPlayer: public Swan::Entity { | |||
public: | |||
class Factory: public Swan::Entity::Factory { | |||
public: | |||
Swan::Entity *create(const Swan::Context &ctx, const Swan::Vec2 &pos) override { | |||
return new EntPlayer(ctx, pos); | |||
Swan::Entity *create(const Swan::Context &ctx, const Swan::SRF ¶ms) override { | |||
return new EntPlayer(ctx, params); | |||
} | |||
}; | |||
EntPlayer(const Swan::Context &ctx, const Swan::Vec2 &pos); | |||
EntPlayer(const Swan::Context &ctx, const Swan::SRF ¶ms); | |||
const Swan::Vec2 &getPos() override { return body_.pos_; } | |||
void draw(const Swan::Context &ctx, Swan::Win &win) override; | |||
void update(const Swan::Context &ctx, float dt) override; | |||
void readSRF(const Swan::SRF &srf) override; | |||
Swan::SRF *writeSRF() override; | |||
private: | |||
static constexpr float FORCE = 3000; |
@@ -9,8 +9,8 @@ namespace Swan { | |||
class Body { | |||
public: | |||
Body(Vec2 pos, Vec2 size, float mass): | |||
pos_(pos), size_(size), mass_(mass) {}; | |||
Body(Vec2 size, float mass, Vec2 pos = Vec2::ZERO): | |||
size_(size), mass_(mass), pos_(pos) {}; | |||
void friction(Vec2 coef); | |||
void gravity(Vec2 g = Vec2(0, 20)); | |||
@@ -21,9 +21,9 @@ public: | |||
Vec2 force_ = { 0, 0 }; | |||
Vec2 vel_ = { 0, 0 }; | |||
Vec2 pos_; | |||
Vec2 size_; | |||
float mass_; | |||
Vec2 pos_; | |||
bool on_ground_ = false; | |||
}; | |||
@@ -3,6 +3,7 @@ | |||
#include <memory> | |||
#include "common.h" | |||
#include "SRF.h" | |||
namespace Swan { | |||
@@ -15,7 +16,7 @@ public: | |||
class Factory { | |||
public: | |||
virtual ~Factory() = default; | |||
virtual Entity *create(const Context &ctx, const Vec2 &pos) = 0; | |||
virtual Entity *create(const Context &ctx, const SRF ¶ms) = 0; | |||
std::string name_; | |||
}; | |||
@@ -26,6 +27,8 @@ public: | |||
virtual void draw(const Context &ctx, Win &win) {} | |||
virtual void update(const Context &ctx, float dt) {} | |||
virtual void tick() {} | |||
virtual void readSRF(const SRF &srf) {} | |||
virtual SRF *writeSRF() { return new SRFNone(); } | |||
}; | |||
} |
@@ -12,124 +12,144 @@ | |||
namespace Swan { | |||
struct SRFVal { | |||
virtual ~SRFVal() = default; | |||
struct SRF { | |||
virtual ~SRF() = default; | |||
virtual void serialize(std::ostream &os) = 0; | |||
virtual void serialize(std::ostream &os) const = 0; | |||
virtual void parse(std::istream &is) = 0; | |||
virtual std::ostream &pretty(std::ostream &os) const = 0; | |||
static SRFVal *read(std::istream &is); | |||
static SRF *read(std::istream &is); | |||
}; | |||
struct SRFObject: SRFVal { | |||
struct SRFObject: SRF { | |||
SRFObject() {} | |||
SRFObject(std::initializer_list<std::pair<std::string, SRFVal *>> &lst); | |||
void serialize(std::ostream &os) override; | |||
SRFObject(std::initializer_list<std::pair<std::string, SRF *>> &lst); | |||
void serialize(std::ostream &os) const override; | |||
void parse(std::istream &os) override; | |||
std::ostream &pretty(std::ostream &os) const override; | |||
std::unordered_map<std::string, std::unique_ptr<SRFVal>> val; | |||
std::unordered_map<std::string, std::unique_ptr<SRF>> val; | |||
}; | |||
struct SRFArray: SRFVal { | |||
struct SRFArray: SRF { | |||
SRFArray() {} | |||
SRFArray(std::initializer_list<SRFVal *> &lst); | |||
void serialize(std::ostream &os) override; | |||
SRFArray(std::initializer_list<SRF *> &lst); | |||
void serialize(std::ostream &os) const override; | |||
void parse(std::istream &os) override; | |||
std::ostream &pretty(std::ostream &os) const override; | |||
std::vector<std::unique_ptr<SRFVal>> val; | |||
std::vector<std::unique_ptr<SRF>> val; | |||
}; | |||
struct SRFString: SRFVal { | |||
struct SRFString: SRF { | |||
SRFString(): val("") {} | |||
SRFString(const std::string &v): val(v) {} | |||
void serialize(std::ostream &os) override; | |||
void serialize(std::ostream &os) const override; | |||
void parse(std::istream &os) override; | |||
std::ostream &pretty(std::ostream &os) const override; | |||
std::string val; | |||
}; | |||
struct SRFInt: SRFVal { | |||
struct SRFInt: SRF { | |||
SRFInt(): val(0) {} | |||
SRFInt(int32_t v): val(v) {} | |||
void serialize(std::ostream &os) override; | |||
void serialize(std::ostream &os) const override; | |||
void parse(std::istream &os) override; | |||
std::ostream &pretty(std::ostream &os) const override; | |||
int32_t val; | |||
}; | |||
struct SRFFloat: SRFVal { | |||
struct SRFFloat: SRF { | |||
SRFFloat(): val(0) {} | |||
SRFFloat(float v): val(v) {} | |||
void serialize(std::ostream &os) override; | |||
void serialize(std::ostream &os) const override; | |||
void parse(std::istream &os) override; | |||
std::ostream &pretty(std::ostream &os) const override; | |||
float val; | |||
}; | |||
struct SRFDouble: SRFVal { | |||
struct SRFDouble: SRF { | |||
SRFDouble(): val(0) {} | |||
SRFDouble(double v): val(v) {} | |||
void serialize(std::ostream &os) override; | |||
void serialize(std::ostream &os) const override; | |||
void parse(std::istream &os) override; | |||
std::ostream &pretty(std::ostream &os) const override; | |||
double val; | |||
}; | |||
struct SRFNone: SRFVal { | |||
void serialize(std::ostream &os) override; | |||
struct SRFNone: SRF { | |||
void serialize(std::ostream &os) const override; | |||
void parse(std::istream &os) override; | |||
std::ostream &pretty(std::ostream &os) const override; | |||
}; | |||
struct SRFByteArray: SRFVal { | |||
struct SRFByteArray: SRF { | |||
SRFByteArray() = default; | |||
SRFByteArray(std::initializer_list<uint8_t> lst): val(lst) {} | |||
SRFByteArray(std::vector<uint8_t> v): val(v) {} | |||
void serialize(std::ostream &os) override; | |||
void serialize(std::ostream &os) const override; | |||
void parse(std::istream &os) override; | |||
std::ostream &pretty(std::ostream &os) const override; | |||
std::vector<uint8_t> val; | |||
}; | |||
struct SRFWordArray: SRFVal { | |||
struct SRFWordArray: SRF { | |||
SRFWordArray() = default; | |||
SRFWordArray(std::initializer_list<uint16_t> v): val(v) {} | |||
SRFWordArray(std::vector<uint16_t> v): val(v) {} | |||
void serialize(std::ostream &os) override; | |||
void serialize(std::ostream &os) const override; | |||
void parse(std::istream &os) override; | |||
std::ostream &pretty(std::ostream &os) const override; | |||
std::vector<uint16_t> val; | |||
}; | |||
struct SRFIntArray: SRFVal { | |||
struct SRFIntArray: SRF { | |||
SRFIntArray() = default; | |||
SRFIntArray(std::initializer_list<int> v): val(v) {} | |||
SRFIntArray(std::vector<int32_t> v): val(v) {} | |||
void serialize(std::ostream &os) override; | |||
void serialize(std::ostream &os) const override; | |||
void parse(std::istream &os) override; | |||
std::ostream &pretty(std::ostream &os) const override; | |||
std::vector<int32_t> val; | |||
}; | |||
struct SRFFloatArray: SRFVal { | |||
struct SRFFloatArray: SRF { | |||
SRFFloatArray() = default; | |||
SRFFloatArray(std::initializer_list<float> v): val(v) {} | |||
SRFFloatArray(std::vector<float> v): val(v) {} | |||
void serialize(std::ostream &os) override; | |||
void serialize(std::ostream &os) const override; | |||
void parse(std::istream &os) override; | |||
std::ostream &pretty(std::ostream &os) const override; | |||
std::vector<float> val; | |||
}; | |||
struct SRFDoubleArray: SRFVal { | |||
struct SRFDoubleArray: SRF { | |||
SRFDoubleArray() = default; | |||
SRFDoubleArray(std::initializer_list<double> v): val(v) {} | |||
SRFDoubleArray(std::vector<double> v): val(v) {} | |||
void serialize(std::ostream &os) override; | |||
void serialize(std::ostream &os) const override; | |||
void parse(std::istream &os) override; | |||
std::ostream &pretty(std::ostream &os) const override; | |||
std::vector<double> val; | |||
}; |
@@ -10,6 +10,12 @@ class Vector2 { | |||
public: | |||
constexpr Vector2(T x = 0, T y = 0): x_(x), y_(y) {} | |||
Vector2<T> &set(T x, T y) { | |||
x_ = x; | |||
y_ = y; | |||
return *this; | |||
} | |||
operator sf::Vector2<T>() const { | |||
return sf::Vector2<T>(x_, y_); | |||
} |
@@ -22,7 +22,7 @@ public: | |||
WorldPlane(ID id, World *world, std::shared_ptr<WorldGen> gen): | |||
id_(id), world_(world), gen_(gen) {} | |||
Entity &spawnEntity(const std::string &name, const Vec2 &pos); | |||
Entity &spawnEntity(const std::string &name, const SRF ¶ms); | |||
Context getContext(); | |||
@@ -105,53 +105,60 @@ static std::string readString(std::istream &is) { | |||
return str; | |||
} | |||
SRFVal *SRFVal::read(std::istream &is) { | |||
static char hexchr(uint8_t nibble) { | |||
if (nibble < 10) | |||
return '0' + nibble; | |||
else | |||
return 'a' + (nibble - 10); | |||
} | |||
SRF *SRF::read(std::istream &is) { | |||
Type type = (Type)readByte(is); | |||
SRFVal *tag; | |||
SRF *srf; | |||
switch (type) { | |||
case Type::OBJECT: | |||
tag = new SRFObject(); break; | |||
srf = new SRFObject(); break; | |||
case Type::ARRAY: | |||
tag = new SRFArray(); break; | |||
srf = new SRFArray(); break; | |||
case Type::STRING: | |||
tag = new SRFString(); break; | |||
srf = new SRFString(); break; | |||
case Type::INT: | |||
tag = new SRFInt(); break; | |||
srf = new SRFInt(); break; | |||
case Type::FLOAT: | |||
tag = new SRFFloat(); break; | |||
srf = new SRFFloat(); break; | |||
case Type::DOUBLE: | |||
tag = new SRFDouble(); break; | |||
srf = new SRFDouble(); break; | |||
case Type::NONE: | |||
tag = new SRFNone(); break; | |||
srf = new SRFNone(); break; | |||
case Type::BYTE_ARRAY: | |||
tag = new SRFByteArray(); break; | |||
srf = new SRFByteArray(); break; | |||
case Type::WORD_ARRAY: | |||
tag = new SRFWordArray(); break; | |||
srf = new SRFWordArray(); break; | |||
case Type::INT_ARRAY: | |||
tag = new SRFIntArray(); break; | |||
srf = new SRFIntArray(); break; | |||
case Type::FLOAT_ARRAY: | |||
tag = new SRFFloatArray(); break; | |||
srf = new SRFFloatArray(); break; | |||
case Type::DOUBLE_ARRAY: | |||
tag = new SRFDoubleArray(); break; | |||
srf = new SRFDoubleArray(); break; | |||
} | |||
tag->parse(is); | |||
return tag; | |||
srf->parse(is); | |||
return srf; | |||
} | |||
SRFObject::SRFObject(std::initializer_list<std::pair<std::string, SRFVal *>> &lst) { | |||
for (auto &pair: lst) | |||
val[pair.first] = std::unique_ptr<SRFVal>(pair.second); | |||
SRFObject::SRFObject(std::initializer_list<std::pair<std::string, SRF *>> &lst) { | |||
for (auto &[k, v]: lst) | |||
val[k] = std::unique_ptr<SRF>(v); | |||
} | |||
void SRFObject::serialize(std::ostream &os) { | |||
void SRFObject::serialize(std::ostream &os) const { | |||
writeByte(os, (uint8_t)Type::OBJECT); | |||
writeInt(os, val.size()); | |||
for (auto &pair: val) { | |||
writeString(os, pair.first); | |||
pair.second->serialize(os); | |||
for (auto &[k, v]: val) { | |||
writeString(os, k); | |||
v->serialize(os); | |||
} | |||
} | |||
@@ -160,21 +167,36 @@ void SRFObject::parse(std::istream &is) { | |||
for (int32_t i = 0; i < count; ++i) { | |||
std::string key = readString(is); | |||
val[key] = std::unique_ptr<SRFVal>(SRFVal::read(is)); | |||
val[key] = std::unique_ptr<SRF>(SRF::read(is)); | |||
} | |||
} | |||
SRFArray::SRFArray(std::initializer_list<SRFVal *> &lst) { | |||
for (auto &tag: lst) | |||
val.push_back(std::unique_ptr<SRFVal>(tag)); | |||
std::ostream &SRFObject::pretty(std::ostream &os) const { | |||
os << "{ "; | |||
bool first = true; | |||
for (auto &[k, v]: val) { | |||
if (!first) | |||
os << ", "; | |||
os << '\'' << k << "': "; | |||
v->pretty(os); | |||
first = false; | |||
} | |||
return os << " }"; | |||
} | |||
void SRFArray::serialize(std::ostream &os) { | |||
SRFArray::SRFArray(std::initializer_list<SRF *> &lst) { | |||
for (auto &v: lst) | |||
val.push_back(std::unique_ptr<SRF>(v)); | |||
} | |||
void SRFArray::serialize(std::ostream &os) const { | |||
writeByte(os, (uint8_t)Type::ARRAY); | |||
writeInt(os, val.size()); | |||
for (auto &tag: val) { | |||
tag->serialize(os); | |||
for (auto &v: val) { | |||
v->serialize(os); | |||
} | |||
} | |||
@@ -183,11 +205,25 @@ void SRFArray::parse(std::istream &is) { | |||
val.resize(count); | |||
for (int32_t i = 0; i < count; ++i) { | |||
val[i] = std::unique_ptr<SRFVal>(SRFVal::read(is)); | |||
val[i] = std::unique_ptr<SRF>(SRF::read(is)); | |||
} | |||
} | |||
std::ostream &SRFArray::pretty(std::ostream &os) const { | |||
os << "[ "; | |||
bool first = true; | |||
for (auto &v: val) { | |||
if (!first) | |||
os << ", "; | |||
v->pretty(os); | |||
first = false; | |||
} | |||
return os << " ]"; | |||
} | |||
void SRFString::serialize(std::ostream &os) { | |||
void SRFString::serialize(std::ostream &os) const { | |||
writeByte(os, (uint8_t)Type::STRING); | |||
writeString(os, val); | |||
} | |||
@@ -196,7 +232,11 @@ void SRFString::parse(std::istream &is) { | |||
val = readString(is); | |||
} | |||
void SRFInt::serialize(std::ostream &os) { | |||
std::ostream &SRFString::pretty(std::ostream &os) const { | |||
return os << '"' << val << '"'; | |||
} | |||
void SRFInt::serialize(std::ostream &os) const { | |||
writeByte(os, (uint8_t)Type::INT); | |||
writeInt(os, val); | |||
} | |||
@@ -205,7 +245,11 @@ void SRFInt::parse(std::istream &is) { | |||
val = readInt(is); | |||
} | |||
void SRFFloat::serialize(std::ostream &os) { | |||
std::ostream &SRFInt::pretty(std::ostream &os) const { | |||
return os << val; | |||
} | |||
void SRFFloat::serialize(std::ostream &os) const { | |||
writeByte(os, (uint8_t)Type::FLOAT); | |||
writeFloat(os, val); | |||
} | |||
@@ -214,7 +258,11 @@ void SRFFloat::parse(std::istream &is) { | |||
val = readFloat(is); | |||
} | |||
void SRFDouble::serialize(std::ostream &os) { | |||
std::ostream &SRFFloat::pretty(std::ostream &os) const { | |||
return os << val; | |||
} | |||
void SRFDouble::serialize(std::ostream &os) const { | |||
writeByte(os, (uint8_t)Type::DOUBLE); | |||
writeDouble(os, val); | |||
} | |||
@@ -223,13 +271,21 @@ void SRFDouble::parse(std::istream &is) { | |||
val = readDouble(is); | |||
} | |||
void SRFNone::serialize(std::ostream &os) { | |||
std::ostream &SRFDouble::pretty(std::ostream &os) const { | |||
return os << val; | |||
} | |||
void SRFNone::serialize(std::ostream &os) const { | |||
writeByte(os, (uint8_t)Type::NONE); | |||
} | |||
void SRFNone::parse(std::istream &is) {} | |||
void SRFByteArray::serialize(std::ostream &os) { | |||
std::ostream &SRFNone::pretty(std::ostream &os) const { | |||
return os << "(null)"; | |||
} | |||
void SRFByteArray::serialize(std::ostream &os) const { | |||
writeByte(os, (uint8_t)Type::BYTE_ARRAY); | |||
writeInt(os, val.size()); | |||
os.write((const char *)val.data(), val.size()); | |||
@@ -241,7 +297,16 @@ void SRFByteArray::parse(std::istream &is) { | |||
is.read((char *)val.data(), count); | |||
} | |||
void SRFWordArray::serialize(std::ostream &os) { | |||
std::ostream &SRFByteArray::pretty(std::ostream &os) const { | |||
os << "byte[ " << std::hex; | |||
for (auto v: val) { | |||
os << hexchr((v & 0xf0) >> 4) << hexchr((v & 0x0f) >> 0) << ' '; | |||
} | |||
return os << ']'; | |||
} | |||
void SRFWordArray::serialize(std::ostream &os) const { | |||
writeByte(os, (uint8_t)Type::WORD_ARRAY); | |||
writeInt(os, val.size()); | |||
@@ -259,7 +324,21 @@ void SRFWordArray::parse(std::istream &is) { | |||
} | |||
} | |||
void SRFIntArray::serialize(std::ostream &os) { | |||
std::ostream &SRFWordArray::pretty(std::ostream &os) const { | |||
os << "word[ "; | |||
for (auto v: val) { | |||
os | |||
<< hexchr((v & 0xf000) >> 12) | |||
<< hexchr((v & 0x0f00) >> 8) | |||
<< hexchr((v & 0x00f0) >> 4) | |||
<< hexchr((v & 0x000f) >> 0) | |||
<< ' '; | |||
} | |||
return os << ']'; | |||
} | |||
void SRFIntArray::serialize(std::ostream &os) const { | |||
writeByte(os, (uint8_t)Type::INT_ARRAY); | |||
writeInt(os, val.size()); | |||
@@ -277,7 +356,16 @@ void SRFIntArray::parse(std::istream &is) { | |||
} | |||
} | |||
void SRFFloatArray::serialize(std::ostream &os) { | |||
std::ostream &SRFIntArray::pretty(std::ostream &os) const { | |||
os << "int[ "; | |||
for (auto v: val) { | |||
os << v << ' '; | |||
} | |||
return os << ']'; | |||
} | |||
void SRFFloatArray::serialize(std::ostream &os) const { | |||
writeByte(os, (uint8_t)Type::FLOAT_ARRAY); | |||
writeInt(os, val.size()); | |||
@@ -295,7 +383,16 @@ void SRFFloatArray::parse(std::istream &is) { | |||
} | |||
} | |||
void SRFDoubleArray::serialize(std::ostream &os) { | |||
std::ostream &SRFFloatArray::pretty(std::ostream &os) const { | |||
os << "float[ "; | |||
for (auto v: val) { | |||
os << v << ' '; | |||
} | |||
return os << ']'; | |||
} | |||
void SRFDoubleArray::serialize(std::ostream &os) const { | |||
writeByte(os, (uint8_t)Type::DOUBLE_ARRAY); | |||
writeInt(os, val.size()); | |||
@@ -313,4 +410,13 @@ void SRFDoubleArray::parse(std::istream &is) { | |||
} | |||
} | |||
std::ostream &SRFDoubleArray::pretty(std::ostream &os) const { | |||
os << "double[ "; | |||
for (auto v: val) { | |||
os << v << ' '; | |||
} | |||
return os << ']'; | |||
} | |||
} |
@@ -2,6 +2,7 @@ | |||
#include <math.h> | |||
#include <SFML/System/Clock.hpp> | |||
#include <iostream> | |||
#include "World.h" | |||
#include "Game.h" | |||
@@ -29,16 +30,16 @@ Context WorldPlane::getContext() { | |||
return { .game = *world_->game_, .world = *world_, .plane = *this }; | |||
} | |||
Entity &WorldPlane::spawnEntity(const std::string &name, const Vec2 &pos) { | |||
Entity &WorldPlane::spawnEntity(const std::string &name, const SRF ¶ms) { | |||
if (world_->ents_.find(name) == world_->ents_.end()) { | |||
fprintf(stderr, "Tried to spawn non-existant entity %s!", | |||
name.c_str()); | |||
fprintf(stderr, "Tried to spawn non-existant entity %s!", name.c_str()); | |||
abort(); | |||
} | |||
Entity *ent = world_->ents_[name]->create(getContext(), pos); | |||
Entity *ent = world_->ents_[name]->create(getContext(), params); | |||
entities_.push_back(std::unique_ptr<Entity>(ent)); | |||
fprintf(stderr, "Spawned %s at %f,%f.\n", name.c_str(), pos.x_, pos.y_); | |||
fprintf(stderr, "Spawned %s. SRF: ", name.c_str()); | |||
params.pretty(std::cerr) << '\n'; | |||
return *ent; | |||
} | |||