So I am kinda confused on how to shoot projectiles in 3D using Irrlicht. I know how to shoot projectiles in 2D, but its different with 3D. I'm using Irrlicht and Bullet Physics. I've done the tutorial on using Bullet physics with Irrlicht, but what I'd like to do, is to be able to shoot boxes when the user presses the left mouse button.
Code: Select all
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <iostream>
#include <irrlicht.h>
#include <btBulletDynamicsCommon.h>
#include <btBulletCollisionCommon.h>
using namespace std;
using namespace irr;
using namespace core;
using namespace video;
using namespace scene;
using namespace io;
using namespace gui;
static void CreateStart();
static void CreateBox(const btVector3 &TPosition, const vector3df &TScale, btScalar TMass);
static void CreateSphere(const btVector3 &TPosition, btScalar TRadius, btScalar TMass);
static void UpdatePhysics(u32 TDeltaTime);
static void UpdateRender(btRigidBody* TObject);
static void ClearObjects();
static int GetRandInt(int TMax) {return rand() % TMax;}
static bool Done = false;
static btDiscreteDynamicsWorld* World;
static IrrlichtDevice* Device;
static IVideoDriver* Driver;
static ISceneManager* Smgr;
static IGUIEnvironment* Env;
static ITimer* Timer;
static list <btRigidBody*> Objects;
class MainEvent : public IEventReceiver
{
public:
virtual bool OnEvent(const SEvent &event)
{
if(event.EventType == EET_KEY_INPUT_EVENT && event.KeyInput.PressedDown)
{
switch(event.KeyInput.Key)
{
case KEY_ESCAPE:
Done = true;
break;
case KEY_KEY_1:
CreateBox(btVector3(GetRandInt(10) - 5.0f, 7.0f, GetRandInt(10) - 5.0f), vector3df(GetRandInt(3) + 0.5f, GetRandInt(3) + 0.5f, GetRandInt(3) + 0.5f), 1.0f);
break;
case KEY_KEY_2:
CreateSphere(btVector3(GetRandInt(10) - 5.0f, 7.0f, GetRandInt(10) - 5.0f), GetRandInt(5) / 5.0f + 0.2f, 1.0f);
break;
case KEY_KEY_X:
CreateStart();
break;
default:
return false;
break;
}
return true;
}
return false;
}
};
int main(int argc, char* argv[])
{
MainEvent receiver;
Device = createDevice(EDT_DIRECT3D9, dimension2d<u32>(800,600), 32, false, false, false, &receiver);
Env = Device->getGUIEnvironment();
Timer = Device->getTimer();
Smgr = Device->getSceneManager();
Driver = Device->getVideoDriver();
btDefaultCollisionConfiguration* collisionConfig = new btDefaultCollisionConfiguration();
btBroadphaseInterface* broadphase = new btAxisSweep3(btVector3(-1000,-1000,-1000), btVector3(1000,1000,1000));
btCollisionDispatcher* dispatcher = new btCollisionDispatcher(collisionConfig);
btSequentialImpulseConstraintSolver* solver = new btSequentialImpulseConstraintSolver();
World = new btDiscreteDynamicsWorld(dispatcher,broadphase,solver,collisionConfig);
ICameraSceneNode* Cam = Smgr->addCameraSceneNodeFPS(0,100,10);
Cam->setPosition(vector3df(0,5,-5));
Cam->setTarget(vector3df(0,0,0));
Smgr->addLightSceneNode(0,vector3df(2,5,-2), SColorf(4,4,4,1));
CreateStart();
u32 TimeStamp = Timer->getTime(), DeltaTime = 0;
while(!Done)
{
DeltaTime = Timer->getTime() - TimeStamp;
TimeStamp = Timer->getTime();
UpdatePhysics(DeltaTime);
Driver->beginScene(true,true,SColor(255,20,0,0));
Smgr->drawAll();
Env->drawAll();
Driver->endScene();
Device->run();
}
ClearObjects();
delete World;
delete solver;
delete dispatcher;
delete broadphase;
delete collisionConfig;
return 0;
}
void UpdatePhysics(u32 TDeltaTime)
{
World->stepSimulation(TDeltaTime * 0.001f, 60);
for(list<btRigidBody*>::Iterator it = Objects.begin(); it != Objects.end(); ++it)
{
UpdateRender(*it);
}
}
void CreateStart()
{
ClearObjects();
CreateBox(btVector3(0.0f,0.0f,0.0f), vector3df(10.0f,0.5f,10.0f), 0.0f);
}
void CreateBox(const btVector3 &TPosition, const vector3df &TScale, btScalar TMass)
{
ISceneNode* Node = Smgr->addCubeSceneNode(1.0f);
Node->setScale(TScale);
Node->setMaterialFlag(EMF_LIGHTING,1);
Node->setMaterialFlag(EMF_NORMALIZE_NORMALS, true);
btTransform Transform;
Transform.setIdentity();
Transform.setOrigin(TPosition);
btDefaultMotionState *MotionState = new btDefaultMotionState(Transform);
btVector3 HalfExtents(TScale.X * 0.5f, TScale.Y * 0.5f, TScale.Z * 0.5f);
btCollisionShape* Shape = new btBoxShape(HalfExtents);
btVector3 LocalInertia;
Shape->calculateLocalInertia(TMass,LocalInertia);
btRigidBody* RigidBody = new btRigidBody(TMass,MotionState,Shape,LocalInertia);
RigidBody->setUserPointer((void*)(Node));
World->addRigidBody(RigidBody);
Objects.push_back(RigidBody);
}
void CreateSphere(const btVector3 &TPosition, btScalar TRadius, btScalar TMass)
{
ISceneNode* Node = Smgr->addSphereSceneNode(TRadius,32);
Node->setMaterialFlag(EMF_LIGHTING,1);
Node->setMaterialFlag(EMF_NORMALIZE_NORMALS, true);
btTransform Transform;
Transform.setIdentity();
Transform.setOrigin(TPosition);
btDefaultMotionState* MotionState = new btDefaultMotionState(Transform);
btCollisionShape* Shape = new btSphereShape(TRadius);
btVector3 LocalInertia;
Shape->calculateLocalInertia(TMass,LocalInertia);
btRigidBody* RigidBody = new btRigidBody(TMass,MotionState,Shape,LocalInertia);
RigidBody->setUserPointer((void*)(Node));
World->addRigidBody(RigidBody);
Objects.push_back(RigidBody);
}
void UpdateRender(btRigidBody* TObject)
{
ISceneNode* Node = static_cast<ISceneNode*>(TObject->getUserPointer());
btVector3 Point = TObject->getCenterOfMassPosition();
Node->setPosition(vector3df((f32)Point[0], (f32)Point[1], (f32)Point[2]));
vector3df Euler;
const btQuaternion& TQuat = TObject->getOrientation();
quaternion q(TQuat.getX(), TQuat.getY(), TQuat.getZ(), TQuat.getW());
q.toEuler(Euler);
Euler *= RADTODEG;
Node->setRotation(Euler);
}
void ClearObjects()
{
for(list<btRigidBody *>::Iterator Iterator = Objects.begin(); Iterator != Objects.end(); ++Iterator) {
btRigidBody *Object = *Iterator;
ISceneNode *Node = static_cast<ISceneNode *>(Object->getUserPointer());
Node->remove();
World->removeRigidBody(Object);
delete Object->getMotionState();
delete Object->getCollisionShape();
delete Object;
}
Objects.clear();
}