Player collision response and movement physics v1.

This commit is contained in:
2025-02-25 16:57:06 -05:00
parent 24790c5c0c
commit b8a59d98c5
10 changed files with 81 additions and 28 deletions

View File

@@ -25,6 +25,7 @@ namespace CaveGame::Client {
Event<std::string> OnInput;
void OnInputEvent(const std::string& msg);
explicit Console(Widget* parent);
@@ -39,6 +40,7 @@ namespace CaveGame::Client {
JUI::ScrollingRect* message_log_box;
JUI::VerticalListLayout* message_log_layout;
bool console_open = false;
std::vector<std::string> history;
private:
};
}

View File

@@ -33,7 +33,6 @@ CaveGame::Client::Console::Console(JUI::Widget *parent) : JUI::Window(parent)
input_box->OnReturn += [this] (const std::string& msg) {
OnInputEvent(msg);
};
CaveGame::Logs::Info.OnLog += [this](std::string m, Color4 c) {Log(m, c); };

View File

@@ -7,8 +7,9 @@
// TODO: Move this shit to Client/Player.cpp
void CaveGame::Core::Player::Draw() {
auto myAsset = Client::AssetService::Get()->player_sprite;
JGL::J2D::DrawPartialSprite(myAsset, position, {0,0}, {16, 24});
JGL::J2D::OutlineRect(Colors::Red, position, bounding_box);
JGL::J2D::DrawPartialSprite(myAsset, RenderTopLeft(), {0,0}, {16, 24}, 0);
JGL::J2D::OutlineRect(Colors::Red, RenderTopLeft(), texture_center * 2.f);
JGL::J2D::OutlineRect(Colors::Blue, TopLeft(), bounding_box);
J2D::DrawString(Colors::White, std::format("vel: {},{}", Math::Round(velocity.x, 2), Math::Round(velocity.y, 2)), position.x, position.y-8, 0.5f, 8);
J2D::DrawString(Colors::White, std::format("ct: {} cd: {}", coll_tests, coll_hits), position.x, position.y-16, 0.5f, 8);
}
@@ -25,6 +26,6 @@ void CaveGame::Core::Player::Update(float elapsed) {
if (InputService::IsKeyDown(Keys::W))
Jump();
if (InputService::IsKeyDown(Keys::S))
Accelerate({0, -1});
//if (InputService::IsKeyDown(Keys::S))
//Accelerate({0, -1});
}

View File

@@ -17,6 +17,7 @@ void CaveGame::Client::TileHotbar::Load(CaveGame::Client::LocalWorld *world) {
hotbar_root->BorderMode(JUI::BorderMode::Outline);
item_label = new JUI::TextRect(hotbar_root);
item_label->BorderWidth(0);
item_label->BGColor({0,0,0,0});
item_label->AnchorPoint({1,0});
item_label->SetContent("Item Name Here");
@@ -75,6 +76,7 @@ void CaveGame::Client::TileHotbar::Load(CaveGame::Client::LocalWorld *world) {
amount_label->Size({30_px, 30_px});
amount_label->Position({95_percent, 95_percent});
amount_label->AlignRight();
amount_label->BorderWidth(0);
hotbar_elements[i] = cell;
}

View File

@@ -28,8 +28,6 @@ namespace CaveGame::ClientApp {
std::function<void(CommandArgs)> callback;
};
/// The main program class. Everything originates here.
/// This class is derived from RWindow class.
class CaveGameWindow : public ReWindow::OpenGLWindow, public SceneManager {

View File

@@ -41,6 +41,11 @@ namespace CaveGame::Core {
Vector2 Position() const;
Vector2 TopLeft() const { return Position()-(bounding_box/2.f);}
Vector2 RenderTopLeft() const { return Position()-(texture_center);}
Vector2 Centroid() const { return Position();}
AABB2D TranslatedBoundingBoxAABB() const { }
Vector2 Size() const;
virtual void CollisionTest(ITileMap* map, float step) {}
@@ -51,8 +56,12 @@ namespace CaveGame::Core {
float age;
Vector2 position;
Vector2 bounding_box;
Vector2 texture_center;
Vector2 render_center;
std::vector<StatusEffect> active_effects;
Color4 color;
bool on_ground;
float climbing_skill = 15;
private:
};

View File

@@ -29,20 +29,19 @@ namespace CaveGame::Core
virtual void PhysicsUpdate(float elapsed);
// TODO: Mechanism for figuring out if you're already stuck inside of tiles: i.e. sand
void CollisionTest(ITileMap* map, float elapsed) override {
// The current "collision system" is unstable,
// One problem in particular is sometimes the entity gets teleported too far out, in a nonsensical way.
// The AABB separation may not be ideal, given how small the tile colliders are.
coll_tests = 0;
coll_hits = 0;
for (int x = -1; x <= bounding_box.x; x++) {
for (int y = -1; y <= bounding_box.y; y++) {
Vector2 tileBoxPos = Vector2(Math::Floor(position.x), Math::Floor(position.y)) + Vector2(x,y);
Vector2 coll_topleft = next_position - (bounding_box / 2.f);
Vector2 tileBoxPos = Vector2(Math::Floor(coll_topleft.x), Math::Floor(coll_topleft.y)) + Vector2(x,y);
TileID id = map->GetTile(tileBoxPos.x, tileBoxPos.y);
@@ -51,35 +50,66 @@ namespace CaveGame::Core
coll_tests++;
Vector2 entity_centroid = position + (bounding_box / 2.f);
Vector2 entity_centroid = next_position; // + (bounding_box / 2.f);
Vector2 entity_halfbox = bounding_box / 2.f;
Vector2 tile_centroid = tileBoxPos + Vector2{0.5f, 0.5f};
Vector2 tile_halfbox = Vector2{0.5f, 0.5f};
if (Solver::AABB2Dvs(entity_centroid, entity_halfbox, tile_centroid, tile_halfbox)) {
coll_hits++;
Vector2 separation = Solver::SolveAABB(entity_centroid, entity_halfbox, tile_centroid, tile_halfbox);
Vector2 normal = Solver::GetNormalForAABB(separation, velocity);
next_position += separation;
//std::cout << std::format("Solved: Sep: {},{}, Norm: {},{}", separation.x, separation.y, normal.x, normal.y) << std::endl;
if (normal.x == 0 && normal.y == 0)
continue;
// Touched top.
if (normal.y == -1)
{
velocity.y = 0;
on_ground = true;
//std::cout << "Touched your feet" << std::endl;
}
if (normal.y == 1) {
velocity.y = -velocity.y*0.5f;
std::cout << "Touched your head" << std::endl;
}
if (normal.x == -1)
{
//std::cout << "Touched your right" << std::endl;
}
if (normal.x == 1)
{
//std::cout << "Touched your left" << std::endl;
}
if (normal.y == 1)
velocity.y = -velocity.y;
// TODO: Refine condition for "step-up"s
if (normal.x != 0 && velocity.y == 0)
if (normal.x != 0 && Math::Abs(velocity.x) > 10 && on_ground) {// && Math::Abs(velocity.y) < 2 ) {
//std::cout << "Step up" << std::endl;
next_position.y -= 1;
//next_position.x -= normal.x;
velocity.y -= climbing_skill;
velocity.x *= 0.75f;
}
next_position += separation;
return;
//next_position += separation;
//return;
}
}
}
@@ -98,6 +128,7 @@ namespace CaveGame::Core
float mass;
int coll_tests;
int coll_hits;
Vector2 last_normal;
private:
};

View File

@@ -14,16 +14,22 @@ namespace CaveGame::Core
void Update(float elapsed) override;
void PhysicsUpdate(float elapsed) override;
void Jump() {
Accelerate({0, -2});
// TODO: Make it so the player falls **slightly** slower
if (on_ground)
{
Accelerate({0, -150});
on_ground = false;
} else
Accelerate({0, -5});
}
void Climb();
void Descend();
void Crouch();
void WalkLeft() {
Accelerate({-1, 0});
Accelerate({-4, 0});
}
void WalkRight() {
Accelerate({1, 0});
Accelerate({4, 0});
}
protected:
};

View File

@@ -18,11 +18,15 @@ namespace CaveGame::Core
void PhysicsEntity::PhysicsUpdate(float elapsed) {
next_position += velocity * elapsed;
float friction = 3.45f;
float air_resistance = 3.45f;
float gravity = 9.81f;
float mass = 32.f;
float mass = 40.f;
velocity *= (1 - (elapsed*friction));
if (Math::Abs(velocity.y) > 1e-2f)
on_ground = false;
//
velocity *= (1 - (elapsed * air_resistance));
velocity.y += (elapsed*gravity*mass);

View File

@@ -4,7 +4,8 @@
namespace CaveGame::Core {
Player::Player(const Vector2 &spawnPoint): Humanoid(spawnPoint) {
bounding_box = {16, 24};
bounding_box = {10, 24};
texture_center = {8, 12};
}
void Player::Draw() {}