4 * Created on: Sep 29, 2012
13 #include "../app/Application.h"
14 #include "../app/Input.h"
18 using app::Application;
20 using geometry::Vector;
24 MapState::MapState(Map *map)
28 , camera(100, 100, &tempTarget)
38 void MapState::EnterState(Application &ctrl, SDL_Surface *screen) {
39 camera.Resize(screen->w, screen->h);
42 void MapState::ExitState(Application &ctrl, SDL_Surface *screen) {
46 void MapState::ResumeState(Application &ctrl, SDL_Surface *screen) {
47 camera.Resize(screen->w, screen->h);
50 void MapState::PauseState(Application &ctrl, SDL_Surface *screen) {
54 void MapState::Resize(int width, int height) {
55 camera.Resize(width, height);
59 void MapState::HandleEvents(const Input &input) {
60 if (!controlled) return;
62 if (input.IsDown(Input::PAD_UP)) {
63 nextDirection = Entity::ORIENTATION_NORTH;
64 } else if (input.IsDown(Input::PAD_RIGHT)) {
65 nextDirection = Entity::ORIENTATION_EAST;
66 } else if (input.IsDown(Input::PAD_DOWN)) {
67 nextDirection = Entity::ORIENTATION_SOUTH;
68 } else if (input.IsDown(Input::PAD_LEFT)) {
69 nextDirection = Entity::ORIENTATION_WEST;
74 if (input.JustPressed(Input::DEBUG_1)) {
79 void MapState::UpdateWorld(float deltaT) {
80 if (controlled && controlled->TileLock(map->Tileset()->Size())) {
83 for (std::vector<Entity *>::iterator i(entities.begin()), end(entities.end()); i != end; ++i) {
88 void MapState::OnTileLock() {
89 if (moveTimer.Running() && !moveTimer.JustHit()) return;
91 Vector<int> nowLock(controlled->Position());
92 if (nowLock != lastLock) {
96 } else if (moveTimer.JustHit()) {
101 // TODO: halt all activity if lock caused a state/map transition
103 if (nextDirection >= 0) {
104 bool blocked(CheckBlocking());
109 controlled->SetOrientation(Entity::Orientation(nextDirection));
111 controlled->SetSpeed(walkingSpeed);
114 controlled->SetSpeed(0.0f);
115 StopFollowers(*controlled);
116 if (!moveTimer.Running()) {
117 int tileSize((controlled->GetOrientation() % 2) ? map->Tileset()->Width() : map->Tileset()->Height());
118 moveTimer = PhysicsTimers().StartInterval(tileSize/walkingSpeed);
121 if (!controlled->AnimationRunning()) {
122 controlled->StartAnimation(*this);
125 controlled->SetSpeed(0.0f);
126 StopFollowers(*controlled);
127 controlled->StopAnimation();
134 bool MapState::CheckBlocking() const {
135 const Tile &tile(map->TileAt(controlled->Position()));
136 Vector<int> nextPosition;
137 switch (nextDirection) {
138 case Entity::ORIENTATION_NORTH:
139 if (tile.BlocksNorth()) {
142 nextPosition = Vector<int>(
143 controlled->Position().X(),
144 controlled->Position().Y() - map->Tileset()->Height());
147 case Entity::ORIENTATION_EAST:
148 if (tile.BlocksEast()) {
151 nextPosition = Vector<int>(
152 controlled->Position().X() + map->Tileset()->Width(),
153 controlled->Position().Y());
156 case Entity::ORIENTATION_SOUTH:
157 if (tile.BlocksSouth()) {
160 nextPosition = Vector<int>(
161 controlled->Position().X(),
162 controlled->Position().Y() + map->Tileset()->Height());
165 case Entity::ORIENTATION_WEST:
166 if (tile.BlocksWest()) {
169 nextPosition = Vector<int>(
170 controlled->Position().X() - map->Tileset()->Width(),
171 controlled->Position().Y());
177 Vector<int> nextTileCoords(map->TileCoordinates(nextPosition));
178 for (std::vector<Entity *>::const_iterator i(entities.begin()), end(entities.end()); i != end; ++i) {
179 const Entity &e(**i);
180 if (map->TileCoordinates(e.Position()) == nextTileCoords && e.Blocking()) {
187 void MapState::OnGridLock() {
197 void MapState::LockEntities() {
198 for (std::vector<Entity *>::iterator i(entities.begin()), end(entities.end()); i != end; ++i) {
199 if (*i == controlled) {
203 (*i)->Position().Lock(map->Tileset()->Size());
207 void MapState::CheckMonster() {
208 Vector<int> coords(map->TileCoordinates(controlled->Position()));
209 Vector<int> neighbor[4];
210 neighbor[0] = Vector<int>(coords.X(), coords.Y() - 1); // N
211 neighbor[1] = Vector<int>(coords.X() + 1, coords.Y()); // E
212 neighbor[2] = Vector<int>(coords.X(), coords.Y() + 1); // S
213 neighbor[3] = Vector<int>(coords.X() - 1, coords.Y()); // W
215 for (int i(0); i < 4; ++i) {
216 for (std::vector<Entity *>::iterator e(entities.begin()), end(entities.end()); e != end; ++e) {
217 if ((*e)->Hostile() && map->TileCoordinates((*e)->Position()) == neighbor[i]) {
218 // TODO: check for turn advantage, see #26
219 // TODO: remove entity, push battle state and transition and halt all other activity
220 // needed information here:
221 // - battle background (from tile?)
222 // - monsters + layout (from entity)
223 // - battle resources (from global resources)
229 void MapState::CheckTrigger() {
230 Trigger *trigger(map->TriggerAt(Vector<int>(controlled->Position())));
232 // TODO: run trigger script
234 Transition(trigger->map, trigger->target);
240 void MapState::OnMove(bool realMove) {
241 // TODO: evaluate monster movements
243 UpdateFollower(*controlled);
245 StopFollowers(*controlled);
249 void MapState::UpdateFollower(Entity &e) {
250 if (!e.Follower()) return;
252 Entity &f(*e.Follower());
255 Vector<int> coords(map->TileCoordinates(e.Position()));
256 Vector<int> fCoords(map->TileCoordinates(f.Position()));
257 Vector<int> direction(coords - fCoords);
259 if (direction.Y() < 0) {
260 f.SetOrientation(Entity::ORIENTATION_NORTH);
261 f.SetSpeed(walkingSpeed);
262 f.StartAnimation(*this);
263 } else if (direction.X() > 0) {
264 f.SetOrientation(Entity::ORIENTATION_EAST);
265 f.SetSpeed(walkingSpeed);
266 f.StartAnimation(*this);
267 } else if (direction.Y() > 0) {
268 f.SetOrientation(Entity::ORIENTATION_SOUTH);
269 f.SetSpeed(walkingSpeed);
270 f.StartAnimation(*this);
271 } else if (direction.X() < 0) {
272 f.SetOrientation(Entity::ORIENTATION_WEST);
273 f.SetSpeed(walkingSpeed);
274 f.StartAnimation(*this);
281 void MapState::StopFollowers(Entity &e) {
282 for (Entity *f(e.Follower()); f; f = f->Follower()) {
289 void MapState::Transition(Map *newMap, const Vector<int> &coordinates) {
290 Vector<int> position(coordinates * map->Tileset()->Size());
292 for (Entity *e(controlled); e; e = e->Follower()) {
293 e->Position() = position;
294 e->SetOrientation(controlled->GetOrientation());
295 entities.push_back(e);
302 void MapState::Render(SDL_Surface *screen) {
303 SDL_FillRect(screen, 0, SDL_MapRGB(screen->format, 0, 0, 0));
305 Vector<int> offset(camera.CalculateOffset());
306 map->Render(screen, offset);
309 map->RenderDebug(screen, offset);
312 std::sort(entities.begin(), entities.end(), ZCompare);
313 for (std::vector<Entity *>::iterator i(entities.begin()), end(entities.end()); i != end; ++i) {
314 (*i)->Render(screen, offset);
319 bool MapState::ZCompare(const Entity *lhs, const Entity *rhs) {
320 return lhs->Position().Y() < rhs->Position().Y();