#include #include #include #include #include #include #include #include #include #include using namespace psemek; struct map { std::vector> platforms; }; struct player { geom::vector size; geom::point position; geom::vector velocity; geom::box bbox() const { return geom::expand(geom::box::singleton(position), size); } }; struct platformer_app : app::app { platformer_app() : app("Platformer", 4) { map_.platforms.push_back({{{-10.f, 10.f}, {-5.f, -4.f}}}); map_.platforms.push_back({{{-5.f, -3.f}, {-2.5f, -2.f}}}); map_.platforms.push_back({{{-1.f, 1.f}, {-2.f, -1.5f}}}); map_.platforms.push_back({{{ 3.f, 5.f}, {-1.5f, -1.f}}}); map_.platforms.push_back({{{-7.f, -6.f}, {-3.5f, -3.f}}}); player_.size = {0.25f, 0.5f}; player_.position = {0.f, 5.f}; player_.velocity = {0.f, 0.f}; } void update() override { float const dt = frame_clock_.restart().count(); float const gravity = -50.f; float const acceleration = 50.f; float const friction = 10.f; float const jump_speed = 15.f; if (is_key_down(SDLK_a)) player_.velocity[0] -= acceleration * dt; if (is_key_down(SDLK_d)) player_.velocity[0] += acceleration * dt; player_.velocity[0] *= std::exp(- friction * dt); player_.velocity[1] += dt * gravity; player_.position += player_.velocity * dt; bool grounded = false; for (auto const & platform : map_.platforms) { auto const player_box = player_.bbox(); auto const intersection = platform & player_box; if (intersection.empty()) continue; if (intersection[0].length() < intersection[1].length()) { if (intersection[0].center() < player_.position[0]) player_.position[0] += intersection[0].length(); else player_.position[0] -= intersection[0].length(); player_.velocity[0] = 0.f; } else { if (intersection[1].center() < player_.position[1]) { player_.position[1] += intersection[1].length(); grounded = true; } else player_.position[1] -= intersection[1].length(); player_.velocity[1] = 0.f; } } if (grounded && is_key_down(SDLK_w)) player_.velocity[1] += jump_speed; } void present() override { gl::ClearColor(1.f, 1.f, 1.f, 0.f); gl::Clear(gl::COLOR_BUFFER_BIT); for (auto const & box : map_.platforms) painter_.rect(box, {0, 0, 0, 255}); painter_.rect(player_.bbox(), {255, 0, 0, 255}); float const aspect_ratio = width() * 1.f / height(); float const view_size = 5.f; geom::box view_box{{{-view_size * aspect_ratio, view_size * aspect_ratio}, {-view_size, view_size}}}; painter_.render(geom::orthographic_camera{view_box}.transform()); } private: map map_; player player_; util::clock<> frame_clock_; gfx::painter painter_; }; int main() { return app::main(); }