• Advertisement
Sign in to follow this  

How to design my collision code properly?

This topic is 579 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Guys, I have problems figuring out the best way to structure my collision algorithms.


Until now I had only two:

1. Collision between a ray and an AABB.

2. Collision between a point and an AABB.


Now that I'm starting to need more different collisions, my code is getting pretty awful.


The first reason for this is the following:


I have two base classes. The class Object is the base class for all static objects.( map, bullets, houses, etc ) and the class Character is the base class for all animated objects.( player, enemies, etc. ). Class Player and class Enemy inherit from the base class Character. 


The problem now is that when I want to check a collision between an Object and an Enemy, I need to declare a function something like this: 


check_collision( Object& obj, Enemy& enemy ).



And when I need to check collision between an object and a player, I need the same function, but with different parameters:


check_collision( Object& obj, Player& player )



And if I create another class that inherits from Character. I need to make a third check_collision() function. Is it ok to overload the function like that, or is it better to somehow use polymorphism?


And the second problem is that I have different kinds of collisions and I don't know how to structure my code. 


1st way is to make the function based on states like that:


check_collision( RAY_AABB, Object& obj, Player& player )

check_collision( SPHERE_AABB, Object& obj, Player& player )


or is it better to just make a different name for the function like this, CheckCollisionRayAABB, and CheckCollisionSphereAABB?


The question is kind of stupid, but I find it really hard to design and name the functions properly, maybe because English is not my mother language, I don't know.


Anyway, thanks for reading, I hope you have some suggestions.

Edited by codeBoggs

Share this post

Link to post
Share on other sites

__SKYe got it exactly, and this is an excellent example of why to prefer composition over inheritance.


All I'd add is that you'll probably want to also write some inline functions for reverse order tests:


ret_type check_collision(A& a, B& b) { /* code */ }

inline ret_type check_collision(B& b, A& a) { return check_collision(a, b); }


And also look for other places where you can delegate. For example, sphere v sphere can be delegated to sphere v point.


The composition approach also makes it easy to create composites, where you have a collection of collision primitives wrapped in an object that allows them behave as a single collider.

Share this post

Link to post
Share on other sites

No chance I could have solved this by myself. Good thing I decided to post here. Thanks for the clear answers.   :)

Edited by codeBoggs

Share this post

Link to post
Share on other sites

Guys, I don't understand how to make the classes to use composition, what to do?


My character class just has a few pointers to models, and the models have the bounding boxes in them ( in the Model class) 


#include "camera.h"
#include "model.h"
#include "timer.h"

#include <glm/gtc/matrix_transform.hpp>
#include <glm/glm.hpp>
#include <glm/gtx/transform.hpp>
#include <glm/gtc/quaternion.hpp>
#include <glm/gtx/quaternion.hpp>

//Base class
class Character

    Model *idleAnimation;
    Model *runAnimation;
    Model *punchAnimation;
    Model *knockdownAnimation;
    Model *deathAnimation;
    Model *currentAnimation;
    Model *bulletModel;

    Shader *shaderanim;
    Shader *shadershadow;

    Timer animTimer;

    glm::vec3 currentPosition{ 0.0f };
    glm::vec3 previousPosition{ 0.0f };
    glm::vec4 rotation{ 0.0f };
    glm::vec3 scale{ 1.0f };
    glm::mat4 modelMatrix{ 1.0f };
    glm::mat4 AABBmodelMatrix{ 1.0f };
    glm::mat4 mvpMatrix{ 1.0f };
    float deltaTime;
    int currentAnimState = ANIM_RUN;
    GLuint boneLocation[ MAX_BONES ];

    Character( vector<Shader*> shaders );

    Camera mainCam;
    Camera moveHelperCam;

    void setScale( glm::vec3 sc );
    void setRotation( glm::vec4 rot );
    void setPosition( glm::vec3 pos );
    void setModelMatrix( glm::mat4 modelmat );
    void setDeltaTime( float delta );
    void setCurrentAnim( int anim );

    glm::vec3 getScale();
    glm::vec4 getRotation();
    glm::vec3 getPosition();
    glm::mat4 getModelMatrix();
    int getCurrentAnim();
    Model* getCurrentModel();

    glm::vec3 getInterpolatedPosition( glm::vec3 previousPos, glm::vec3 currentPos, float interpRatio );
    glm::vec3 getInterpolatedRotation( glm::quat previousRot, glm::quat currentRot, float interpRatio );

    void storeBoneLocations( Shader* shader );
    void setBoneTransform( GLuint index, const Matrix4f& Transform );
    void renderModel( Camera& playerCam, Shader& shader, Shader& shaderAABB, float extrapolRatio );



then your collision functions only need to know the type of collision surface, which would, in turn, simplify them even more.

??  :huh:

Edited by codeBoggs

Share this post

Link to post
Share on other sites

I fixed it, extremely easy solution. Instead of passing class Player and class Enemy as an argument, I just pass their models. And in the model Class I make a struct called BoundingObject which decides how collision is done, and now my collision is done like this: checkCollision( Model& model, Model& model2 ) I don't know if this is called composition, but it works perfectly fine. I thought the term "composition" means something very complicated but it's just an object inside another object.

Edited by codeBoggs

Share this post

Link to post
Share on other sites
Sign in to follow this  

  • Advertisement