BGE: This patch adds a character wrapper (similar to the already implemented vehicle...
authorMitchell Stokes <mogurijin@gmail.com>
Sun, 4 Nov 2012 20:56:02 +0000 (20:56 +0000)
committerMitchell Stokes <mogurijin@gmail.com>
Sun, 4 Nov 2012 20:56:02 +0000 (20:56 +0000)
  * jump() -- causes the character to jump
  * onGround -- specifies whether or not the character is on the ground
  * gravity -- controls the "gravity" that the character physics uses for the character

More options could be added (such as jump speed, step height, make fall speed, max slope, etc).

13 files changed:
doc/python_api/rst/bge.constraints.rst
doc/python_api/rst/bge.types.rst
source/gameengine/Ketsji/CMakeLists.txt
source/gameengine/Ketsji/KX_CharacterWrapper.cpp [new file with mode: 0644]
source/gameengine/Ketsji/KX_CharacterWrapper.h [new file with mode: 0644]
source/gameengine/Ketsji/KX_PyConstraintBinding.cpp
source/gameengine/Ketsji/KX_PythonInitTypes.cpp
source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h
source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h
source/gameengine/Physics/common/CMakeLists.txt
source/gameengine/Physics/common/PHY_ICharacter.h [new file with mode: 0644]
source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h

index 83f2a6b4950febcaaf36fa80279302e7f1140dec..7757e11d41f386851218f063bc05d18b402155fe 100644 (file)
@@ -78,6 +78,14 @@ Physics Constraints (bge.constraints)
 
    :return: a vehicle constraint object.
    :rtype: :class:`bge.types.KX_VehicleWrapper`
+   
+.. function:: getCharacter(gameobj)
+
+   :arg gameobj: The game object with the character physics.
+   :type gameobj: :class:`bge.types.KX_GameObject`
+
+   :return: character wrapper
+   :rtype: :class:`bge.types.KX_CharacterWrapper`
 
 .. function:: removeConstraint(constraintId)
 
index a173137e50c5a41da70c6bb427c85a7bb7668c32..fdaeb61173fc0b6a7d4ee854f729d97f9fbdafdf 100644 (file)
@@ -3464,6 +3464,26 @@ Types
       :arg wheelIndex: the wheel index
       :type wheelIndex: integer
 
+.. class:: KX_CharacterWrapper(PyObjectPlus)
+
+   A wrapper to expose character physics options.
+
+   .. attribute:: onGround
+
+      Whether or not the character is on the ground. (read-only)
+
+         :type: boolean
+
+   .. attribute:: gravity
+
+      The gravity value used for the character.
+
+      :type: float
+
+   .. method:: jump()
+
+      The character jumps based on it's jump speed.
+
 .. class:: KX_VertexProxy(SCA_IObject)
 
    A vertex holds position, UV, color and normal information.
index b42c2c27075ef33994ceb8b31742c186fa73d2c3..4778a6ef9b9c9a5a00dc1194939bd0a287d4389e 100644 (file)
@@ -74,6 +74,7 @@ set(SRC
        KX_Camera.cpp
        KX_CameraActuator.cpp
        KX_CameraIpoSGController.cpp
+       KX_CharacterWrapper.cpp
        KX_ConstraintActuator.cpp
        KX_ConstraintWrapper.cpp
        KX_ConvertPhysicsObjects.cpp
@@ -149,6 +150,7 @@ set(SRC
        KX_Camera.h
        KX_CameraActuator.h
        KX_CameraIpoSGController.h
+       KX_CharacterWrapper.h
        KX_ClientObjectInfo.h
        KX_ConstraintActuator.h
        KX_ConstraintWrapper.h
diff --git a/source/gameengine/Ketsji/KX_CharacterWrapper.cpp b/source/gameengine/Ketsji/KX_CharacterWrapper.cpp
new file mode 100644 (file)
index 0000000..ce208f3
--- /dev/null
@@ -0,0 +1,94 @@
+/** \file gameengine/Ketsji/KX_CharacterWrapper.cpp
+ *  \ingroup ketsji
+ */
+
+
+#include "KX_CharacterWrapper.h"
+#include "PHY_ICharacter.h"
+
+KX_CharacterWrapper::KX_CharacterWrapper(PHY_ICharacter* character) :
+               PyObjectPlus(),
+               m_character(character)
+{
+}
+
+KX_CharacterWrapper::~KX_CharacterWrapper()
+{
+       if (m_character)
+               delete m_character; // We're responsible for the character object!
+}
+
+#ifdef WITH_PYTHON
+
+PyTypeObject KX_CharacterWrapper::Type = {
+       PyVarObject_HEAD_INIT(NULL, 0)
+       "KX_CharacterWrapper",
+       sizeof(PyObjectPlus_Proxy),
+       0,
+       py_base_dealloc,
+       0,
+       0,
+       0,
+       0,
+       py_base_repr,
+       0,0,0,0,0,0,0,0,0,
+       Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+       0,0,0,0,0,0,0,
+       Methods,
+       0,
+       0,
+       &PyObjectPlus::Type,
+       0,0,0,0,0,0,
+       py_base_new
+};
+
+PyAttributeDef KX_CharacterWrapper::Attributes[] = {
+       KX_PYATTRIBUTE_RO_FUNCTION("onGround", KX_CharacterWrapper, pyattr_get_onground),
+       KX_PYATTRIBUTE_RW_FUNCTION("gravity", KX_CharacterWrapper, pyattr_get_gravity, pyattr_set_gravity),
+       { NULL }        //Sentinel
+};
+
+PyObject *KX_CharacterWrapper::pyattr_get_onground(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+       KX_CharacterWrapper* self = static_cast<KX_CharacterWrapper*>(self_v);
+
+       return PyBool_FromLong(self->m_character->OnGround());
+}
+
+PyObject *KX_CharacterWrapper::pyattr_get_gravity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+       KX_CharacterWrapper* self = static_cast<KX_CharacterWrapper*>(self_v);
+
+       return PyFloat_FromDouble(self->m_character->GetGravity());
+}
+
+int KX_CharacterWrapper::pyattr_set_gravity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+       KX_CharacterWrapper* self = static_cast<KX_CharacterWrapper*>(self_v);
+       double param = PyFloat_AsDouble(value);
+
+       if (param == -1)
+       {
+               PyErr_SetString(PyExc_ValueError, "KX_CharacterWrapper.gravity: expected a float");
+               return PY_SET_ATTR_FAIL;
+       }
+
+       self->m_character->SetGravity((float)param);
+       return PY_SET_ATTR_SUCCESS;
+}
+
+PyMethodDef KX_CharacterWrapper::Methods[] = {
+       KX_PYMETHODTABLE_NOARGS(KX_CharacterWrapper, jump),
+       {NULL,NULL} //Sentinel
+};
+
+KX_PYMETHODDEF_DOC_NOARGS(KX_CharacterWrapper, jump,
+       "jump()\n"
+       "makes the character jump.\n")
+{
+       m_character->Jump();
+
+       Py_RETURN_NONE;
+}
+
+#endif // WITH_PYTHON
diff --git a/source/gameengine/Ketsji/KX_CharacterWrapper.h b/source/gameengine/Ketsji/KX_CharacterWrapper.h
new file mode 100644 (file)
index 0000000..cc99aba
--- /dev/null
@@ -0,0 +1,35 @@
+
+/** \file KX_CharacterWrapper.h
+ *  \ingroup ketsji
+ */
+
+#ifndef __KX_CHARACTERWRAPPER_H__
+#define __KX_CHARACTERWRAPPER_H__
+
+#include "Value.h"
+#include "PHY_DynamicTypes.h"
+class PHY_ICharacter;
+
+
+///Python interface to character physics
+class  KX_CharacterWrapper : public PyObjectPlus
+{
+       Py_Header
+
+public:
+       KX_CharacterWrapper(PHY_ICharacter* character);
+       virtual ~KX_CharacterWrapper();
+#ifdef WITH_PYTHON
+       KX_PYMETHOD_DOC_NOARGS(KX_CharacterWrapper, jump);
+
+       static PyObject* pyattr_get_onground(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+       
+       static PyObject*        pyattr_get_gravity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+       static int                      pyattr_set_gravity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+#endif // WITH_PYTHON
+
+private:
+       PHY_ICharacter*                  m_character;
+};
+
+#endif //__KX_CHARACTERWRAPPER_H__
index 5f3a4879150aa1aa3aaca19814062952f8867625..4475ac8ec968b3b2a099f757c330fb6018486e39 100644 (file)
 #include "PHY_IPhysicsEnvironment.h"
 #include "KX_ConstraintWrapper.h"
 #include "KX_VehicleWrapper.h"
+#include "KX_CharacterWrapper.h"
 #include "KX_PhysicsObjectWrapper.h"
 #include "PHY_IPhysicsController.h"
 #include "PHY_IVehicle.h"
 #include "PHY_DynamicTypes.h"
 #include "MT_Matrix3x3.h"
 
+#include "KX_GameObject.h" // ConvertPythonToGameObject()
+
 #include "PyObjectPlus.h" 
 
 #ifdef USE_BULLET
@@ -81,6 +84,7 @@ static char gPySetSolverType__doc__[] = "setSolverType(int solverType) Very expe
 
 static char gPyCreateConstraint__doc__[] = "createConstraint(ob1,ob2,float restLength,float restitution,float damping)";
 static char gPyGetVehicleConstraint__doc__[] = "getVehicleConstraint(int constraintId)";
+static char gPyGetCharacter__doc__[] = "getCharacter(KX_GameObject obj)";
 static char gPyRemoveConstraint__doc__[] = "removeConstraint(int constraintId)";
 static char gPyGetAppliedImpulse__doc__[] = "getAppliedImpulse(int constraintId)";
 
@@ -402,6 +406,33 @@ static PyObject *gPyGetVehicleConstraint(PyObject *self,
        Py_RETURN_NONE;
 }
 
+static PyObject* gPyGetCharacter(PyObject* self,
+                                 PyObject* args,
+                                 PyObject* kwds)
+{
+       PyObject* pyob;
+       KX_GameObject *ob;
+
+       if (!PyArg_ParseTuple(args,"O", &pyob))
+               return NULL;
+
+       if (!ConvertPythonToGameObject(pyob, &ob, false, "bge.constraints.getCharacter(value)"))
+               return NULL;
+
+       if (PHY_GetActiveEnvironment())
+       {
+                       
+               PHY_ICharacter* character= PHY_GetActiveEnvironment()->getCharacterController(ob);
+               if (character)
+               {
+                       KX_CharacterWrapper* pyWrapper = new KX_CharacterWrapper(character);
+                       return pyWrapper->NewProxy(true);
+               }
+
+       }
+
+       Py_RETURN_NONE;
+}
 
 static PyObject *gPyCreateConstraint(PyObject *self,
                                      PyObject *args,
@@ -631,6 +662,9 @@ static struct PyMethodDef physicsconstraints_methods[] = {
        {"getVehicleConstraint",(PyCFunction) gPyGetVehicleConstraint,
         METH_VARARGS, (const char *)gPyGetVehicleConstraint__doc__},
 
+       {"getCharacter",(PyCFunction) gPyGetCharacter,
+        METH_VARARGS, (const char *)gPyGetCharacter__doc__},
+
        {"removeConstraint",(PyCFunction) gPyRemoveConstraint,
         METH_VARARGS, (const char *)gPyRemoveConstraint__doc__},
        {"getAppliedImpulse",(PyCFunction) gPyGetAppliedImpulse,
index d0e3d26f61b23065e01e7f1218d47660d6d5aa91..805b9ce2fc2a6b8a92924fa71af0a97e4f2f31f4 100644 (file)
@@ -42,6 +42,7 @@
 #include "BL_ArmatureChannel.h"
 #include "KX_BlenderMaterial.h"
 #include "KX_CameraActuator.h"
+#include "KX_CharacterWrapper.h"
 #include "KX_ConstraintActuator.h"
 #include "KX_ConstraintWrapper.h"
 #include "KX_GameActuator.h"
@@ -189,6 +190,7 @@ void initPyTypes(void)
                PyType_Ready_Attr(dict, KX_BlenderMaterial, init_getset);
                PyType_Ready_Attr(dict, KX_Camera, init_getset);
                PyType_Ready_Attr(dict, KX_CameraActuator, init_getset);
+               PyType_Ready_Attr(dict, KX_CharacterWrapper, init_getset);
                PyType_Ready_Attr(dict, KX_ConstraintActuator, init_getset);
                PyType_Ready_Attr(dict, KX_ConstraintWrapper, init_getset);
                PyType_Ready_Attr(dict, KX_GameActuator, init_getset);
index 687fc116234f4841d243715eada917994e220064..486411d7e35d33c47ae0af7cb27d060ddaa1c058 100644 (file)
@@ -37,6 +37,7 @@ subject to the following restrictions:
 
 
 #include "PHY_IMotionState.h"
+#include "PHY_ICharacter.h"
 #include "KX_GameObject.h"
 #include "RAS_MeshObject.h"
 #include "RAS_Polygon.h"
@@ -266,6 +267,36 @@ public:
 };
 #endif //NEW_BULLET_VEHICLE_SUPPORT
 
+class CharacterWrapper : public PHY_ICharacter
+{
+private:
+       btKinematicCharacterController* m_controller;
+
+public:
+       CharacterWrapper(btKinematicCharacterController* cont)
+               : m_controller(cont)
+       {}
+
+       virtual void Jump()
+       {
+               m_controller->jump();
+       }
+
+       virtual bool OnGround()
+       {
+               return m_controller->onGround();
+       }
+
+       virtual float GetGravity()
+       {
+               return m_controller->getGravity();
+       }
+       virtual void SetGravity(float gravity)
+       {
+               m_controller->setGravity(gravity);
+       }
+};
+
 class CcdOverlapFilterCallBack : public btOverlapFilterCallback
 {
 private:
@@ -2285,6 +2316,15 @@ PHY_IVehicle*    CcdPhysicsEnvironment::getVehicleConstraint(int constraintId)
 #endif //NEW_BULLET_VEHICLE_SUPPORT
 
 
+PHY_ICharacter* CcdPhysicsEnvironment::getCharacterController(KX_GameObject *ob)
+{
+       CcdPhysicsController* controller = (CcdPhysicsController*)ob->GetPhysicsController()->GetUserData();
+       if (controller->GetCharacterController())
+               return new CharacterWrapper(controller->GetCharacterController());
+
+       return NULL;
+}
+
 int currentController = 0;
 int numController = 0;
 
index 350ecd2588a1a429ddf7b8dc6083d51d8167fa2b..18ce0550498ae7e82c88f4fd7ce62ea4bb70e7ae 100644 (file)
@@ -184,6 +184,8 @@ protected:
                        return 0;
                }
 #endif  /* NEW_BULLET_VEHICLE_SUPPORT */
+               // Character physics wrapper
+               virtual PHY_ICharacter* getCharacterController(class KX_GameObject* ob);
 
                btTypedConstraint*      getConstraintById(int constraintId);
 
index 70de9c255531725779c3deff6c7edda6e4db4961..233c4412d9e108ffff203e8ed6f61c9f0d67b2ad 100644 (file)
@@ -68,6 +68,12 @@ public:
 
                //complex constraint for vehicles
        virtual PHY_IVehicle*   getVehicleConstraint(int constraintId)
+       {
+               return 0;
+       }
+
+               // Character physics wrapper
+       virtual PHY_ICharacter* getCharacterController(class KX_GameObject* ob)
        {
                return 0;
        }
index ceb7a8ba548e8d132d2e3c93895a888811451e90..400e475f8a2ffa1c42fb1ef64682adcdbf3e4d43 100644 (file)
@@ -41,6 +41,7 @@ set(SRC
        PHY_IVehicle.cpp
 
        PHY_DynamicTypes.h
+       PHY_ICharacter.h
        PHY_IController.h
        PHY_IGraphicController.h
        PHY_IMotionState.h
diff --git a/source/gameengine/Physics/common/PHY_ICharacter.h b/source/gameengine/Physics/common/PHY_ICharacter.h
new file mode 100644 (file)
index 0000000..e2fc5e4
--- /dev/null
@@ -0,0 +1,30 @@
+
+/** \file PHY_ICharacter.h
+ *  \ingroup phys
+ */
+
+#ifndef __PHY_ICHARACTER_H__
+#define __PHY_ICHARACTER_H__
+
+//PHY_ICharacter provides a generic interface for "character" controllers
+
+#ifdef WITH_CXX_GUARDEDALLOC
+#include "MEM_guardedalloc.h"
+#endif
+
+class PHY_ICharacter
+{
+public:        
+
+       virtual void Jump()= 0;
+       virtual bool OnGround()= 0;
+
+       virtual float GetGravity()= 0;
+       virtual void SetGravity(float gravity)= 0;
+
+#ifdef WITH_CXX_GUARDEDALLOC
+       MEM_CXX_CLASS_ALLOC_FUNCS("GE:PHY_ICharacter")
+#endif
+};
+
+#endif //__PHY_ICHARACTER_H__
index 66ca037aa47eb16bf67418604ffea528574c8fa5..077d225903ca395a126f9bc2ddc8190ec049d151 100644 (file)
@@ -40,6 +40,7 @@
 #endif
 
 class PHY_IVehicle;
+class PHY_ICharacter;
 class RAS_MeshObject;
 class PHY_IPhysicsController;
 
@@ -156,6 +157,9 @@ class PHY_IPhysicsEnvironment
                //complex constraint for vehicles
                virtual PHY_IVehicle*   getVehicleConstraint(int constraintId) =0;
 
+               // Character physics wrapper
+               virtual PHY_ICharacter* getCharacterController(class KX_GameObject* ob) =0;
+
                virtual PHY_IPhysicsController* rayTest(PHY_IRayCastFilterCallback &filterCallback, float fromX,float fromY,float fromZ, float toX,float toY,float toZ)=0;
 
                //culling based on physical broad phase