Quad Pang
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
Public Member Functions | Private Member Functions | Private Attributes
CollisionMaster Class Reference

Encapsulate Quad colision handling. More...

#include <CollisionMaster.h>

List of all members.

Public Member Functions

 CollisionMaster (Engine *pParent)
 Associate CM with parent class.
bool UpdateCollisions ()
 Detect collisions and perform actions.
 CollisionMaster (Engine *pParent)
 Associate CM with parent class.
bool UpdateCollisions ()
 Detect collisions and perform actions.

Private Member Functions

void AddToDeleteList (Quad *quad)
 Add Quad to delete list.
void AddToNewList (Quad *quad)
 Add Quad to new list.
void AddToDeleteList (Quad *quad)
 Add Quad to delete list.
void AddToNewList (Quad *quad)
 Add Quad to new list.
Collision detection routines

Colision(Quad, Quad) will call other routines depending of Quad type

bool Collision (Quad *q1, Quad *q2)
bool Collision (Arrow *arrow, Bongo *bongo)
 Arrow and Bongo are in collision if arrow that bellongs to bongo expires.
bool Collision (Arrow *arrow, Ball *ball)
 If Arrow and Ball are in collision, Ball Will be either broken into two smaller balls or removed from scene.
bool Collision (Box *box, Arrow *arrow)
 Arrow will stuck in the roof and hitti will bi created at that spot.
bool Collision (Box *box, Hitti *hitti)
 Box and hitti are in collosion when hitti expire.
bool Collision (Box *box, Bongo *bongo)
 Don't allow bongo to get out of the box.
bool Collision (Box *box, Ball *ball)
 Ball is bouncing inside the box.
bool Collision (Ball *ball1, Ball *ball2)
 ignore collision of two balls
bool Collision (Ball *ball, Bongo *bongo)
bool Collision (Quad *q1, Quad *q2)
bool Collision (Arrow *arrow, Bongo *bongo)
 Arrow and Bongo are in collision if arrow that bellongs to bongo expires.
bool Collision (Arrow *arrow, Ball *ball)
 If Arrow and Ball are in collision, Ball Will be either broken into two smaller balls or removed from scene.
bool Collision (Box *box, Arrow *arrow)
 Arrow will stuck in the roof and hitti will bi created at that spot.
bool Collision (Box *box, Hitti *hitti)
 Box and hitti are in collosion when hitti expire.
bool Collision (Box *box, Bongo *bongo)
 Don't allow bongo to get out of the box.
bool Collision (Box *box, Ball *ball)
 Ball is bouncing inside the box.
bool Collision (Ball *ball1, Ball *ball2)
 ignore collision of two balls
bool Collision (Ball *ball, Bongo *bongo)

Private Attributes

EnginempParent
std::list< Quad * > mQuadNewList
std::list< Quad * > mQuadDeleteList

Detailed Description

Encapsulate Quad colision handling.

This class is part of Engine that takes care of colisions. It is separated in own class only for clearnes of the concept

Definition at line 28 of file CollisionMaster.h.


Constructor & Destructor Documentation

Associate CM with parent class.

Definition at line 17 of file CollisionMaster.cpp.

: mpParent(pParent)
{}

Associate CM with parent class.


Member Function Documentation

void CollisionMaster::AddToDeleteList ( Quad quad) [private]

Add Quad to delete list.

Active flag in Quad Object is used to avoid duplicate entries

Definition at line 133 of file CollisionMaster.cpp.

References Quad::IsActive(), mQuadDeleteList, and Quad::SetActive().

Referenced by Collision().

{
    if (quad->IsActive() )
    {
        quad->SetActive(false);
        mQuadDeleteList.push_back(quad);
    }
}
void CollisionMaster::AddToDeleteList ( Quad quad) [private]

Add Quad to delete list.

Active flag in Quad Object is used to avoid duplicate entries

void CollisionMaster::AddToNewList ( Quad quad) [private]

Add Quad to new list.

Definition at line 142 of file CollisionMaster.cpp.

References mQuadNewList.

Referenced by Collision().

{    
    mQuadNewList.push_front(quad);
}
void CollisionMaster::AddToNewList ( Quad quad) [private]

Add Quad to new list.

bool CollisionMaster::Collision ( Quad q1,
Quad q2 
) [private]

Definition at line 458 of file CollisionMaster.cpp.

References Bongo::ClassName(), Ball::ClassName(), Arrow::ClassName(), and Quad::ClassName().

Referenced by UpdateCollisions().

{  
    Quad *qtemp;

    if (0 == strcmp(q1->ClassName(), "Quad") || 0 == strcmp(q2->ClassName(), "Quad") )
        return false;

    if (0 == strcmp(q2->ClassName(), "Box") )
    {
        qtemp = q2;
        q2 = q1;
        q1 = qtemp;
    }
   
    if (0 == strcmp(q1->ClassName(), "Box") )
    {
        if (0 == strcmp(q2->ClassName(), "Ball") )
            return Collision((Box*)q1, (Ball*)q2);
        else if (0 == strcmp(q2->ClassName(), "Bongo") )
            return Collision((Box*)q1, (Bongo*)q2);
        else if (0 == strcmp(q2->ClassName(), "Arrow") )
            return Collision((Box*)q1, (Arrow*)q2);
        else if (0 == strcmp(q2->ClassName(), "Hitti") )
            return Collision((Box*)q1, (Hitti*)q2);
        else
            return false;
    }
   
    if (0 == strcmp(q2->ClassName(), "Arrow") )
    {
        qtemp = q2;
        q2 = q1;
        q1 = qtemp;
    }
    if (0 == strcmp(q1->ClassName(), "Arrow") )
    {
        if (0 == strcmp(q2->ClassName(), "Bongo") )
            return Collision((Arrow*)q1, (Bongo*)q2);
        else if (0 == strcmp(q2->ClassName(), "Ball") )
            return Collision((Arrow*)q1, (Ball*)q2);
        else
            return false;
    }
 
    if (0 == strcmp(q2->ClassName(), "Ball") )
    {
        qtemp = q2;
        q2 = q1;
        q1 = qtemp;
    }
    if (0 == strcmp(q1->ClassName(), "Ball") )
    {
        if (0 == strcmp(q2->ClassName(), "Bongo") )
            return Collision((Ball*)q1, (Bongo*)q2);
        else
            return false;
    }
 
    return false;
}
bool CollisionMaster::Collision ( Quad q1,
Quad q2 
) [private]
bool CollisionMaster::Collision ( Arrow arrow,
Bongo bongo 
) [private]

Arrow and Bongo are in collision if arrow that bellongs to bongo expires.

Note that this is not geometrical collision

bool CollisionMaster::Collision ( Arrow arrow,
Bongo bongo 
) [private]

Arrow and Bongo are in collision if arrow that bellongs to bongo expires.

Note that this is not geometrical collision

Definition at line 148 of file CollisionMaster.cpp.

References Bongo::AddArrow(), AddToDeleteList(), Arrow::GetParent(), and Lifetime::IsExpired().

{
    if (!arrow->IsExpired() || arrow->GetParent() != bongo)
        return false;

    arrow->GetParent()->AddArrow();
    AddToDeleteList(arrow);
   
    return true;
}
bool CollisionMaster::Collision ( Arrow arrow,
Ball ball 
) [private]

If Arrow and Ball are in collision, Ball Will be either broken into two smaller balls or removed from scene.

bool CollisionMaster::Collision ( Arrow arrow,
Ball ball 
) [private]

If Arrow and Ball are in collision, Ball Will be either broken into two smaller balls or removed from scene.

Basicaly if collide ball will be destoyed and if ball has more 'lives' left two smaller copies will be created.

Definition at line 167 of file CollisionMaster.cpp.

References Bongo::AddArrow(), AddToDeleteList(), AddToNewList(), Quad_impl::Direction(), Arrow::GetParent(), halfball(), mpParent, Engine::mToKill, Quad_impl::Position(), Ball::Reincarnate(), Ball::SetDirection(), Quad_impl::SetSize(), Quad_impl::Size(), and vec_rotateY().

{
    // aproximate minimal possible (gemetricaly) distance
    // between two Quads and assign to variable delta.
    double delta = ball->Size() /2  + arrow->Size() / 4;
    delta = delta * delta;
    
    const double *ball_pos = ball->Position();
    const double *arrow_pos = arrow->Position();
    bool colided = false;

    // delta2 will be actual distance between 
    // centers.
    double delta2 = 0;
    double pom;
    for (int i = 0; i < 3; i++)
    {
        pom = ball_pos[i] - arrow_pos[i];
        delta2 += pom * pom;       
    }
    
    if (delta2 < delta)
        colided = true;
    else
    {
        // improve aproximation
        delta = ball->Size() / 2 + arrow->Size() / 12;
        delta = delta * delta;
        if (ball_pos[1] < arrow_pos[1])
        {
            pom = ball_pos[1] - arrow_pos[1];
            delta2 -= pom * pom;
        
            if (delta2 < delta)
               colided = true; 
        }
    }

    if (colided)
    {
        // create first smaller ball
        Ball *b1 = ball->Reincarnate();
        if (b1)
        {
            // create second smaller ball
            Ball *b2 = new Ball(*b1);
            double r2 = halfball(ball->Size());
            b1->SetSize(r2);
            b2->SetSize(r2);
            
            const double* dir = b1->Direction();
            double dr1[] = { dir[0], dir[1], dir[2] };
            double dr2[] = { dir[0], dir[1], dir[2] };
            
            // rotate for PI/4
            vec_rotateY(dr1, M_PI_4);
            vec_rotateY(dr2, -M_PI_4);

            b1->SetDirection(dr1);
            b2->SetDirection(dr2);
                        
            AddToNewList(b1);
            mpParent->mToKill++;
            AddToNewList(b2);
            mpParent->mToKill++;
        }
            
        // get back arrow to bongo  
        arrow->GetParent()->AddArrow();
    
        AddToDeleteList(arrow);

        AddToDeleteList(ball); 
        mpParent->mToKill--;

        return true;
    }
    return false;
}
bool CollisionMaster::Collision ( Box box,
Arrow arrow 
) [private]

Arrow will stuck in the roof and hitti will bi created at that spot.

bool CollisionMaster::Collision ( Box box,
Arrow arrow 
) [private]

Arrow will stuck in the roof and hitti will bi created at that spot.

Definition at line 247 of file CollisionMaster.cpp.

References AddToNewList(), Quad_impl::Color(), Box::Dim(), Arrow::HitBox(), Arrow::Move(), mpParent, Engine::mTimerDelay, Quad_impl::Position(), Quad_impl::SetDirection(), Quad_impl::Size(), and VZERO.

{
    const double *arrow_pos = arrow->Position();
    const double *box_dim = box->Dim();
    double forse[] = { 0.0, 0.0, 0.0 };

    // arrow passed trough the box floor
    if (arrow_pos[1] > box_dim[1] )
    {
        // get it back
        forse[1] = - (arrow_pos[1] - box_dim[1]);
        arrow->Move(forse);
        // notify arrow. it shell ignore gravitation afterwards
        arrow->HitBox();
        arrow->SetDirection(VZERO);
        
        // create hitti at this spot
        double pos[] = { arrow_pos[0], box_dim[1], arrow_pos[2] };
        Hitti *hit = new Hitti(
            pos, 
            arrow->Size(), 
            pos, 0.0, 
            arrow->Color(), 
            3, 
            1000/mpParent->mTimerDelay);
        AddToNewList(hit);
    }

    return false;
}
bool CollisionMaster::Collision ( Box box,
Hitti hitti 
) [private]

Box and hitti are in collosion when hitti expire.

Note that this is not geometrical collision.

Definition at line 279 of file CollisionMaster.cpp.

References AddToDeleteList(), and Hitti::IsExpired().

{
    if (!hitti->IsExpired() )
        return false;

    AddToDeleteList(hitti);

    return true;
}
bool CollisionMaster::Collision ( Box box,
Hitti hitti 
) [private]

Box and hitti are in collosion when hitti expire.

Note that this is not geometrical collision.

bool CollisionMaster::Collision ( Box box,
Bongo bongo 
) [private]

Don't allow bongo to get out of the box.

bool CollisionMaster::Collision ( Box box,
Bongo bongo 
) [private]

Don't allow bongo to get out of the box.

ignore z coordinate

Definition at line 289 of file CollisionMaster.cpp.

References Box::Dim(), Quad_impl::Move(), Quad_impl::Position(), Quad_impl::SetDirection(), Quad_impl::Size(), and VZERO.

{
    const double *bongo_pos = bongo->Position();
    const double *box_dim = box->Dim();
    double forse[] = { 0.0, 0.0, 0.0 };

    bool col = false;
    // for each coordinate check two two sides of the box
    for (int i = 0; i < 3; i++)
    {
        if (i == 1) continue;
        
        
        if (bongo_pos[i] < bongo->Size()/2)
        {
            forse[i] = -2 * (bongo_pos[i] - bongo->Size()/2) ;
            col = true;
        }

        if (bongo_pos[i] > box_dim[i] - bongo->Size()/2)
        {
            forse[i] = -2 * (bongo_pos[i] - box_dim[i] + bongo->Size()/2);
            col = true;
        }
    }

    if (col)
    {
        // get it back
        bongo->Move(forse);
        bongo->SetDirection(VZERO);
    }

    return col;
}
bool CollisionMaster::Collision ( Box box,
Ball ball 
) [private]

Ball is bouncing inside the box.

Hitti will be crated at the place of hit.

bool CollisionMaster::Collision ( Box box,
Ball ball 
) [private]

Ball is bouncing inside the box.

Hitti will be crated at the place of hit.

Definition at line 326 of file CollisionMaster.cpp.

References AddToNewList(), Quad_impl::Color(), Box::Dim(), Quad_impl::Direction(), Box::HasHitti(), Ball::Move(), mpParent, Engine::mTimerDelay, Quad_impl::Position(), Quad_impl::Power(), Ball::SetDirection(), and Quad_impl::Size().

{
    const double *ball_pos = ball->Position();
    double ball_size = ball->Size() / 2;
    const double *box_dim = box->Dim();
    const double *ball_dir = ball->Direction();
    
    double forse[] = { 0.0, 0.0, 0.0 };
    double new_dir[] = { ball_dir[0], ball_dir[1], ball_dir[2] };
    double hit_pos[] = { ball_pos[0], ball_pos[1], ball_pos[2] };
    double hit_rot[] = { 0.0, 0.0, 0.0 };
    double hit_angle = 0.0;

    bool col = false;
    bool gcol = false;
    for (int i = 0; i < 3; i++)
    {
        col = false;
        if (ball_pos[i] < ball_size)
        {
            col = true;
            forse[i] = 2 * (ball_size - ball_pos[i]);
            hit_pos[i] = 0.01;
            hit_rot[2 - i] = 1.0;
            if (0 == i)
                hit_angle = 90.0;
            else if (1 == i)
                hit_angle = 0.0;
            else
                hit_angle = -90;
        }
        else if (ball_pos[i] >  box_dim[i] - ball_size)
        {
            col = true;
            forse[i] = - 2 * (ball_size + ball_pos[i] - box_dim[i]);
            // make hitti apear in front of the box
            hit_pos[i] = box_dim[i] - 0.01;
            hit_rot[2-i] = 1.0;         
            if (0 == i)
                hit_angle = -90.0;
            else if (1 == i)
                hit_angle = 180.0;
            else
                hit_angle = 90;
        }
            
        if (col)    
        {
            gcol = true;
            if (1 == i && (-new_dir[i] > pow(ball->Size(), 0.5)  * ball->Power() ) )
                new_dir[i] = pow(ball->Size(), 0.5) * ball->Power();
            else
                new_dir[i] = -new_dir[i];
        }
    }

    if (gcol)
    {
        if (box->HasHitti() && hit_pos[1] > 0)
        {
            AddToNewList(
                new Hitti(
                    hit_pos, 
                    ball_size*0.8, 
                    hit_rot, 
                    hit_angle, 
                    ball->Color(), 
                    3, 
                    1000/mpParent->mTimerDelay) 
            ); 
        }
        ball->Move(forse);
        ball->SetDirection(new_dir);
    }

    return gcol;
}
bool CollisionMaster::Collision ( Ball ball1,
Ball ball2 
) [private]

ignore collision of two balls

bool CollisionMaster::Collision ( Ball ball1,
Ball ball2 
) [private]

ignore collision of two balls

Definition at line 404 of file CollisionMaster.cpp.

{
    return false;
}
bool CollisionMaster::Collision ( Ball ball,
Bongo bongo 
) [private]

if ball hit the bongo it will lose a life if it lost last life game will be over.

bool CollisionMaster::Collision ( Ball ball,
Bongo bongo 
) [private]

if ball hit the bongo it will lose a life if it lost last life game will be over.

Definition at line 409 of file CollisionMaster.cpp.

References AddToDeleteList(), AddToNewList(), Ball::Capture(), Bongo::IsVulnerable(), Bongo::Kill(), Engine::mLives, mpParent, Engine::mpStatusDisplay, Quad_impl::Position(), StrokeDisplay::Print(), Quad_impl::SetActive(), Lifetime::SetLongLife(), Quad_impl::Size(), and Engine::UpdateLivesDisplay().

{
    // it's flashing or dead
    if (!bongo->IsVulnerable() )
        return false;

    // minimal distance
    double delta = (ball->Size() + bongo->Size() )/2;
    delta = delta * delta;

    const double *ball_pos = ball->Position();
    const double *arrow_pos = bongo->Position();
    bool colided = false;

    double delta2 = 0;
    double pom;
    for (int i = 0; i < 3; i++)
    {
        pom = ball_pos[i] - arrow_pos[i];
        delta2 += pom * pom;       
    }
   
    if (delta2 < delta)
        colided = true;

    if (colided)
    {
        int lives = bongo->Kill();
        mpParent->mLives = lives;
        mpParent->UpdateLivesDisplay();
        
        // is it game over? let's see
        if (0 == lives)
        {
            bongo->SetActive(false);
            Ball* bl = new Ball(*ball);
            
            // capture bongo in the ball
            bl->Capture(bongo);
            AddToDeleteList(ball);
            AddToNewList(bl);
        
            mpParent->mpStatusDisplay->Print("\nGame Over");
            mpParent->mpStatusDisplay->SetLongLife(true);
        }   
    }
    return colided;
}

Detect collisions and perform actions.

Detect collisions and perform actions.

Update collision will use two passes.

In pass 1 Quad will be first moved and then check for collisions. During collision check some objects will be added to mQuadNewList and some to mQuadDelete list.

In pass 2 Quads from delete list will be deleted and quads in new list will be added to the scene

Definition at line 30 of file CollisionMaster.cpp.

References Quad::ClassName(), Collision(), Quad::Direction(), Quad::Forse(), Quad::IsActive(), Engine::mGravitation, Quad::Move(), mpParent, mQuadDeleteList, mQuadNewList, Engine::mQuads, Engine::mToKill, and Engine::NextLevel().

{
    list<Quad*>::iterator i, j;
    Quad *q1; 

    // first pass: move objects and detect collisions
    // update mQuadNewList and mQuadDeleteList
    bool col = false;
    for (i = mpParent->mQuads.begin(); i != mpParent->mQuads.end(); i++)
    {
        q1 = *i;
        // ignore object that is already deactivated (added to delete list)
        if (!q1->IsActive() )
            continue;

        q1->Move(q1->Direction());

        // gravitation will affect all objects except bongo
        if (0 != strcmp(q1->ClassName(), "Bongo") )
        {
            // move object
            q1->Move(mpParent->mGravitation);
            // speed up falling
            q1->Forse(mpParent->mGravitation);
        }

        // detect collision with remainig objects in list
        j = i;
        j++;
        for (; j != mpParent->mQuads.end(); j++)
        {
            // Ignore deactivated Quads 
            // (alredy added to delete list)
            if (!(*j)->IsActive() )
                continue;

            if (Collision(q1, *j) )
                col = true;
            
            // If current object is deactivated
            // doent check any further
            if (!q1->IsActive() ) 
                break;
        }
    }

    
    // pragmatic algorityham efficency check
    static unsigned long traversing = 0;
    static unsigned long searches = 0;
    searches++;
    // pass two: delete and add objects
    if (col)
    {
        list<Quad*>::const_iterator i = mQuadDeleteList.begin();
        list<Quad*>::iterator j = mpParent->mQuads.begin();
    
        // delete Quads from mQuadDeleteList
        while (i != mQuadDeleteList.end() && j!= mpParent->mQuads.end() )
        {   
            while (*j != *i)
            {
                j++;
                // we could avoid this traversing, but it happend only in 0.1%
                if (j == mpParent->mQuads.end() )
                {
                    traversing++;
                    // assert(traversing-1 < searches / 100);
                    printf("traversiing %ld, searchs %ld...\n", traversing, searches);

                    j = mpParent->mQuads.begin();                   
                }
            }
            delete *j;  
          
            j = mpParent->mQuads.erase(j);
            i++;
        }
        mQuadDeleteList.clear();
   
        // add Quads from mQuadNewList
        for (i = mQuadNewList.begin(); i != mQuadNewList.end(); i++)
            if ( (*i)->Color()[3] == 1.0 )
                mpParent->mQuads.push_back(*i);
            else
        {
                mpParent->mQuads.push_front(*i);
        }
        mQuadNewList.clear();
        
    }

    // if there are no Balls to kill 
    // it's time to go to the next level
    if (0 == mpParent->mToKill)
    {
        mpParent->NextLevel();
    }
    return col;
}

Member Data Documentation

Definition at line 99 of file CollisionMaster.h.

Referenced by Collision(), and UpdateCollisions().

std::list< Quad * > CollisionMaster::mQuadDeleteList [private]

Definition at line 101 of file CollisionMaster.h.

Referenced by AddToDeleteList(), and UpdateCollisions().

std::list< Quad * > CollisionMaster::mQuadNewList [private]

Definition at line 100 of file CollisionMaster.h.

Referenced by AddToNewList(), and UpdateCollisions().


The documentation for this class was generated from the following files: