From: Daniel Karbach Date: Fri, 5 Oct 2012 13:54:50 +0000 (+0200) Subject: more Vector operations X-Git-Url: https://git.localhorst.tv/?a=commitdiff_plain;h=be3b4e75c82b6e9d2b5c4300138d490ec1a4932a;p=l2e.git more Vector operations there are not real vector operations in a mathematical sense, but are useful nonetheless --- diff --git a/src/geometry/Vector.h b/src/geometry/Vector.h index 7c698ff..c6a42fb 100644 --- a/src/geometry/Vector.h +++ b/src/geometry/Vector.h @@ -8,6 +8,8 @@ #ifndef GEOMETRY_VECTOR_H_ #define GEOMETRY_VECTOR_H_ +#include +#include #include namespace geometry { @@ -27,6 +29,13 @@ public: Scalar X() const { return x; } Scalar Y() const { return y; } + Scalar Index(Scalar lineLength) const { return Y() * lineLength + X(); } + static Vector FromIndex(Scalar index, Scalar lineLength) { + return Vector(index % lineLength, index / lineLength); + } + + void Lock(const Vector &to); + private: Scalar x, y; @@ -74,6 +83,10 @@ inline Vector operator -(const Vector &v) { return Vector(-v.X(), -v.Y()); } +template +inline Vector operator *(const Vector &v1, const Vector &v2) { + return Vector(v1.X() * v2.X(), v1.Y() * v2.Y()); +} template inline Vector operator *(const Vector &v, T s) { return Vector(v.X() * s, v.Y() * s); @@ -83,10 +96,51 @@ inline Vector operator *(T s, const Vector &v) { return Vector(s * v.X(), s * v.Y()); } +template +inline Vector operator /(const Vector &v1, const Vector &v2) { + return Vector(v1.X() / v2.X(), v1.Y() / v2.Y()); +} template inline Vector operator /(const Vector &v, T s) { return Vector(v.X() / s, v.Y() / s); } +template +inline Vector operator /(T s, const Vector &v) { + return Vector(s / v.X(), s / v.Y()); +} + +template +inline Vector operator %(const Vector &v1, const Vector &v2) { + return Vector(v1.X() % v2.X(), v1.Y() % v2.Y()); +} +template<> +inline Vector operator %(const Vector &v1, const Vector &v2) { + return Vector(std::fmod(v1.X(), v2.X()), std::fmod(v1.Y(), v2.Y())); +} +template<> +inline Vector operator %(const Vector &v1, const Vector &v2) { + return Vector(std::fmod(v1.X(), v2.X()), std::fmod(v1.Y(), v2.Y())); +} +template<> +inline Vector operator %(const Vector &v1, const Vector &v2) { + return Vector(std::fmod(v1.X(), v2.X()), std::fmod(v1.Y(), v2.Y())); +} +template +inline Vector operator %(const Vector &v, T s) { + return Vector(v.X() % s, v.Y() % s); +} +template<> +inline Vector operator %(const Vector &v, float s) { + return Vector(std::fmod(v.X(), s), std::fmod(v.Y(), s)); +} +template<> +inline Vector operator %(const Vector &v, double s) { + return Vector(std::fmod(v.X(), s), std::fmod(v.Y(), s)); +} +template<> +inline Vector operator %(const Vector &v, long double s) { + return Vector(std::fmod(v.X(), s), std::fmod(v.Y(), s)); +} template inline bool operator ==(const Vector &lhs, const Vector &rhs) { @@ -104,6 +158,26 @@ inline std::ostream &operator <<(std::ostream &out, const Vector &v) { return out; } + +template +void Vector::Lock(const Vector &to) { + Vector half(to / Scalar(2)); + Vector dist((*this) % to); + + if (dist.X() > half.X()) { + x += (to.X() - dist.X()); + } else { + x -= dist.X(); + } + + if (dist.Y() > half.Y()) { + y += (to.Y() - dist.Y()); + } else { + y -= dist.Y(); + } +} + + } #endif /* GEOMETRY_VECTOR_H_ */ diff --git a/src/map/Area.h b/src/map/Area.h index 9832809..e2b6a1e 100644 --- a/src/map/Area.h +++ b/src/map/Area.h @@ -25,6 +25,7 @@ public: public: int Width() const { return width; } int Height() const { return numTiles / width + (numTiles % width ? 1 : 0); } + geometry::Vector Size() const { return geometry::Vector(Width(), Height()); } const Tile &TileAt(const geometry::Vector &) const; void Render(SDL_Surface *dest, const graphics::Sprite *tileset, const geometry::Vector &offset) const; diff --git a/src/map/Map.cpp b/src/map/Map.cpp index 10b74d0..20f2fa5 100644 --- a/src/map/Map.cpp +++ b/src/map/Map.cpp @@ -31,8 +31,8 @@ Map::Map() const Area &Map::AreaAt(const Vector &offset) const { if (numAreas > 0) { Vector coords(TileCoordinates(offset)); - Vector areaOffset(coords.X() / areas[0].Width(), coords.Y() / areas[0].Height()); - int areaIndex(areaOffset.Y() * width + areaOffset.X()); + Vector areaOffset(coords / areas[0].Size()); + int areaIndex(areaOffset.Index(width)); if (areaIndex < numAreas) { return areas[areaIndex]; } @@ -42,7 +42,7 @@ const Area &Map::AreaAt(const Vector &offset) const { const Tile &Map::TileAt(const Vector &offset) const { const Area &area(AreaAt(offset)); - Vector tileOffset((offset.X() / tileset->Width()) % area.Width(), (offset.Y() / tileset->Height()) % area.Height()); + Vector tileOffset(TileCoordinates(offset) % area.Size()); return area.TileAt(tileOffset); } @@ -58,7 +58,7 @@ Trigger *Map::TriggerAt(const geometry::Vector &offset) { } Vector Map::TileCoordinates(const Vector &position) const { - return Vector(position.X() / tileset->Width(), position.Y() / tileset->Height()); + return position / tileset->Size(); } @@ -66,9 +66,7 @@ void Map::Render(SDL_Surface *dest, const Vector &inOffset) const { // TODO: skip invisible areas for (int i(0); i < numAreas; ++i) { const Area &area(areas[i]); - Vector offset( - inOffset.X() + (i % width) * area.Width() * tileset->Width(), - inOffset.Y() + (i / width) * area.Height() * tileset->Height()); + Vector offset(inOffset + Vector::FromIndex(i, width) * area.Size() * tileset->Size()); area.Render(dest, tileset, offset); } }