From 5c476344f7f7a289cc4cb195622e8f789ee2ff18 Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Sun, 28 Feb 2010 16:47:29 +0000 Subject: [PATCH] Only allow track to be placed on level ground --- include/IMap.hpp | 6 ++++++ include/Maths.hpp | 7 +++++++ src/Editor.cpp | 13 +++++++++++-- src/Map.cpp | 40 ++++++++++++++++++++++++++++++++++++---- 4 files changed, 60 insertions(+), 6 deletions(-) diff --git a/include/IMap.hpp b/include/IMap.hpp index 115f3db..7246c70 100644 --- a/include/IMap.hpp +++ b/include/IMap.hpp @@ -109,6 +109,12 @@ public: // Get the height above ground at a particular point virtual float heightAt(float x, float y) const = 0; + // Given a tile and an axis, return a vector indicating the slope + // along that axis. `level' is set if the slope is the same across + // the tile + virtual Vector slopeAt(Point where, + track::Direction axis, bool& level) const = 0; + // Place a tree, building, etc. at a location virtual void addScenery(Point where, ISceneryPtr s) = 0; diff --git a/include/Maths.hpp b/include/Maths.hpp index 4005667..90a0a6b 100644 --- a/include/Maths.hpp +++ b/include/Maths.hpp @@ -112,6 +112,13 @@ struct Vector { { return !(v == *this); } + + bool approxEqual(const Vector& rhs, T delta) const + { + return (abs(rhs.x - x) < delta) + && (abs(rhs.y - y) < delta) + && (abs(rhs.z - z) < delta); + } T x, y, z; }; diff --git a/src/Editor.cpp b/src/Editor.cpp index 407f6f1..ef2388f 100644 --- a/src/Editor.cpp +++ b/src/Editor.cpp @@ -233,8 +233,17 @@ bool Editor::drawTrackTile(const Point& aPoint, const track::Direction& anA } } else { - map->setTrackAt(aPoint, makeStraightTrack(anAxis)); - return true; + bool level; + Vector slope = map->slopeAt(aPoint, anAxis, level); + + if (level) { + map->setTrackAt(aPoint, makeStraightTrack(anAxis)); + return true; + } + else { + warn() << "Track must be placed on level ground"; + return false; + } } } diff --git a/src/Map.cpp b/src/Map.cpp index 3eed064..f5fff54 100644 --- a/src/Map.cpp +++ b/src/Map.cpp @@ -110,6 +110,8 @@ public: IStationPtr extendStation(Point aStartPos, Point aFinishPos); float heightAt(float x, float y) const; + Vector slopeAt(Point where, track::Direction axis, + bool& level) const; void addScenery(Point where, ISceneryPtr s); // ISectorRenderable interface @@ -888,10 +890,10 @@ void Map::tileVertices(int x, int y, int* indexes) const { assert(x >= 0 && x < myWidth && y >= 0 && y < myDepth); - indexes[3] = x + (y * (myWidth+1)); - indexes[2] = (x+1) + (y * (myWidth+1)); - indexes[1] = (x+1) + ((y+1) * (myWidth+1)); - indexes[0] = x + ((y+1) * (myWidth+1)); + indexes[3] = x + (y * (myWidth+1)); // (X, Y) + indexes[2] = (x+1) + (y * (myWidth+1)); // (X+1, Y) + indexes[1] = (x+1) + ((y+1) * (myWidth+1)); // (X+1, Y+1) + indexes[0] = x + ((y+1) * (myWidth+1)); // (X, Y+1) } // True if changing the height of this tile will affect @@ -968,6 +970,36 @@ float Map::heightAt(float x, float y) const return avg / 4.0f; } +Vector Map::slopeAt(Point where, + track::Direction axis, bool &level) const +{ + int indexes[4]; + tileVertices(where.x, where.y, indexes); + + // This is slightly consfusing since the track Y axis + // is the Z axis in the height map + + Vector v1, v2; + + if (axis == axis::X) { + v1 = heightMap[indexes[2]].pos - heightMap[indexes[3]].pos; + v2 = heightMap[indexes[1]].pos - heightMap[indexes[0]].pos; + } + else { + v1 = heightMap[indexes[0]].pos - heightMap[indexes[3]].pos; + v2 = heightMap[indexes[1]].pos - heightMap[indexes[2]].pos; + } + + level = v1.approxEqual(v2, 0.001f); + + debug() << "slopeAt where=" << where + << " axis=" << axis + << " v1=" << v1 << " v2=" << v2 + << " level=" << level; + + return v1; +} + void Map::changeAreaHeight(const Point& aStartPos, const Point& aFinishPos, float aHeightDelta) -- 2.39.2