From 1ef17e89181619c830f75e75f7b2e43ab3d1ed43 Mon Sep 17 00:00:00 2001 From: lisyarus Date: Sat, 13 May 2023 00:04:18 +0300 Subject: [PATCH] Add platformer example --- examples/platformer.cpp | 132 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 examples/platformer.cpp diff --git a/examples/platformer.cpp b/examples/platformer.cpp new file mode 100644 index 00000000..a50166de --- /dev/null +++ b/examples/platformer.cpp @@ -0,0 +1,132 @@ +#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(); +}