Jump only on floor not int the air.

toum

14-11-2009 12:54:00

Hi all,

I would like to jump a NxOgre body into my app but only if this one is on floor. You can't jump if you are always in the air :D

Today when i press space key i add "y" force to my body:

bool GameFrameListener::keyPressed(const OIS::KeyEvent &e) {
if(e.key == OIS::KC_SPACE) {
mForceVector.y = mForceApply; // int value : 20
}
return true;
}


Into Framestarted i had:

bool GameFrameListener::frameStarted(const FrameEvent& evt) {

mTimeController->advance(evt.timeSinceLastFrame);

if(mKeyboard)
mKeyboard->capture();

// Apply for on body
mBody->addForce(mForceVector);

return (true);
}


1 - How can perform a test which be able to say me: If body in the air then no force is applied. A raycast from body to plane will be able to do that? By getting the distance of the ray?

Thanks for your support,

Thomas

Druha

14-11-2009 15:02:17

Yes, raycast is exactly what you need to determine, whether your body is in the air or not.
Just use Scene::raycastClosestShape() pointing it straight down. And don't forget to correct its origin, that it doesn't hit your body, which position you are testing :wink:

betajaen

14-11-2009 15:25:04

that it doesn't hit your body

I believe you can cast within side a shape and that shape won't get reported, I think I did it with the Fake Camera Actor in Cake.

Makes things easier when working out ray origin positions.

toum

14-11-2009 16:04:18

I am trying for that:

bool GameFrameListener::keyPressed(const OIS::KeyEvent &e) {
if(e.key == OIS::KC_SPACE) {

NxOgre::Vec3 bodyPos = NxOgre::Vec3(mBody->getGlobalPosition());

mBodyRayHit = mScene->raycastClosestShape( NxOgre::Ray(bodyPos, NxOgre::Vec3(bodyPos.x, -10, bodyPos.z)),
NxOgre::Enums::ShapesType_Static);

if(mBodyRayHit.mDistance == 0) {
mForceVector.y = mForceApply;
LogManager::getSingletonPtr()->logMessage("IF zone");
} else {
LogManager::getSingletonPtr()->logMessage("ELSE zone");
}

}
}


I declared into my members the following variable:

NxOgre::RaycastHit mBodyRayHit;

Problem: i cannot jump the body. My "Ogre.log" file always write "ELSE zone" regarding to my log message on the first block of code i posted.
LogManager::getSingletonPtr()->logMessage("ELSE zone");

The body jump from a plane declared like this:

// Create floor plane (BloodyMess)
mScene->createSceneGeometry(new NxOgre::PlaneGeometry(0, NxOgre::Vec3(0, 1, 0)), Matrix44_Identity);

// Create floor plane (Ogre)
MovablePlane *plane = new MovablePlane("Plane");
plane->d = 0;
plane->normal = Vector3::UNIT_Y;
Ogre::MeshManager::getSingleton().createPlane("PlaneMesh",
ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
*plane, 120, 120, 1, 1, true, 1, 3, 3, Vector3::UNIT_Z);
Entity *planeEnt = mSceneManager->createEntity("PlaneEntity", "PlaneMesh");
planeEnt->setMaterialName("Examples/NxFloor");

planeEnt->setCastShadows(false);

Ogre::SceneNode* mPlaneNode = mSceneManager->getRootSceneNode()->createChildSceneNode();
mPlaneNode->attachObject(planeEnt);


1 - What's going wrong?

I believe you can cast within side a shape and that shape won't get reported

2 - i'am quite interested about this feature. How does it works? Which function i have to use?

Thanks for the support you bring to me,

Thomas (from france).

Druha

14-11-2009 16:13:20

Your object probably not at 0 distance from the ground. It may stay at 0.0001 for example, close enough, but not at zero. It's not a good idea to test float vars for equality to smth. Try to replace your condition for example with:
mBodyRayHit.mDistance < 0.1

To betajaen:
I have an expirience with raycasts, when my object start flying away exactly because it get reported as a query result. I had to change Shape type to NxOgre::Enums::ShapesType_Static to avoid false reports.

deshan

14-11-2009 16:15:39

I think the problem is in this line

if(mBodyRayHit.mDistance == 0)
because it may never reach to zero

I suggest you to print the mDistance value and check whether what is the it when the body is on the floor. Following is my code
void PlayerCharacter::jumpPlayer()
{
// ray casting
NxOgre::RaycastHit hit;
hit = gameEngData->mScene->raycastClosestShape(NxOgre::Ray(NxOgre::Vec3(characterNode->getPosition().x,characterNode->getPosition().y,characterNode->getPosition().z),NxOgre::Vec3(0,-1,0)),NxOgre::Enums::ShapesType_Static,1,40);

if(hit.mDistance < MINIMUM_FLOUR_TOUCH_LIMIT)
this->playerBody->addForce(NxOgre::Vec3(0,fpForceJumpPower,0), NxOgre::Enums::ForceMode_Force);
}


EDIT: Oh druha almost posted the code :D

toum

14-11-2009 16:20:33

Your object probably not at 0 distance from the ground. It may stay at 0.0001 for example, close enough, but not at zero. It's not a good idea to test float vars for equality to smth. Try to replace your condition for example with:
mBodyRayHit.mDistance < 0.1


Unfortunately it's not working with

mBodyRayHit.mDistance < 0.1

The definition of my ray is really correct? I use Vec3(mBody.x, -10, mBody.z) for the second vector of my ray:

mBodyRayHit = mScene->raycastClosestShape( NxOgre::Ray(bodyPos, NxOgre::Vec3(bodyPos.x, -10, bodyPos.z)),
NxOgre::Enums::ShapesType_Static);


Thanks for the support,

Thomas

toum

14-11-2009 16:27:57


Unfortunately it's not working with

mBodyRayHit.mDistance < 0.1



It Works with more greater value: 1 instead of 0.1
mBodyRayHit.mDistance < 1

1 - There is a way to debug raycast? To view on screen my ray? Which plane or actor, body does he hit?

Thanks all!

Thomas

Druha

14-11-2009 16:49:02


The definition of my ray is really correct? I use Vec3(mBody.x, -10, mBody.z) for the second vector of my ray:
mBodyRayHit = mScene->raycastClosestShape( NxOgre::Ray(bodyPos, NxOgre::Vec3(bodyPos.x, -10, bodyPos.z)),
NxOgre::Enums::ShapesType_Static);


The second vector in Ray constructor is a direction vector. In your case there should be NxOgre::Vec3(0,-1,0)
The one you are using now after normalisation may point in almost any direction, but not down :wink:

toum

14-11-2009 18:09:36


The definition of my ray is really correct? I use Vec3(mBody.x, -10, mBody.z) for the second vector of my ray:
mBodyRayHit = mScene->raycastClosestShape( NxOgre::Ray(bodyPos, NxOgre::Vec3(bodyPos.x, -10, bodyPos.z)),
NxOgre::Enums::ShapesType_Static);


The second vector in Ray constructor is a direction vector. In your case there should be NxOgre::Vec3(0,-1,0)
The one you are using now after normalisation may point in almost any direction, but not down :wink:


Ok i understand and i correct. Thanks.

I ask again about the debug:

1 - There's a way to view Ray on the scene to debug?

2 - There is a to make a "surface ray" which describe a volume? This volume could intersec with other bodies, actor or static shape...

Thanks for support,

Thomas

betajaen

14-11-2009 19:28:17

1. No not really. Rays are preformed instantaneously, so they are to quick to be drawn. You can use an Ogre::ManualObject though to draw a line though.

2. Yep. You can use sweep testing if you like, it should be accessible via Scene.


However, I am really surprised how much difficulty you have had with this. Honestly it isn't hard to do.

I'll assume your player is 2 metres high, has a default skin width of 0.025:

float minFloorHeight = (2 * 0.5) + 0.025 + 0.05) // Half the height + skin width + 0.05 safety.

if (mScene->raycastAnyShape(NxOgre::Ray(bodyPos, NxOgre::Vec3(0,-1,0)), NxOgre::Enums::ShapesType_Static, INT_MAX, minFloorHeight)
; // On Floor
else
; // In air

toum

14-11-2009 19:45:20

Thanks for the support.