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)
35 void MapState::EnterState(Application &ctrl, SDL_Surface *screen) {
36 camera.Resize(screen->w, screen->h);
39 void MapState::ExitState(Application &ctrl, SDL_Surface *screen) {
43 void MapState::ResumeState(Application &ctrl, SDL_Surface *screen) {
44 camera.Resize(screen->w, screen->h);
47 void MapState::PauseState(Application &ctrl, SDL_Surface *screen) {
51 void MapState::Resize(int width, int height) {
52 camera.Resize(width, height);
56 void MapState::HandleEvents(const Input &input) {
57 if (!controlled) return;
59 if (input.IsDown(Input::PAD_UP)) {
60 nextDirection = Entity::ORIENTATION_NORTH;
61 } else if (input.IsDown(Input::PAD_RIGHT)) {
62 nextDirection = Entity::ORIENTATION_EAST;
63 } else if (input.IsDown(Input::PAD_DOWN)) {
64 nextDirection = Entity::ORIENTATION_SOUTH;
65 } else if (input.IsDown(Input::PAD_LEFT)) {
66 nextDirection = Entity::ORIENTATION_WEST;
72 void MapState::UpdateWorld(float deltaT) {
73 if (controlled && controlled->TileLock(map->Tileset()->Size())) {
76 for (std::vector<Entity *>::iterator i(entities.begin()), end(entities.end()); i != end; ++i) {
81 void MapState::OnTileLock() {
82 if (moveTimer.Running() && !moveTimer.JustHit()) return;
84 Vector<int> nowLock(controlled->Position());
85 if (nowLock != lastLock) {
89 } else if (moveTimer.JustHit()) {
94 // TODO: halt all activity if lock caused a state/map transition
96 if (nextDirection >= 0) {
97 bool blocked(CheckBlocking());
102 controlled->SetOrientation(Entity::Orientation(nextDirection));
104 controlled->SetSpeed(walkingSpeed);
107 controlled->SetSpeed(0.0f);
108 StopFollowers(*controlled);
109 if (!moveTimer.Running()) {
110 int tileSize((controlled->GetOrientation() % 2) ? map->Tileset()->Width() : map->Tileset()->Height());
111 moveTimer = PhysicsTimers().StartInterval(tileSize/walkingSpeed);
114 if (!controlled->AnimationRunning()) {
115 controlled->StartAnimation(*this);
118 controlled->SetSpeed(0.0f);
119 StopFollowers(*controlled);
120 controlled->StopAnimation();
127 bool MapState::CheckBlocking() const {
128 const Tile &tile(map->TileAt(controlled->Position()));
129 Vector<int> nextPosition;
130 switch (nextDirection) {
131 case Entity::ORIENTATION_NORTH:
132 if (tile.BlocksNorth()) {
135 nextPosition = Vector<int>(
136 controlled->Position().X(),
137 controlled->Position().Y() - map->Tileset()->Height());
140 case Entity::ORIENTATION_EAST:
141 if (tile.BlocksEast()) {
144 nextPosition = Vector<int>(
145 controlled->Position().X() + map->Tileset()->Width(),
146 controlled->Position().Y());
149 case Entity::ORIENTATION_SOUTH:
150 if (tile.BlocksSouth()) {
153 nextPosition = Vector<int>(
154 controlled->Position().X(),
155 controlled->Position().Y() + map->Tileset()->Height());
158 case Entity::ORIENTATION_WEST:
159 if (tile.BlocksWest()) {
162 nextPosition = Vector<int>(
163 controlled->Position().X() - map->Tileset()->Width(),
164 controlled->Position().Y());
170 Vector<int> nextTileCoords(map->TileCoordinates(nextPosition));
171 for (std::vector<Entity *>::const_iterator i(entities.begin()), end(entities.end()); i != end; ++i) {
172 const Entity &e(**i);
173 if (map->TileCoordinates(e.Position()) == nextTileCoords && e.Blocking()) {
180 void MapState::OnGridLock() {
186 void MapState::LockEntities() {
187 for (std::vector<Entity *>::iterator i(entities.begin()), end(entities.end()); i != end; ++i) {
188 if (*i == controlled) {
192 (*i)->Position().Lock(map->Tileset()->Size());
196 void MapState::CheckMonster() {
197 Vector<int> coords(map->TileCoordinates(controlled->Position()));
198 Vector<int> neighbor[4];
199 neighbor[0] = Vector<int>(coords.X(), coords.Y() - 1); // N
200 neighbor[1] = Vector<int>(coords.X() + 1, coords.Y()); // E
201 neighbor[2] = Vector<int>(coords.X(), coords.Y() + 1); // S
202 neighbor[3] = Vector<int>(coords.X() - 1, coords.Y()); // W
204 for (int i(0); i < 4; ++i) {
205 for (std::vector<Entity *>::iterator e(entities.begin()), end(entities.end()); e != end; ++e) {
206 if ((*e)->Hostile() && map->TileCoordinates((*e)->Position()) == neighbor[i]) {
207 // TODO: check for turn advantage, see #26
208 // TODO: remove entity, push battle state and transition and halt all other activity
209 // needed information here:
210 // - battle background (from tile?)
211 // - monsters + layout (from entity)
212 // - battle resources (from global resources)
218 void MapState::CheckTrigger() {
219 Trigger *trigger(map->TriggerAt(Vector<int>(controlled->Position())));
226 void MapState::OnMove(bool realMove) {
227 // TODO: evaluate monster movements
229 UpdateFollower(*controlled);
231 StopFollowers(*controlled);
235 void MapState::UpdateFollower(Entity &e) {
236 if (!e.Follower()) return;
238 Entity &f(*e.Follower());
241 Vector<int> coords(map->TileCoordinates(e.Position()));
242 Vector<int> fCoords(map->TileCoordinates(f.Position()));
243 Vector<int> direction(coords - fCoords);
245 if (direction.Y() < 0) {
246 f.SetOrientation(Entity::ORIENTATION_NORTH);
247 f.SetSpeed(walkingSpeed);
248 f.StartAnimation(*this);
249 } else if (direction.X() > 0) {
250 f.SetOrientation(Entity::ORIENTATION_EAST);
251 f.SetSpeed(walkingSpeed);
252 f.StartAnimation(*this);
253 } else if (direction.Y() > 0) {
254 f.SetOrientation(Entity::ORIENTATION_SOUTH);
255 f.SetSpeed(walkingSpeed);
256 f.StartAnimation(*this);
257 } else if (direction.X() < 0) {
258 f.SetOrientation(Entity::ORIENTATION_WEST);
259 f.SetSpeed(walkingSpeed);
260 f.StartAnimation(*this);
267 void MapState::StopFollowers(Entity &e) {
268 for (Entity *f(e.Follower()); f; f = f->Follower()) {
275 void MapState::Render(SDL_Surface *screen) {
276 SDL_FillRect(screen, 0, SDL_MapRGB(screen->format, 0, 0, 0));
278 Vector<int> offset(camera.CalculateOffset());
279 map->Render(screen, offset);
281 std::sort(entities.begin(), entities.end(), ZCompare);
282 for (std::vector<Entity *>::iterator i(entities.begin()), end(entities.end()); i != end; ++i) {
283 (*i)->Render(screen, offset);
288 bool MapState::ZCompare(const Entity *lhs, const Entity *rhs) {
289 return lhs->Position().Y() < rhs->Position().Y();