From 3159efb2574e7540f6ce95ffbf28e7e01b2b7243 Mon Sep 17 00:00:00 2001 From: Andrew Haynes Macbook Date: Sun, 25 Jan 2026 15:37:54 -0500 Subject: [PATCH] remaking entire collsion system --- include/elements.hpp | 19 +- src/data.cpp | 2 +- src/elements.cpp | 411 +++++++++++++++++++++---------------------- src/main.cpp | 51 +++--- 4 files changed, 240 insertions(+), 243 deletions(-) diff --git a/include/elements.hpp b/include/elements.hpp index c2071b9..6a01fbd 100644 --- a/include/elements.hpp +++ b/include/elements.hpp @@ -27,8 +27,9 @@ class Object { public: Object(ObjectData data); - CollisionDir find_intersection(Object& entity); + // CollisionDir find_intersection(Object& entity); float find_horizontal_difference_from_interesection(Object& entity); + float find_intersection(Object &entity); sf::RectangleShape rect; }; @@ -62,17 +63,17 @@ class Player : public Entity void update_bounding_box(); int check_bounding_box( std::array, MAX_COLS>, MAX_ROWS>& tilemap); - void handle_movment(Timer& dash); + void handle_movment(Timer& dash, std::array, 19>, 13> &tilemap); void handle_gravity(); bool get_jumping(); void horizontal_no_out_of_bounds(); - void vertical_no_out_of_bounds(Entity& base); - bool get_horizontal_collision( - std::array, MAX_COLS>, MAX_ROWS>& tilemap); - bool get_vertical_top_collision( - std::array, MAX_COLS>, MAX_ROWS>& tilemap); - bool get_vertical_bottom_collision( - std::array, MAX_COLS>, MAX_ROWS>& tilemap); + void vertical_no_out_of_bounds(); + // bool get_horizontal_collision( + // std::array, MAX_COLS>, MAX_ROWS>& tilemap); + // bool get_vertical_top_collision( + // std::array, MAX_COLS>, MAX_ROWS>& tilemap); + // bool get_vertical_bottom_collision( + // std::array, MAX_COLS>, MAX_ROWS>& tilemap); private: sf::Vector2f _min_velocity { 0, 0 }; diff --git a/src/data.cpp b/src/data.cpp index 045fb00..d1e50dd 100644 --- a/src/data.cpp +++ b/src/data.cpp @@ -47,7 +47,7 @@ PlayerData player_data = [] data.size = { TILESIZE / 2.0f, TILESIZE / 2.0f }; data.edge = -1.0f; data.velocity = { 3.0f, 0.0f }; - data.max_dash_acceleration = 15.0f; // 15 + data.max_dash_acceleration = 30.0f; // 15 data.max_vertical_acceleration = 12.5f; return data; }(); diff --git a/src/elements.cpp b/src/elements.cpp index 8381667..91a0f16 100644 --- a/src/elements.cpp +++ b/src/elements.cpp @@ -3,11 +3,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include "data.hpp" #include "globals.hpp" @@ -20,6 +22,19 @@ namespace rv = ranges::views; namespace rv = std::views; #endif +float +total_distance(int k) +{ + if (k > 0) return k + total_distance(k - 1); + else return 0; +} + +float +distance_to_acceleration(int target) +{ + return roundf(-1 + sqrtf(1 + 8 * target) / 2); +} + Object::Object(ObjectData data) { rect.setSize(data.size); @@ -53,140 +68,119 @@ Entity::get_velocity() return _velocity; } -CollisionDir +float Object::find_intersection(Object& entity) { - sf::FloatRect a = rect.getGlobalBounds(); - sf::FloatRect b = entity.rect.getGlobalBounds(); - auto inter = a.findIntersection(b); - if (!inter) - { - return CollisionDir::None; - } - - const auto overlap = *inter; - - float overlapW = overlap.size.x; - float overlapH = overlap.size.y; - - if (overlapW < overlapH) - { - // Horizontal collision - return (a.position.x < b.position.x) - ? CollisionDir::Right // a hit b from the left side - : CollisionDir::Left; // a hit b from the right side - } - else - { - return (a.position.y < b.position.y) ? CollisionDir::Bottom : CollisionDir::Top; - } + std::optional intersection = + rect.getGlobalBounds().findIntersection(entity.rect.getGlobalBounds()); + return intersection->size.x; + // return false; } -float -Object::find_horizontal_difference_from_interesection(Object& entity) -{ - sf::FloatRect a = rect.getGlobalBounds(); - sf::FloatRect b = entity.rect.getGlobalBounds(); - auto inter = a.findIntersection(b); - if (!inter) - { - return 0; - } +// CollisionDir +// Object::find_intersection(Object& entity) +// { +// sf::FloatRect a = rect.getGlobalBounds(); +// sf::FloatRect b = entity.rect.getGlobalBounds(); +// auto inter = a.findIntersection(b); +// if (!inter) +// { +// return CollisionDir::None; +// } +// +// const auto overlap = *inter; +// +// float overlapW = overlap.size.x; +// float overlapH = overlap.size.y; +// +// if (overlapW < overlapH) +// { +// // Horizontal collision +// return (a.position.x < b.position.x) +// ? CollisionDir::Right // a hit b from the left side +// : CollisionDir::Left; // a hit b from the right side +// } +// else +// { +// return (a.position.y < b.position.y) ? CollisionDir::Bottom : CollisionDir::Top; +// } +// } - const auto overlap = *inter; +// float +// Object::find_horizontal_difference_from_interesection(Object& entity) +// { +// sf::FloatRect a = rect.getGlobalBounds(); +// sf::FloatRect b = entity.rect.getGlobalBounds(); +// auto inter = a.findIntersection(b); +// if (!inter) +// { +// return 0; +// } +// +// const auto overlap = *inter; +// +// return (a.position.x < b.position.x) +// ? b.position.x - a.position.x // a hit b from the left side +// : a.position.x - b.position.x; // a hit b from the right side +// } - return (a.position.x < b.position.x) - ? b.position.x - a.position.x // a hit b from the left side - : a.position.x - b.position.x; // a hit b from the right side -} - -/* Bounding Box - * Create on dash in front of player and check if the box collides with a wall, - * if so find the difference of the wall and the player and set the dash_distance - * to difference. - * */ - -float -total_distance(int k) -{ - if (k > 0) return k + total_distance(k - 1); - else return 0; -} - -float -distance_to_acceleration(int target) -{ - return roundf(-1 + sqrtf(1 + 8 * target) / 2); -} +// +// void +// Player::initialize_bounding_box() +// { +// bounding_box = std::make_unique(object_data[1]); +// float length = total_distance(max_dash_acceleration); +// if (direction == "left") +// { +// bounding_box->rect.setSize({ -length, rect.getSize().y }); +// } +// else +// { +// bounding_box->rect.setSize({ length, rect.getSize().y }); +// } +// } +// +// void +// Player::update_bounding_box() +// { +// bounding_box->rect.setPosition({ rect.getPosition().x, rect.getPosition().y }); +// } +// +// int +// Player::check_bounding_box( +// std::array, MAX_COLS>, MAX_ROWS>& tilemap) +// { +// int distance = 0; +// float max_dist = total_distance(player_data.max_dash_acceleration); +// float min_dist = max_dist; +// +// for (auto [i, j] : rv::cartesian_product(rv::iota(0, MAX_ROWS), rv::iota(0, MAX_COLS))) +// { +// if (tilemap[i][j] == nullptr) continue; +// float current_dist = +// bounding_box->find_horizontal_difference_from_interesection(*tilemap[i][j]); +// +// if (current_dist > 0 && current_dist < min_dist) +// { +// min_dist = current_dist; +// } +// } +// float final_dist = min_dist; +// if (direction == "left") +// { +// bounding_box->rect.setSize({ -final_dist, bounding_box->rect.getSize().y }); +// } +// else +// { +// bounding_box->rect.setSize({ final_dist, bounding_box->rect.getSize().y }); +// } +// max_dash_acceleration = distance_to_acceleration(final_dist); +// return final_dist; +// } void -Player::initialize_bounding_box() -{ - bounding_box = std::make_unique(object_data[1]); - float length = total_distance(max_dash_acceleration); - if (direction == "left") - { - bounding_box->rect.setSize({ -length, rect.getSize().y }); - } - else if (direction == "right") - { - bounding_box->rect.setSize({ length, rect.getSize().y }); - } - bounding_box->rect.setPosition({ rect.getPosition().x, rect.getPosition().y }); -} - -void -Player::update_bounding_box() -{ - bounding_box->rect.setPosition({ rect.getPosition().x, rect.getPosition().y }); -} - -int -Player::check_bounding_box( - std::array, MAX_COLS>, MAX_ROWS>& tilemap) -{ - int distance = 0; - /* - * The box checks the wall farthest into the hitbox and not the closest one to the player - * - * Best idea is to just check if there is a collision and set hitbox to that size and then - * see if that checks the one closest to the player - * - * Make a way to find the shortest distance on the collsion becuase the wall closest to the - * player will ahve a shorter difference_from_interesection than a one further from it will - * - * */ - for (auto [i, j] : rv::cartesian_product(rv::iota(0, MAX_ROWS), rv::iota(0, MAX_COLS))) - { - if (tilemap[i][j] == nullptr) continue; - if (bounding_box->find_horizontal_difference_from_interesection(*tilemap[i][j]) > 0) - { - std::cout << "Intersection: " - << bounding_box->find_horizontal_difference_from_interesection( - *tilemap[i][j]) - << "\n"; - bounding_box->rect.setSize( - { bounding_box->find_horizontal_difference_from_interesection( - *tilemap[i][j]), - bounding_box->rect.getSize().y }); - distance = bounding_box->rect.getSize().x; - max_dash_acceleration = distance_to_acceleration(distance); - } - else if (bounding_box->find_horizontal_difference_from_interesection( - *tilemap[i][j]) <= 0 && - bounding_box->rect.getSize().x <= total_distance(15)) - { - bounding_box->rect.setSize( - { bounding_box->rect.getSize().x + 1, bounding_box->rect.getSize().y }); - max_dash_acceleration = - distance_to_acceleration(bounding_box->rect.getSize().x); - } - } - return distance; -} - -void -Player::handle_movment(Timer& dash) +Player::handle_movment(Timer& dash, + std::array, 19>, 13>& tilemap) { if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::D)) { @@ -198,15 +192,18 @@ Player::handle_movment(Timer& dash) direction = "left"; rect.move({ -_velocity.x, 0 }); } - if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::W) && dash.get_time() <= 0) - { - // Dash order: spawn hitbox, check distance and set max_dash_acceleration - // Outside of this set max_dash_acceleration back to 15 { default } - max_dash_acceleration = player_data.max_dash_acceleration; - initialize_bounding_box(); - _velocity.x = max_dash_acceleration; - dash.reset(); - } + // if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::W) && dash.get_time() <= 0) + // { + // // Dash order: spawn hitbox, check distance and set max_dash_acceleration + // // Outside of this set max_dash_acceleration back to 15 { default } + // max_dash_acceleration = player_data.max_dash_acceleration; + // initialize_bounding_box(); + // update_bounding_box(); + // std::cout << check_bounding_box(tilemap) << "\n"; + // _velocity.x = max_dash_acceleration; + // // _velocity.x = 15; + // dash.reset(); + // } if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::Space) && !m_jumping && _velocity.x <= 3) { m_jumping = true; @@ -245,83 +242,81 @@ Player::horizontal_no_out_of_bounds() } void -Player::vertical_no_out_of_bounds(Entity& base) +Player::vertical_no_out_of_bounds() { - float groundY = base.rect.getPosition().y - base.rect.getSize().y - rect.getSize().y - - base.rect.getOutlineThickness() - rect.getOutlineThickness(); - if (rect.getPosition().y >= groundY) + if (rect.getPosition().y >= HEIGHT - 48) { - rect.setPosition({ rect.getPosition().x, groundY }); + rect.setPosition({ rect.getPosition().x, HEIGHT - 48 }); set_velocity_y(0); m_jumping = false; } } -bool -Player::get_horizontal_collision( - std::array, MAX_COLS>, MAX_ROWS>& tilemap) -{ - for (auto [i, j] : rv::cartesian_product(rv::iota(0, MAX_ROWS), rv::iota(0, MAX_COLS))) - { - if (tilemap[i][j] == nullptr) continue; - auto collision = tilemap[i][j]->find_intersection(*this); - if (collision == CollisionDir::None) continue; - if (collision == CollisionDir::Left) - { - rect.setPosition({ tilemap[i][j]->rect.getPosition().x - rect.getSize().x, - rect.getPosition().y }); - return true; - } - if (collision == CollisionDir::Right) - { - rect.setPosition( - { tilemap[i][j]->rect.getPosition().x + tilemap[i][j]->rect.getSize().x, - rect.getPosition().y }); - return true; - } - } - return false; -} - -bool -Player::get_vertical_top_collision( - std::array, MAX_COLS>, MAX_ROWS>& tilemap) -{ - for (auto [i, j] : rv::cartesian_product(rv::iota(0, MAX_ROWS), rv::iota(0, MAX_COLS))) - { - if (tilemap[i][j] == nullptr) continue; - auto collision = find_intersection(*tilemap[i][j]); - if (collision == CollisionDir::None) continue; - if (collision == CollisionDir::Top) - { - rect.setPosition( - { rect.getPosition().x, tilemap[i][j]->rect.getSize().y + - tilemap[i][j]->rect.getPosition().y }); - set_velocity_y(0); - return true; - } - } - return false; -} - -bool -Player::get_vertical_bottom_collision( - std::array, MAX_COLS>, MAX_ROWS>& tilemap) -{ - for (auto [i, j] : rv::cartesian_product(rv::iota(0, MAX_ROWS), rv::iota(0, MAX_COLS))) - { - if (tilemap[i][j] == nullptr) continue; - auto collision = find_intersection(*tilemap[i][j]); - if (collision == CollisionDir::None) continue; - if (collision == CollisionDir::Bottom && get_velocity().y > 0) - { - rect.setPosition( - { rect.getPosition().x, - tilemap[i][j]->rect.getPosition().y - rect.getSize().y }); - m_jumping = false; - set_velocity_y(0); - return true; - } - } - return false; -} +// bool +// Player::get_horizontal_collision( +// std::array, MAX_COLS>, MAX_ROWS>& tilemap) +// { +// for (auto [i, j] : rv::cartesian_product(rv::iota(0, MAX_ROWS), rv::iota(0, MAX_COLS))) +// { +// if (tilemap[i][j] == nullptr) continue; +// auto collision = tilemap[i][j]->find_intersection(*this); +// if (collision == CollisionDir::None) continue; +// if (collision == CollisionDir::Left) +// { +// rect.setPosition({ tilemap[i][j]->rect.getPosition().x - rect.getSize().x, +// rect.getPosition().y }); +// return true; +// } +// if (collision == CollisionDir::Right) +// { +// rect.setPosition( +// { tilemap[i][j]->rect.getPosition().x + tilemap[i][j]->rect.getSize().x, +// rect.getPosition().y }); +// return true; +// } +// } +// return false; +// } +// +// bool +// Player::get_vertical_top_collision( +// std::array, MAX_COLS>, MAX_ROWS>& tilemap) +// { +// for (auto [i, j] : rv::cartesian_product(rv::iota(0, MAX_ROWS), rv::iota(0, MAX_COLS))) +// { +// if (tilemap[i][j] == nullptr) continue; +// auto collision = find_intersection(*tilemap[i][j]); +// if (collision == CollisionDir::None) continue; +// if (collision == CollisionDir::Top) +// { +// rect.setPosition( +// { rect.getPosition().x, tilemap[i][j]->rect.getSize().y + +// tilemap[i][j]->rect.getPosition().y }); +// set_velocity_y(0); +// return true; +// } +// } +// return false; +// } +// +// bool +// Player::get_vertical_bottom_collision( +// std::array, MAX_COLS>, MAX_ROWS>& tilemap) +// { +// for (auto [i, j] : rv::cartesian_product(rv::iota(0, MAX_ROWS), rv::iota(0, MAX_COLS))) +// { +// if (tilemap[i][j] == nullptr) continue; +// auto collision = find_intersection(*tilemap[i][j]); +// if (collision == CollisionDir::None) continue; +// if (collision == CollisionDir::Bottom && get_velocity().y > 0) +// { +// rect.setPosition( +// { rect.getPosition().x, +// tilemap[i][j]->rect.getPosition().y - rect.getSize().y }); +// m_jumping = false; +// set_velocity_y(0); +// return true; +// } +// } +// return false; +// } diff --git a/src/main.cpp b/src/main.cpp index a533463..b02a8cc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -32,10 +32,6 @@ std::string assets = "/home/andrew/personal/Projects/CPP/engine/assets/"; int main() { - // float dist = total_distance(12); - // std::cout << "Distance: " << dist << "\n"; - // float acc = distance_to_acceleration(total_distance(12)); - // std::cout << "Distance: " << acc << "\n"; Scheduler scheduler; Manager map_manager; map_manager.load(level_data[BASE]); @@ -93,34 +89,39 @@ main() scheduler.timers.at(1).reset(); } - player.handle_movment(scheduler.timers.at(scheduler.pull("Dash"))); - player.get_horizontal_collision(map_manager.tilemap); + player.handle_movment(scheduler.timers.at(scheduler.pull("Dash")), map_manager.tilemap); + // player.get_horizontal_collision(map_manager.tilemap); player.handle_gravity(); - std::cout << "Vel: " << player.get_velocity().x << ", " << player.get_velocity().y - << "\n"; - if (player.get_velocity().y > ((float)TILESIZE / 2 - GRAVITY)) - { - player.set_velocity_y((TILESIZE / 2) - GRAVITY); - } + player.vertical_no_out_of_bounds(); + // if (player.get_velocity().y > ((float)TILESIZE / 2 - GRAVITY)) + // { + // player.set_velocity_y((TILESIZE / 2) - GRAVITY); + // } - if (!player.get_vertical_bottom_collision(map_manager.tilemap)) - { - player.get_vertical_top_collision(map_manager.tilemap); - } - if (player.bounding_box != nullptr) - { - player.update_bounding_box(); - player.check_bounding_box(map_manager.tilemap); + // if (!player.get_vertical_bottom_collision(map_manager.tilemap)) + // { + // player.get_vertical_top_collision(map_manager.tilemap); + // } + // if (player.bounding_box != nullptr) + // { + // player.update_bounding_box(); + // // player.check_bounding_box(map_manager.tilemap); + // } + for (auto [i, j] : rv::cartesian_product(rv::iota(0, MAX_ROWS), rv::iota(0, MAX_COLS))) { + if(map_manager.tilemap[i][j]) { + std::cout << player.find_intersection(*map_manager.tilemap[i][j]); + window.close(); + } } map_manager.draw(window); window.draw(player.rect); - if (player.bounding_box != nullptr) - { - window.draw(player.bounding_box->rect); - } - window.draw(text); + // if (player.bounding_box != nullptr) + // { + // window.draw(player.bounding_box->rect); + // } + // window.draw(text); window.display(); }