Player Controls help.

Problems building or running the engine, queries about how to use features etc.
Post Reply
smoovegee
Gnoblar
Posts: 2
Joined: Sat Aug 01, 2020 3:37 pm

Player Controls help.

Post by smoovegee »

Ogre Version: :?: v1.12.8
Operating System: :?: Windows
Render System: :?: Visual Studio

Im trying to get a player controls. But my box just moves forward and back only. trying to make it move forward and back. Or like a full 3D character like the Sinbad example in Ogre.



#include "Player.h"

Player::Player()
{
boxSceneNode = nullptr;
box = nullptr;
Vector3 meshBoundingBox(0.0f, 0.0f, 0.0f);

colShape = nullptr;
dynamicsWorld = nullptr;

/* Note: These are hardcoded in player. Should probably be read in from a
* config file or similar.
*/
backwardForce = 100.0f;
forwardForce = -100.0f;
leftForce = -100.0f;
rightForce = -100.0f;
//turningForceLeft = -40.0f;
//turningForceRight = 40.0f;
//int jumpSpeed = 10;
linearDamping = 0.0f;
angularDamping = 0.0f;
}

Player::~Player()
{

}

void Player::createMesh(SceneManager* scnMgr)
{
box = scnMgr->createEntity("cube.mesh");


}

void Player::attachToNode(SceneNode* parent)
{


boxSceneNode = parent->createChildSceneNode();
boxSceneNode->attachObject(box);
boxSceneNode->setScale(1.0f, 1.0f, 1.0f);
boundingBoxFromOgre();
}

void Player::setScale(float x, float y, float z)
{
boxSceneNode->setScale(x, y, z);
}


void Player::setRotation(Vector3 axis, Radian rads)
{
//quat from axis angle
Quaternion quat(rads, axis);
boxSceneNode->setOrientation(quat);
}

void Player::setPosition(float x, float y, float z)
{
boxSceneNode->setPosition(x, y, z);
}

void Player::boundingBoxFromOgre()
{
//get bounding box here.
boxSceneNode->_updateBounds();
const AxisAlignedBox& b = boxSceneNode->_getWorldAABB();
Vector3 temp(b.getSize());
meshBoundingBox = temp;
}

void Player::createRigidBody(float bodyMass)
{
colShape = new btBoxShape(btVector3(meshBoundingBox.x / 2.0f, meshBoundingBox.y / 2.0f, meshBoundingBox.z / 2.0f));

/// Create Dynamic Objects
btTransform startTransform;
startTransform.setIdentity();

Quaternion quat2 = boxSceneNode->_getDerivedOrientation();
startTransform.setRotation(btQuaternion(quat2.x, quat2.y, quat2.z, quat2.w));

Vector3 pos = boxSceneNode->_getDerivedPosition();
startTransform.setOrigin(btVector3(pos.x, pos.y, pos.z));

btScalar mass(bodyMass);

//rigidbody is dynamic if and only if mass is non zero, otherwise static
bool isDynamic = (mass != 0.f);

btVector3 localInertia(0, 0, 0);
if (isDynamic)
{
// Debugging
//std::cout << "I see the cube is dynamic" << std::endl;
colShape->calculateLocalInertia(mass, localInertia);
}

//using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform);
btRigidBody::btRigidBodyConstructionInfo rbInfo(mass, myMotionState, colShape, localInertia);
body = new btRigidBody(rbInfo);

//Set the linear and angular damping
//I'm using this to bring the object to rest when moving.
//An alternative would be to use friciton for the collison.
//No good for hovering stuff though.
body->setDamping(linearDamping, angularDamping);

//Set the user pointer to this object.
body->setUserPointer((void*)this);
}

void Player::addToCollisionShapes(btAlignedObjectArray<btCollisionShape*> &collisionShapes)
{
collisionShapes.push_back(colShape);
}

void Player::addToDynamicsWorld(btDiscreteDynamicsWorld* dynamicsWorld)
{
this->dynamicsWorld = dynamicsWorld;
dynamicsWorld->addRigidBody(body);
}

void Player::update()
{
btTransform trans;

if (body && body->getMotionState())
{
body->getMotionState()->getWorldTransform(trans);
btQuaternion orientation = trans.getRotation();

boxSceneNode->setPosition(Ogre::Vector3(trans.getOrigin().getX(), trans.getOrigin().getY(), trans.getOrigin().getZ()));
boxSceneNode->setOrientation(Ogre::Quaternion(orientation.getW(), orientation.getX(), orientation.getY(), orientation.getZ()));
}
}

void Player::forward()
{
//Create a vector in local coordinates
//pointing down z.
btVector3 fwd(0.0f, 0.0f, forwardForce);
btVector3 push;

btTransform trans;

if (body && body->getMotionState())
{
//get the orientation of the rigid body in world space.
body->getMotionState()->getWorldTransform(trans);
btQuaternion orientation = trans.getRotation();

//rotate the local force, into the global space.
//i.e. push in down the local z.
push = quatRotate(orientation, fwd);

//activate the body, this is essential if the body
//has gone to sleep (i.e. stopped moving/colliding).
body->activate();

//apply a force to the center of the body
body->applyCentralForce(push);
}
}

void Player::backward()
{
//Create a vector in local coordinates
//pointing down z.
btVector3 bwd(0.0f, 0.0f, backwardForce);
btVector3 pull;

btTransform trans;

if (body && body->getMotionState())
{
//get the orientation of the rigid body in world space.
body->getMotionState()->getWorldTransform(trans);
btQuaternion orientation = trans.getRotation();

//rotate the local force, into the global space.
//i.e. push in down the local z.
pull = quatRotate(orientation, bwd);

//activate the body, this is essential if the body
//has gone to sleep (i.e. stopped moving/colliding).
body->activate();

//apply a force to the center of the body
body->applyCentralForce(pull);
}
}
*****************************************


this is in Game.cpp

bool Game::frameStarted (const Ogre::FrameEvent &evt)
{
//Be sure to call base class - otherwise events are not polled.
ApplicationContext::frameStarted(evt);
if (this->dynamicsWorld != NULL)
{
// Apply new forces
if(wDown)
player->forward();

if(sDown)
{
player->backward();
//player->spinRight(); // -- Doesnt' work
}

if (aDown) {
player->movesLeft();
}

if (dDown) {
player->movesRight();
}
// Bullet can work with a fixed timestep
//dynamicsWorld->stepSimulation(1.f / 60.f, 10);

// Or a variable one, however, under the hood it uses a fixed timestep
// then interpolates between them.

dynamicsWorld->stepSimulation((float)evt.timeSinceLastFrame, 10);

// update positions of all objects
for (int j = dynamicsWorld->getNumCollisionObjects() - 1; j >= 0; j--)
{
btCollisionObject* obj = dynamicsWorld->getCollisionObjectArray()[j];
btRigidBody* body = btRigidBody::upcast(obj);
btTransform trans;

if (body && body->getMotionState())
{
body->getMotionState()->getWorldTransform(trans);

/* https://oramind.com/ogre-bullet-a-begin ... sic-guide/ */
void *userPointer = body->getUserPointer();

// Player should know enough to update itself.
if(userPointer == player)
{
// Ignore player, he's always updated!
}
else //This is just to keep the other objects working.
{
if (userPointer)
{
btQuaternion orientation = trans.getRotation();
Ogre::SceneNode *sceneNode = static_cast<Ogre::SceneNode *>(userPointer);
sceneNode->setPosition(Ogre::Vector3(trans.getOrigin().getX(), trans.getOrigin().getY(), trans.getOrigin().getZ()));
sceneNode->setOrientation(Ogre::Quaternion(orientation.getW(), orientation.getX(), orientation.getY(), orientation.getZ()));
}
}
}
else
{
trans = obj->getWorldTransform();
}
}

//Update player here, his movement is not dependent on collisions.
player->update();
}
return true;
}

bool Game::frameEnded(const Ogre::FrameEvent &evt)
{
if (this->dynamicsWorld != NULL)
{
// Bullet can work with a fixed timestep
//dynamicsWorld->stepSimulation(1.f / 60.f, 10);

// Or a variable one, however, under the hood it uses a fixed timestep
// then interpolates between them.

dynamicsWorld->stepSimulation((float)evt.timeSinceLastFrame, 10);
}
return true;
}

void Game::setupLights()
{
// Setup Abient light
scnMgr->setAmbientLight(ColourValue(0.5, 0.5, 0.5));
scnMgr->setShadowTechnique(ShadowTechnique::SHADOWTYPE_STENCIL_MODULATIVE);

// Add a spotlight
Light* spotLight = scnMgr->createLight("SpotLight");

// Configure
spotLight->setDiffuseColour(0, 0, 1.0);
spotLight->setSpecularColour(0, 0, 1.0);
spotLight->setType(Light::LT_SPOTLIGHT);
spotLight->setSpotlightRange(Degree(35), Degree(50));


// Create a schene node for the spotlight
SceneNode* spotLightNode = scnMgr->getRootSceneNode()->createChildSceneNode();
spotLightNode->setDirection(-1, -1, 0);
spotLightNode->setPosition(Vector3(200, 200, 0));

// Add spotlight to the scene node.
spotLightNode->attachObject(spotLight);

// Create directional light
Light* directionalLight = scnMgr->createLight("DirectionalLight");

// Configure the light
directionalLight->setType(Light::LT_DIRECTIONAL);
directionalLight->setDiffuseColour(ColourValue(0.4, 0, 0));
directionalLight->setSpecularColour(ColourValue(0.4, 0, 0));

// Setup a scene node for the directional lightnode.
SceneNode* directionalLightNode = scnMgr->getRootSceneNode()->createChildSceneNode();
directionalLightNode->attachObject(directionalLight);
directionalLightNode->setDirection(Vector3(0, -1, 1));

// Create a point light
Light* pointLight = scnMgr->createLight("PointLight");

// Configure the light
pointLight->setType(Light::LT_POINT);
pointLight->setDiffuseColour(0.3, 0.3, 0.3);
pointLight->setSpecularColour(0.3, 0.3, 0.3);

// setup the scene node for the point light
SceneNode* pointLightNode = scnMgr->getRootSceneNode()->createChildSceneNode();

// Configure the light
pointLightNode->setPosition(Vector3(0, 150, 250));

// Add the light to the scene.
pointLightNode->attachObject(pointLight);




}


//direction *= timeSinceLastFrame * speedMultiplier;
bool Game::keyPressed(const KeyboardEvent& evt)
{

std::cout << "Got key down event" << std::endl;
if (evt.keysym.sym == SDLK_ESCAPE)
{
getRoot()->queueEndRendering();
}

if(evt.keysym.sym == 'w')
{
wDown = true;

}

if(evt.keysym.sym == 'a')
{
aDown = true;
}

if (evt.keysym.sym == 's')
{
sDown = true;
}

if (evt.keysym.sym == 'd')
{
dDown = true;
}


return true;
}

bool Game::keyReleased(const KeyboardEvent& evt)
{

std::cout << "Got key up event" << std::endl;

if(evt.keysym.sym == 'w')
{
wDown = false;

}

if(evt.keysym.sym == 'a')
{
aDown = false;
}

if (evt.keysym.sym == 's')
{
sDown = false;
}

if (evt.keysym.sym == 'd')
{
dDown = false;
}
return true;
}




bool Game::mouseMoved(const MouseMotionEvent& evt)
{
std::cout << "Got Mouse" << std::endl;
return true;
}

User avatar
sercero
Bronze Sponsor
Bronze Sponsor
Posts: 68
Joined: Sun Jan 18, 2015 4:20 pm
Location: Buenos Aires, Argentina
x 15

Re: Player Controls help.

Post by sercero »

Hello,

Next time, please use the the "code" button to insert code, otherwise the post looks ugly and the code is unreadable.

I have taken a quick look at the code, your problem might be here:

Code: Select all

        if (aDown) {
            player->movesLeft();
        }

        if (dDown) {
            player->movesRight();
        }
I don't see those functions implemented in the code, only "player->forward();" and "player->backward();"

It is unclear to me why you are using a function for each direction, it would be better to have a direction vector that is influenced by the buttons and a general move() function that moves the player.
That way you can also sum the directions to have diagonal movement for example.

Another thing: your player is a rigid body... in general it is best to use a kinematic character controller to control the player character since it makes it more responsive.
The whole rigid vs kinematic discussion is quite extensive perhaps you made an informed decision just know that there is another way.

smoovegee
Gnoblar
Posts: 2
Joined: Sat Aug 01, 2020 3:37 pm

Re: Player Controls help.

Post by smoovegee »

thanks for the reply. Ill have a look at it.

Post Reply