Commits

Anonymous committed f638fcb

Removed physics module for now - it won't be ready to use early enough (if ever).

Comments (0)

Files changed (17)

 CRITICAL:
 =========
 * recheck and redesign X11 implementation for pygame.sdlext.scrap
-* complete physics collision and contacts and merge it back to the branch
 * make LayeredGroups class independent from sdl surfaces, where possible
 * check anything for possible integer/float overflows
 * use copy.copy and copy.deepcopy for consistent object copies
 * >8 bpp surfaces with palettes - it is supported (although it might be
   pointless) by SDL and so should we.
 
-* Fix issues with new and existing surface rendering (e.g. blending)
 * freetype: render to buffer buffer support (like new bytearray, but
   write to a buffer instead)
 * freetype: correct error messages (e.g. on trying to scale pcf fonts)

doc/src/modules.rst

    pygame2_font.rst
    pygame2_freetype_base.rst
    pygame2_mask.rst
-   pygame2_physics.rst
    pygame2_sdl.rst
    pygame2_sdl_audio.rst
    pygame2_sdl_cdrom.rst

doc/src/physics.xml

-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE module SYSTEM "api.dtd">
-
-<module name="pygame2.physics">
-  <short>TODO</short>
-  <desc>None</desc>
-
-  <example></example>
-  <class name="Body">
-    <constructor>TODO</constructor>
-    <desc></desc>
-    <example></example>
-    <attr name="angle_vel_damping">
-      <desc>None</desc>
-      <example></example>
-    </attr>
-    <attr name="angular_velocity">
-      <desc>None</desc>
-      <example></example>
-    </attr>
-    <attr name="force">
-      <desc>None</desc>
-      <example></example>
-    </attr>
-    <attr name="friction">
-      <desc>None</desc>
-      <example></example>
-    </attr>
-    <method name="get_points">
-      <call></call>
-      <desc></desc>
-      <example></example>
-    </method>
-    <attr name="lin_vel_damping">
-      <desc>None</desc>
-      <example></example>
-    </attr>
-    <attr name="mass">
-      <desc>None</desc>
-      <example></example>
-    </attr>
-    <attr name="position">
-      <desc>None</desc>
-      <example></example>
-    </attr>
-    <attr name="restitution">
-      <desc>None</desc>
-      <example></example>
-    </attr>
-    <attr name="rotation">
-      <desc>None</desc>
-      <example></example>
-    </attr>
-    <attr name="shape">
-      <desc>None</desc>
-      <example></example>
-    </attr>
-    <attr name="static">
-      <desc>None</desc>
-      <example></example>
-    </attr>
-    <attr name="torque">
-      <desc>None</desc>
-      <example></example>
-    </attr>
-    <attr name="velocity">
-      <desc>None</desc>
-      <example></example>
-    </attr>
-  </class>
-
-  <class name="Contact">
-    <constructor>TODO</constructor>
-    <desc></desc>
-    <example></example>
-  </class>
-
-  <class name="Joint">
-    <constructor>TODO</constructor>
-    <desc></desc>
-    <example></example>
-    <attr name="body1">
-      <desc>None</desc>
-      <example></example>
-    </attr>
-    <attr name="body2">
-      <desc>None</desc>
-      <example></example>
-    </attr>
-    <attr name="is_collide_connect">
-      <desc>None</desc>
-      <example></example>
-    </attr>
-    <method name="solve_constraints">
-      <call></call>
-      <desc></desc>
-      <example></example>
-    </method>
-  </class>
-
-  <class name="RectShape">
-    <constructor>TODO</constructor>
-    <desc></desc>
-    <example></example>
-    <attr name="rect">
-      <desc>None</desc>
-      <example></example>
-    </attr>
-  </class>
-
-  <class name="Shape">
-    <constructor>TODO</constructor>
-    <desc></desc>
-    <example></example>
-    <method name="collide">
-      <call></call>
-      <desc></desc>
-      <example></example>
-    </method>
-    <method name="get_aabbox">
-      <call></call>
-      <desc></desc>
-      <example></example>
-    </method>
-    <method name="get_vertices">
-      <call></call>
-      <desc></desc>
-      <example></example>
-    </method>
-    <attr name="inertia">
-      <desc>None</desc>
-      <example></example>
-    </attr>
-    <attr name="rotation">
-      <desc>None</desc>
-      <example></example>
-    </attr>
-    <method name="update">
-      <call></call>
-      <desc></desc>
-      <example></example>
-    </method>
-  </class>
-
-  <class name="World">
-    <constructor>TODO</constructor>
-    <desc></desc>
-    <example></example>
-    <method name="add_body">
-      <call></call>
-      <desc></desc>
-      <example></example>
-    </method>
-    <method name="add_joint">
-      <call></call>
-      <desc></desc>
-      <example></example>
-    </method>
-    <attr name="bodies">
-      <desc>None</desc>
-      <example></example>
-    </attr>
-    <attr name="damping">
-      <desc>None</desc>
-      <example></example>
-    </attr>
-    <attr name="gravity">
-      <desc>None</desc>
-      <example></example>
-    </attr>
-    <attr name="joints">
-      <desc>None</desc>
-      <example></example>
-    </attr>
-    <method name="remove_body">
-      <call></call>
-      <desc></desc>
-      <example></example>
-    </method>
-    <method name="remove_joint">
-      <call></call>
-      <desc></desc>
-      <example></example>
-    </method>
-    <method name="update">
-      <call></call>
-      <desc></desc>
-      <example></example>
-    </method>
-  </class>
-
-</module>
-
         docfile = "mask.xml",
         optional_dep = ['SDL']),
 
-    Module ("physics",
-        sources = [
-            "src/physics/aabbox.c",
-            "src/physics/body.c",
-            "src/physics/collision.c",
-            "src/physics/contact.c",
-            "src/physics/joint.c",
-            "src/physics/physicsmod.c",
-            "src/physics/rectshape.c",
-            "src/physics/shape.c",
-            "src/physics/vector.c",
-            "src/physics/world.c" ],
-
-        instheaders = [ "src/physics/pgphysics.h" ],
-        docfile = "physics.xml"),
-
     Module ("sdl.base",
         sources = [ "src/sdl/sdlmod.c" ],
         instheaders = [ "src/sdl/pgsdl.h" ],

src/physics/aabbox.c

-/* 
-  pygame physics - Pygame physics module
-
-  Copyright (C) 2008 Zhang Fan
-
-  This library is free software; you can redistribute it and/or
-  modify it under the terms of the GNU Library General Public
-  License as published by the Free Software Foundation; either
-  version 2 of the License, or (at your option) any later version.
-
-  This library is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  Library General Public License for more details.
-
-  You should have received a copy of the GNU Library General Public
-  License along with this library; if not, write to the Free
-  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#define PHYSICS_AABBOX_INTERNAL
-
-#include <float.h>
-#include "physicsmod.h"
-#include "pgphysics.h"
-
-AABBox
-AABBox_New (double left, double right, double bottom, double top)
-{
-    AABBox box;
-    box.left = left;
-    box.right = right;
-    box.bottom = bottom;
-    box.top = top;
-    return box;
-}
-
-void
-AABBox_Reset (AABBox* box)
-{
-    if (!box)
-    {
-        PyErr_SetString (PyExc_TypeError, "argument must not be NULL");
-        return;
-    }
-
-    box->top = DBL_MAX;
-    box->left = DBL_MAX;
-    box->bottom = -DBL_MAX;
-    box->right = -DBL_MAX;
-}
-
-void
-AABBox_ExpandTo (AABBox* box, PyVector2* p)
-{
-    if (!box || !p)
-    {
-        PyErr_SetString (PyExc_TypeError, "arguments must not be NULL");
-        return;
-    }
-    box->left = MIN (box->left, p->real);
-    box->top = MIN (box->top, p->imag);
-    box->right = MAX (box->right, p->real);
-    box->bottom = MAX (box->bottom, p->imag);
-}
-
-int
-AABBox_Overlaps (AABBox* boxA, AABBox* boxB, double eps)
-{
-    if (!boxA || !boxB)
-    {
-        PyErr_SetString (PyExc_TypeError, "arguments must not be NULL");
-        return 0;
-    }
-
-    /* TODO: add eps threshold */
-    if (((boxA->left >= boxB->left && boxA->left < boxB->right)  ||
-         (boxB->left >= boxA->left && boxB->left < boxA->right)) &&
-        ((boxA->top >= boxB->top && boxA->top < boxB->bottom) ||
-        (boxB->top >= boxA->top && boxB->top < boxA->bottom)))
-        return 1;
-    return 0;
-}
-
-int
-AABBox_Contains (AABBox* box, PyVector2* p, double eps)
-{
-    if (!box || !p)
-    {
-        PyErr_SetString (PyExc_TypeError, "arguments must not be NULL");
-        return 0;
-    }
-    return box->left - eps < p->real && p->real < box->right + eps
-        && box->bottom - eps > p->imag && p->imag > box->top + eps;
-}
-
-PyObject*
-AABBox_AsFRect (AABBox *box)
-{
-    if (!box)
-    {
-        PyErr_SetString (PyExc_TypeError, "argument must not be NULL");
-        return NULL;
-    }
-
-    return PyFRect_New (box->left, box->top, box->right - box->left,
-        box->bottom - box->top);
-}
-
-int
-AABBox_FromSequence (PyObject *seq, AABBox *box)
-{
-    double x, y, w, h;
-
-    if (!box)
-    {
-        PyErr_SetString (PyExc_TypeError, "box argument must not be NULL");
-        return 0;
-    }
-
-    if (!seq || !PySequence_Check (seq) || PySequence_Size (seq) < 4)
-    {
-        PyErr_SetString (PyExc_TypeError,
-            "argument must be a 4-value sequence");
-        return 0;
-    }
-
-    if (!DoubleFromSeqIndex (seq, 0, &x))
-        return 0;
-    if (!DoubleFromSeqIndex (seq, 1, &y))
-        return 0;
-    if (!DoubleFromSeqIndex (seq, 2, &w))
-        return 0;
-    if (!DoubleFromSeqIndex (seq, 3, &h))
-        return 0;
-    
-    box->top = y;
-    box->left = x;
-    box->bottom = y + h;
-    box->right = x + w;
-    return 1;
-}
-
-int
-AABBox_FromRect (PyObject *rect, AABBox *box)
-{
-    double t, l, b, r;
-
-    if (!box)
-    {
-        PyErr_SetString (PyExc_TypeError, "box argument must not be NULL");
-        return 0;
-    }
-    if (!rect)
-    {
-        PyErr_SetString (PyExc_TypeError,
-            "argument must be a Rect, FRect or 4-value sequence");
-        return 0;
-    }
-
-    if (PyRect_Check (rect))
-    {
-        l = ((PyRect*)rect)->x;
-        t = ((PyRect*)rect)->y;
-        b = ((PyRect*)rect)->h + t;
-        r = ((PyRect*)rect)->w + l;
-    }
-    else if (PyFRect_Check (rect))
-    {
-        l = ((PyFRect*)rect)->x;
-        t = ((PyFRect*)rect)->y;
-        b = ((PyFRect*)rect)->h + t;
-        r = ((PyFRect*)rect)->w + l;
-    }
-    else
-        return AABBox_FromSequence (rect, box);
-    
-    box->top = t;
-    box->left = l;
-    box->bottom = b;
-    box->right = r;
-    return 1;
-}
-
-void
-aabbox_export_capi (void **capi)
-{
-    capi[PHYSICS_AABBOX_FIRSTSLOT+0] = AABBox_New;
-    capi[PHYSICS_AABBOX_FIRSTSLOT+1] = AABBox_Reset;
-    capi[PHYSICS_AABBOX_FIRSTSLOT+2] = AABBox_ExpandTo;
-    capi[PHYSICS_AABBOX_FIRSTSLOT+3] = AABBox_Overlaps;
-    capi[PHYSICS_AABBOX_FIRSTSLOT+4] = AABBox_Contains;
-    capi[PHYSICS_AABBOX_FIRSTSLOT+5] = AABBox_AsFRect;
-    capi[PHYSICS_AABBOX_FIRSTSLOT+6] = AABBox_FromSequence;
-    capi[PHYSICS_AABBOX_FIRSTSLOT+7] = AABBox_FromRect;
-}

src/physics/body.c

-/*
-  pygame physics - Pygame physics module
-
-  Copyright (C) 2008 Zhang Fan
-
-  This library is free software; you can redistribute it and/or
-  modify it under the terms of the GNU Library General Public
-  License as published by the Free Software Foundation; either
-  version 2 of the License, or (at your option) any later version.
-
-  This library is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  Library General Public License for more details.
-
-  You should have received a copy of the GNU Library General Public
-  License along with this library; if not, write to the Free
-  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#define PHYSICS_BODY_INTERNAL
-
-#include "physicsmod.h"
-#include "pgphysics.h"
-
-static void _body_init_values (PyBody *body);
-static void _body_dealloc (PyBody *body);
-static PyObject* _body_new (PyTypeObject *type, PyObject *args,
-    PyObject *kwds);
-static int _body_init (PyBody *body, PyObject *args, PyObject *kwds);
-
-static PyObject* _body_getdict (PyBody *body, void *closure);
-static PyObject* _body_getmass (PyBody *body, void *closure);
-static int _body_setmass (PyBody *body, PyObject *value, void *closure);
-static PyObject* _body_getshape (PyBody *body, void *closure);
-static PyObject* _body_getrotation (PyBody *body, void *closure);
-static int _body_setrotation (PyBody *body, PyObject *value, void *closure);
-static PyObject* _body_gettorque (PyBody *body, void *closure);
-static int _body_settorque (PyBody *body, PyObject *value, void *closure);
-static PyObject* _body_getrestitution (PyBody *body, void *closure);
-static int _body_setrestitution (PyBody *body, PyObject *value, void *closure);
-static PyObject* _body_getfriction (PyBody *body, void *closure);
-static int _body_setfriction (PyBody *body, PyObject *value, void *closure);
-static PyObject* _body_getlinveldamping (PyBody *body, void *closure);
-static int _body_setlinveldamping (PyBody *body, PyObject *value,
-    void *closure);
-static PyObject* _body_getangleveldamping (PyBody *body, void *closure);
-static int _body_setangleveldamping (PyBody *body, PyObject *value,
-    void *closure);
-static PyObject* _body_getvelocity (PyBody *body, void *closure);
-static int _body_setvelocity (PyBody *body, PyObject *value, void *closure);
-static PyObject* _body_getanglevelocity (PyBody *body, void *closure);
-static int _body_setanglevelocity (PyBody *body, PyObject *value,
-    void *closure);
-static PyObject* _body_getposition (PyBody *body, void *closure);
-static int _body_setposition (PyBody *body, PyObject *value, void *closure);
-static PyObject* _body_getforce (PyBody *body, void *closure);
-static int _body_setforce (PyBody *body, PyObject *value, void *closure);
-static PyObject* _body_getstatic (PyBody *body, void *closure);
-static int _body_setstatic (PyBody *body, PyObject *value, void *closure);
-
-static PyObject *_body_getpoints (PyObject *self, PyObject *args);
-
-/**
- * Methods, which are bound to the PyBody type.
- */
-static PyMethodDef _body_methods[] =
-{
-    { "get_points", _body_getpoints, METH_VARARGS, NULL },
-    { NULL, NULL, 0, NULL }
-};
-
-/**
- * Getters/Setters
- */
-static PyGetSetDef _body_getsets[] =
-{
-    { "__dict__", (getter) _body_getdict, NULL, NULL, NULL },
-    { "mass", (getter) _body_getmass, (setter) _body_setmass, NULL, NULL },
-    { "shape", (getter) _body_getshape, NULL, NULL, NULL },
-    { "rotation", (getter) _body_getrotation, (setter) _body_setrotation,
-      NULL, NULL },
-    { "torque", (getter) _body_gettorque, (setter) _body_settorque, NULL,
-      NULL },
-    { "restitution", (getter) _body_getrestitution,
-      (setter) _body_setrestitution, NULL, NULL },
-    { "friction", (getter) _body_getfriction, (setter) _body_setfriction, NULL,
-      NULL },
-    { "lin_vel_damping", (getter) _body_getlinveldamping,
-      (setter) _body_setlinveldamping, NULL, NULL },
-    { "angle_vel_damping", (getter) _body_getangleveldamping,
-      (setter) _body_setangleveldamping, NULL, NULL },
-    { "velocity", (getter) _body_getvelocity, (setter) _body_setvelocity, NULL
-      , NULL },
-    { "angular_velocity", (getter) _body_getanglevelocity,
-      (setter) _body_setanglevelocity, NULL, NULL },
-    { "position", (getter) _body_getposition, (setter) _body_setposition, NULL,
-      NULL },
-    { "force", (getter) _body_getforce, (setter) _body_setforce, NULL, NULL },
-    { "static", (getter) _body_getstatic, (setter) _body_setstatic, NULL,
-      NULL },
-    { NULL, NULL, NULL, NULL, NULL }
-};
-
-
-PyTypeObject PyBody_Type =
-{
-    TYPE_HEAD(NULL, 0)
-    "physics.Body",             /* tp_name */
-    sizeof (PyBody),            /* tp_basicsize */
-    0,                          /* tp_itemsize */
-    (destructor) _body_dealloc, /* tp_dealloc */
-    0,                          /* tp_print */
-    0,                          /* tp_getattr */
-    0,                          /* tp_setattr */
-    0,                          /* tp_compare */
-    0,                          /* tp_repr */
-    0,                          /* tp_as_number */
-    0,                          /* tp_as_sequence */
-    0,                          /* tp_as_mapping */
-    0,                          /* tp_hash */
-    0,                          /* tp_call */
-    0,                          /* tp_str */
-    0,                          /* tp_getattro */
-    0,                          /* tp_setattro */
-    0,                          /* tp_as_buffer */
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
-    "",
-    0,                          /* tp_traverse */
-    0,                          /* tp_clear */
-    0,                          /* tp_richcompare */
-    0,                          /* tp_weaklistoffset */
-    0,                          /* tp_iter */
-    0,                          /* tp_iternext */
-    _body_methods,              /* tp_methods */
-    0,                          /* tp_members */
-    _body_getsets,              /* tp_getset */
-    0,                          /* tp_base */
-    0,                          /* tp_dict */
-    0,                          /* tp_descr_get */
-    0,                          /* tp_descr_set */
-    offsetof (PyBody, dict),    /* tp_dictoffset */
-    (initproc)_body_init,       /* tp_init */
-    0,                          /* tp_alloc */
-    _body_new,                  /* tp_new */
-    0,                          /* tp_free */
-    0,                          /* tp_is_gc */
-    0,                          /* tp_bases */
-    0,                          /* tp_mro */
-    0,                          /* tp_cache */
-    0,                          /* tp_subclasses */
-    0,                          /* tp_weaklist */
-    0,                          /* tp_del */
-#if PY_VERSION_HEX >= 0x02060000
-    0                           /* tp_version_tag */
-#endif
-};
-
-static void
-_body_init_values (PyBody *body)
-{
-    body->dict = NULL;
-    body->shape = NULL;
-    body->mass = 1.0;
-    body->isstatic = 0;
-    body->rotation = 0.0;
-    PyVector2_Set (body->position, 0.0, 0.0);
-    PyVector2_Set (body->impulse, 0.0, 0.0);
-    PyVector2_Set (body->force, 0.0, 0.0);
-    body->torque = 0.0;
-    PyVector2_Set (body->linear_velocity, 0.0, 0.0);
-    body->angle_velocity = 0.0;
-    body->restitution = 1.0;
-    body->friction = 0.0;
-    body->linear_vel_damping = 0.0;
-    body->angle_vel_damping = 0.06;
-    PyVector2_Set (body->bias_lv, 0.0, 0.0);    
-    body->bias_w = 0.0;
-}
-
-static void
-_body_dealloc (PyBody *body)
-{
-    Py_XDECREF (body->shape);
-    ((PyObject*)body)->ob_type->tp_free ((PyObject*)body);
-}
-
-static PyObject*
-_body_new (PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
-    PyBody *body = (PyBody*) type->tp_alloc (type, 0);
-    if (!body)
-        return NULL;
-    _body_init_values (body);
-    return (PyObject*) body;
-}
-
-static int
-_body_init (PyBody *body, PyObject *args, PyObject *kwds)
-{
-    PyObject *shape;
-
-    if (!PyArg_ParseTuple (args, "O", &shape))
-        return -1;
-
-    if (!shape || !PyShape_Check (shape))
-    {
-        PyErr_SetString (PyExc_TypeError, "shape must be a Shape");
-        return -1;
-    }
-
-    Py_INCREF (shape);
-    body->shape = shape;
-
-    if (!PyShape_Update_FAST ((PyShape*) body->shape, body))
-    {
-        /* An error occured. */
-        Py_DECREF (shape);
-        return -1;
-    }
-
-    return 0;
-}
-
-/* Getters/Setters */
-static PyObject*
-_body_getdict (PyBody *body, void *closure)
-{
-    if (!body->dict)
-    {
-        body->dict = PyDict_New ();
-        if (!body->dict)
-            return NULL;
-    }
-    Py_INCREF (body->dict);
-    return body->dict;
-}
-
-static PyObject*
-_body_getmass (PyBody *body, void *closure)
-{
-    return PyFloat_FromDouble (body->mass);
-}
-
-static int
-_body_setmass (PyBody *body, PyObject *value, void *closure)
-{
-    double mass;
-
-    if (!DoubleFromObj (value, &mass))
-        return -1;
-    if (mass <= 0)
-    {
-        PyErr_SetString (PyExc_ValueError, "mass must not be smaller than 0");
-        return -1;
-    }
-    body->mass = mass;
-
-    if (body->shape)
-    {
-        if (!PyShape_Update_FAST ((PyShape*) body->shape, body))
-            return -1;
-    }
-    return 0;
-}
-
-static PyObject*
-_body_getshape (PyBody *body, void *closure)
-{
-    if (!body->shape)
-        Py_RETURN_NONE;
-    Py_INCREF (body->shape);
-    return body->shape;
-}
-
-static PyObject*
-_body_getrotation (PyBody *body, void *closure)
-{
-    return PyFloat_FromDouble (RAD2DEG (body->rotation));
-}
-
-static int
-_body_setrotation (PyBody *body, PyObject *value, void *closure)
-{
-    double rotation;
-    if (!DoubleFromObj (value, &rotation))
-        return -1;
-    body->rotation = DEG2RAD (rotation);
-    return 0;
-}
-
-static PyObject*
-_body_gettorque (PyBody *body, void *closure)
-{
-    return PyFloat_FromDouble (body->torque);
-}
-
-static int
-_body_settorque (PyBody *body, PyObject *value, void *closure)
-{
-    double torque;
-    if (!DoubleFromObj (value, &torque))
-        return -1;
-    body->torque = torque;
-    return 0;
-}
-
-static PyObject*
-_body_getrestitution (PyBody *body, void *closure)
-{
-    return PyFloat_FromDouble (body->restitution);
-}
-
-static int
-_body_setrestitution (PyBody *body, PyObject *value, void *closure)
-{
-    double restitution;
-    if (!DoubleFromObj (value, &restitution))
-        return -1;
-    if (restitution < 0 || restitution > 1)
-    {
-        PyErr_SetString(PyExc_ValueError,
-            "restitution must be in the range [0,1]");
-        return -1;
-    }
-    body->restitution = restitution;
-    return 0;
-}
-
-static PyObject*
-_body_getfriction (PyBody *body, void *closure)
-{
-    return PyFloat_FromDouble (body->friction);
-}
-
-static int
-_body_setfriction (PyBody *body, PyObject *value, void *closure)
-{
-    double friction;
-    if (!DoubleFromObj (value, &friction))
-        return -1;
-    if (friction < 0)
-    {
-        PyErr_SetString (PyExc_ValueError, "friction must not be negative");
-        return -1;
-    }
-    body->friction = friction;
-    return 0;
-}
-
-static PyObject*
-_body_getlinveldamping (PyBody *body, void *closure)
-{
-    return PyFloat_FromDouble (body->linear_vel_damping);
-}
-
-static int
-_body_setlinveldamping (PyBody *body, PyObject *value, void *closure)
-{
-    double damping;
-    if (!DoubleFromObj (value, &damping))
-        return -1;
-    if (damping < 0 || damping > 1)
-    {
-        PyErr_SetString(PyExc_ValueError,
-            "linear_vel_damping must be in the range [0,1]");
-        return -1;
-    }
-    body->linear_vel_damping = damping;
-    return 0;
-}
-
-static PyObject*
-_body_getangleveldamping (PyBody *body, void *closure)
-{
-    return PyFloat_FromDouble (body->angle_vel_damping);
-}
-
-static int
-_body_setangleveldamping (PyBody *body, PyObject *value, void *closure)
-{
-    double damping;
-    if (!DoubleFromObj (value, &damping))
-        return -1;
-    if (damping < 0 || damping > 1)
-    {
-        PyErr_SetString(PyExc_ValueError,
-            "angle_vel_damping must be in the range [0,1]");
-        return -1;
-    }
-    body->angle_vel_damping = damping;
-    return 0;
-}
-
-static PyObject*
-_body_getvelocity (PyBody *body, void *closure)
-{
-    return Py_BuildValue ("(ff)", body->linear_velocity.real,
-        body->linear_velocity.imag);
-}
-
-static int
-_body_setvelocity (PyBody *body, PyObject *value, void *closure)
-{
-    double real, imag;
-
-    if (!PySequence_Check (value) || PySequence_Size (value) != 2)
-    {
-        PyErr_SetString (PyExc_TypeError, "velocity must be a x, y sequence");
-        return -1;
-    }
-    if (!DoubleFromSeqIndex (value, 0, &real))
-        return -1;
-    if (!DoubleFromSeqIndex (value, 1, &imag))
-        return -1;
-    body->linear_velocity.real = real;
-    body->linear_velocity.imag = imag;
-    return 0;
-}
-
-static PyObject*
-_body_getanglevelocity (PyBody *body, void *closure)
-{
-    return PyFloat_FromDouble (RAD2DEG(body->angle_velocity));
-}
-
-static int
-_body_setanglevelocity (PyBody *body, PyObject *value, void *closure)
-{
-    double velocity;
-    if (!DoubleFromObj (value, &velocity))
-        return -1;
-    body->angle_velocity = DEG2RAD (velocity);
-    return 0;
-}
-
-static PyObject*
-_body_getposition (PyBody *body, void *closure)
-{
-    return Py_BuildValue ("(ff)", body->position.real, body->position.imag);
-}
-
-static int
-_body_setposition (PyBody *body, PyObject *value, void *closure)
-{
-    double real, imag;
-
-    if (!PySequence_Check (value) || PySequence_Size (value) != 2)
-    {
-        PyErr_SetString (PyExc_TypeError, "position must be a x, y sequence");
-        return -1;
-    }
-    if (!DoubleFromSeqIndex (value, 0, &real))
-        return -1;
-    if (!DoubleFromSeqIndex (value, 1, &imag))
-        return -1;
-    body->position.real = real;
-    body->position.imag = imag;
-    return 0;
-}
-
-static PyObject*
-_body_getforce (PyBody *body, void *closure)
-{
-    return Py_BuildValue ("(ff)", body->force.real, body->force.imag);
-}
-
-static int
-_body_setforce (PyBody *body, PyObject *value, void *closure)
-{
-    double real, imag;
-
-    if (!PySequence_Check(value) || PySequence_Size (value) != 2)
-    {
-        PyErr_SetString (PyExc_TypeError, "force must be a x, y sequence");
-        return -1;
-    }
-    if (!DoubleFromSeqIndex (value, 0, &real))
-        return -1;
-    if (!DoubleFromSeqIndex (value, 1, &imag))
-        return -1;
-    body->force.real = real;
-    body->force.imag = imag;
-    return 0;
-}
-
-static PyObject*
-_body_getstatic (PyBody *body, void *closure)
-{
-    if (body->isstatic)
-        Py_RETURN_TRUE;
-    Py_RETURN_FALSE;
-}
-
-static int
-_body_setstatic (PyBody *body, PyObject *value, void *closure)
-{
-    int isstatic = PyObject_IsTrue (value);
-    if (isstatic == -1)
-        return -1;
-    body->isstatic = isstatic;
-    return 0;
-}
-
-/* Methods */
-static PyObject*
-_body_getpoints (PyObject *self, PyObject *args)
-{
-    PyBody* body = (PyBody*)self;
-    Py_ssize_t i, count;
-    PyObject* list;
-    PyVector2 *vertices;
-    PyVector2 golVertex;
-    PyObject* tuple;
-
-    if (!body->shape)
-    {
-        Py_RETURN_NONE;
-    }
-
-    vertices = PyShape_GetVertices_FAST ((PyShape*)body->shape, &count);
-    if (!vertices)
-    {
-        /* TODO: does get_vertices() set the error? */
-        return NULL;
-    }
-
-    list = PyList_New (count);
-    if (!list)
-    {
-        PyMem_Free (vertices);
-        return NULL;
-    }
-
-    for (i = 0; i < count; i++)
-    {
-        PyBody_GetGlobalPos (body, vertices[i], golVertex);
-        tuple = PyVector2_AsTuple (golVertex);
-        if (!tuple)
-        {
-            Py_DECREF (list);
-            PyMem_Free (vertices);
-            return NULL;
-        }
-        PyList_SET_ITEM (list, i, tuple);
-    }
-    PyMem_Free (vertices);
-    return list;
-}
-
-/* C API */
-PyObject*
-PyBody_New (PyObject *shape)
-{
-    PyBody* body = (PyBody*) PyBody_Type.tp_new (&PyBody_Type, NULL, NULL);
-    if (!body)
-        return NULL;
-
-    if (!shape || !PyShape_Check (shape))
-    {
-        PyErr_SetString (PyExc_TypeError, "shape must be a Shape");
-        Py_DECREF (body);
-        return NULL;
-    }
-
-    Py_INCREF (shape);
-    body->shape = shape;
-    if (!PyShape_Update_FAST ((PyShape*) body->shape, body))
-    {
-        /* An error occured. */
-        Py_DECREF (body);
-        return NULL;
-    }
-
-    return (PyObject*) body;
-}
-
-PyObject*
-PyBody_CheckCollision (PyObject *body1, PyObject *body2)
-{
-    if (!body1 || !body2 || !PyBody_Check (body1) || !PyBody_Check (body2))
-    {
-        PyErr_SetString (PyExc_TypeError,
-            "body arguments must be Body objects");
-        return NULL;
-    }
-    if (!((PyBody*)body1)->shape || !((PyBody*)body2)->shape)
-    {
-        PyErr_SetString (PyExc_ValueError,
-            "body arguments must have shapes assigned");
-        return NULL;
-    }
-    return PyBody_CheckCollision_FAST ((PyBody*)body1, (PyBody*)body2);
-}
-
-PyObject*
-PyBody_CheckCollision_FAST (PyBody *body1, PyBody *body2)
-{
-    PyObject *retval = NULL;
-    PyBody *refbody, *incbody;
-    PyVector2 refr, incr;
-    PyContact *contact;
-    double tmp1, tmp2, refinertia, incinertia;
-    int refid;
-    Py_ssize_t i;
-    
-    PyErr_Clear ();
-
-    /* Assume, the objects are consistent! */
-    retval = PyShape_Collide_FAST ((PyShape*)body1->shape, body1->position,
-        body1->rotation, (PyShape*)body2->shape, body2->position,
-        body2->rotation, &refid);
-    
-    if (!retval) /* Error */
-        return NULL;
-    if (retval == Py_None)
-        return retval;
-    
-    refbody = (refid == 0) ? body1 : body2;
-    incbody = (refid == 0) ? body2 : body1;
-    refinertia = (refid == 0) ? ((PyShape*)body1->shape)->inertia :
-        ((PyShape*)body2->shape)->inertia;
-    incinertia = (refid == 0) ? ((PyShape*)body2->shape)->inertia :
-        ((PyShape*)body1->shape)->inertia;
-    for (i = 0; i < PyList_GET_SIZE (retval); i++)
-    {
-        /* Update the empty contacts. */
-        contact = (PyContact*) PyList_GET_ITEM (retval, i);
-        contact->joint.body1 = (PyObject*) body1;
-        contact->joint.body2 = (PyObject*) body2;
-        
-        /* precompute KFactor */
-        refr = c_diff (contact->position, refbody->position);
-        incr = c_diff (contact->position, incbody->position);
-        tmp1 = PyVector2_Dot (PyVector2_fCross (PyVector2_Cross (refr,
-            contact->normal), refr), contact->normal) / refinertia;
-        tmp2 = PyVector2_Dot (PyVector2_fCross (PyVector2_Cross (incr,
-            contact->normal), incr), contact->normal) / incinertia;
-        contact->kfactor = 1 / refbody->mass + 1 / incbody->mass + tmp1 + tmp2;
-    }
-    return retval;
-}
-
-PyObject*
-PyBody_GetPoints (PyObject *body)
-{
-    if (!body || !PyBody_Check (body))
-    {
-        PyErr_SetString (PyExc_TypeError, "argument must be a Body");
-        return NULL;
-    }
-    return _body_getpoints (body, NULL);
-}
-
-void
-body_export_capi (void **capi)
-{
-    capi[PHYSICS_BODY_FIRSTSLOT] = &PyBody_Type;
-    capi[PHYSICS_BODY_FIRSTSLOT + 1] = PyBody_New;
-    capi[PHYSICS_BODY_FIRSTSLOT + 2] = PyBody_CheckCollision;
-    capi[PHYSICS_BODY_FIRSTSLOT + 3] = PyBody_CheckCollision_FAST;
-    capi[PHYSICS_BODY_FIRSTSLOT + 4] = PyBody_GetPoints;
-}

src/physics/collision.c

-#define PHYSICS_COLLISION_INTERNAL
-
-#include "physicsmod.h"
-#include "pgphysics.h"
-
-#define CLIP_LB(p,q,u1,u2,ret)         \
-    if (IS_NEAR_ZERO(p))               \
-        ret = (q < 0) ? 0 : 1;         \
-    else                               \
-    {                                  \
-        if (p < 0)                     \
-            u1 = MAX (u1, q / p);      \
-        else                           \
-            u2 = MIN (u2, q / p);      \
-        ret = 1;                       \
-    }
-
-typedef enum
-{
-    CF_LEFT,
-    CF_BOTTOM,
-    CF_RIGHT,
-    CF_TOP
-} CollisionFace;
-
-#define MAX_CONTACTS 16
-typedef struct
-{
-    PyVector2 normal;
-    PyVector2 contacts[MAX_CONTACTS];
-    int       contact_size;
-    int       refno;
-    double    min_depth;
-} _Collision;
-    
-static int _clip_test (AABBox *box, PyVector2 *vertices, int count,
-    _Collision *collision);
-static void _sat_collision (PyVector2 *pos1, double rot1, PyVector2 *pos2,
-    double rot2, AABBox *box1, AABBox *box2, _Collision *collision);
-
-static PyObject* _collide_rect_rect (PyShape* shape1, PyVector2 pos1,
-    double rot1, PyShape *shape2, PyVector2 pos2, double rot2, int *refid);
-static PyObject* _collide_rect_circle (PyShape* shape1, PyVector2 pos1,
-    double rot1, PyShape *shape2, PyVector2 pos2, double rot2, int *refid);
-static PyObject* _collide_circle_circle (PyShape* shape1, PyVector2 pos1,
-    double rot1, PyShape *shape2, PyVector2 pos2, double rot2, int *refid);
-
-static int
-_clip_test (AABBox *box, PyVector2 *vertices, int count, _Collision *collision)
-{
-    int i, i1, apart = 1, ret;
-    PyVector2 dp;
-    double u1, u2;
-    collision->contact_size = 0;
-    
-    for (i = 0; i < count; i++)
-    {
-        i1 = (i + 1) % count;
-        u1 = 0.f;
-        u2 = 1.f;
-        dp = c_diff (vertices[i], vertices[i1]);
-        
-        CLIP_LB (dp.real, vertices[i].real - box->left, u1, u2, ret);
-        if (!ret)
-            continue;
-        CLIP_LB (-dp.real, box->right - vertices[i].real, u1, u2, ret);
-        if (!ret)
-            continue;
-        CLIP_LB (dp.imag, vertices[i].imag - box->bottom, u1, u2, ret);
-        if (!ret)
-            continue;
-        CLIP_LB (-dp.imag, box->top - vertices[i].imag, u1, u2, ret);
-        if (!ret)
-            continue;
-        
-        if (u1 > u2)
-            continue;
-        
-        apart = 0;
-        if (u1 == 0.f)
-            collision->contacts[collision->contact_size++] = vertices[i];
-        else
-            collision->contacts[collision->contact_size++] =
-                c_sum (vertices[i], PyVector2_MultiplyWithReal (dp, u1));
-        if (u2 == 1.f)
-            collision->contacts[collision->contact_size++] = vertices[i1];
-        else
-            collision->contacts[collision->contact_size++] =
-                c_sum (vertices[i], PyVector2_MultiplyWithReal (dp, u2));
-    }
-    return !apart;
-}
-
-static void
-_sat_collision (PyVector2 *pos1, double rot1, PyVector2 *pos2, double rot2,
-    AABBox *box1, AABBox *box2, _Collision *collision)
-{
-    int i, k, size, face_id[2]; 
-    double deps[4], min_dep[2];
-    PyVector2 conts[2][MAX_CONTACTS];
-    AABBox* box[2];
-    PyVector2 ppos[2], incpos[2];
-    double prot[2], incrot[2];
-    
-    /**
-     * pos1 = body1 pos
-     * pos2 = body2 pos
-     */
-     
-    /*
-     * Here conts[0][i] represent the contacts calculated in selfBody's local
-     * coordinate.
-     * conts[1][i] represent the contacts translated to incBody's local
-     *  coordinate.
-     * then we can rightly get the two minimal depth.
-     *
-     * The key is whether we appoint which one to be the reference body, the
-     * resuting contacts
-     * are equivalent only except for different coordinate. but while
-     * calculating the penetrating
-     * depth to all the candidate collision face, we must make sure all the
-     * contacts are in the
-     * same local coordinate at one time.
-     */
-    for (i = 0; i < collision->contact_size; ++i)
-    {
-        conts[0][i] = collision->contacts[i];
-        /* TODO: Maybe invert pos1/pos2 */
-        conts[1][i] = PyVector2_Transform (conts[0][i], *pos1, rot1,
-            *pos2, rot2);
-    }
-    
-    box[0] = box1;
-    box[1] = box2;
-    ppos[0] = incpos[1] = *pos1;
-    prot[0] = incrot[1] = rot1;
-    ppos[1] = incpos[0] = *pos2;
-    prot[1] = incrot[0] = rot2;
-
-    /*
-     * Now we appoint selfBody to be the reference body and incBody
-     * to be the incident body for computing min_dep[0]. And vice versa for
-     * min_dep[1].
-     *
-     * Since each computation happens in reference body's local coordinate,
-     * it's very simple to get the minimal penetrating depth.
-     */
-    for (k = 0; k <= 1; ++k)
-    {
-        memset (deps, 0, sizeof (deps));
-        for (i = 0; i < collision->contact_size; ++i)
-        {
-            deps[CF_LEFT] += fabs (conts[k][i].real - box[k]->left);
-            deps[CF_RIGHT] += fabs (box[k]->right - conts[k][i].real);
-            deps[CF_BOTTOM] += fabs (conts[k][i].imag - box[k]->bottom);
-            deps[CF_TOP] += fabs (box[k]->top - conts[k][i].imag);
-        }
-        
-        min_dep[k] = DBL_MAX;
-        for (i = CF_LEFT; i <= CF_TOP; ++i)
-        {
-            if (min_dep[k] > deps[i])
-            {
-                face_id[k] = i;
-                min_dep[k] = deps[i];
-            }
-        }
-    }
-    
-    /*
-     * If min_dep[0] < min_dep[1], we choose selfBody to be the right reference
-     * body and incBody to be the incident one. And vice versa.
-     */
-    collision->refno = k = min_dep[0] < min_dep[1] ? 0 : 1;
-    collision->min_depth = min_dep[k];
-    size = collision->contact_size;
-    collision->contact_size = 0;
-    
-    /*
-     * Get collision normal according to the collision face
-     * and delete the contacts on the collision face.
-     */
-    switch (face_id[k])
-    {
-    case CF_LEFT:
-        PyVector2_Set (collision->normal, -1, 0);
-        for (i = 0; i < size; ++i)
-            if (!PyMath_IsNearEqual(conts[k][i].real, box[k]->left))
-                collision->contacts[collision->contact_size++] = conts[k][i];
-        break;
-    case CF_RIGHT:
-        PyVector2_Set (collision->normal, 1, 0);
-        for(i = 0; i < size; ++i)
-            if(!PyMath_IsNearEqual(conts[k][i].real, box[k]->right))
-                collision->contacts[collision->contact_size++] = conts[k][i];
-        break;
-    case CF_BOTTOM:
-        PyVector2_Set (collision->normal, 0, -1);
-        for (i = 0; i < size; ++i)
-            if (!PyMath_IsNearEqual(conts[k][i].imag, box[k]->bottom))
-                collision->contacts[collision->contact_size++] = conts[k][i];
-        break;
-    case CF_TOP:
-        PyVector2_Set (collision->normal, 0, 1);
-        for (i = 0; i < size; ++i)
-            if (!PyMath_IsNearEqual(conts[k][i].imag, box[k]->top))
-                collision->contacts[collision->contact_size++] = conts[k][i];
-         break;
-    default:
-        assert (0);
-        break;
-     }
-
-    /*
-     * We are nearly reaching the destination except for three things:
-     *
-     * First, collsion normal and contact are in reference body's local
-     * coordinate.
-     * We must translate them to the global coordinate for easy usage.
-     *
-     * Second, In the impulse-based collsion reaction formula, we find there
-     * is a small
-     * part can be precomputed to speed up the total computation. that's so
-     * called kFactor.
-     * For more information of that you can read Helmut Garstenauer's thesis.
-     */
-    PyVector2_Rotate (&(collision->normal), prot[k]);
-    for (i = 0; i < collision->contact_size; ++i)
-    {
-        PyVector2_Rotate (&(collision->contacts[i]), prot[k]);
-        collision->contacts[i] = c_sum (collision->contacts[i], ppos[k]);
-    }
-}
-
-/**
- * The shapes must contains absolute positional values.
- * Returns a list of contacts.
- */
-static PyObject*
-_collide_rect_rect (PyShape* shape1, PyVector2 pos1, double rot1,
-    PyShape *shape2, PyVector2 pos2, double rot2, int *refid)
-{
-    AABBox box1, box2;
-    PyVector2 *vertices1, *vertices2;
-    PyVector2 inpos1[4], inpos2[4];
-    int count1, count2, i;
-    PyObject *retval;
-    PyContact *contact;
-    _Collision collision;
-    PyRectShape *rsh1 = (PyRectShape*) shape1;
-    PyRectShape *rsh2 = (PyRectShape*) shape2;
-
-    if (!shape1 || !shape2)
-        return NULL;
-
-    collision.normal.real = collision.normal.imag = 0;
-    
-    if (!PyShape_GetAABBox_FAST (shape1, &box1) ||
-        !PyShape_GetAABBox_FAST (shape2, &box2))
-        return NULL;
-
-    if (!AABBox_Overlaps (&box1, &box2, OVERLAP_ZERO))
-    {
-        Py_RETURN_NONE; /* No collision at all. */
-    }
-
-    /* The boxes overlap, do a fine-grained check. */
-    vertices1 = PyShape_GetVertices_FAST (shape1, &count1);
-    vertices2 = PyShape_GetVertices_FAST (shape2, &count2);
-    if (!vertices1 || !vertices2)
-    {
-        retval = NULL;
-        goto back;
-    }
-
-    /* TODO: problem here! */
-    PyVector2_TransformMultiple (vertices1, inpos1, count1, pos2, rot2, pos1,
-        rot1);
-    PyVector2_TransformMultiple (vertices2, inpos2, count2, pos1, rot1, pos2,
-        rot2);
-
-/*
-    for (i = 0; i < count1; i++)
-    {
-        printf ("vertices1, %d: %.3f, %.3f\n", i, inpos1[i].real,
-            inpos1[i].imag);
-    }
-    puts ("---");
-    for (i = 0; i < count2; i++)
-    {
-        printf ("vertices2, %d: %.3f, %.3f\n", i, vertices2[i].real,
-            vertices2[i].imag);
-    }
-    puts ("---");
-*/
-
-    if (!_clip_test (&box1, inpos2, count2, &collision))
-    {
-        retval = Py_None;
-        Py_INCREF (retval);
-        goto back;
-    }
-
-    puts ("DSA");
-    if (AABBox_Contains (&box2, &vertices1[0], 0.f))
-        collision.contacts[collision.contact_size++] = rsh1->bottomleft;
-    if (AABBox_Contains (&box2, &vertices1[1], 0.f))
-        collision.contacts[collision.contact_size++] = rsh1->bottomright;
-    if (AABBox_Contains (&box2, &vertices1[2], 0.f))
-        collision.contacts[collision.contact_size++] = rsh1->topright;
-    if (AABBox_Contains (&box2, &vertices1[3], 0.f))
-        collision.contacts[collision.contact_size++] = rsh1->topleft;
-
-    _sat_collision (&pos1, rot1, &pos2, rot2, &box1, &box2, &collision);
-
-    /*
-     *
-     */
-    retval = PyList_New (0);
-    if (!retval)
-        goto back;
-
-    for (i = 0; i < collision.contact_size; ++i)
-    {
-        contact = (PyContact*) PyContact_New ();
-        if (!contact)
-        {
-            Py_DECREF (retval);
-            retval = NULL;
-            goto back;
-        }
-        
-        contact->position = collision.contacts[i];
-        contact->normal = collision.normal;
-        PyVector2_Set (contact->acc_moment, 0, 0);
-        PyVector2_Set (contact->split_acc_moment, 0, 0);
-        contact->weight = collision.contact_size;
-        contact->depth = collision.min_depth;
-        
-        if (PyList_Append (retval, (PyObject*)contact) == -1)
-        {
-            Py_DECREF (retval);
-            retval = NULL;
-            goto back;
-        }
-        Py_DECREF ((PyObject*)contact);
-    }
-    
-    *refid = collision.refno;
-    
-back:
-    if (vertices1)
-        PyMem_Free (vertices1);
-    if (vertices2)
-        PyMem_Free (vertices2);
-    return retval;
-}
-
-static PyObject*
-_collide_rect_circle (PyShape* shape1, PyVector2 pos1, double rot1,
-    PyShape *shape2, PyVector2 pos2, double rot2, int *refid)
-{
-    return NULL;
-}
-
-static PyObject*
-_collide_circle_circle (PyShape* shape1, PyVector2 pos1, double rot1,
-    PyShape *shape2, PyVector2 pos2, double rot2, int *refid)
-{
-    return NULL;
-}
-
-collisionfunc
-PyCollision_GetCollisionFunc (ShapeType t1, ShapeType t2, int *swap)
-{
-    if (!swap)
-    {
-        PyErr_SetString (PyExc_RuntimeError, "swap argument missing");
-        return NULL;
-    }
-
-    swap = 0;
-    switch (t1)
-    {
-        case ST_RECT:
-            switch (t2)
-            {
-                case ST_RECT:
-                    return _collide_rect_rect;
-                case ST_CIRCLE:
-                    return _collide_rect_circle;
-                default:
-                    break;
-            }
-            break;
-        case ST_CIRCLE:
-            switch (t2)
-            {
-                case ST_RECT:
-                    *swap = 1;
-                    return _collide_rect_circle;
-                case ST_CIRCLE:
-                    return _collide_circle_circle;
-                default:
-                    break;
-            }
-            break;
-        default:
-            break;
-    }
-    return NULL;
-}

src/physics/contact.c

-/*
-  pygame physics - Pygame physics module
-
-  Copyright (C) 2008 Zhang Fan
-
-  This library is free software; you can redistribute it and/or
-  modify it under the terms of the GNU Library General Public
-  License as published by the Free Software Foundation; either
-  version 2 of the License, or (at your option) any later version.
-
-  This library is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  Library General Public License for more details.
-
-  You should have received a copy of the GNU Library General Public
-  License along with this library; if not, write to the Free
-  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#define PHYSICS_CONTACT_INTERNAL
-
-#include "physicsmod.h"
-#include "pgphysics.h"
-
-static void  _solve_constraints (PyJoint *joint, double steptime);
-
-static void _contact_dealloc (PyContact *contact);
-static PyObject* _contact_new (PyTypeObject *type, PyObject *args,
-    PyObject *kwds);
-static int _contact_init (PyContact *self, PyObject *args, PyObject *kwds);
-
-/**
- * Methods, which are bound to the PyContact type.
- */
-static PyMethodDef _contact_methods[] =
-{
-    { NULL, NULL, 0, NULL }
-};
-
-/**
- * Getters/Setters
- */
-static PyGetSetDef _contact_getsets[] =
-{
-    { NULL, NULL, NULL, NULL, NULL }
-};
-
-PyTypeObject PyContact_Type =
-{
-    TYPE_HEAD(NULL, 0)
-    "physics.Contact",          /* tp_name */
-    sizeof (PyContact),         /* tp_basicsize */
-    0,                          /* tp_itemsize */
-    (destructor) _contact_dealloc,/* tp_dealloc */
-    0,                          /* tp_print */
-    0,                          /* tp_getattr */
-    0,                          /* tp_setattr */
-    0,                          /* tp_compare */
-    0,                          /* tp_repr */
-    0,                          /* tp_as_number */
-    0,                          /* tp_as_sequence */
-    0,                          /* tp_as_mapping */
-    0,                          /* tp_hash */
-    0,                          /* tp_call */
-    0,                          /* tp_str */
-    0,                          /* tp_getattro */
-    0,                          /* tp_setattro */
-    0,                          /* tp_as_buffer */
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
-    "",
-    0,                          /* tp_traverse */
-    0,                          /* tp_clear */
-    0,                          /* tp_richcompare */
-    0,                          /* tp_weaklistoffset */
-    0,                          /* tp_iter */
-    0,                          /* tp_iternext */
-    _contact_methods,           /* tp_methods */
-    0,                          /* tp_members */
-    _contact_getsets,           /* tp_getset */
-    0,                          /* tp_base */
-    0,                          /* tp_dict */
-    0,                          /* tp_descr_get */
-    0,                          /* tp_descr_set */
-    0,                          /* tp_dictoffset */
-    (initproc)_contact_init,    /* tp_init */
-    0,                          /* tp_alloc */
-    _contact_new,               /* tp_new */
-    0,                          /* tp_free */
-    0,                          /* tp_is_gc */
-    0,                          /* tp_bases */
-    0,                          /* tp_mro */
-    0,                          /* tp_cache */
-    0,                          /* tp_subclasses */
-    0,                          /* tp_weaklist */
-    0,                          /* tp_del */
-#if PY_VERSION_HEX >= 0x02060000
-    0                           /* tp_version_tag */
-#endif
-};
-
-static void
-_solve_constraints (PyJoint *joint, double steptime)
-{
-    PyContact *contact = (PyContact*) joint;
-    PyBody *refbody, *incbody;
-    PyVector2 moment, bm, refr, incidr;
-    PyShape *refshape, *incshape;
-
-    if (!contact)
-        return;
-    
-    refbody = (PyBody*)joint->body1;
-    incbody = (PyBody*)joint->body2;
-    refshape = (PyShape*) refbody->shape;
-    incshape = (PyShape*) incbody->shape;
-
-    moment = contact->acc_moment;
-    bm = contact->split_acc_moment;
-
-    refr = c_diff (contact->position, refbody->position);
-    incidr = c_diff (contact->position, incbody->position);
-
-    if (PyVector2_Dot (contact->dv, contact->normal) > 0)
-
-        return;
-    if (!refbody->isstatic)
-    {
-        refbody->linear_velocity = c_diff (refbody->linear_velocity, 
-            PyVector2_DivideWithReal (moment, refbody->mass));
-        refbody->angle_velocity -=
-            PyVector2_Cross (refr, moment) / refshape->inertia;
-
-        refbody->bias_lv = c_diff (refbody->bias_lv,
-            PyVector2_DivideWithReal (bm, refbody->mass));
-        refbody->bias_w -= PyVector2_Cross (refr, bm) / refshape->inertia;
-    }
-
-    if (!incbody->isstatic)
-    {
-        incbody->linear_velocity = c_sum(incbody->linear_velocity, 
-            PyVector2_DivideWithReal (moment, incbody->mass));
-        incbody->angle_velocity +=
-            PyVector2_Cross (incidr, moment) / incshape->inertia;
-
-        incbody->bias_lv = c_sum (incbody->bias_lv,
-            PyVector2_DivideWithReal (bm, incbody->mass));
-        incbody->bias_w += PyVector2_Cross (incidr, bm) / incshape->inertia;
-    }
-}
-
-static void
-_contact_dealloc (PyContact *contact)
-{
-    PyObject *obj = (PyObject*) &(contact->joint);
-    obj->ob_type->tp_free ((PyObject*)contact);
-}
-
-static PyObject*
-_contact_new (PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
-    PyContact *contact = (PyContact*) PyJoint_Type.tp_new (type, args, kwds);
-    if (!contact)
-        return NULL;
-    PyVector2_Set (contact->position, 0, 0);
-    PyVector2_Set (contact->normal, 0, 0);
-    PyVector2_Set (contact->dv, 0, 0);
-    contact->depth = 0;
-    contact->weight = 0;
-    contact->resist = 0;
-    contact->kfactor = 0;
-    contact->tfactor = 0;
-    PyVector2_Set (contact->acc_moment, 0, 0);
-    PyVector2_Set (contact->split_acc_moment, 0, 0);
-    contact->joint.solve_constraints = _solve_constraints;
-    return (PyObject*) contact;
-}
-
-static int
-_contact_init (PyContact *self, PyObject *args, PyObject *kwds)
-{
-    if (PyJoint_Type.tp_init ((PyObject *)self, args, kwds) < 0)
-        return -1;
-    /* TODO */
-    return 0;
-}
-
-/* Getters/Setters */
-
-/* C API */
-PyObject*
-PyContact_New (void)
-{
-    return (PyObject*) PyContact_Type.tp_new (&PyContact_Type, NULL, NULL);
-}
-
-int
-PyContact_Collision (PyObject *contact, double steptime)
-{
-    if (!contact || !PyContact_Check (contact))
-    {
-        PyErr_SetString (PyExc_TypeError, "contact must be a Contact");
-        return 0;
-    }
-    return PyContact_Collision_FAST ((PyContact*)contact, steptime);
-}
-
-int
-PyContact_Collision_FAST (PyContact *contact, double steptime)
-{
-/**
- * MAX_C_DEP is the maximal permitted penetrating depth after collision
- * reaction.
- * BIAS_FACTOR is a empirical factor. The two constants are used for
- * position collision after collision reaction is done.
- * for further learning you can read Erin Canto's GDC 2006 Slides, page 23.
- * (You can download it from www.gphysics.com)
- */
-#define MAX_C_DEP 0.01
-#define BIAS_FACTOR 0.2
-
-    PyVector2 neg_dV, refV, incidV;
-    PyVector2 refR, incidR;
-    PyBody *refBody, *incidBody;
-    double moment_len;
-    PyVector2 moment;
-
-    double vbias;
-    PyVector2 brefV, bincidV, bneg_dV;
-    double bm_len;
-    PyVector2 bm;
-
-    refBody = (PyBody *) contact->joint.body1;
-    incidBody = (PyBody *)contact->joint.body2;
-
-    contact->resist = sqrt(refBody->restitution*incidBody->restitution);
-
-    /*
-     * The algorithm below is an implementation of the empirical formula for
-     * impulse-based collision reaction. You can learn the formula thoroughly
-     * from Helmut Garstenauer's thesis, Page 60.
-     */
-    refR = c_diff(contact->position, refBody->position);
-    incidR = c_diff(contact->position, incidBody->position);
-    //dV = v2 + w2xr2 - (v1 + w1xr1)
-    incidV = c_sum(incidBody->linear_velocity,
-        PyVector2_fCross(incidBody->angle_velocity, incidR));
-    refV = c_sum(refBody->linear_velocity,
-        PyVector2_fCross(refBody->angle_velocity, refR));
-
-    contact->dv = c_diff(incidV, refV);
-    neg_dV = c_diff(refV, incidV);
-	
-    moment_len = PyVector2_Dot (PyVector2_MultiplyWithReal(neg_dV,
-            (1 + contact->resist)), contact->normal)/contact->kfactor;
-    moment_len = MAX(0, moment_len);
-    
-    /* finally we get the momentum(oh...) */
-    moment = PyVector2_MultiplyWithReal(contact->normal, moment_len);
-    contact->acc_moment.real += moment.real/contact->weight;
-    contact->acc_moment.imag += moment.imag/contact->weight; 
-
-    /* split impulse */
-    vbias = BIAS_FACTOR*MAX(0, contact->depth - MAX_C_DEP)/steptime;
-    /* biased dv */
-    bincidV = c_sum(incidBody->bias_lv,
-        PyVector2_fCross(incidBody->bias_w, incidR));
-    brefV = c_sum(refBody->bias_lv, PyVector2_fCross(refBody->bias_w, refR));
-    bneg_dV = c_diff(brefV, bincidV); 
-    /* biased moment */
-    bm_len = PyVector2_Dot(PyVector2_MultiplyWithReal(bneg_dV, 1.),
-        contact->normal)/contact->kfactor;
-    bm_len = MAX(0, bm_len + vbias/contact->kfactor);
-    bm = PyVector2_MultiplyWithReal(contact->normal, bm_len);
-    contact->split_acc_moment.real += bm.real/contact->weight;
-    contact->split_acc_moment.imag += bm.imag/contact->weight;
-
-#undef MAX_C_DEP
-#undef BIAS_FACTOR
-    return 1;
-}
-
-void
-contact_export_capi (void **capi)
-{
-    capi[PHYSICS_CONTACT_FIRSTSLOT + 0] = &PyContact_Type;
-    capi[PHYSICS_CONTACT_FIRSTSLOT + 1] = PyContact_New;
-}
-

src/physics/joint.c

-/*
-  pygame physics - Pygame physics module
-
-  Copyright (C) 2008 Zhang Fan
-
-  This library is free software; you can redistribute it and/or
-  modify it under the terms of the GNU Library General Public
-  License as published by the Free Software Foundation; either
-  version 2 of the License, or (at your option) any later version.
-
-  This library is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  Library General Public License for more details.
-
-  You should have received a copy of the GNU Library General Public
-  License along with this library; if not, write to the Free
-  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#define PHYSICS_JOINT_INTERNAL
-
-#include "physicsmod.h"
-#include "pgphysics.h"
-
-static void _joint_dealloc (PyJoint *joint);
-static PyObject* _joint_new (PyTypeObject *type, PyObject *args,
-    PyObject *kwds);
-static int _joint_init (PyJoint *joint, PyObject *args, PyObject *kwds);
-
-static PyObject* _joint_getdict (PyJoint *joint, void *closure);
-static PyObject* _joint_getbody1 (PyJoint *joint, void *closure);
-static PyObject* _joint_getbody2 (PyJoint *joint, void *closure);
-static PyObject* _joint_getcollideconnect (PyJoint *joint, void *closure);
-
-static PyObject* _joint_solveconstraints (PyJoint *joint, PyObject *args);
-
-/**
- * Methods, which are bound to the PyJoint type.
- */
-static PyMethodDef _joint_methods[] =
-{
-    { "solve_constraints", (PyCFunction)_joint_solveconstraints, METH_VARARGS,
-      NULL },
-    { NULL, NULL, 0, NULL }
-};
-
-/**
- * Getters/Setters
- */
-static PyGetSetDef _joint_getsets[] =
-{
-    { "__dict__", (getter) _joint_getdict, NULL, NULL, NULL },
-    { "body1", (getter) _joint_getbody1, NULL, NULL, NULL },
-    { "body2", (getter) _joint_getbody2, NULL, NULL, NULL },
-    { "is_collide_connect", (getter) _joint_getcollideconnect, NULL, NULL,
-      NULL },
-    { NULL, NULL, NULL, NULL, NULL }
-};
-
-PyTypeObject PyJoint_Type =
-{
-    TYPE_HEAD(NULL, 0)
-    "physics.Joint",            /* tp_name */
-    sizeof (PyJoint),           /* tp_basicsize */
-    0,                          /* tp_itemsize */
-    (destructor) _joint_dealloc,/* tp_dealloc */
-    0,                          /* tp_print */
-    0,                          /* tp_getattr */
-    0,                          /* tp_setattr */
-    0,                          /* tp_compare */
-    0,                          /* tp_repr */
-    0,                          /* tp_as_number */
-    0,                          /* tp_as_sequence */
-    0,                          /* tp_as_mapping */
-    0,                          /* tp_hash */
-    0,                          /* tp_call */
-    0,                          /* tp_str */
-    0,                          /* tp_getattro */
-    0,                          /* tp_setattro */
-    0,                          /* tp_as_buffer */
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
-    "",
-    0,                          /* tp_traverse */
-    0,                          /* tp_clear */
-    0,                          /* tp_richcompare */
-    0,                          /* tp_weaklistoffset */
-    0,                          /* tp_iter */
-    0,                          /* tp_iternext */
-    _joint_methods,             /* tp_methods */
-    0,                          /* tp_members */
-    _joint_getsets,             /* tp_getset */
-    0,                          /* tp_base */
-    0,                          /* tp_dict */
-    0,                          /* tp_descr_get */
-    0,                          /* tp_descr_set */
-    offsetof (PyJoint, dict),   /* tp_dictoffset */
-    (initproc)_joint_init,      /* tp_init */
-    0,                          /* tp_alloc */
-    _joint_new,                 /* tp_new */
-    0,                          /* tp_free */
-    0,                          /* tp_is_gc */
-    0,                          /* tp_bases */
-    0,                          /* tp_mro */
-    0,                          /* tp_cache */
-    0,                          /* tp_subclasses */
-    0,                          /* tp_weaklist */
-    0,                          /* tp_del */
-#if PY_VERSION_HEX >= 0x02060000
-    0                           /* tp_version_tag */
-#endif
-};
-
-static void
-_joint_dealloc (PyJoint *joint)
-{
-    Py_XDECREF (joint->dict);
-    ((PyObject*)joint)->ob_type->tp_free ((PyObject*)joint);
-}
-
-static PyObject*
-_joint_new (PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
-    PyJoint* joint = (PyJoint*) type->tp_alloc (type, 0);
-    if (!joint)
-        return NULL;
-    
-    joint->dict = NULL;
-    joint->body1 = NULL;
-    joint->body2 = NULL;
-    joint->iscollideconnect = 0;
-    joint->solve_constraints = NULL;
-    return (PyObject *) joint;
-}
-
-static int
-_joint_init (PyJoint *joint, PyObject *args, PyObject *kwds)
-{
-    PyObject *body1, *body2;
-    int collide;
-    
-    if (!PyArg_ParseTuple (args, "O!O!i", &PyBody_Type, &body1,
-        &PyBody_Type, &body2, &collide))
-        return -1;
-    if (collide)
-        joint->iscollideconnect = 1;
-    Py_INCREF (body1);
-    Py_INCREF (body2);
-    joint->body1 = body1;
-    joint->body1 = body2;
-    return 0;
-}
-
-/* Getters/Setters */
-static PyObject*
-_joint_getdict (PyJoint *joint, void *closure)
-{
-    if (!joint->dict)
-    {
-        joint->dict = PyDict_New ();
-        if (!joint->dict)
-            return NULL;
-    }
-    Py_INCREF (joint->dict);
-    return joint->dict;
-}
-
-static PyObject*
-_joint_getbody1 (PyJoint *joint, void *closure)
-{
-    Py_INCREF (joint->body1);
-    return joint->body1;
-}
-
-static PyObject*
-_joint_getbody2 (PyJoint *joint, void *closure)
-{
-    Py_INCREF (joint->body2);
-    return joint->body2;
-}
-
-static PyObject*
-_joint_getcollideconnect (PyJoint *joint, void *closure)
-{
-    return PyBool_FromLong (joint->iscollideconnect);
-}
-
-/* Methods */
-static PyObject*
-_joint_solveconstraints (PyJoint *joint, PyObject *args)
-{
-    if (joint->solve_constraints)
-    {
-        double steptime;
-        if (!PyArg_ParseTuple (args, "d", &steptime))
-            return NULL;
-        joint->solve_constraints (joint, steptime);
-        Py_RETURN_NONE;
-    }
-    PyErr_SetString (PyExc_NotImplementedError, "method not implemented");
-    return NULL;
-}
-
-/* C API */
-int
-PyJoint_SolveConstraints (PyObject *joint, double steptime)
-{
-    if (!joint || !PyJoint_Check (joint))
-    {
-        PyErr_SetString (PyExc_TypeError, "joint must be a Joint");
-        return 0;
-    }
-    return PyJoint_SolveConstraints_FAST ((PyJoint*)joint, steptime);
-}
-
-int
-PyJoint_SolveConstraints_FAST (PyJoint *joint, double steptime)
-{
-    PyObject *result;
-    
-    if (joint->solve_constraints)
-    {
-        joint->solve_constraints (joint, steptime);
-        return 1;
-    }
-    result = PyObject_CallMethod ((PyObject*)joint, "solve_constraints", "d",
-        steptime);
-    if (!result)
-        return 0;
-
-    Py_DECREF (result);
-    return 1;
-}
-
-void
-joint_export_capi (void **capi)
-{
-    capi[PHYSICS_JOINT_FIRSTSLOT + 0] = &PyJoint_Type;
-}

src/physics/pgphysics.h

-/*
-  pygame physics - Pygame physics module
-
-  Copyright (C) 2008 Zhang Fan
-
-  This library is free software; you can redistribute it and/or
-  modify it under the terms of the GNU Library General Public
-  License as published by the Free Software Foundation; either
-  version 2 of the License, or (at your option) any later version.
-
-  This library is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  Library General Public License for more details.
-
-  You should have received a copy of the GNU Library General Public
-  License along with this library; if not, write to the Free
-  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#ifndef _PHYSICS_H_
-#define _PHYSICS_H_
-
-#include <math.h>
-#include "pgbase.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * Zero tolerance constants for vector calculations.
- */
-#define ZERO_EPSILON 1e-6
-#define RELATIVE_ZERO 1e-6
-#define OVERLAP_ZERO 1e-8
-
-#define IS_NEAR_ZERO(num) (fabs(num) <= ZERO_EPSILON)
-
-/**
- * 2D vector definition.
- */
-typedef Py_complex PyVector2;
-
-#define PyVector2_Check(x) (PyObject_TypeCheck(op, &PyComplex_Type))
-#define PyVector2_CheckExact(x) ((op)->ob_type == &PyComplex_Type)
-#define PyVector2_Set(vec, x, y)                \
-    {                                           \
-        (vec).real = (x);                       \
-        (vec).imag = (y);                       \
-    }
-
-#define PyVector2_GetLengthSquare(x) ((x).real * (x).real + (x).imag * (x).imag)
-#define PyVector2_GetLength(x) (sqrt(PyVector2_GetLengthSquare(x)))
-#define PyVector2_Dot(x, y) ((x).real * (y).real + (x).imag * (y).imag)
-#define PyVector2_Cross(x, y) ((x).real * (y).imag - (x).imag * (y).real)
-#define PyVector2_Normalize(x)                          \
-    {                                                   \
-        double __pg_tmp = PyVector2_GetLength(*(x));    \
-        (x)->real /=  __pg_tmp;                         \
-        (x)->imag /=  __pg_tmp;                         \
-    }
-
-#define PyVector2_Rotate(x, a)                          \
-    {                                                   \
-        double __pg_x = (x)->real;                      \
-        double __pg_y = (x)->imag;                      \
-        (x)->real = __pg_x * cos(a) - __pg_y * sin(a);  \
-        (x)->imag = __pg_x * sin(a) + __pg_y * cos(a);  \
-    }
-
-#define PHYSICS_MATH_FIRSTSLOT 0
-#define PHYSICS_MATH_NUMSLOTS 13
-#ifndef PHYSICS_MATH_INTERNAL
-#define PyMath_IsNearEqual                                              \
-    (*(int(*)(double,double))PyPhysics_C_API[PHYSICS_MATH_FIRSTSLOT+0])
-#define PyMath_LessEqual                                                \
-    (*(int(*)(double,double))PyPhysics_C_API[PHYSICS_MATH_FIRSTSLOT+1])
-#define PyMath_MoreEqual                                                \
-    (*(int(*)(double,double))PyPhysics_C_API[PHYSICS_MATH_FIRSTSLOT+2])
-
-#define PyVector2_Equal                                                 \
-    (*(int(*)(PyVector2,PyVector2))PyPhysics_C_API[PHYSICS_MATH_FIRSTSLOT+3])
-#define PyVector2_MultiplyWithReal                                      \
-    (*(PyVector2(*)(PyVector2,double))PyPhysics_C_API[PHYSICS_MATH_FIRSTSLOT+4])
-#define PyVector2_DivideWithReal                                        \
-    (*(PyVector2(*)(PyVector2,double))PyPhysics_C_API[PHYSICS_MATH_FIRSTSLOT+5])
-#define PyVector2_fCross                                                \
-    (*(PyVector2(*)(double,PyVector2))PyPhysics_C_API[PHYSICS_MATH_FIRSTSLOT+6])
-#define PyVector2_Crossf                                                \
-    (*(PyVector2(*)(PyVector2,double))PyPhysics_C_API[PHYSICS_MATH_FIRSTSLOT+7])
-#define PyVector2_Project                                               \
-    (*(PyVector2(*)(PyVector2,PyVector2))PyPhysics_C_API[PHYSICS_MATH_FIRSTSLOT+8])
-#define PyVector2_AsTuple                                               \
-    (*(PyObject*(*)(PyVector2))PyPhysics_C_API[PHYSICS_MATH_FIRSTSLOT+9])
-#define PyVector2_FromSequence                                          \
-    (*(int(*)(PyObject*, PyVector2*))PyPhysics_C_API[PHYSICS_MATH_FIRSTSLOT+10])
-#define PyVector2_Transform                                             \
-    (*(PyVector2(*)(PyVector2,PyVector2,double,PyVector2,double))PyPhysics_C_API[PHYSICS_MATH_FIRSTSLOT+11])
-#define PyVector2_TransformMultiple                                     \
-    (*(PyVector2(*)(PyVector2*,PyVector2*,int,double,PyVector2,double))PyPhysics_C_API[PHYSICS_MATH_FIRSTSLOT+12])
-#endif /* PHYSICS_MATH_INTERNAL */
-
-/**
- * AABBox
- */
-typedef struct
-{
-    double top;
-    double left;
-    double right;
-    double bottom;
-} AABBox;
-
-#define PHYSICS_AABBOX_FIRSTSLOT \
-    (PHYSICS_MATH_FIRSTSLOT + PHYSICS_MATH_NUMSLOTS)
-#define PHYSICS_AABBOX_NUMSLOTS 8
-#ifndef PHYSICS_AABBOX_INTERNAL
-#define AABBox_New                                                     \
-    (*(AABBox(*)(double,double,double,double))PyPhysics_C_API[PHYSICS_AABBOX_FIRSTSLOT+0])
-#define AABBox_Reset                                                   \
-    (*(void(*)(AABBox*))PyPhysics_C_API[PHYSICS_AABBOX_FIRSTSLOT+1])
-#define AABBox_ExpandTo                                                \
-    (*(void(*)(AABBox*,PyVector2*))PyPhysics_C_API[PHYSICS_AABBOX_FIRSTSLOT+2])
-#define AABBox_Overlaps                                                \
-    (*(int(*)(AABBox*,AABBox*,double))PyPhysics_C_API[PHYSICS_AABBOX_FIRSTSLOT+3])
-#define AABBox_Contains                                                \
-    (*(int(*)(AABBox*,PyVector2*,double))PyPhysics_C_API[PHYSICS_AABBOX_FIRSTSLOT+4])
-#define AABBox_AsFRect                                                 \
-    (*(PyObject*(*)(AABBox*))PyPhysics_C_API[PHYSICS_AABBOX_FIRSTSLOT+5])
-#define AABBox_FromSequence                                            \
-    (*(int(*)(PyObject*,AABBox*))PyPhysics_C_API[PHYSICS_AABBOX_FIRSTSLOT+6])
-#define AABBox_FromRect                                                \
-    (*(int(*)(PyObject*,AABBox*))PyPhysics_C_API[PHYSICS_AABBOX_FIRSTSLOT+7])
-#endif /* PHYSICS_AABBOX_INTERNAL */
-
-/**
- */
-typedef struct
-{
-    PyObject_HEAD
-
-    PyObject *dict;
-    PyObject *shape;
-    double    mass;
-    int       isstatic : 1;
-    double    rotation;
-    PyVector2 position;
-    PyVector2 impulse;
-    PyVector2 force;
-    double    torque;
-    PyVector2 linear_velocity;
-    double    angle_velocity;
-    double    restitution;
-    double    friction;
-    double    linear_vel_damping;
-    double    angle_vel_damping;
-    PyVector2 bias_lv;
-    double    bias_w;
-} PyBody;
-
-#define PHYSICS_BODY_FIRSTSLOT \
-    (PHYSICS_AABBOX_FIRSTSLOT + PHYSICS_AABBOX_NUMSLOTS)
-#define PHYSICS_BODY_NUMSLOTS 5
-#ifndef PHYSICS_BODY_INTERNAL
-#define PyBody_Type                                             \
-    (*(PyTypeObject*)PyPhysics_C_API[PHYSICS_BODY_FIRSTSLOT+0])
-#define PyBody_Check(x)                                                 \
-    (PyObject_TypeCheck(x,                                              \
-        (PyTypeObject*)PyPhysics_C_API[PHYSICS_BODY_FIRSTSLOT+0]))
-#define PyBody_New                                                      \
-    (*(PyObject*(*)(PyObject*))PyPhysics_C_API[PHYSICS_BODY_FIRSTSLOT+1])
-#define PyBody_CheckCollision                                           \
-    (*(PyObject*(*)(PyObject*,PyObject*))PyPhysics_C_API[PHYSICS_BODY_FIRSTSLOT+2])
-#define PyBody_CheckCollision_FAST                                      \
-    (*(PyObject*(*)(PyBody*,PyBody*))PyPhysics_C_API[PHYSICS_BODY_FIRSTSLOT+3])
-#define PyBody_GetPoints                                                \
-    (*(PyObject*(*)(PyObject*))PyPhysics_C_API[PHYSICS_BODY_FIRSTSLOT+4])
-#endif /* PHYSICS_BODY_INTERNAL */
-
-typedef enum
-{
-    UNKNOWN = -1,
-    ST_RECT,
-    ST_CIRCLE,
-} ShapeType;
-
-/**
- */
-typedef struct _PyShape PyShape;
-struct _PyShape
-{
-    PyObject_HEAD
-
-    ShapeType   type;
-    double      inertia;
-    double      rotation;
-    PyObject   *dict;
-
-    PyVector2*  (*get_vertices)(PyShape*,Py_ssize_t*);
-    int         (*get_aabbox)(PyShape*,AABBox*);
-    int         (*update)(PyShape*,PyBody*);
-};
-
-/**