Skip to content

WIP: Separating collision system into multiple groups #3254

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/badguy/crusher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -705,7 +705,7 @@ CrusherRoot::CrusherRoot(Vector position, Crusher::Direction direction, float de
}
else
{
m_col.m_group = COLGROUP_DISABLED;
set_group(COLGROUP_DISABLED);
}
}

Expand Down Expand Up @@ -765,7 +765,7 @@ CrusherRoot::update(float dt_sec)
void
CrusherRoot::start_animation()
{
m_col.m_group = COLGROUP_TOUCHABLE;
set_group(COLGROUP_TOUCHABLE);

switch (m_direction)
{
Expand Down
103 changes: 78 additions & 25 deletions src/collision/collision_system.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ static const float FORGIVENESS = 256.f; // 16.f * 16.f - half a tile by half a t
CollisionSystem::CollisionSystem(Sector& sector) :
m_sector(sector),
m_objects(),
m_objects_by_collision_part(),
m_ground_movement_manager(new CollisionGroundMovementManager)
{
}
Expand All @@ -49,11 +50,36 @@ CollisionSystem::add(CollisionObject* object)
{
object->set_ground_movement_manager(m_ground_movement_manager);
m_objects.push_back(object);
add_to_collision_buckets(object);
}

void
CollisionSystem::add_to_collision_buckets(CollisionObject* object)
{
if(object->get_group() == COLGROUP_MOVING ||
object->get_group() == COLGROUP_MOVING_STATIC ||
object->get_group() == COLGROUP_MOVING_ONLY_STATIC)
{
m_objects_by_collision_part[CollisionPart::MOVING_MOVING_STATIC_ONLY_STATIC].push_back(object);
}

if(object->get_group() == COLGROUP_MOVING ||
object->get_group() == COLGROUP_MOVING_STATIC)
{
m_objects_by_collision_part[CollisionPart::MOVING_MOVING_STATIC].push_back(object);
}

if(object->get_group() == COLGROUP_TOUCHABLE)
{
m_objects_by_collision_part[CollisionPart::TOUCHABLE].push_back(object);
}
}

void
CollisionSystem::remove(CollisionObject* object)
{
remove_from_collision_buckets(object);

m_objects.erase(
std::find(m_objects.begin(), m_objects.end(),
object));
Expand All @@ -67,6 +93,46 @@ CollisionSystem::remove(CollisionObject* object)
}
}

void
CollisionSystem::remove_from_collision_buckets(CollisionObject* object)
{
if(object->get_group() == COLGROUP_MOVING ||
object->get_group() == COLGROUP_MOVING_STATIC ||
object->get_group() == COLGROUP_MOVING_ONLY_STATIC)
{
auto it = std::find(
m_objects_by_collision_part[CollisionPart::MOVING_MOVING_STATIC_ONLY_STATIC].begin(),
m_objects_by_collision_part[CollisionPart::MOVING_MOVING_STATIC_ONLY_STATIC].end(),
object);

if(it != m_objects_by_collision_part[CollisionPart::MOVING_MOVING_STATIC_ONLY_STATIC].end())
m_objects_by_collision_part[CollisionPart::MOVING_MOVING_STATIC_ONLY_STATIC].erase(it);
}

if(object->get_group() == COLGROUP_MOVING ||
object->get_group() == COLGROUP_MOVING_STATIC)
{
auto it = std::find(
m_objects_by_collision_part[CollisionPart::MOVING_MOVING_STATIC].begin(),
m_objects_by_collision_part[CollisionPart::MOVING_MOVING_STATIC].end(),
object);

if(it != m_objects_by_collision_part[CollisionPart::MOVING_MOVING_STATIC].end())
m_objects_by_collision_part[CollisionPart::MOVING_MOVING_STATIC].erase(it);
}

if(object->get_group() == COLGROUP_TOUCHABLE)
{
auto it = std::find(
m_objects_by_collision_part[CollisionPart::TOUCHABLE].begin(),
m_objects_by_collision_part[CollisionPart::TOUCHABLE].end(),
object);

if(it != m_objects_by_collision_part[CollisionPart::TOUCHABLE].end())
m_objects_by_collision_part[CollisionPart::TOUCHABLE].erase(it);
}
}

void
CollisionSystem::draw(DrawingContext& context)
{
Expand Down Expand Up @@ -593,22 +659,16 @@ CollisionSystem::update()
}

// Part 1: COLGROUP_MOVING vs COLGROUP_STATIC and tilemap.
for (const auto& object : m_objects) {
if ((object->get_group() != COLGROUP_MOVING
&& object->get_group() != COLGROUP_MOVING_STATIC
&& object->get_group() != COLGROUP_MOVING_ONLY_STATIC)
|| !object->is_valid())
for (const auto& object : m_objects_by_collision_part[CollisionPart::MOVING_MOVING_STATIC_ONLY_STATIC]) {
if (object && !object->is_valid())
continue;

collision_static_constrains(*object);
}

// Part 2: COLGROUP_MOVING vs tile attributes.
for (const auto& object : m_objects) {
if ((object->get_group() != COLGROUP_MOVING
&& object->get_group() != COLGROUP_MOVING_STATIC
&& object->get_group() != COLGROUP_MOVING_ONLY_STATIC)
|| !object->is_valid())
for (const auto& object : m_objects_by_collision_part[CollisionPart::MOVING_MOVING_STATIC_ONLY_STATIC]) {
if (object && !object->is_valid())
continue;

uint32_t tile_attributes = collision_tile_attributes(object->m_dest, object->get_movement());
Expand All @@ -618,16 +678,13 @@ CollisionSystem::update()
}

// Part 2.5: COLGROUP_MOVING vs COLGROUP_TOUCHABLE.
for (const auto& object : m_objects)
for (const auto& object : m_objects_by_collision_part[CollisionPart::MOVING_MOVING_STATIC])
{
if ((object->get_group() != COLGROUP_MOVING
&& object->get_group() != COLGROUP_MOVING_STATIC)
|| !object->is_valid())
if (object && !object->is_valid())
continue;

for (auto& object_2 : m_objects) {
if (object_2->get_group() != COLGROUP_TOUCHABLE
|| !object_2->is_valid())
for (auto& object_2 : m_objects_by_collision_part[CollisionPart::TOUCHABLE]) {
if (!object_2->is_valid())
continue;

if (object->m_dest.overlaps(object_2->m_dest)) {
Expand All @@ -646,20 +703,16 @@ CollisionSystem::update()
}

// Part 3: COLGROUP_MOVING vs COLGROUP_MOVING.
for (auto i = m_objects.begin(); i != m_objects.end(); ++i)
for (auto i = m_objects_by_collision_part[CollisionPart::MOVING_MOVING_STATIC].begin(); i != m_objects_by_collision_part[CollisionPart::MOVING_MOVING_STATIC].end(); ++i)
{
auto object = *i;

if (!object->is_valid() ||
(object->get_group() != COLGROUP_MOVING &&
object->get_group() != COLGROUP_MOVING_STATIC))
if (object && !object->is_valid())
continue;

for (auto i2 = i+1; i2 != m_objects.end(); ++i2) {
for (auto i2 = i+1; i2 != m_objects_by_collision_part[CollisionPart::MOVING_MOVING_STATIC].end(); ++i2) {
auto object_2 = *i2;
if ((object_2->get_group() != COLGROUP_MOVING
&& object_2->get_group() != COLGROUP_MOVING_STATIC)
|| !object_2->is_valid())
if (!object_2->is_valid())
continue;

collision_object(object, object_2);
Expand Down
22 changes: 22 additions & 0 deletions src/collision/collision_system.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,14 @@
#define HEADER_SUPERTUX_COLLISION_COLLISION_SYSTEM_HPP

#include <vector>
#include <map>
#include <memory>
#include <unordered_map>
#include <variant>
#include <stdint.h>

#include "collision/collision.hpp"
#include "collision/collision_group.hpp"
#include "supertux/tile.hpp"
#include "math/fwd.hpp"

Expand All @@ -47,7 +50,9 @@ class CollisionSystem final
CollisionSystem(Sector& sector);

void add(CollisionObject* object);
void add_to_collision_buckets(CollisionObject* object);
void remove(CollisionObject* object);
void remove_from_collision_buckets(CollisionObject* object);

/** Draw collision shapes for debugging */
void draw(DrawingContext& context);
Expand Down Expand Up @@ -112,6 +117,23 @@ class CollisionSystem final

std::vector<CollisionObject*> m_objects;

enum CollisionPart {
// Corresponds to:
// Part 1: COLGROUP_MOVING vs COLGROUP_STATIC and tilemap.
// Part 2: COLGROUP_MOVING vs tile attributes.
// Contains objects in collision groups COLGROUP_MOVING, COLGROUP_MOVING_STATIC, COLGROUP_ONLY_STATIC
MOVING_MOVING_STATIC_ONLY_STATIC,

// Corresponds to Part 2.5: COLGROUP_MOVING vs COLGROUP_TOUCHABLE etc.
// Contains objects in collision groups COLGROUP_MOVING and COLGROUP_MOVING_STATIC
MOVING_MOVING_STATIC,

// Contains objects in collision group COLGROUP_TOUCHABLE
TOUCHABLE
};

std::unordered_map<CollisionPart, std::vector<CollisionObject*> > m_objects_by_collision_part;

std::shared_ptr<CollisionGroundMovementManager> m_ground_movement_manager;

private:
Expand Down
4 changes: 2 additions & 2 deletions src/object/ambient_sound.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ AmbientSound::AmbientSound(const ReaderMapping& mapping) :
m_volume(),
m_has_played_sound(false)
{
m_col.m_group = COLGROUP_DISABLED;
set_group(COLGROUP_DISABLED);

float w, h;
mapping.get("x", m_col.m_bbox.get_left(), 0.0f);
Expand All @@ -65,7 +65,7 @@ AmbientSound::AmbientSound(const Vector& pos, float radius, float vol, const std
m_volume(vol),
m_has_played_sound(false)
{
m_col.m_group = COLGROUP_DISABLED;
set_group(COLGROUP_DISABLED);

m_col.m_bbox.set_pos(pos);
m_col.m_bbox.set_size(32, 32);
Expand Down
2 changes: 1 addition & 1 deletion src/object/invisible_wall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ InvisibleWall::InvisibleWall(const ReaderMapping& mapping):

m_col.m_bbox.set_size(width, height);

m_col.m_group = COLGROUP_STATIC;
set_group(COLGROUP_STATIC);
}

ObjectSettings
Expand Down
2 changes: 1 addition & 1 deletion src/object/spotlight.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ Spotlight::Spotlight(const ReaderMapping& mapping) :
m_layer(0),
m_enabled(true)
{
m_col.m_group = COLGROUP_DISABLED;
set_group(COLGROUP_DISABLED);

mapping.get("x", m_col.m_bbox.get_left(), 0.0f);
mapping.get("y", m_col.m_bbox.get_top(), 0.0f);
Expand Down
10 changes: 10 additions & 0 deletions src/supertux/moving_object.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "collision/collision_hit.hpp"
#include "collision/collision_object.hpp"
#include "math/rectf.hpp"
#include "supertux/sector.hpp"

class Dispenser;
class Sector;
Expand Down Expand Up @@ -157,7 +158,16 @@ class MovingObject : public GameObject
protected:
void set_group(CollisionGroup group)
{
/*if (Sector::current() != nullptr)
{
Sector::current()->remove_from_collision_buckets(&m_col);
}*/
m_col.m_group = group;
/*
if (Sector::current() != nullptr)
{
Sector::current()->add_to_collision_buckets(&m_col);
}*/
}

protected:
Expand Down
4 changes: 2 additions & 2 deletions src/supertux/player_status.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,7 @@ PlayerStatus::PocketPowerUp::PocketPowerUp(BonusType bonustype, Vector pos):
physic.set_velocity_y(-325.f);
physic.set_gravity_modifier(0.4f);
set_layer(LAYER_FOREGROUND1);
m_col.m_group = COLGROUP_DISABLED;
set_group(COLGROUP_DISABLED);
}

void
Expand All @@ -422,7 +422,7 @@ PlayerStatus::PocketPowerUp::update(float dt_sec)
{
m_visible = true;
m_blink_timer.stop();
m_col.m_group = COLGROUP_TOUCHABLE;
set_group(COLGROUP_TOUCHABLE);
}

if (m_blink_timer.check())
Expand Down
12 changes: 12 additions & 0 deletions src/supertux/sector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -734,6 +734,18 @@ Sector::get_nearby_objects(const Vector& center, float max_distance) const
return result;
}

void
Sector::add_to_collision_buckets(CollisionObject* object)
{
m_collision_system->add_to_collision_buckets(object);
}

void
Sector::remove_from_collision_buckets(CollisionObject* object)
{
m_collision_system->remove_from_collision_buckets(object);
}

void
Sector::stop_looping_sounds()
{
Expand Down
3 changes: 3 additions & 0 deletions src/supertux/sector.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,9 @@ class Sector final : public Base::Sector
/** globally changes solid tilemaps' tile ids */
void change_solid_tiles(uint32_t old_tile_id, uint32_t new_tile_id);

void add_to_collision_buckets(CollisionObject* object);
void remove_from_collision_buckets(CollisionObject* object);

/**
* @scripting
* Sets the sector's gravity.
Expand Down
Loading