Added custom movement code for when player is noclipping.
This commit is contained in:
@@ -56,6 +56,22 @@ void CaveGame::Core::Player::Update(float elapsed) {
|
||||
|
||||
Vector2 dpad = jstick::GetDPadAxisNormalized();
|
||||
|
||||
if (noclip) {
|
||||
if (InputService::IsKeyDown(Keys::A) || dpad.x <= -0.5f)
|
||||
Accelerate({-500*elapsed, 0});
|
||||
|
||||
if (InputService::IsKeyDown(Keys::D) || dpad.x >= +0.5f)
|
||||
Accelerate({500*elapsed, 0});
|
||||
|
||||
if (InputService::IsKeyDown(Keys::W) || dpad.y <= -0.5f)
|
||||
Accelerate({0, -500*elapsed});
|
||||
|
||||
if (InputService::IsKeyDown(Keys::S) || dpad.y >= 0.5f)
|
||||
Accelerate({0, 500*elapsed});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (InputService::IsKeyDown(Keys::A) || dpad.x <= -0.5f)
|
||||
WalkLeft(elapsed);
|
||||
|
||||
|
@@ -9,7 +9,6 @@
|
||||
/// @edit 1/28/2025
|
||||
/// @auth Josh O'Leary
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Core/Entity.hpp>
|
||||
@@ -19,6 +18,10 @@ namespace CaveGame::Core
|
||||
{
|
||||
class PhysicsEntity : public Entity {
|
||||
public:
|
||||
constexpr static const float gravity = 9.81f;
|
||||
constexpr static const float air_resistance = 2.45f;
|
||||
|
||||
|
||||
bool freeze_in_void = true;
|
||||
explicit PhysicsEntity(const Vector2& spawnPoint);
|
||||
|
||||
@@ -30,123 +33,25 @@ 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 {
|
||||
void CollisionTest(ITileMap* map, float elapsed) override;
|
||||
|
||||
coll_tests = 0;
|
||||
coll_hits = 0;
|
||||
void Update(float elapsed) override;
|
||||
|
||||
for (int x = -1; x <= bounding_box.x; x++) {
|
||||
for (int y = -1; y <= bounding_box.y; 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);
|
||||
|
||||
if (id == Tiles()["void"].numeric_id) {
|
||||
if (freeze_in_void)
|
||||
{
|
||||
velocity = {0,0};
|
||||
next_position = position;
|
||||
return;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (id == Tiles()["air"].numeric_id)
|
||||
continue;
|
||||
|
||||
coll_tests++;
|
||||
|
||||
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);
|
||||
|
||||
|
||||
|
||||
//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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// TODO: Refine condition for "step-up"s
|
||||
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;
|
||||
|
||||
|
||||
//next_position += separation;
|
||||
//return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Update(float elapsed) override {
|
||||
|
||||
if (!on_ground)
|
||||
airtime += elapsed;
|
||||
else
|
||||
airtime = 0;
|
||||
|
||||
// TODO: Sophisticated mechanism to maintain locked-timestep, multiple-iteration physics steps.
|
||||
PhysicsUpdate(elapsed);
|
||||
|
||||
}
|
||||
virtual inline float Mass() { return 40;}
|
||||
|
||||
protected:
|
||||
Vector2 velocity;
|
||||
Vector2 next_position;
|
||||
float mass;
|
||||
int coll_tests;
|
||||
int coll_hits;
|
||||
Vector2 last_normal;
|
||||
private:
|
||||
void ApplyHorizontalFriction(float elapsed);
|
||||
|
||||
void ApplyGravityForce(float elapsed);
|
||||
|
||||
void ApplyAirResistance(float coefficient, float elapsed);
|
||||
};
|
||||
|
||||
}
|
||||
|
@@ -15,27 +15,168 @@ namespace CaveGame::Core
|
||||
velocity += vector;
|
||||
}
|
||||
|
||||
void PhysicsEntity::ApplyHorizontalFriction(float elapsed)
|
||||
{
|
||||
float base_friction_coefficient = 4.f;
|
||||
|
||||
velocity.x *= (1 - (elapsed * base_friction_coefficient));
|
||||
}
|
||||
|
||||
void PhysicsEntity::ApplyGravityForce(float elapsed)
|
||||
{
|
||||
velocity.y += (elapsed*gravity*Mass());
|
||||
}
|
||||
|
||||
void PhysicsEntity::Update(float elapsed) {
|
||||
|
||||
if (!on_ground)
|
||||
airtime += elapsed;
|
||||
else
|
||||
airtime = 0;
|
||||
|
||||
// TODO: Sophisticated mechanism to maintain locked-timestep, multiple-iteration physics steps.
|
||||
PhysicsUpdate(elapsed);
|
||||
|
||||
}
|
||||
|
||||
void PhysicsEntity::ApplyAirResistance(float coefficient, float elapsed)
|
||||
{
|
||||
velocity *= (1 - (elapsed * coefficient));
|
||||
}
|
||||
|
||||
void PhysicsEntity::PhysicsUpdate(float elapsed) {
|
||||
|
||||
if (noclip)
|
||||
{
|
||||
on_ground = true;
|
||||
|
||||
next_position += velocity * elapsed;
|
||||
|
||||
ApplyAirResistance(air_resistance*4, elapsed);
|
||||
|
||||
position = next_position;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
next_position += velocity * elapsed;
|
||||
|
||||
float air_resistance = 2.45f;
|
||||
float base_friction_coefficient = 4.f;
|
||||
float gravity = 9.81f;
|
||||
float mass = 40.f;
|
||||
|
||||
if (Math::Abs(velocity.y) > 1e-2f)
|
||||
if (Math::Abs(velocity.y) > 2)
|
||||
on_ground = false;
|
||||
|
||||
// Simulate friction.
|
||||
if (on_ground)
|
||||
velocity.x *= (1 - (elapsed * base_friction_coefficient));
|
||||
ApplyHorizontalFriction(elapsed);
|
||||
|
||||
|
||||
// Air resistance.
|
||||
velocity *= (1 - (elapsed * air_resistance));
|
||||
|
||||
velocity.y += (elapsed*gravity*mass);
|
||||
ApplyAirResistance(air_resistance, elapsed);
|
||||
ApplyGravityForce(elapsed);
|
||||
|
||||
position = next_position;
|
||||
}
|
||||
|
||||
void PhysicsEntity::CollisionTest(ITileMap *map, float elapsed) {
|
||||
|
||||
if (noclip)
|
||||
return;
|
||||
|
||||
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 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);
|
||||
|
||||
if (id == Tiles()["void"].numeric_id) {
|
||||
if (freeze_in_void)
|
||||
{
|
||||
velocity = {0,0};
|
||||
next_position = position;
|
||||
return;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (id == Tiles()["air"].numeric_id)
|
||||
continue;
|
||||
|
||||
// TODO: Profile this bit.
|
||||
if (Tiles().GetByNumericID(id).solid == false)
|
||||
continue;
|
||||
|
||||
coll_tests++;
|
||||
|
||||
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);
|
||||
|
||||
|
||||
|
||||
//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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// TODO: Refine condition for "step-up"s
|
||||
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;
|
||||
|
||||
|
||||
//next_position += separation;
|
||||
//return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user