4 * Created on: Sep 29, 2012
12 #include "../app/Application.h"
13 #include "../app/Input.h"
17 using app::Application;
19 using geometry::Vector;
23 MapState::MapState(Map *map)
27 , camera(100, 100, &tempTarget)
36 void MapState::EnterState(Application &ctrl, SDL_Surface *screen) {
37 camera.Resize(screen->w, screen->h);
40 void MapState::ExitState(Application &ctrl, SDL_Surface *screen) {
44 void MapState::ResumeState(Application &ctrl, SDL_Surface *screen) {
45 camera.Resize(screen->w, screen->h);
48 void MapState::PauseState(Application &ctrl, SDL_Surface *screen) {
52 void MapState::Resize(int width, int height) {
53 camera.Resize(width, height);
57 void MapState::HandleEvents(const Input &input) {
58 if (!controlled) return;
60 if (input.IsDown(Input::PAD_UP)) {
61 nextDirection = Entity::ORIENTATION_NORTH;
62 } else if (input.IsDown(Input::PAD_RIGHT)) {
63 nextDirection = Entity::ORIENTATION_EAST;
64 } else if (input.IsDown(Input::PAD_DOWN)) {
65 nextDirection = Entity::ORIENTATION_SOUTH;
66 } else if (input.IsDown(Input::PAD_LEFT)) {
67 nextDirection = Entity::ORIENTATION_WEST;
72 if (input.JustPressed(Input::DEBUG_1)) {
77 void MapState::UpdateWorld(float deltaT) {
78 if (controlled && controlled->TileLock(map->Tileset()->Size())) {
81 for (std::vector<Entity *>::iterator i(entities.begin()), end(entities.end()); i != end; ++i) {
86 void MapState::OnTileLock() {
87 if (moveTimer.Running() && !moveTimer.JustHit()) return;
89 Vector<int> nowLock(controlled->Position());
90 if (nowLock != lastLock) {
94 } else if (moveTimer.JustHit()) {
99 // TODO: halt all activity if lock caused a state/map transition
101 if (nextDirection >= 0) {
102 bool blocked(CheckBlocking());
107 controlled->SetOrientation(Entity::Orientation(nextDirection));
109 controlled->SetSpeed(walkingSpeed);
112 controlled->SetSpeed(0.0f);
113 StopFollowers(*controlled);
114 if (!moveTimer.Running()) {
115 int tileSize((controlled->GetOrientation() % 2) ? map->Tileset()->Width() : map->Tileset()->Height());
116 moveTimer = PhysicsTimers().StartInterval(tileSize/walkingSpeed);
119 if (!controlled->AnimationRunning()) {
120 controlled->StartAnimation(*this);
123 controlled->SetSpeed(0.0f);
124 StopFollowers(*controlled);
125 controlled->StopAnimation();
132 bool MapState::CheckBlocking() const {
133 const Tile &tile(map->TileAt(controlled->Position()));
134 Vector<int> nextPosition;
135 switch (nextDirection) {
136 case Entity::ORIENTATION_NORTH:
137 if (tile.BlocksNorth()) {
140 nextPosition = Vector<int>(
141 controlled->Position().X(),
142 controlled->Position().Y() - map->Tileset()->Height());
145 case Entity::ORIENTATION_EAST:
146 if (tile.BlocksEast()) {
149 nextPosition = Vector<int>(
150 controlled->Position().X() + map->Tileset()->Width(),
151 controlled->Position().Y());
154 case Entity::ORIENTATION_SOUTH:
155 if (tile.BlocksSouth()) {
158 nextPosition = Vector<int>(
159 controlled->Position().X(),
160 controlled->Position().Y() + map->Tileset()->Height());
163 case Entity::ORIENTATION_WEST:
164 if (tile.BlocksWest()) {
167 nextPosition = Vector<int>(
168 controlled->Position().X() - map->Tileset()->Width(),
169 controlled->Position().Y());
175 Vector<int> nextTileCoords(map->TileCoordinates(nextPosition));
176 for (std::vector<Entity *>::const_iterator i(entities.begin()), end(entities.end()); i != end; ++i) {
177 const Entity &e(**i);
178 if (map->TileCoordinates(e.Position()) == nextTileCoords && e.Blocking()) {
185 void MapState::OnGridLock() {
191 void MapState::LockEntities() {
192 for (std::vector<Entity *>::iterator i(entities.begin()), end(entities.end()); i != end; ++i) {
193 if (*i == controlled) {
197 (*i)->Position().Lock(map->Tileset()->Size());
201 void MapState::CheckMonster() {
202 Vector<int> coords(map->TileCoordinates(controlled->Position()));
203 Vector<int> neighbor[4];
204 neighbor[0] = Vector<int>(coords.X(), coords.Y() - 1); // N
205 neighbor[1] = Vector<int>(coords.X() + 1, coords.Y()); // E
206 neighbor[2] = Vector<int>(coords.X(), coords.Y() + 1); // S
207 neighbor[3] = Vector<int>(coords.X() - 1, coords.Y()); // W
209 for (int i(0); i < 4; ++i) {
210 for (std::vector<Entity *>::iterator e(entities.begin()), end(entities.end()); e != end; ++e) {
211 if ((*e)->Hostile() && map->TileCoordinates((*e)->Position()) == neighbor[i]) {
212 // TODO: check for turn advantage, see #26
213 // TODO: remove entity, push battle state and transition and halt all other activity
214 // needed information here:
215 // - battle background (from tile?)
216 // - monsters + layout (from entity)
217 // - battle resources (from global resources)
223 void MapState::CheckTrigger() {
224 Trigger *trigger(map->TriggerAt(Vector<int>(controlled->Position())));
231 void MapState::OnMove(bool realMove) {
232 // TODO: evaluate monster movements
234 UpdateFollower(*controlled);
236 StopFollowers(*controlled);
240 void MapState::UpdateFollower(Entity &e) {
241 if (!e.Follower()) return;
243 Entity &f(*e.Follower());
246 Vector<int> coords(map->TileCoordinates(e.Position()));
247 Vector<int> fCoords(map->TileCoordinates(f.Position()));
248 Vector<int> direction(coords - fCoords);
250 if (direction.Y() < 0) {
251 f.SetOrientation(Entity::ORIENTATION_NORTH);
252 f.SetSpeed(walkingSpeed);
253 f.StartAnimation(*this);
254 } else if (direction.X() > 0) {
255 f.SetOrientation(Entity::ORIENTATION_EAST);
256 f.SetSpeed(walkingSpeed);
257 f.StartAnimation(*this);
258 } else if (direction.Y() > 0) {
259 f.SetOrientation(Entity::ORIENTATION_SOUTH);
260 f.SetSpeed(walkingSpeed);
261 f.StartAnimation(*this);
262 } else if (direction.X() < 0) {
263 f.SetOrientation(Entity::ORIENTATION_WEST);
264 f.SetSpeed(walkingSpeed);
265 f.StartAnimation(*this);
272 void MapState::StopFollowers(Entity &e) {
273 for (Entity *f(e.Follower()); f; f = f->Follower()) {
280 void MapState::Render(SDL_Surface *screen) {
281 SDL_FillRect(screen, 0, SDL_MapRGB(screen->format, 0, 0, 0));
283 Vector<int> offset(camera.CalculateOffset());
284 map->Render(screen, offset);
287 map->RenderDebug(screen, offset);
290 std::sort(entities.begin(), entities.end(), ZCompare);
291 for (std::vector<Entity *>::iterator i(entities.begin()), end(entities.end()); i != end; ++i) {
292 (*i)->Render(screen, offset);
297 bool MapState::ZCompare(const Entity *lhs, const Entity *rhs) {
298 return lhs->Position().Y() < rhs->Position().Y();