void AppBody() { bool done = false; bool redraw = false; TileMap map("data/maps/test1.tmx"); Sprite sprt("data/sprites/demo.adf"); sprt.SendNewState(AnimState::IDLE, AnimDir::DOWN); ALLEGRO_TRANSFORM camera; int x_offset = 0, y_offset = 0; int x_delta, y_delta; int key_state[2] = {0, 0}; x_delta = applicationConfig.iDispW - al_get_bitmap_width(map.GetFullMap()); y_delta = applicationConfig.iDispH - al_get_bitmap_height(map.GetFullMap()); Vec2D playerPos {0, 0}; Vec2D playerVel {0, 0}; al_start_timer(timer); while (!done) { ALLEGRO_EVENT ev; al_wait_for_event(queue, &ev); switch (ev.type) { case ALLEGRO_EVENT_TIMER: al_identity_transform(&camera); x_offset += key_state[0]; y_offset += key_state[1]; if (x_delta > 0) { x_offset = x_delta / 2; } else { if (x_offset < x_delta) x_offset = x_delta; if (x_offset > 0) x_offset = 0; } if (y_delta > 0) { y_offset = y_delta / 2; } else { if (y_offset < y_delta) y_offset = y_delta; if (y_offset > 0) y_offset = 0; } if (map.CanWalktoTileAt(playerPos, sprt.GetSize(), {0.0f, 32.0f}) == true) { playerPos = playerPos + playerVel; } else { Vec2D backtracing = playerVel; playerVel = {0, 0}; // we delete player velocitity to stop oscillating in place during collision. if (backtracing == playerVel) // If for whatever reason we are stuck and cannot determine orig vector... MAGIC! { backtracing.x = 2.0f; backtracing.y = 2.0f; float angle = rand() % 359 + 1; backtracing.rotate(angle * (ALLEGRO_PI / 180)); std::cerr << "Warning: Unknown velocity vector. Will use [" << backtracing.x << "," << backtracing.y << "] as direction to solve collision." << std::endl; } while (map.CanWalktoTileAt(playerPos, sprt.GetSize(), {0.0f, 32.0f}) == false) { playerPos = playerPos - backtracing; } } sprt.Update(); redraw = true; break; case ALLEGRO_EVENT_DISPLAY_CLOSE: done = true; break; case ALLEGRO_EVENT_KEY_DOWN: if (ev.keyboard.keycode == ALLEGRO_KEY_ESCAPE) { done = true; } switch (ev.keyboard.keycode) { case ALLEGRO_KEY_LEFT: key_state[0] = 4; break; case ALLEGRO_KEY_RIGHT: key_state[0] = -4; break; case ALLEGRO_KEY_UP: key_state[1] = 4; break; case ALLEGRO_KEY_DOWN: key_state[1] = -4; break; case ALLEGRO_KEY_A: playerVel.x = -2; sprt.SendNewState(AnimState::MOVE, AnimDir::LEFT); break; case ALLEGRO_KEY_D: playerVel.x = 2; sprt.SendNewState(AnimState::MOVE, AnimDir::RIGHT); break; case ALLEGRO_KEY_W: playerVel.y = -2; sprt.SendNewState(AnimState::MOVE, AnimDir::UP); break; case ALLEGRO_KEY_S: playerVel.y = 2; sprt.SendNewState(AnimState::MOVE, AnimDir::DOWN); break; } break; case ALLEGRO_EVENT_KEY_UP: switch (ev.keyboard.keycode) { case ALLEGRO_KEY_LEFT: case ALLEGRO_KEY_RIGHT: key_state[0] = 0; break; case ALLEGRO_KEY_UP: case ALLEGRO_KEY_DOWN: key_state[1] = 0; break; case ALLEGRO_KEY_A: playerVel.x = 0; sprt.SendNewState(AnimState::IDLE, AnimDir::LEFT); break; case ALLEGRO_KEY_D: playerVel.x = 0; sprt.SendNewState(AnimState::IDLE, AnimDir::RIGHT); break; case ALLEGRO_KEY_W: playerVel.y = 0; sprt.SendNewState(AnimState::IDLE, AnimDir::UP); break; case ALLEGRO_KEY_S: playerVel.y = 0; sprt.SendNewState(AnimState::IDLE, AnimDir::DOWN); break; } break; default: break; } if (redraw && al_is_event_queue_empty(queue)) { al_translate_transform(&camera, x_offset, y_offset); al_use_transform(&camera); redraw = false; al_clear_to_color(styleConfig.colBackgroundColor); map.DrawLayerMap("Background"); map.DrawLayerMap("Foreground"); /* Playable characters should draw on this position */ sprt.Render(playerPos.x, playerPos.y); map.DrawLayerMap("Top"); al_flip_display(); } } }