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);
43 void MapState::ExitState(Application &ctrl, SDL_Surface *screen) {
47 void MapState::ResumeState(Application &ctrl, SDL_Surface *screen) {
48 camera.Resize(screen->w, screen->h);
51 void MapState::PauseState(Application &ctrl, SDL_Surface *screen) {
55 void MapState::Resize(int width, int height) {
56 camera.Resize(width, height);
60 void MapState::HandleEvents(const Input &input) {
61 if (!controlled) return;
63 if (input.IsDown(Input::PAD_UP)) {
64 nextDirection = Entity::ORIENTATION_NORTH;
65 } else if (input.IsDown(Input::PAD_RIGHT)) {
66 nextDirection = Entity::ORIENTATION_EAST;
67 } else if (input.IsDown(Input::PAD_DOWN)) {
68 nextDirection = Entity::ORIENTATION_SOUTH;
69 } else if (input.IsDown(Input::PAD_LEFT)) {
70 nextDirection = Entity::ORIENTATION_WEST;
75 if (input.JustPressed(Input::DEBUG_1)) {
80 void MapState::UpdateWorld(float deltaT) {
81 if (controlled && controlled->TileLock(map->Tileset()->Size())) {
84 for (std::vector<Entity *>::iterator i(entities.begin()), end(entities.end()); i != end; ++i) {
89 void MapState::OnTileLock() {
90 if (moveTimer.Running() && !moveTimer.JustHit()) return;
92 Vector<int> nowLock(controlled->Position());
93 if (nowLock != lastLock) {
97 } else if (moveTimer.JustHit()) {
102 // TODO: halt all activity if lock caused a state/map transition
104 if (nextDirection >= 0) {
105 bool blocked(CheckBlocking());
110 controlled->SetOrientation(Entity::Orientation(nextDirection));
112 controlled->SetSpeed(walkingSpeed);
115 controlled->SetSpeed(0.0f);
116 StopFollowers(*controlled);
117 if (!moveTimer.Running()) {
118 int tileSize((controlled->GetOrientation() % 2) ? map->Tileset()->Width() : map->Tileset()->Height());
119 moveTimer = PhysicsTimers().StartInterval(tileSize/walkingSpeed);
122 if (!controlled->AnimationRunning()) {
123 controlled->StartAnimation(*this);
126 controlled->SetSpeed(0.0f);
127 StopFollowers(*controlled);
128 controlled->StopAnimation();
135 bool MapState::CheckBlocking() const {
136 const Tile &tile(map->TileAt(controlled->Position()));
137 Vector<int> nextPosition;
138 switch (nextDirection) {
139 case Entity::ORIENTATION_NORTH:
140 if (tile.BlocksNorth()) {
143 nextPosition = Vector<int>(
144 controlled->Position().X(),
145 controlled->Position().Y() - map->Tileset()->Height());
148 case Entity::ORIENTATION_EAST:
149 if (tile.BlocksEast()) {
152 nextPosition = Vector<int>(
153 controlled->Position().X() + map->Tileset()->Width(),
154 controlled->Position().Y());
157 case Entity::ORIENTATION_SOUTH:
158 if (tile.BlocksSouth()) {
161 nextPosition = Vector<int>(
162 controlled->Position().X(),
163 controlled->Position().Y() + map->Tileset()->Height());
166 case Entity::ORIENTATION_WEST:
167 if (tile.BlocksWest()) {
170 nextPosition = Vector<int>(
171 controlled->Position().X() - map->Tileset()->Width(),
172 controlled->Position().Y());
178 Vector<int> nextTileCoords(map->TileCoordinates(nextPosition));
179 for (std::vector<Entity *>::const_iterator i(entities.begin()), end(entities.end()); i != end; ++i) {
180 const Entity &e(**i);
181 if (map->TileCoordinates(e.Position()) == nextTileCoords && e.Blocking()) {
188 void MapState::OnGridLock() {
198 void MapState::LockEntities() {
199 for (std::vector<Entity *>::iterator i(entities.begin()), end(entities.end()); i != end; ++i) {
200 if (*i == controlled) {
204 (*i)->Position().Lock(map->Tileset()->Size());
208 void MapState::CheckMonster() {
209 Vector<int> coords(map->TileCoordinates(controlled->Position()));
210 Vector<int> neighbor[4];
211 neighbor[0] = Vector<int>(coords.X(), coords.Y() - 1); // N
212 neighbor[1] = Vector<int>(coords.X() + 1, coords.Y()); // E
213 neighbor[2] = Vector<int>(coords.X(), coords.Y() + 1); // S
214 neighbor[3] = Vector<int>(coords.X() - 1, coords.Y()); // W
216 for (int i(0); i < 4; ++i) {
217 for (std::vector<Entity *>::iterator e(entities.begin()), end(entities.end()); e != end; ++e) {
218 if ((*e)->Hostile() && map->TileCoordinates((*e)->Position()) == neighbor[i]) {
219 // TODO: check for turn advantage, see #26
220 // TODO: remove entity, push battle state and transition and halt all other activity
221 // needed information here:
222 // - battle background (from tile?)
223 // - monsters + layout (from entity)
224 // - battle resources (from global resources)
230 void MapState::CheckTrigger() {
231 Trigger *trigger(map->TriggerAt(Vector<int>(controlled->Position())));
233 // TODO: run trigger script
235 Transition(trigger->map, trigger->target);
241 void MapState::OnMove(bool realMove) {
242 // TODO: evaluate monster movements
244 UpdateFollower(*controlled);
246 StopFollowers(*controlled);
250 void MapState::UpdateFollower(Entity &e) {
251 if (!e.Follower()) return;
253 Entity &f(*e.Follower());
256 Vector<int> coords(map->TileCoordinates(e.Position()));
257 Vector<int> fCoords(map->TileCoordinates(f.Position()));
258 Vector<int> direction(coords - fCoords);
260 if (direction.Y() < 0) {
261 f.SetOrientation(Entity::ORIENTATION_NORTH);
262 f.SetSpeed(walkingSpeed);
263 f.StartAnimation(*this);
264 } else if (direction.X() > 0) {
265 f.SetOrientation(Entity::ORIENTATION_EAST);
266 f.SetSpeed(walkingSpeed);
267 f.StartAnimation(*this);
268 } else if (direction.Y() > 0) {
269 f.SetOrientation(Entity::ORIENTATION_SOUTH);
270 f.SetSpeed(walkingSpeed);
271 f.StartAnimation(*this);
272 } else if (direction.X() < 0) {
273 f.SetOrientation(Entity::ORIENTATION_WEST);
274 f.SetSpeed(walkingSpeed);
275 f.StartAnimation(*this);
282 void MapState::StopFollowers(Entity &e) {
283 for (Entity *f(e.Follower()); f; f = f->Follower()) {
290 void MapState::Transition(Map *newMap, const Vector<int> &coordinates) {
292 Vector<int> position(coordinates * map->Tileset()->Size());
293 for (Entity *e(controlled); e; e = e->Follower()) {
294 e->Position() = position;
295 e->SetOrientation(controlled->GetOrientation());
301 void MapState::UnloadMap() {
305 void MapState::LoadMap(Map *m) {
307 entities.insert(entities.end(), m->EntitiesBegin(), m->EntitiesEnd());
308 for (Entity *e(controlled); e; e = e->Follower()) {
309 entities.push_back(e);
314 void MapState::Render(SDL_Surface *screen) {
315 SDL_FillRect(screen, 0, SDL_MapRGB(screen->format, 0, 0, 0));
317 Vector<int> offset(camera.CalculateOffset());
318 map->Render(screen, offset);
321 map->RenderDebug(screen, offset);
324 std::sort(entities.begin(), entities.end(), ZCompare);
325 for (std::vector<Entity *>::iterator i(entities.begin()), end(entities.end()); i != end; ++i) {
326 (*i)->Render(screen, offset);
331 bool MapState::ZCompare(const Entity *lhs, const Entity *rhs) {
332 return lhs->Position().Y() < rhs->Position().Y();