Quote:
What are the masses and sizes of your blocks and character? Bullet doesn't deal well with two objects that have very different masses or objects that are very small.
As far I know they are 1. I just copied most of the code from the samples because this is my first time using bullet.
Quote:
Might also want to think about using a a fixed timestep for you physics. As seen in this article.
Doesn't this give me the same issue as I have currently? Bad performace or stucking inside something?
Quote:
Might think about using a kinematic object for your character instead of a rigid body. Continually applying forces to a rigid body probably will never give you a true sidescroller feel. And might be a cause of your issue.
What is that, and how does it differ from a regular rigid body? I've read somewhere that this is something which collides with other rigid bodys, but the rigid bodys don't collide with it or something like that. But I need that two-way collision. (If I'm right here[smile])
Quote:
Might also want to take a look at Box2D.
I make this game because I want to use bullet in my larger project. You can see it as a "testing-game" but it is still a game!
Quote:
Posing your Bullet initialization and rigid body creation would be helpful too. I would suspect there is something wrong in one of those.
I guess here's the problem, too. Here it is:
Main initialization:
PhysicalComponent::PhysicalComponent(void){ DefaultGravity=D3DXVECTOR3(0,900,0); ///collision configuration contains default setup for memory, collision setup. Advanced users can create their own configuration. CollisionConfiguration = new btDefaultCollisionConfiguration(); ///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded) Dispatcher = new btCollisionDispatcher(CollisionConfiguration); ///btDbvtBroadphase is a good general purpose broadphase. You can also try out btAxis3Sweep. OverlappingPairCache = new btDbvtBroadphase(); ///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded) Solver = new btSequentialImpulseConstraintSolver; DynamicsWorld = new btDiscreteDynamicsWorld(Dispatcher,OverlappingPairCache,Solver,CollisionConfiguration); DynamicsWorld->setGravity(*(btVector3*)&DefaultGravity); Simplex = new btVoronoiSimplexSolver(); pdSolver = new btMinkowskiPenetrationDepthSolver(); ConvexAlgo2d = new btConvex2dConvex2dAlgorithm::CreateFunc(Simplex,pdSolver); Dispatcher->registerCollisionCreateFunc(CONVEX_2D_SHAPE_PROXYTYPE,CONVEX_2D_SHAPE_PROXYTYPE,ConvexAlgo2d); Dispatcher->registerCollisionCreateFunc(BOX_2D_SHAPE_PROXYTYPE,CONVEX_2D_SHAPE_PROXYTYPE,ConvexAlgo2d); Dispatcher->registerCollisionCreateFunc(CONVEX_2D_SHAPE_PROXYTYPE,BOX_2D_SHAPE_PROXYTYPE,ConvexAlgo2d); Dispatcher->registerCollisionCreateFunc(BOX_2D_SHAPE_PROXYTYPE,BOX_2D_SHAPE_PROXYTYPE,new btBox2dBox2dCollisionAlgorithm::CreateFunc());}
And here is the code the blocks are using:
void LevelBlock::InitCollisionOnly(){ ///create a few basic rigid bodies CollisionShape = new btBoxShape(btVector3(Scale.x/2,Scale.y/2,1)); //keep track of the shapes, we release memory at exit. //make sure to re-use collision shapes among rigid bodies whenever possible! btAlignedObjectArray<btCollisionShape*> collisionShapes; btTransform groundTransform; groundTransform.setIdentity(); groundTransform.setOrigin(btVector3(Position.x,Position.y,Position.z)); btScalar mass(0.); //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) CollisionShape->calculateLocalInertia(mass,localInertia); //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects myMotionState = new btDefaultMotionState(groundTransform); btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,CollisionShape,localInertia); RigidBody = new btRigidBody(rbInfo); //add the body to the dynamics world Physics.DynamicsWorld->addRigidBody(RigidBody); RigidBody->setFriction(0.5); InitialPosition=Position;}void LevelBlock::InitPhysics(){ //create a dynamic rigidbody //btCollisionShape* colShape = new btBoxShape(btVector3(1,1,1)); CollisionShape = new btBoxShape(btVector3(Scale.x/2,Scale.y/2,1)); /// Create Dynamic Objects btTransform startTransform; startTransform.setIdentity(); startTransform.setOrigin(btVector3(Position.x,Position.y,Position.z)); btScalar mass(1.f); //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) CollisionShape->calculateLocalInertia(mass,localInertia); //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects myMotionState = new btDefaultMotionState(startTransform); btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,CollisionShape,localInertia); RigidBody = new btRigidBody(rbInfo); Physics.DynamicsWorld->addRigidBody(RigidBody); RigidBody->setLinearFactor(btVector3(1,1,0)); RigidBody->setAngularFactor(btVector3(0,0,1)); RigidBody->setFriction(0.5); InitialPosition=Position;}
And this is my function for controlling the player-block (Kinda messy, sorry, not all my code looks like this [smile]):
void PlayerBlock::TickBlock(){ TexturedBlock::TickBlock(); if(RigidBody->isActive()==false) { //The player must be always active RigidBody->activate(true); } //This is the force apply this frame D3DXVECTOR3 Force=D3DXVECTOR3(0,0,0); //Movement: if(Input.bPressedKeys[VK_LEFT]) { Force.x-=LR_MoveSpeed; SetAnimationState(AS_Walk); bLeft=true; } if(Input.bPressedKeys[VK_RIGHT]) { Force.x+=LR_MoveSpeed; SetAnimationState(AS_Walk); bLeft=false; } //-- //Make it fit to the FPS Force*=FPS.GetElapsedTime(); //Cap the speed of the player, so he never gets too fast (Set at the end of this function) btVector3 Vel = RigidBody->getLinearVelocity(); if(Vel.x()>LR_MaxSpeed) { Vel.setX(LR_MaxSpeed); } if(Vel.x()<-LR_MaxSpeed) { Vel.setX(-LR_MaxSpeed); } //Key-Check if(bOldSpace==true && Input.bPressedKeys[VK_SPACE]==false) { bOldSpace=false; } //Do a ray test to check if we are on the ground or not btCollisionObjectArray ColArray; btVector3 ToRay(Position.x,Position.y+(Scale.y/2)+0.001,Position.z); btCollisionWorld::ClosestRayResultCallback rc(*(btVector3 *)&Position,ToRay); Physics.DynamicsWorld->rayTest(*(btVector3 *)&Position,ToRay,rc); if(rc.hasHit()) { //We are on ground, make doublejumping possible bHasDoubleJumped=false; LastDJTime=0; bIsOnGround=true; }else { bIsOnGround=false; } if(bOldSpace==false && Input.bPressedKeys[VK_SPACE]==true) { //Cheat to get out when stucking somewhere if(Input.bPressedKeys['T']) { D3DXVECTOR3 pos=Position; pos.y-=BlockPlacer.BlockGridSize.y; SetPosition(&pos); } //Do a jump if(bIsOnGround || (bIsOnGround==false && bHasDoubleJumped==false)) { if((bIsOnGround==false && bHasDoubleJumped==false) && LastDJTime+DoubleJumpWait<timeGetTime()) { bHasDoubleJumped=true; LastDJTime=timeGetTime(); Force.y-=JumpStrength; SetAnimationState(AS_Jump); //Double jumped, so stop any falling Vel.setY(0); }else if(bIsOnGround) { Force.y-=JumpStrength; SetAnimationState(AS_Jump); } } bOldSpace=true; } //Clamp the Velocity here RigidBody->setLinearVelocity(Vel); if(D3DXVec3Length(&Force)>0) { //Force does nothing?? (So impulse) RigidBody->applyCentralImpulse(*(btVector3*)&Force); }else { SetAnimationState(AS_Idle); } UpdateAnimation(); //RigidBody->setLinearVelocity(*(btVector3*)&Force);}