Ok.
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 Pacperson
class PacPersonObj
{
public:
// 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);
private:
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 Pacperson
Vector3 direction; // direction of the Pacperson
}; // end of class PacPersonObj
#endif // PacPersonObj_H
PacpersonObj Class .cpp
void PacPersonObj::setDirection(Vector3 newNirection)
{
direction = newNirection;
}
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::waitTrueToggle();
} // 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 Pacperson's vertical direction
void PacPersonObj::reverseVerticalDirection()
{
direction *= Vector3( 1, -1, 1 ); // reverse the vertical direction
} // end function reverseVerticalDirection
Class that implements ( relevent functions)
#include <sstream>
using std::ostringstream;
#include <stdexcept>
using std::runtime_error;
#include <Ogre.h> // Ogre class definition
using namespace Ogre; // use the Ogre namespace
#include <OgreStringConverter.h> // OgreStringConverter class definition
#include <OIS\OISEvents.h> // OISEvents class definition
#include <OIS\OISInputManager.h> // OISInputManager class definition
#include <OIS\OISKeyboard.h> // OISKeyboard class definition
#include "powerUp.h"
#include "PacPersonObj.h"
#include "newTut.h"
int Pacperson::player1Score = 0; // initialize player 1's score to 0
int Pacperson::player2Score = 0; // initialize player 2's score to 0
bool Pacperson::wait = false; // initialize wait to false
// directions to move the Paddles
const Vector3 PACPERSON_DOWN = Vector3( 0, -1, 0 );
const Vector3 PACPERSON_UP = Vector3( 0, 1, 0 );
const Vector3 PACPERSON_LEFT = Vector3( -1, 0, 0 );
const Vector3 PACPERSON_RIGHT = Vector3( 1, 0, 0 );
//////////////ommitted objects///////////////
PacPersonObjPtr = new PacPersonObj( sceneManagerPtr ); // make the PacPerson
PacPersonObjPtr->addToScene(); // add the PacPersonObj to the scene
// update the score
void Pacperson::updateScore( Players player )
{
// increase the correct player's score
if ( player == Players::PLAYER1 )
player1Score++;
else
player2Score++;
wait = true; // the game should wait to restart the Pacperson
updateScoreText(); // update the score text on the screen
} // end function updateScore
// update the score text
void Pacperson::updateScoreText()
{
ostringstream scoreText; // text to be displayed
scoreText << "Player 2 Score: " << player2Score; // make the text
// get the right player's TextArea
OverlayElement *textElementPtr =
OverlayManager::getSingletonPtr()->getOverlayElement( "right" );
textElementPtr->setCaption( scoreText.str() ); // set the text
scoreText.str( "" ); // reset the text in scoreText
scoreText << "Player 1 Score: " << player1Score; // make the text
// get the left player's TextArea
textElementPtr =
OverlayManager::getSingletonPtr()->getOverlayElement( "left" );
textElementPtr->setCaption( scoreText.str() ); // set the text
} // end function updateScoreText
// respond to user keyboard input
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;
break;
case OIS::KC_UP: // up-arrow key hit: move the right Pacpersonup
PacPersonObjPtr->setDirection(PACPERSON_UP);
wait = false;
break;
case OIS::KC_DOWN: // down-arrow key hit: move the right Pacpersondown
PacPersonObjPtr->setDirection( PACPERSON_DOWN );
wait = false;
break;
case OIS::KC_LEFT: // up-arrow key hit: move the right Pacpersonup
PacPersonObjPtr->setDirection( PACPERSON_LEFT );
wait = false;
break;
case OIS::KC_RIGHT: // down-arrow key hit: move the right Pacpersondown
PacPersonObjPtr->setDirection( PACPERSON_RIGHT );
wait = false;
break;
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
break;
} // 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
// process key released events
bool Pacperson::keyReleased( const OIS::KeyEvent &keyEventRef )
{
return true;
} // end function keyReleased
// return true if the program should render the next frame
bool Pacperson::frameEnded( const FrameEvent &frameEvent )
{
return !quit; // quit = false if the user hasn't quit yet
} // end function frameEnded
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;
else
{
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
// sets wait to true
void Pacperson::waitTrueToggle()
{
wait = true;
}
OK now for the explanation.
In the PacpersonObj Class .cpp source, I define the function.
void PacPersonObj::movePac2( Real time)
This function recieves a time parameter from the class that implements its.
It uses that time to to move the object using .
nodePtr->translate( ( direction * ( speed * time ) ) );
Vector3 position = nodePtr->getPosition();
I sets the location of the walls and uses if/ else statements to check for collisions with the walls .
The directions is set by the
void PacPersonObj::setDirection(Vector3 newNirection)
This direction is sent to it by the from the class that implements its.
Specifically the keyPressed function , and the frameStarted functions.
???????????????????
My Problem!
???????????????????
When ever I run the game. the ball dissapears. I have tried many diffrent things to fix this, and have discovered something that I don't understand.
When the code is like this :
if ( ( position.x - RADIUS ) <= leftPosition.x + ( WALL_WIDTH / 2 ) )
{
nodePtr->setPosition(0,0,0); // move pac
Pacperson::waitTrueToggle();
}
The ball appears, and the collision detection works, except for this first part of the if/else statements. I can set the " nodePtr->setPosition(0,0,0); " to anywhere , and it will go back to that point after it hits the wall, but it also starts there when the game starts.
I just want it to stop at the wall like my other if else's do , but if I change the code like the other if/else statements, the ball dissapears as soon as it starts.
My though is that is is reading my fist if statement too early.
any ideas??
Thanks.