BGE: This patch adds a character wrapper (similar to the already implemented vehicle wrapper) to control character physics options. Currently supported options are:

* 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).
This commit is contained in:
Mitchell Stokes 2012-11-04 20:56:02 +00:00
parent cc77001416
commit f840bd4a9f
13 changed files with 278 additions and 0 deletions

@ -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)

@ -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.

@ -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

@ -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

@ -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__

@ -33,12 +33,15 @@
#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,

@ -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);

@ -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;

@ -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);

@ -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;
}

@ -41,6 +41,7 @@ set(SRC
PHY_IVehicle.cpp
PHY_DynamicTypes.h
PHY_ICharacter.h
PHY_IController.h
PHY_IGraphicController.h
PHY_IMotionState.h

@ -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__

@ -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