4 * Created on: Sep 29, 2012
12 #include "TransitionState.h"
14 #include "../app/Application.h"
15 #include "../app/Input.h"
16 #include "../graphics/ColorFade.h"
20 using app::Application;
22 using geometry::Vector;
23 using graphics::ColorFade;
27 MapState::MapState(Map *map)
32 , camera(100, 100, &tempTarget)
42 void MapState::EnterState(Application &c, SDL_Surface *screen) {
44 camera.Resize(screen->w, screen->h);
48 void MapState::ExitState(Application &ctrl, SDL_Surface *screen) {
52 void MapState::ResumeState(Application &ctrl, SDL_Surface *screen) {
53 camera.Resize(screen->w, screen->h);
56 void MapState::PauseState(Application &ctrl, SDL_Surface *screen) {
60 void MapState::Resize(int width, int height) {
61 camera.Resize(width, height);
65 void MapState::HandleEvents(const Input &input) {
66 if (!controlled) return;
68 if (input.IsDown(Input::PAD_UP)) {
69 nextDirection = Entity::ORIENTATION_NORTH;
70 } else if (input.IsDown(Input::PAD_RIGHT)) {
71 nextDirection = Entity::ORIENTATION_EAST;
72 } else if (input.IsDown(Input::PAD_DOWN)) {
73 nextDirection = Entity::ORIENTATION_SOUTH;
74 } else if (input.IsDown(Input::PAD_LEFT)) {
75 nextDirection = Entity::ORIENTATION_WEST;
80 if (input.JustPressed(Input::DEBUG_1)) {
85 void MapState::UpdateWorld(float deltaT) {
86 if (controlled && controlled->TileLock(map->Tileset()->Size())) {
89 for (std::vector<Entity *>::iterator i(entities.begin()), end(entities.end()); i != end; ++i) {
94 void MapState::OnTileLock() {
95 if (moveTimer.Running() && !moveTimer.JustHit()) return;
97 Vector<int> nowLock(controlled->Position());
98 if (nowLock != lastLock) {
102 } else if (moveTimer.JustHit()) {
107 // TODO: halt all activity if lock caused a state/map transition
109 if (nextDirection >= 0) {
110 bool blocked(CheckBlocking());
115 controlled->SetOrientation(Entity::Orientation(nextDirection));
117 controlled->SetSpeed(walkingSpeed);
120 controlled->SetSpeed(0.0f);
121 StopFollowers(*controlled);
122 if (!moveTimer.Running()) {
123 int tileSize((controlled->GetOrientation() % 2) ? map->Tileset()->Width() : map->Tileset()->Height());
124 moveTimer = PhysicsTimers().StartInterval(tileSize/walkingSpeed);
127 if (!controlled->AnimationRunning()) {
128 controlled->StartAnimation(*this);
131 controlled->SetSpeed(0.0f);
132 StopFollowers(*controlled);
133 controlled->StopAnimation();
140 bool MapState::CheckBlocking() const {
141 const Tile *tile(map->TileAt(controlled->Position()));
145 Vector<int> nextPosition;
146 switch (nextDirection) {
147 case Entity::ORIENTATION_NORTH:
148 if (tile->BlocksNorth()) {
151 nextPosition = Vector<int>(
152 controlled->Position().X(),
153 controlled->Position().Y() - map->Tileset()->Height());
156 case Entity::ORIENTATION_EAST:
157 if (tile->BlocksEast()) {
160 nextPosition = Vector<int>(
161 controlled->Position().X() + map->Tileset()->Width(),
162 controlled->Position().Y());
165 case Entity::ORIENTATION_SOUTH:
166 if (tile->BlocksSouth()) {
169 nextPosition = Vector<int>(
170 controlled->Position().X(),
171 controlled->Position().Y() + map->Tileset()->Height());
174 case Entity::ORIENTATION_WEST:
175 if (tile->BlocksWest()) {
178 nextPosition = Vector<int>(
179 controlled->Position().X() - map->Tileset()->Width(),
180 controlled->Position().Y());
186 Vector<int> nextTileCoords(map->TileCoordinates(nextPosition));
187 for (std::vector<Entity *>::const_iterator i(entities.begin()), end(entities.end()); i != end; ++i) {
188 const Entity &e(**i);
189 if (map->TileCoordinates(e.Position()) == nextTileCoords && e.Blocking()) {
196 void MapState::OnGridLock() {
206 void MapState::LockEntities() {
207 for (std::vector<Entity *>::iterator i(entities.begin()), end(entities.end()); i != end; ++i) {
208 if (*i == controlled) {
212 (*i)->Position().Lock(map->Tileset()->Size());
216 void MapState::CheckMonster() {
217 Vector<int> coords(map->TileCoordinates(controlled->Position()));
218 Vector<int> neighbor[4];
219 neighbor[0] = Vector<int>(coords.X(), coords.Y() - 1); // N
220 neighbor[1] = Vector<int>(coords.X() + 1, coords.Y()); // E
221 neighbor[2] = Vector<int>(coords.X(), coords.Y() + 1); // S
222 neighbor[3] = Vector<int>(coords.X() - 1, coords.Y()); // W
224 for (int i(0); i < 4; ++i) {
225 for (std::vector<Entity *>::iterator e(entities.begin()), end(entities.end()); e != end; ++e) {
226 if ((*e)->Hostile() && map->TileCoordinates((*e)->Position()) == neighbor[i]) {
227 // TODO: check for turn advantage, see #26
228 // TODO: remove entity, push battle state and transition and halt all other activity
229 // needed information here:
230 // - battle background (from tile?)
231 // - monsters + layout (from entity)
232 // - battle resources (from global resources)
238 void MapState::CheckTrigger() {
239 Trigger *trigger(map->TriggerAt(Vector<int>(controlled->Position())));
241 // TODO: run trigger script
243 ctrl->PushState(new ColorFade(this, 0, 500, true));
244 ctrl->PushState(new TransitionState(this, trigger->map, trigger->target));
245 ColorFade *fadeOut(new ColorFade(this, 0, 500, false));
246 fadeOut->SetLeadOutTime(500);
247 ctrl->PushState(fadeOut);
253 void MapState::OnMove(bool realMove) {
254 // TODO: evaluate monster movements
256 UpdateFollower(*controlled);
258 StopFollowers(*controlled);
262 void MapState::UpdateFollower(Entity &e) {
263 if (!e.Follower()) return;
265 Entity &f(*e.Follower());
268 Vector<int> coords(map->TileCoordinates(e.Position()));
269 Vector<int> fCoords(map->TileCoordinates(f.Position()));
270 Vector<int> direction(coords - fCoords);
272 if (direction.Y() < 0) {
273 f.SetOrientation(Entity::ORIENTATION_NORTH);
274 f.SetSpeed(walkingSpeed);
275 f.StartAnimation(*this);
276 } else if (direction.X() > 0) {
277 f.SetOrientation(Entity::ORIENTATION_EAST);
278 f.SetSpeed(walkingSpeed);
279 f.StartAnimation(*this);
280 } else if (direction.Y() > 0) {
281 f.SetOrientation(Entity::ORIENTATION_SOUTH);
282 f.SetSpeed(walkingSpeed);
283 f.StartAnimation(*this);
284 } else if (direction.X() < 0) {
285 f.SetOrientation(Entity::ORIENTATION_WEST);
286 f.SetSpeed(walkingSpeed);
287 f.StartAnimation(*this);
294 void MapState::StopFollowers(Entity &e) {
295 for (Entity *f(e.Follower()); f; f = f->Follower()) {
302 void MapState::Transition(Map *newMap, const Vector<int> &coordinates) {
304 Vector<int> position(coordinates * map->Tileset()->Size());
305 for (Entity *e(controlled); e; e = e->Follower()) {
306 e->Position() = position;
307 e->SetOrientation(controlled->GetOrientation());
313 void MapState::UnloadMap() {
317 void MapState::LoadMap(Map *m) {
319 entities.insert(entities.end(), m->EntitiesBegin(), m->EntitiesEnd());
320 for (Entity *e(controlled); e; e = e->Follower()) {
321 entities.push_back(e);
326 void MapState::Render(SDL_Surface *screen) {
327 SDL_FillRect(screen, 0, SDL_MapRGB(screen->format, 0, 0, 0));
329 Vector<int> offset(camera.CalculateOffset());
330 map->Render(screen, offset);
333 map->RenderDebug(screen, offset);
336 std::sort(entities.begin(), entities.end(), ZCompare);
337 for (std::vector<Entity *>::iterator i(entities.begin()), end(entities.end()); i != end; ++i) {
338 (*i)->Render(screen, offset);
343 bool MapState::ZCompare(const Entity *lhs, const Entity *rhs) {
344 return lhs->Position().Y() < rhs->Position().Y();