From bd1e12d636b25afc837daeda163ed40ca7d1b8a3 Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Sat, 13 Jun 2009 21:40:12 +0100 Subject: [PATCH] Mechanism for making choices --- include/IController.hpp | 8 ++++++++ include/ITrackSegment.hpp | 14 ++++++++++++++ include/IterateTrack.hpp | 1 + src/CrossoverTrack.cpp | 4 +++- src/CurvedTrack.cpp | 4 +++- src/Engine.cpp | 21 ++++++++++++++++++++- src/Game.cpp | 21 +++++++++++++++++++-- src/IterateTrack.cpp | 5 ++++- src/Points.cpp | 6 ++++++ src/StraightTrack.cpp | 4 +++- src/Train.cpp | 9 +++++++++ 11 files changed, 90 insertions(+), 7 deletions(-) diff --git a/include/IController.hpp b/include/IController.hpp index 29ee9c8..d51604d 100644 --- a/include/IController.hpp +++ b/include/IController.hpp @@ -19,6 +19,7 @@ #define INC_ICONTROLLER_HPP #include "Platform.hpp" +#include "ITrackSegment.hpp" // Actions the user can send enum Action { @@ -26,6 +27,9 @@ enum Action { SHOVEL_COAL, THROTTLE_UP, THROTTLE_DOWN, + GO_STRAIGHT_ON, + GO_LEFT, + GO_RIGHT, }; // Interface to something that can be controlled by the user @@ -34,6 +38,10 @@ struct IController { virtual void actOn(Action anAction) = 0; + // Return the choice for the next section of track and reset + // it to the default + virtual track::Choice consumeChoice() = 0; + // Get current values for the display virtual int throttle() const = 0; virtual bool brakeOn() const = 0; diff --git a/include/ITrackSegment.hpp b/include/ITrackSegment.hpp index e17e39e..f5a6b34 100644 --- a/include/ITrackSegment.hpp +++ b/include/ITrackSegment.hpp @@ -22,6 +22,7 @@ #include "Maths.hpp" #include +#include namespace xml { struct element; @@ -43,6 +44,13 @@ namespace track { typedef int Angle; typedef std::tr1::function TransformFunc; + + // Choices that the player may make for a track segment + enum Choice { + CHOOSE_STRAIGHT_ON, + CHOOSE_GO_LEFT, + CHOOSE_GO_RIGHT + }; // Sums up all the information required to travel along a piece // of track @@ -53,6 +61,12 @@ namespace track { // Position of entry Position position; + // Default choice + Choice activeChoice; + + // Choices available to the player + set choices; + // A function that transforms the location of the train // so it will render in the correct place for this track segment // The functions assumes that it is initially placed at the origin diff --git a/include/IterateTrack.hpp b/include/IterateTrack.hpp index ff52761..1217871 100644 --- a/include/IterateTrack.hpp +++ b/include/IterateTrack.hpp @@ -32,6 +32,7 @@ enum IterationStatus { TRACK_OK, // No problems TRACK_NO_MORE, // Run off the end of the track! TRACK_STATION, // This segment contains a valid station + TRACK_CHOICE, // Choice to be made! }; // Handle to the current iteration diff --git a/src/CrossoverTrack.cpp b/src/CrossoverTrack.cpp index d86053f..6a2a080 100644 --- a/src/CrossoverTrack.cpp +++ b/src/CrossoverTrack.cpp @@ -108,8 +108,10 @@ CrossoverTrack::getTravelToken(track::Position aPosition, track::TravelToken tok = { aDirection, aPosition, - bind(&CrossoverTrack::transform, this, aDirection, _1) + track::CHOOSE_STRAIGHT_ON }; + tok.transformer = bind(&CrossoverTrack::transform, this, aDirection, _1); + tok.choices.insert(track::CHOOSE_STRAIGHT_ON); return tok; } diff --git a/src/CurvedTrack.cpp b/src/CurvedTrack.cpp index 3c9ba63..858c0ba 100644 --- a/src/CurvedTrack.cpp +++ b/src/CurvedTrack.cpp @@ -89,9 +89,11 @@ CurvedTrack::getTravelToken(track::Position aPosition, track::TravelToken tok = { aDirection, - aPosition + aPosition, + track::CHOOSE_STRAIGHT_ON, }; tok.transformer = bind(&CurvedTrack::transform, this, tok, _1); + tok.choices.insert(track::CHOOSE_STRAIGHT_ON); return tok; } diff --git a/src/Engine.cpp b/src/Engine.cpp index 037fbca..7729144 100644 --- a/src/Engine.cpp +++ b/src/Engine.cpp @@ -75,6 +75,7 @@ public: bool brakeOn() const { return isBrakeOn; } double pressure() const { return myBoilerPressure; } double temp() const { return myFireTemp; } + track::Choice consumeChoice(); private: double tractiveEffort() const; double resistance() const; @@ -87,6 +88,8 @@ private: bool isBrakeOn; int myThrottle; // Ratio measured in tenths + track::Choice myNextChoice; + // Boiler pressure lags behind temperature MovingAverage myBoilerDelay; @@ -169,6 +172,13 @@ void Engine::update(int aDelta) << " (delta=" << aDelta << ")";*/ } +track::Choice Engine::consumeChoice() +{ + track::Choice c = myNextChoice; + myNextChoice = track::CHOOSE_STRAIGHT_ON; + return c; +} + // User interface to the engine void Engine::actOn(Action anAction) { @@ -185,7 +195,16 @@ void Engine::actOn(Action anAction) break; case THROTTLE_DOWN: myThrottle = max(myThrottle - 1, 0); - break; + break; + case GO_STRAIGHT_ON: + myNextChoice = track::CHOOSE_STRAIGHT_ON; + break; + case GO_LEFT: + myNextChoice = track::CHOOSE_GO_LEFT; + break; + case GO_RIGHT: + myNextChoice = track::CHOOSE_GO_RIGHT; + break; default: break; } diff --git a/src/Game.cpp b/src/Game.cpp index bf3b1f8..4e24ac2 100644 --- a/src/Game.cpp +++ b/src/Game.cpp @@ -213,18 +213,26 @@ void Game::lookAhead() it = it.next(); if (it.status != TRACK_OK) { + bool clearStation = true; + switch (it.status) { case TRACK_STATION: setStatus("Approaching station " + it.station->name()); nearStation(it.station); - break; + clearStation = false; + return; case TRACK_NO_MORE: setStatus("Oh no! You're going to crash!"); - leftStation(); + break; + case TRACK_CHOICE: + setStatus("Oh no! You have to make a decision!"); break; default: break; } + + if (!clearStation) + leftStation(); return; } } @@ -260,6 +268,15 @@ void Game::onKeyDown(SDLKey aKey) case SDLK_PRINT: getGameWindow()->takeScreenShot(); break; + case SDLK_LEFT: + myTrain->controller()->actOn(GO_LEFT); + break; + case SDLK_RIGHT: + myTrain->controller()->actOn(GO_RIGHT); + break; + case SDLK_UP: + myTrain->controller()->actOn(GO_STRAIGHT_ON); + break; default: break; } diff --git a/src/IterateTrack.cpp b/src/IterateTrack.cpp index 410e323..a838bb3 100644 --- a/src/IterateTrack.cpp +++ b/src/IterateTrack.cpp @@ -36,7 +36,7 @@ TrackIterator iterateTrack(IMapPtr aMap, track::Position aPosition, { TrackIterator it; it.map = aMap; - it.status = TRACK_OK; + it.status = TRACK_OK ; if (aMap->isValidTrack(aPosition)) { it.track = aMap->trackAt(aPosition); @@ -61,6 +61,9 @@ TrackIterator iterateTrack(IMapPtr aMap, track::Position aPosition, it.status = TRACK_STATION; break; } + + if (it.token.choices.size() > 1) + it.status = TRACK_CHOICE; return it; } diff --git a/src/Points.cpp b/src/Points.cpp index 6b9bda1..b23590a 100644 --- a/src/Points.cpp +++ b/src/Points.cpp @@ -131,8 +131,14 @@ track::TravelToken Points::getTravelToken(track::Position aPosition, track::TravelToken tok = { aDirection, aPosition, + track::CHOOSE_STRAIGHT_ON, }; tok.transformer = bind(&Points::transform, this, tok, _1); + tok.choices.insert(track::CHOOSE_STRAIGHT_ON); + + if (aPosition.x == myX && aPosition.y == myY) + tok.choices.insert(track::CHOOSE_GO_RIGHT); + return tok; } diff --git a/src/StraightTrack.cpp b/src/StraightTrack.cpp index 2afd8fa..d92161d 100644 --- a/src/StraightTrack.cpp +++ b/src/StraightTrack.cpp @@ -81,8 +81,10 @@ StraightTrack::getTravelToken(track::Position aPosition, track::TravelToken tok = { aDirection, aPosition, - bind(&StraightTrack::transform, this, aDirection, _1) + track::CHOOSE_STRAIGHT_ON }; + tok.transformer = bind(&StraightTrack::transform, this, aDirection, _1); + tok.choices.insert(track::CHOOSE_STRAIGHT_ON); return tok; } diff --git a/src/Train.cpp b/src/Train.cpp index 49aa4e9..360c598 100644 --- a/src/Train.cpp +++ b/src/Train.cpp @@ -213,6 +213,15 @@ void Train::enterSegment(Part& aPart, const track::Connection& aConnection) aPart.segmentDelta = 0.0; aPart.segment = myMap->trackAt(pos); aPart.travelToken = aPart.segment->getTravelToken(pos, aPart.direction); + + if (aPart.travelToken.choices.size() > 1) { + // Need to make a choice: see what the controller has pre-set + track::Choice choice = engine().vehicle->controller()->consumeChoice(); + + debug() << "Choice: " << choice; + + aPart.travelToken.activeChoice = choice; + } } void Train::render() const -- 2.39.2