How to use the Collider API to implement Ping Pong physics?


#1

I am new to game development and trying to build a simple Ping Pong game to under how Physics work in game engine.

I built a little program to simulate the Ping Pong game environment and do not quite understand how to properly setup the Collider API for the ball and the paddle so they will interact probably.

The piece of code I have for setting up the ball is as below. One thing I noticed. If I have the scale from 15.0f to 10.0f for example, the ball will just pass through the table without bouncing up and down. If I have this back to 15.0f. I will bounce.

I probably don’t understand how to configure the collider parameters such as the mass, the physical material and etc to setup this up correctly.

A few questions in these APIs:

  1. How to configure the physical material surface and the ball’s mass to ensure it would be bounce probably.
  2. How to configure the collider boundary so that it would align witht he size of the mesh?
  3. Is there additional setup to make the paddle becomes the player in addition of setting it as a rigid body?
  4. How to implement a callback event for the ball when it hits the paddle? Do I have to create a paddle class to implement the onCollide event?

Any advice to pointers here would be appreciated!

The scene setup

The source code:

int main()
{
using namespace bs;

// Initializes the application and creates a window with the specified
// properties
VideoMode videoMode(1928, 1080);
Application::startUp(videoMode, “Table Tennis Table”, false);

// Application
SPtr primaryWindow = gApplication().getPrimaryWindow();
primaryWindow->onResized.connect(&notifyResized);
setupInputConfig();

// Shader
HShader shader = gBuiltinResources().getBuiltinShader(BuiltinShader::Standard);

// Table Scene
HSceneObject tableSO = SceneObject::create(“Table”);
//tableSO->addComponent();
tableSO->setPosition(Vector3(0, 50, 0));
tableSO->setScale(Vector3(1.0f, 1.0f, 1.0f));

HMesh tableMesh = gImporter().import("/home/tangth/bsfdev/bsfExamples/Data/table.fbx");
HRenderable tableRenderable = tableSO->addComponent();
tableRenderable->setMesh(tableMesh);

HMaterial tableMaterial = Material::create(shader);
HTexture tableTexture = gImporter().import("/home/tangth/bsfdev/bsfExamples/Data/wood.png");
tableMaterial->setTexture(“gAlbedoTex”, tableTexture);
tableRenderable->setMaterial(tableMaterial);

HPhysicsMaterial tableColliderMaterial = PhysicsMaterial::create(1.0f, 1.0f, 1.0f);
HPlaneCollider tableCollider = tableSO->addComponent();
tableCollider->setMaterial(tableColliderMaterial);
tableCollider->setMass(500.0f);

// Floor Scene
HSceneObject floorSO = SceneObject::create(“Floor”);
floorSO->setPosition(Vector3(0, 0, 0));
floorSO->setScale(Vector3(500.0f, 1.0f, 500.0f));

HMesh floorMesh = gBuiltinResources().getMesh(BuiltinMesh::Quad);
HRenderable floorRenderable = floorSO->addComponent();
floorRenderable->setMesh(floorMesh);

HMaterial floorMaterial = Material::create(shader);
HTexture floorTexture = gImporter().import("/home/tangth/bsfdev/bsfExamples/Data/Floor.png");
floorMaterial->setTexture(“gAlbedoTex”, floorTexture);
floorMaterial->setVec2(“gUVTile”, Vector2::ONE * 50.0f * 0.5f);
floorRenderable->setMaterial(floorMaterial);

HPlaneCollider floorCollider = floorSO->addComponent();
HPhysicsMaterial floorColliderMaterial = PhysicsMaterial::create(1.0f, 1.0f, 0.0f);
floorCollider->setMaterial(floorColliderMaterial);
floorCollider->setNormal(Vector3(0, 1, 0));

// Ball Scene
HSceneObject ballSO = SceneObject::create(“Ball”);
// ballSO->setParent(tableSO);
ballSO->setPosition(Vector3(-100.0f, 200.5f, -320.0f));
ballSO->setScale(Vector3(15.0f, 15.0f, 15.0f));

HRenderable ballRenderable = ballSO->addComponent();
HMesh ballMesh = gImporter().import("/home/tangth/bsfdev/bsfExamples/Data/ball.fbx");
ballRenderable->setMesh(ballMesh);

HTexture ballTexture = gImporter().import("/home/tangth/bsfdev/bsfExamples/Data/Floor.png");
HMaterial ballMaterial = Material::create(shader);
ballMaterial->setTexture(“gAlbedoTex”, ballTexture);
ballRenderable->setMaterial(ballMaterial);

HSphereCollider ballCollider = ballSO->addComponent();
HPhysicsMaterial ballColliderMaterial = PhysicsMaterial::create(1.0f, 1.0f, 0.5f);
ballCollider->setMaterial(ballColliderMaterial);
//ballCollider->setRadius(50.0f);
ballCollider->setMass(2.0f);

HRigidbody ballRigidbody = ballSO->addComponent();

// Paddle Scene
HSceneObject paddleSO = SceneObject::create(“Paddle”);
// paddleSO->setParent(tableSO);
paddleSO->setPosition(Vector3(-5.0f, 150.5f, -300.0f));
paddleSO->setScale(Vector3(1.0f, 1.0f, 1.0f));
paddleSO->addComponent();

HRenderable paddleRenderable = paddleSO->addComponent();
HMesh paddleMesh = gImporter().import("/home/tangth/bsfdev/bsfExamples/Data/paddle.fbx");
paddleRenderable->setMesh(paddleMesh);

HTexture paddleTexture = gImporter().import("/home/tangth/bsfdev/bsfExamples/Data/wood.png");
HMaterial paddleMaterial = Material::create(shader);
paddleMaterial->setTexture(“gAlbedoTex”, paddleTexture);
paddleRenderable->setMaterial(paddleMaterial);

HPlaneCollider paddleCollider = paddleSO->addComponent();
HPhysicsMaterial paddleColliderMaterial = PhysicsMaterial::create(1.0f, 1.0f, 0.8f);
paddleCollider->setMaterial(paddleColliderMaterial);
paddleCollider->setMass(0.5f);
paddleCollider->setDistance(2.0f);
paddleCollider->setNormal(Vector3(0, 1, 0));

HRigidbody paddleRigidbody = paddleSO->addComponent();
//paddleRigidbody->setIsKinematic(true);
paddleRigidbody->setUseGravity(false);

// Camera Scene
HSceneObject cameraSO = SceneObject::create(“Camera”);
// cameraSO->addComponent();
cameraSO->setPosition(Vector3(0.0f, 300.0f, -500.0f));
cameraSO->lookAt(Vector3(0.0f, 0.0f, 0.0f));
cameraSO->addComponent();

HCamera camera = cameraSO->addComponent();
camera->getViewport()->setTarget(primaryWindow);
camera->setNearClipDistance(0.5f);
camera->setFarClipDistance(2000);
camera->setProjectionType(PT_PERSPECTIVE);
camera->setAspectRatio(1928/1080.00);

// Light Scene
HSceneObject lightSO = SceneObject::create(“Light”);
lightSO->setPosition(Vector3(0.0f, 300.0f, 0.0f));

HLight light = lightSO->addComponent();
light->setIntensity(50.0f);

Application::instance().runMainLoop();
Application::shutDown();

return 0;
}


#2

Just found from the documentation how to implement the collision trigger event. Added the piece of code below and start to see the event being reported:

auto collisionStarted =
[](const CollisionData &data) {
HCollider otherCollider = data.collider[1];
String otherSceneObjectName = otherCollider->SO()->getName();
Vector3 contactPoint = data.contactPoints[0].position;
bs::gDebug().logDebug("Started colliding with " + otherSceneObjectName +
" at point " + toString(contactPoint));
};

paddleCollider->setCollisionReportMode(CollisionReportMode::Report);
paddleCollider->onCollisionBegin.connect(collisionStarted);


#3

Try to use realistic positions, sizes and quantities. In bsf, 1 unit = 1 meter for size, and 1 kilogram for weight. So your ball has a radius of 15 meters, and a weight of two kilograms, which is too much. Physics system depends on you keeping these realistic.

If your objects are passing through each other you can enable Continous Collision Detection (on the Rigibody and on the global Physics object) but it might not be necessary if you adjust your scale/weight.

To have colliders line up with the visual mesh either use multiple primitive colliders, or create a mesh collider.