I've been working on a pacman game using C++, and OGRE. Things have been going good, but I have run across a problem with the collision detection of pacman hitting the walls.
Before I explaing, here is some of the source code.

PacpersonObj Class Header

// PacPersonObj.h
 // PacPersonObj class definition (represents a PacPersonObj in the game).
 #ifndef PacPersonObj_H
 #define PacPersonObj_H

 #include <Ogre.h> // Ogre class definition
 using namespace Ogre; // use the Ogre namespace

 const int RADIUS = 5; // the radius of the Ball

 class PacPersonObj
    // constructor
    PacPersonObj( SceneManager *sceneManagerPtr );
    ~PacPersonObj(); // destructor
	void movePac( const Vector3 &direction ); // move a PacPersonObj
    void addToScene(); // add a PacPersonObj to the scene
	void movePac2( Real time ); // move the pacperson across the screen
	void setDirection(Vector3);


    SceneManager* sceneManagerPtr; // pointer to the SceneManager
    SceneNode *nodePtr; // pointer to a SceneNode                
    String name; // name of the PacPersonObj
    //int x;// x-coordinate of the PacPersonObj
//	int y;
	void reverseHorizontalDirection() ; // change horizontal direction
    void reverseVerticalDirection(); // change vertical direction
	int speed; // speed of the Ball
    Vector3 direction; // direction of the Ball

 }; // end of class PacPersonObj

 #endif // PacPersonObj_H

PacpersonObj Class .cpp

void PacPersonObj::movePac2( Real time)
   nodePtr->translate( ( direction * ( speed * time ) ) ); // move pac 
   Vector3 position = nodePtr->getPosition(); // get pac's new position

     // get the positions of the four walls
    Vector3 topPosition = sceneManagerPtr->     
       getSceneNode( "WallTop" )->getPosition();
    Vector3 bottomPosition = sceneManagerPtr->
       getSceneNode( "WallBottom" )->getPosition();
    Vector3 leftPosition = sceneManagerPtr->
       getSceneNode( "WallLeft" )->getPosition();
    Vector3 rightPosition = sceneManagerPtr->
       getSceneNode( "WallRight" )->getPosition();

    const int WALL_WIDTH = 20; // the width of the walls

	// check if the Pac hit the left side
    if ( ( position.x - RADIUS ) <= leftPosition.x + ( WALL_WIDTH / 2 ) )
       nodePtr->setPosition(0,0,0); // move pac 
       Pacperson::updateScore( Players::PLAYER2 ); // update the score
    } // end if
    // check if the Pac hit the right side
    if (                                                           
       ( position.x + RADIUS ) >= rightPosition.x - ( WALL_WIDTH / 2 ) )
       nodePtr->setPosition( (rightPosition.x - ( WALL_WIDTH / 2 ) - RADIUS ),                                   
           position.y , position.z );
       Pacperson::updateScore( Players::PLAYER1 ); // update the score
    } // end else
    // check if the Pac hit the bottom wall
    else if (                                                             
       ( position.y - RADIUS ) <= bottomPosition.y + ( WALL_WIDTH / 2 ) &&
       direction.y < 0 )                                                  
       // place the Pac on the bottom wall
       nodePtr->setPosition( position.x,                                   
          ( bottomPosition.y + ( WALL_WIDTH / 2 ) + RADIUS ), position.z );
    } // end else
    // check if the Pac hit the top wall
    else if (                                                          
      ( position.y + RADIUS ) >= topPosition.y - ( WALL_WIDTH / 2 ) &&
      direction.y > 0 )                                               
      // place the Pac on the top wall
      nodePtr->setPosition( position.x,                                
         ( topPosition.y - ( WALL_WIDTH / 2 ) - RADIUS ), position.z );
   } // end else

 } // end function movePac

void PacPersonObj::reverseHorizontalDirection()
    direction *= Vector3( -1, 1, 1 ); // reverse the horizontal direction
 } // end function reverseHorizontalDirection

 // reverse the Ball's vertical direction
 void PacPersonObj::reverseVerticalDirection()
    direction *= Vector3( 1, -1, 1 ); // reverse the vertical direction
 } // end function reverseVerticalDirection

Class that implements

7 Years
Discussion Span
Last Post by firstPerson

What is wall? How do you have it oriented. Depending of the orientations
of the wall, the collision detection will be easy or harder.


This is how my walls are set up.

The code sets the locations of them.

// get the positions of the four walls    

  Vector3 topPosition = sceneManagerPtr->  
  getSceneNode( "WallTop" )->getPosition();

This is the omitted code from the source. It contains all the walls and barriers. Pretty long, so i omitted.

entityPtr = sceneManagerPtr->createEntity( "WallBottom", "cube.mesh" );
    entityPtr->setMaterialName( "wall" ); // set material for bottom wall
    // create the SceneNode for the bottom wall
    nodePtr = sceneManagerPtr->getRootSceneNode()->
       createChildSceneNode( "WallBottom" );
    nodePtr->attachObject( entityPtr ); // attach bottom wall to SceneNode
    nodePtr->setPosition( 0, -80, 0 ); // set the bottom wall's position
    nodePtr->setScale( 2.55, .05, .1 ); // set bottom wall's size

Edited by luskbo: n/a

nodePtr->setPosition( 0, -80, 0 );

assuming its setPosition( x , y , z), then your x is 0 and your wall is
just at position (0,-80). You can just check if the pacman + its radius is
at posX = 0, and at posY = -80. If so then a collision is detected, else not.

This assumes that the pacman can't hit the wall from behind.

If I misunderstood, then maybe a snapshot would help more.

Edited by firstPerson: n/a


Here is a screen shot of my game.
In this picture the pacman is moving towards the left wall. This is the wall in the first if statement.
When the pacman( which right now is a grey ball) hits those walls it stops. The width of the wall is used in the if statements to keep pacman from actually touching the walls.

The code that you posted.
It was actually the x axis, but yes that is the idea.
nodePtr->setPosition( -130, 0, 0 );

The problem is when I start the game the pacman is not visible on the screen. If I hit one of the arrow keys, it will appear in the position
"( -130, 0, 0 )" like set above.

at that point it will work like it is supposed.

MY code for determining the collision for the walls with the other directions work. When they come in contact with the wall, they stop.

But if I try to use that code in the first if statement , the ball never appears, at all.

The only code that will make the ball appear, is a
"nodePtr->setPosition( -130, 0, 0 );" statement.



That tells me that you are updating the ball late. Specifically, you have
some render method inside you move function or you call some render
function inside your move function. Do you have a render function for
the pacman thats being called inside the move function or do you
draw the pacman on the move function( whatever the move function maybe)?


I got the wall to react correctly.

In my first if statement of the movePac2 function, I changed the line in question to:

nodePtr->setPosition((-125 +( WALL_WIDTH / 2 )),position.y,0);

Its not like the else if statements below it, (like i was trying to acheive), but It does make it stop correctly.

To Answer your last reply,

I'm calling the movepac2 function from the another class called Pacman.cpp. The function call is inclosed in the frameStarted() function.

bool Pacperson::frameStarted( const FrameEvent &frameEvent )

	 keyboardPtr->capture(); // get keyboard events

	 if ( !wait && !pause )
       // move the Pacperson
       PacPersonObjPtr->movePac2( frameEvent.timeSinceLastFrame);
    } // end if
    // don't move the Pacperson if wait is true
    else if ( wait )
       // increase time if it is less than 4 seconds
       if ( time < 4 )
          // add the seconds since the last frame
          time += frameEvent.timeSinceLastFrame;
          wait = false; // shouldn't wait to move the Pacperson any more
          time = 0; // reset the control variable to 0
       } // end else
    } // end else

	 return !quit; // quit = false if the user hasn't quit yet
 } // end function frameStarted

wait is set to false by a switch statement in my keyPressed function.
time is a timer i am using to move the pacman.

bool Pacperson::keyPressed( const OIS::KeyEvent &keyEventRef )
    // if the game is not paused
    if ( !pause )
       // process KeyEvents that apply when the game is not paused
       switch ( keyEventRef.key )
       case OIS::KC_ESCAPE: // escape key hit: quit
          quit = true;
      case OIS::KC_UP: // up-arrow key hit: move the right Pacpersonup
		 wait = false;
     case OIS::KC_DOWN: // down-arrow key hit: move the right Pacpersondown
          PacPersonObjPtr->setDirection( PACPERSON_DOWN );
		  wait = false;
	   case OIS::KC_LEFT: // up-arrow key hit: move the right Pacpersonup
          PacPersonObjPtr->setDirection( PACPERSON_LEFT );
		  wait = false;
       case OIS::KC_RIGHT: // down-arrow key hit: move the right Pacpersondown
          PacPersonObjPtr->setDirection( PACPERSON_RIGHT );
		  wait = false;
      case OIS::KC_P: // P key hit: pause the game
          pause = true; // set pause to true when the user pauses the game
          Overlay *pauseOverlayPtr =                                    
             OverlayManager::getSingleton().getByName( "PauseOverlay" );
          pauseOverlayPtr->show(); // show the pause Overlay            
       } // end switch
    } // end if
    else // game is paused
       // user hit 'R' on the keyboard
       if ( keyEventRef.key == OIS::KC_R )
          pause = false; // set pause to false when user resumes the game
          Overlay *pauseOverlayPtr =                                    
             OverlayManager::getSingleton().getByName( "PauseOverlay" );
          pauseOverlayPtr->hide(); // hide the pause Overlay            
       } // end if
    } // end else
    return true;
 } // end function keyPressed

If I am updating my pacman late, is it when I call the move function in the frameStarted() function?


Solved the problem:

The problem was that I set the initial position of the pacman object, but I never set the initial direction. Since there was no initial direction, and the formula for the collision detection depended on it, the first if statement would never work correctly. By the time it got to the else if statements, it had aquired a direction from the keyboard, and then all the if statements worked.

That explains why the only thing that would work was a direct setPosition(0,0,0) or other position.

Thanks for the help.
I'm now working on the barriers, which are proving to be a little more involved. Wish me luck.

Edited by luskbo: SOLVED!

This topic has been dead for over six months. Start a new discussion instead.
Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.