Physics tuning window and some other fun edits.

This commit is contained in:
2025-06-13 13:31:33 -05:00
parent 631a2a17db
commit b8bed66928

View File

@@ -8,6 +8,48 @@
#include <JUI/Widgets/Window.hpp>
#include <SimpleAABBSolver.hpp>
#include "JUI/Widgets/ListLayout.hpp"
#include "JUI/Widgets/Slider.hpp"
float gravity = 9.8f;
float mass = 12.f;
float air_resistance = 8.f;
float friction = 0.001f;
float acceleration = 1200;
JGL::Texture* player_tex;
class LabeledSlider : public JUI::Slider, public JUI::TextBase {
public:
LabeledSlider() : Slider(), TextBase() {
}
explicit LabeledSlider(Widget* parent) : LabeledSlider()
{
this->Parent(parent);
}
void Draw() override {
Slider::Draw();
auto abs_pos = this->GetAbsolutePosition();
auto abs_size = this->GetAbsoluteSize();
auto pos_pad = GetAbsolutePaddingTopLeft();
auto size_pad = GetAbsolutePaddingBottomRight();
TextBase::Draw(abs_pos + pos_pad, abs_size - size_pad);
}
void Update(float elapsed) override {
Slider::Update(elapsed);
TextBase::Update(elapsed);
}
protected:
private:
};
class GameEntity
{
@@ -22,12 +64,12 @@ public:
virtual void Draw() = 0;
Vector2 pos;
Vector2 next_pos;
Vector2 bbox;
Vector2 velocity;
bool noclip = false;
bool on_ground = true;
};
class Player : public GameEntity
@@ -46,28 +88,38 @@ public:
// This means we can collision solve our next_pos in between calls to entity->Update();
pos = next_pos;
const float gravity = 9.8f;
const float mass = 1.f;
velocity.x *= 1 - (elapsed * air_resistance);
//velocity.y *= 1 - (elapsed * air_resistance);
//if (on_ground)
//velocity.x *= friction;
velocity.y += (elapsed*gravity*mass);
float constant_move_spd = 40;
next_pos += velocity * elapsed;
if (Math::Abs(velocity.y) > 2)
on_ground = false;
if (InputService::IsKeyDown(Keys::A))
next_pos.x -= constant_move_spd * elapsed;
velocity.x -= acceleration * elapsed;
if (InputService::IsKeyDown(Keys::D))
next_pos.x += constant_move_spd * elapsed;
velocity.x += acceleration * elapsed;
if (InputService::IsKeyDown(Keys::W))
next_pos.y -= constant_move_spd * elapsed;
velocity.y -= acceleration * elapsed;
if (InputService::IsKeyDown(Keys::S))
next_pos.y += constant_move_spd * elapsed;
velocity.y += acceleration * elapsed;
}
void Draw() override {
J2D::FillRect(Colors::Blue, pos, bbox);
J2D::DrawPartialSprite(player_tex, pos, {0,0}, bbox);
}
};
@@ -99,13 +151,75 @@ public:
using namespace JUI::UDimLiterals;
scene = new JUI::Scene();
player_tex = new JGL::Texture("assets/player.png");
//auto* fps_graph_window = new JUI::Window(scene);
//fps_graph_window->Size({500_px, 50_px});
//fps_graph_window->AnchorPoint({1, 0.f});
//fps_graph_window->Position({100_percent, 0_percent});
auto* fps_graph = new JUI::FpsGraph(scene);
fps_graph->Size({100_percent, 50_px});
fps_graph->AnchorPoint({1, 1});
fps_graph->Position({100_percent, 100_percent});
auto* phys_params_slider_window = new JUI::Window(scene);
phys_params_slider_window->Title("Physics Parameters");
auto* layout = new JUI::VerticalListLayout(phys_params_slider_window->Content());
auto* grav_slider = new LabeledSlider(layout);
grav_slider->Size({100_percent, 20_px});
grav_slider->Minimum(0); grav_slider->Maximum(1); grav_slider->Interval(1.f/10000.f);
grav_slider->CurrentValue(0.098f);
grav_slider->TextColor(Colors::Black);
grav_slider->Content(std::format("Gravity: {}", gravity));
grav_slider->ValueChanged += [&, grav_slider](float value) mutable {
gravity = value * 100.f;
grav_slider->Content(std::format("Gravity: {}", Math::Round(gravity, 3)));
};
auto* air_resist_slider = new LabeledSlider(layout);
air_resist_slider->Size({100_percent, 20_px});
air_resist_slider->Minimum(0); grav_slider->Maximum(1); air_resist_slider->Interval(1.f/10000.f);
air_resist_slider->CurrentValue(0.12f);
air_resist_slider->Content(std::format("Air Resistance: {}", gravity));
air_resist_slider->TextColor(Colors::Black);
air_resist_slider->ValueChanged += [&, air_resist_slider](float value) mutable {
air_resistance = value * 100.f;
air_resist_slider->Content(std::format("Air Resistance: {}", Math::Floor(air_resistance)));
};
auto* mass_slider = new LabeledSlider(layout);
mass_slider->Size({100_percent, 20_px});
mass_slider->Minimum(0); mass_slider->Maximum(1); mass_slider->Interval(1/10000.f);
mass_slider->CurrentValue(0.08f);
mass_slider->TextColor(Colors::Black);
mass_slider->Content(std::format("Player Mass: {}", gravity));
mass_slider->ValueChanged += [&, mass_slider](float value) mutable {
mass = value * 100.f;
mass_slider->Content(std::format("Player Mass: {}", mass));
};
auto* accel_slider = new LabeledSlider(layout);
accel_slider->Size({100_percent, 20_px});
accel_slider->Minimum(0); accel_slider->Maximum(1); accel_slider->Interval(1/10000.f);
accel_slider->CurrentValue(0.12f);
accel_slider->TextColor(Colors::Black);
accel_slider->Content(std::format("Player Accel: {}", acceleration));
accel_slider->ValueChanged += [&, accel_slider](float value) mutable {
acceleration = value * 10000.f;
accel_slider->Content(std::format("Player Accel: {}", acceleration));
};
auto* fps_graph_window = new JUI::Window(scene);
fps_graph_window->Size({500_px, 50_px});
fps_graph_window->AnchorPoint({1, 0.f});
fps_graph_window->Position({100_percent, 0_percent});
auto* fps_graph = new JUI::FpsGraph(fps_graph_window->Content());
fps_graph->Size({500_px, 50_px});
// TODO: More sophisticated order-of-operations is required.
@@ -150,8 +264,11 @@ public:
auto* plr = new Player({50, 50});
entities.emplace_back(plr);
for (int i = 0; i < 100; i++) {
auto* plr = new Player({50, 50});
entities.emplace_back(plr);
}
return true;
}
@@ -216,10 +333,14 @@ public:
//if (normal.x == 0 && normal.y == 0) continue; // Why though?
// Touched top.
if (normal.y == -1) { }
if (normal.y == -1) {
entity->velocity.y = 0;
}
// Touched bottom.
if (normal.y == 1) { }
if (normal.y == 1) {
entity->velocity.y *= -0.5f;
}
// Touched left, I think.
if (normal.x == -1) { }
@@ -250,6 +371,18 @@ public:
for (auto* entity : entities) {
entity->Update(elapsed);
}
if (!focused)
std::this_thread::sleep_for(std::chrono::milliseconds(48));
}
void OnFocusGain(const ReWindow::RWindowEvent &e) override {
focused = true;
}
void OnFocusLost(const ReWindow::RWindowEvent &e) override {
focused = false;
}
void DrawLayer(const Layer* layer) const
@@ -306,6 +439,41 @@ public:
Draw();
SwapBuffers();
}
enum JUI::MouseButton ToJUIEnum(const MouseButton& btn) {
if (btn == MouseButtons::Left) return JUI::MouseButton::Left;
if (btn == MouseButtons::Middle) return JUI::MouseButton::Middle;
if (btn == MouseButtons::Right) return JUI::MouseButton::Right;
// Default condition.
return JUI::MouseButton::Left;
}
void OnMouseButtonDown(const ReWindow::MouseButtonDownEvent &e) override {
auto btn = ToJUIEnum(e.Button);
if (scene->ObserveMouseInput(btn, true)) return;
}
void OnMouseButtonUp(const ReWindow::MouseButtonUpEvent &e) override {
auto btn = ToJUIEnum(e.Button);
if (scene->ObserveMouseInput(btn, false)) return;
}
void OnMouseMove(const ReWindow::MouseMoveEvent &e) override {
Vector2 mposv2(e.Position.x, e.Position.y);
if (scene->ObserveMouseMovement(mposv2)) return;
}
void OnKeyDown(const ReWindow::KeyDownEvent &e) override {
if (scene->ObserveKeyInput(e.key, true)) return;
}
void OnKeyUp(const ReWindow::KeyUpEvent &e) override {
if (scene->ObserveKeyInput(e.key, false)) return;
}
};
int main()