Kajetan Johannes Hammerle 2 years ago
parent
commit
182f9dc0a5
3 changed files with 152 additions and 11 deletions
  1. 149 8
      Game.cpp
  2. 2 2
      rendering/Renderer.cpp
  3. 1 1
      rendering/Renderer.h

+ 149 - 8
Game.cpp

@@ -7,6 +7,16 @@
 struct Line final {
     Vector2 a;
     Vector2 b;
+    Color4 color;
+    float friction;
+
+    Line(const Vector2& a, const Vector2& b, Color4 color, float friction)
+        : a(a), b(b), color(color), friction(friction) {
+    }
+
+    Line(const Vector2& a, const Vector2& b)
+        : a(a), b(b), color(Color4(0xFF, 0xFF, 0xFF, 0xFF)), friction(0.0f) {
+    }
 };
 
 static List<Line> lines;
@@ -26,12 +36,18 @@ static float mass = 5.0f;
 static bool onGround = false;
 static float jumpPower = 0.0f;
 static float steepness = 0.0f;
+static float friction = 0.0f;
 
 static bool physicsToggle = true;
 
 static Vector2 waterPosition;
 static Vector2 waterSize;
 
+static Vector2 projectileLastPosition;
+static Vector2 projectilePosition;
+static Vector2 projectileVelocity;
+static Vector2 projectileSize{20.0f, 20.0f};
+
 static void addForce(const Vector2& force) {
     acceleration += force / mass;
 }
@@ -130,7 +146,7 @@ static bool doesPlayerCollide() {
     return false;
 }
 
-static float slopeSteepness() {
+static void slopeSteepnessAndFriction() {
     Line left{position - Vector2(0.0f, 10.0f * COLLISION_STEP),
               position + Vector2(0.0f, size[1])};
     Line right{position + Vector2(size[0], -10.0f * COLLISION_STEP),
@@ -143,10 +159,11 @@ static float slopeSteepness() {
             if(std::abs(f) < min) {
                 min = std::abs(f);
                 value = f;
+                friction = line.friction;
             }
         }
     }
-    return value;
+    steepness = value;
 }
 
 static void applyDrag() {
@@ -175,6 +192,69 @@ static void handleJump() {
     jumpPower *= Controller::a.isDown() && (velocity[1] > 0.0f || justJumped);
 }
 
+static void relaunchProjectile() {
+    if(projectilePosition[1] >= 0.0f &&
+       !isIn(position, size, projectilePosition, projectileSize)) {
+        return;
+    }
+    projectilePosition = windowSize * Vector2(0.0f, 0.5f);
+    projectileLastPosition = projectilePosition;
+
+    Vector2 start = projectilePosition;
+    Vector2 end = position + size * 0.5f;
+    constexpr float strengh = 25.0f;
+
+    float best = 100000000.0f;
+    float bestRad = 0.0f;
+
+    for(float angle = -30.0f; angle < 90.0f; angle += 0.25f) {
+        float rad = angle * 0.017453293f;
+        Vector2 v(strengh * cosf(rad), strengh * sinf(rad));
+
+        float t = (end[0] - start[0]) / v[0];
+        float y = v[1] * t - GRAVITY * t * t * 0.5f + start[1];
+
+        float diff = std::abs(y - end[1]);
+        if(diff < best) {
+            bestRad = rad;
+            best = diff;
+        }
+    }
+
+    projectileVelocity =
+        Vector2(strengh * cosf(bestRad), strengh * sinf(bestRad));
+}
+
+static float sign(float f) {
+    return (f > 0.0f) - (f < 0.0f);
+}
+
+static void applyFriction() {
+    if(!onGround) {
+        return;
+    }
+    float rad = atanf(steepness);
+    float c = cosf(rad);
+    float fnLength = mass * GRAVITY * c;
+    Vector2 fn(fnLength * c, fnLength * sinf(rad)); // already swapt
+    Vector2 fullFriction = fn * friction;
+    fullFriction =
+        Vector2(std::abs(fullFriction[0]), std::abs(fullFriction[1]));
+
+    float signX = sign(acceleration[0]);
+    float signY = sign(acceleration[1]);
+
+    fullFriction *= -Vector2(signX, signY);
+
+    addForce(fullFriction);
+    if(sign(acceleration[0]) != signX) {
+        acceleration[0] = 0.0f;
+    }
+    if(sign(acceleration[1]) != signY) {
+        acceleration[1] = 0.0f;
+    }
+}
+
 void Game::tick() {
     windowSize = Vector2(static_cast<float>(Engine::getSize().width),
                          static_cast<float>(Engine::getSize().height));
@@ -184,6 +264,7 @@ void Game::tick() {
     applyGravity();
     addMovement();
     handleJump();
+    applyFriction();
     applyDrag();
 
     if(steepness != 100.0f) {
@@ -205,7 +286,40 @@ void Game::tick() {
     lines.add({{0.0f, 90.0f}, {200.0f, 0.0f}});
     lines.add({{0.0f, 120.0f}, {100.0f, 0.0f}});
     lines.add({{100.0f, 180.0f}, {200.0f, 180.0f}});
-    lines.add({{200.0f, 180.0f}, {600.0f, 380.0f}});
+
+    lines.add({{200.0f, 180.0f},
+               {300.0f, 230.0f},
+               Color4(0xF0, 0x00, 0x00, 0xFF),
+               0.2f});
+    lines.add({{300.0f, 230.0f},
+               {400.0f, 280.0f},
+               Color4(0xC0, 0x00, 0x00, 0xFF),
+               0.4f});
+    lines.add({{400.0f, 280.0f},
+               {500.0f, 330.0f},
+               Color4(0x90, 0x00, 0x00, 0xFF),
+               0.6f});
+    lines.add({{500.0f, 330.0f},
+               {600.0f, 380.0f},
+               Color4(0x60, 0x00, 0x00, 0xFF),
+               0.8f});
+
+    lines.add({{300.0f, 140.0f},
+               {400.0f, 200.0f},
+               Color4(0xF0, 0x00, 0x00, 0xFF),
+               0.2f});
+    lines.add({{400.0f, 200.0f},
+               {500.0f, 220.0f},
+               Color4(0xC0, 0x00, 0x00, 0xFF),
+               0.4f});
+    lines.add({{500.0f, 220.0f},
+               {600.0f, 240.0f},
+               Color4(0x90, 0x00, 0x00, 0xFF),
+               0.6f});
+    lines.add({{600.0f, 240.0f},
+               {700.0f, 260.0f},
+               Color4(0x60, 0x00, 0x00, 0xFF),
+               0.8f});
 
     velocity += acceleration;
 
@@ -241,11 +355,20 @@ void Game::tick() {
             }
         }
     }
-    steepness = slopeSteepness();
+    float oldSteepness = steepness;
+    slopeSteepnessAndFriction();
     onGround = std::abs(steepness) < 1.0f;
     if(onGround) {
         velocity[1] = 0.0f;
     }
+    if(steepness == 100.0f) {
+        steepness = oldSteepness;
+    }
+
+    projectileLastPosition = projectilePosition;
+    projectileVelocity -= Vector2(0.0f, GRAVITY);
+    projectilePosition += projectileVelocity;
+    relaunchProjectile();
 }
 
 void Game::render(float lag, Renderer& r) {
@@ -255,8 +378,22 @@ void Game::render(float lag, Renderer& r) {
         .update();
     r.drawRectangle(waterPosition, waterSize, Color4(0x00, 0x00, 0xFF, 0xFF));
 
-    Vector2 pos = Utils::interpolate(lastPosition, position, lag);
-    r.drawRectangle(pos, size, Color4(0xFF, 0x00, 0x00, 0xFF));
+    r.push();
+    r.translateTo(0.0f, 0.0f)
+        .translate(-size * 0.5f)
+        .rotate(atanf(steepness) * 180.0f / M_PI)
+        .translate(Utils::interpolate(lastPosition, position, lag))
+        .translate(size * 0.5f)
+        .scale(1.0f, -1.0f)
+        .translateY(Engine::getSize().height)
+        .update();
+    r.drawRectangle(Vector2(), size, Color4(0xFF, 0x00, 0x00, 0xFF));
+    r.pop();
+    r.update();
+
+    r.drawRectangle(
+        Utils::interpolate(projectileLastPosition, projectilePosition, lag),
+        projectileSize, Color4(0xFF, 0xFF, 0x00, 0xFF));
 
     for(const Line& line : lines) {
         Vector2 dir = line.b - line.a;
@@ -267,8 +404,8 @@ void Game::render(float lag, Renderer& r) {
         Vector2 bp = line.b + normal;
         Vector2 an = line.a - normal;
         Vector2 bn = line.b - normal;
-        r.drawTriangle(ap, bp, an, Color4(0xFF, 0xFF, 0xFF, 0xFF));
-        r.drawTriangle(bp, an, bn, Color4(0xFF, 0xFF, 0xFF, 0xFF));
+        r.drawTriangle(ap, bp, an, line.color);
+        r.drawTriangle(bp, an, bn, line.color);
     }
 
     r.translateTo(0.0f, 0.0f).update();
@@ -284,6 +421,10 @@ void Game::render(float lag, Renderer& r) {
     y = r.drawString(10.0f, y, s);
     s.clear().append("Ground = ").append(onGround);
     y = r.drawString(10.0f, y, s);
+    s.clear().append("Angle = ").append(atanf(steepness) * 57.295779513f);
+    y = r.drawString(10.0f, y, s);
+    s.clear().append("Friction = ").append(friction);
+    y = r.drawString(10.0f, y, s);
 }
 
 bool Game::isRunning() {

+ 2 - 2
rendering/Renderer.cpp

@@ -31,8 +31,8 @@ Renderer& Renderer::scale(float s) {
     return *this;
 }
 
-Renderer& Renderer::translate(float tx, float ty) {
-    stack.peek().translateX(tx).translateY(ty);
+Renderer& Renderer::translate(const Vector2& v) {
+    stack.peek().translateX(v[0]).translateY(v[1]);
     return *this;
 }
 

+ 1 - 1
rendering/Renderer.h

@@ -25,7 +25,7 @@ public:
     Renderer& scale(float sx, float sy);
     Renderer& scale(float s);
 
-    Renderer& translate(float tx, float ty);
+    Renderer& translate(const Vector2& v);
     Renderer& translateX(float tx);
     Renderer& translateY(float ty);
     Renderer& translateTo(float tx, float ty);