]> git.localhorst.tv Git - orbi.git/commitdiff
simple controller
authorDaniel Karbach <daniel.karbach@localhorst.tv>
Wed, 9 Apr 2014 08:22:08 +0000 (10:22 +0200)
committerDaniel Karbach <daniel.karbach@localhorst.tv>
Thu, 24 Apr 2014 08:36:47 +0000 (10:36 +0200)
src/app/Application.cpp
src/app/Application.h
src/app/Controller.cpp [new file with mode: 0644]
src/app/Controller.h [new file with mode: 0644]
src/orbi.cpp
src/world/Entity.h
src/world/World.cpp
src/world/World.h

index 01568d91fbd6ca2d01068b494dba3ebd93ea1e8e..cbfafd374537935625dbaad63955d4d7edacbcd6 100644 (file)
@@ -13,8 +13,10 @@ Application::Application(Canvas &c, World &w, Tileset &t)
 : canvas(c)
 , world(w)
 , tiles(t)
-, focus(Vector<float>(5, 5), 2)
-, cam(c.Size(), focus.Pos())
+, ctrl()
+, focus(5, 5)
+, target(focus, 2)
+, cam(c.Size(), focus)
 , last(SDL_GetTicks())
 , running(false)
 , paused(false) {
@@ -22,6 +24,15 @@ Application::Application(Canvas &c, World &w, Tileset &t)
 }
 
 
+void Application::Control(Entity &e) {
+       ctrl.Control(e);
+}
+
+void Application::Relinquish() {
+       ctrl.Relinquish();
+}
+
+
 void Application::Run() {
        running = true;
        while (running) {
@@ -85,17 +96,22 @@ void Application::HandleEvents() {
 
 void Application::OnKeyDown(const SDL_KeyboardEvent &e) {
        switch (e.keysym.sym) {
-               case SDLK_UP:
-                       focus.MoveUp();
+               case SDLK_w:
+                       target.MoveUp();
+                       break;
+               case SDLK_s:
+                       target.MoveDown();
                        break;
-               case SDLK_DOWN:
-                       focus.MoveDown();
+               case SDLK_a:
+                       ctrl.MoveLeft();
+                       target.MoveLeft();
                        break;
-               case SDLK_LEFT:
-                       focus.MoveLeft();
+               case SDLK_d:
+                       ctrl.MoveRight();
+                       target.MoveRight();
                        break;
-               case SDLK_RIGHT:
-                       focus.MoveRight();
+               case SDLK_SPACE:
+                       ctrl.StartJump();
                        break;
                case SDLK_p:
                        paused = !paused;
@@ -107,17 +123,22 @@ void Application::OnKeyDown(const SDL_KeyboardEvent &e) {
 
 void Application::OnKeyUp(const SDL_KeyboardEvent &e) {
        switch (e.keysym.sym) {
-               case SDLK_UP:
-                       focus.StopUp();
+               case SDLK_w:
+                       target.StopUp();
                        break;
-               case SDLK_DOWN:
-                       focus.StopDown();
+               case SDLK_s:
+                       target.StopDown();
                        break;
-               case SDLK_LEFT:
-                       focus.StopLeft();
+               case SDLK_a:
+                       ctrl.StopLeft();
+                       target.StopLeft();
                        break;
-               case SDLK_RIGHT:
-                       focus.StopRight();
+               case SDLK_d:
+                       ctrl.StopRight();
+                       target.StopRight();
+                       break;
+               case SDLK_SPACE:
+                       ctrl.StopJump();
                        break;
                default:
                        break;
@@ -127,9 +148,15 @@ void Application::OnKeyUp(const SDL_KeyboardEvent &e) {
 
 void Application::Update(int dt) {
        const float delta = dt / 1e3;
+       ctrl.Update(delta);
+       target.Update(delta);
+       focus = ctrl.Controlling()
+               ? ctrl.Controlled().bounds.Center()
+               : target.Pos();
        cam.Update(delta);
-       world.Update(dt);
-       focus.Update(delta);
+       for (int i = 0; i < dt; ++i) {
+               world.Update(1e-3);
+       }
 }
 
 
@@ -163,21 +190,21 @@ void Application::RenderEntities() {
        canvas.SetColor(entityColor);
 
        for (const Entity &e : world.Entities()) {
-               const Vector<float> pos(e.Bounds().Left(), e.Bounds().Top());
-               const Vector<float> size(e.Bounds().Size());
+               const Vector<float> pos(e.bounds.Left(), e.bounds.Top());
+               const Vector<float> size(e.bounds.Size());
                canvas.OutlineRect(cam.ToScreen(pos), cam.ToScale(size));
        }
 }
 
 void Application::RenderUI() {
        constexpr Color outlineColor(0x00, 0x00, 0xFA);
-       constexpr Color focusColor(0xFA, 0xFA, 0x00);
+       constexpr Color targetColor(0xFA, 0xFA, 0x00);
 
        canvas.SetColor(outlineColor);
        canvas.Grid(cam.ToScreen(Vector<int>(0, 0)), cam.ToScale(world.Size()), cam.ToScale(Vector<float>(1, 1)));
 
-       canvas.SetColor(focusColor);
-       canvas.Cross(cam.ToScreen(focus.Pos()), 15);
+       canvas.SetColor(targetColor);
+       canvas.Cross(cam.ToScreen(target.Pos()), 15);
 }
 
 }
index 2b0b361a04f7fbfd8cfb32431704ae8ce0216bbb..d714be674eb4d98af3d45d34ad57ca3553f5ab8d 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef ORBI_APPLICATION_H_
 #define ORBI_APPLICATION_H_
 
+#include "Controller.h"
 #include "../graphics/Camera.h"
 #include "../graphics/Moveable.h"
 #include "../graphics/Texture.h"
@@ -20,6 +21,9 @@ class Application {
 public:
        Application(Canvas &, World &, Tileset &);
 
+       void Control(Entity &);
+       void Relinquish();
+
 public:
        void Run();
 
@@ -43,7 +47,9 @@ private:
        World &world;
        Tileset &tiles;
 
-       Moveable<float> focus;
+       Controller ctrl;
+       Vector<float> focus;
+       Moveable<float> target;
        Camera cam;
 
        Uint32 last;
diff --git a/src/app/Controller.cpp b/src/app/Controller.cpp
new file mode 100644 (file)
index 0000000..88dd5eb
--- /dev/null
@@ -0,0 +1,65 @@
+#include "Controller.h"
+
+#include "../world/Entity.h"
+#include "../graphics/const.h"
+
+#include <algorithm>
+
+
+namespace orbi {
+
+Controller::Controller(Entity *ent)
+: e(ent)
+, moving(0)
+, moveAcc(3.5)
+, moveTerm(5)
+, jumping(false)
+, jumpVel(-5) {
+
+}
+
+void Controller::Update(float delta) {
+       if (!e) return;
+
+       if (moving) {
+               if (std::abs(e->acc.x) < moveTerm) {
+                       e->acc.x = sigma(moving) * moveAcc;
+               } else {
+                       e->acc.x = 0;
+               }
+       } else {
+               e->acc.x = sigma(e->vel.x) * -moveAcc;
+       }
+
+       if (jumping && e->onGround) {
+               e->vel.y += jumpVel;
+               jumping = false;
+       }
+}
+
+
+void Controller::MoveLeft() {
+       moving -= 1;
+}
+
+void Controller::StopLeft() {
+       moving += 1;
+}
+
+void Controller::MoveRight() {
+       moving += 1;
+}
+
+void Controller::StopRight() {
+       moving -= 1;
+}
+
+void Controller::StartJump() {
+       jumping = true;
+}
+
+void Controller::StopJump() {
+       jumping = false;
+}
+
+}
diff --git a/src/app/Controller.h b/src/app/Controller.h
new file mode 100644 (file)
index 0000000..356d78e
--- /dev/null
@@ -0,0 +1,44 @@
+#ifndef ORBI_CONTROLLER_H_
+#define ORBI_CONTROLLER_H_
+
+namespace orbi {
+
+class Entity;
+
+class Controller {
+
+public:
+       explicit Controller(Entity * = nullptr);
+
+       void Control(Entity &ent) { e = &ent; }
+       void Relinquish() { e = nullptr; }
+
+       bool Controlling() const { return e; }
+       const Entity &Controlled() const { return *e; }
+
+       void Update(float delta);
+
+public:
+       void MoveLeft();
+       void StopLeft();
+       void MoveRight();
+       void StopRight();
+
+       void StartJump();
+       void StopJump();
+
+private:
+       Entity *e;
+
+       int moving;
+       float moveAcc;
+       float moveTerm;
+
+       bool jumping;
+       float jumpVel;
+
+};
+
+}
+
+#endif
index 42ee9109f450c8f4e3e61dd11be42cdb49bfb077..b05244189b05a5c9535fee342f1cde49eb522d92 100644 (file)
@@ -49,10 +49,11 @@ int main(int argc, const char *argv[]) {
        world.SetTile(Vector<int>(9, 6), Tile(0));
 
        Entity e;
-       e.Bounds() = AABB(Vector<float>(5, 2), Vector<float>(2, 3));
-       world.AddEntity(e);
+       e.bounds = AABB(Vector<float>(5, 0), Vector<float>(2, 3));
+       Entity &player = world.AddEntity(e);
 
        Application app(canv, world, tiles);
+       app.Control(player);
        app.Run();
 
        return 0;
index f9671ca03cb13e7f4c45ee410dede7be463476a6..f8576c15374c33708fd010e20890197320266f43 100644 (file)
@@ -17,10 +17,6 @@ public:
        void Move(Vector<float> delta) { bounds.Move(delta); }
 
 public:
-       AABB &Bounds() { return bounds; }
-       const AABB &Bounds() const { return bounds; }
-
-private:
        AABB bounds;
        Vector<float> vel;
        Vector<float> acc;
@@ -28,6 +24,8 @@ private:
        float mass = 1.0f;
        float elast = 0.75f;
 
+       bool onGround = false;
+
 };
 
 }
index e390914fae7eb34adccc08de26649c697fe15165..f4d80f95476beab74a2e32eac354f5f10c062659 100644 (file)
@@ -15,65 +15,78 @@ World::World(Vector<int> size)
 }
 
 
-void World::Update(int delta) {
-       for (int i = 0; i < delta; ++i) {
-               const float dt = 1e-3;
-               for (Entity &e : entities) {
-                       e.Update(dt, gravity, terminal);
-
-                       const AABB &b = e.Bounds();
-
-                       // world bounds collision
-                       if (b.Top() < 0) e.Move(Vector<float>(0, -b.Top()));
-                       if (b.Right() > size.x) e.Move(Vector<float>(size.x - b.Right(), 0));
-                       if (b.Bottom() > size.y) e.Move(Vector<float>(0, size.y - b.Bottom()));
-                       if (b.Left() < 0) e.Move(Vector<float>(-b.Left(), 0));
-
-                       const Vector<int> cBegin(b.Left(), b.Top());
-                       const Vector<int> cEnd(b.Right(), b.Bottom());
-
-                       Vector<float> topResponse;
-                       for (Vector<int> pos(cBegin); pos.x < cEnd.x; ++pos.x) {
-                               if (TileAt(pos).IsSolid()) {
-                                       topResponse = Vector<float>(0, pos.y + 1 - b.Top());
-                                       break;
-                               }
-                       }
-                       Vector<float> bottomResponse;
-                       for (Vector<int> pos(cBegin.x, cEnd.y); pos.x < cEnd.x; ++pos.x) {
-                               if (TileAt(pos).IsSolid()) {
-                                       bottomResponse = Vector<float>(0, pos.y - b.Bottom());
-                                       break;
-                               }
-                       }
-                       if (!IsZero(topResponse)) {
-                               if (IsZero(bottomResponse)) {
-                                       e.Move(topResponse);
+void World::Update(float dt) {
+       for (Entity &e : entities) {
+               e.Update(dt, gravity, terminal);
+               e.onGround = false;
+
+               const AABB &b = e.bounds;
+
+               // world bounds collision
+               if (b.Top() < 0) {
+                       e.Move(Vector<float>(0, -b.Top()));
+                       e.vel.y = 0;
+               }
+               if (b.Right() > size.x) {
+                       e.Move(Vector<float>(size.x - b.Right(), 0));
+                       e.vel.x = 0;
+               }
+               if (b.Bottom() > size.y) {
+                       e.Move(Vector<float>(0, size.y - b.Bottom()));
+                       e.vel.y = 0;
+                       e.onGround = true;
+               }
+               if (b.Left() < 0) {
+                       e.Move(Vector<float>(-b.Left(), 0));
+                       e.vel.x = 0;
+               }
+
+               const Vector<int> cBegin(b.Left(), b.Top());
+               const Vector<int> cEnd(b.Right() + 1, b.Bottom() + 1);
+
+               Vector<float> min;
+               Vector<float> max;
+
+               for (Vector<int> pos(cBegin); pos.y < cEnd.y; ++pos.y) {
+                       for (pos.x = cBegin.x; pos.x < cEnd.x; ++pos.x) {
+                               if (!TileAt(pos).IsSolid()) continue;
+                               const AABB tBounds(pos, Vector<float>(1, 1));
+                               Vector<float> pos;
+                               Vector<float> norm;
+                               Vector<float> depth;
+                               if (!e.bounds.Intersects(tBounds, pos, norm, depth)) {
+                                       continue;
                                }
-                       } else if (!IsZero(bottomResponse)) {
-                               e.Move(bottomResponse);
+                               if (depth.x < min.x) min.x = depth.x;
+                               if (depth.x > max.x) max.x = depth.x;
+                               if (depth.y < min.y) min.y = depth.y;
+                               if (depth.y > max.y) max.y = depth.y;
                        }
+               }
 
-                       Vector<float> leftResponse;
-                       for (Vector<int> pos(cBegin); pos.y < cEnd.y; ++pos.y) {
-                               if (TileAt(pos).IsSolid()) {
-                                       leftResponse = Vector<float>(pos.x + 1 - b.Left(), 0);
-                                       break;
-                               }
+               Vector<float> resp;
+               if (min.x != 0) {
+                       if (max.x == 0) {
+                               resp.x = min.x;
                        }
-                       Vector<float> rightResponse;
-                       for (Vector<int> pos(cEnd.x, cBegin.y); pos.y < cEnd.y; ++pos.y) {
-                               if (TileAt(pos).IsSolid()) {
-                                       rightResponse = Vector<float>(pos.x - b.Right(), 0);
-                                       break;
-                               }
+               } else {
+                       resp.x = max.x;
+               }
+               if (min.y != 0) {
+                       if (max.y == 0) {
+                               resp.y = min.y;
                        }
-                       if (!IsZero(leftResponse)) {
-                               if (IsZero(rightResponse)) {
-                                       e.Move(leftResponse);
-                               }
-                       } else if (!IsZero(rightResponse)) {
-                               e.Move(rightResponse);
+               } else {
+                       resp.y = max.y;
+               }
+               e.Move(resp);
+               if (resp.x != 0) {
+                       e.vel.x = 0;
+               }
+               if (resp.y != 0) {
+                       e.vel.y = 0;
+                       if (resp.y < 0) {
+                               e.onGround = true;
                        }
                }
        }
index 3483f66fba9fe9a205c528d890179aab8fc07e7b..d77b15b3d55db40ed96822a852e32d7cae273438 100644 (file)
@@ -20,7 +20,7 @@ public:
        Vector<int> Size() const { return size; }
 
 public:
-       void Update(int dt);
+       void Update(float dt);
 
        bool InBounds(Vector<int> pos) const
                { return pos.x > 0 && pos.y > 0 && pos.x < size.x && pos.y < size.y; }