EDIT: ok, the corruption is actually happening with the "body" pointer. I've printed the pointer address at every cycle, and just before the error it changes to another value. Time for more bug tracing
Oh sorry, forgot to include it.
"objectList" is a std::vector of Object, defined globally.
body->v.x is being changed in my main cycle (the "while" cycle below), which resides in my main() function, and is posted below:
P.S.: END_OF_MAIN is required by allegro.
Below, i post my whole program's code, excluding code for libraries (I think the libraries function calls are self explanatory).
Code: Select all
#include <iostream>
#include <vector>
#include <allegro.h>
#include "chipmunk.h"
#include "Graphics/Graphics.h"
#include "Vector/Vector2.h"
#include "Math/Math.h"
#include <cmath>
cpSpace *space;
cpBody *staticBody;
//cpBody *body;
typedef struct Object
{
std::string name;
cpBody* physBody;
cpShape *physShape;
Vector2 shapeOffset; // offset of the shape relative to the body
};
std::vector<Object> objectList;
int some_value = 42;
bool graphicsInitialize();
void graphicsUpdate();
bool graphicsTerminate();
void physicsInitialize(void);
void physicsUpdate(int ticks);
static int collFunc(
cpShape *a, cpShape *b, cpContact *contacts, int numContacts,
cpFloat normal_coef, void *data);
void physicsTerminate(void);
void addObjectBox(Vector2 pos, Vector2 dimensions, float angleRadians, bool isStatic);
void addObjectBox(std::string objectName, Vector2 pos, Vector2 dimensions, float angleRadians, bool isStatic);
void addObjectCircle(std::string name, Vector2 pos, float radius, bool isStatic);
std::vector<cpVect> getVerticesForBox(Vector2 dimensions);
std::vector<cpVect> getVerticesForBox(Vector2 dimensions, Vector2 offset);
//cpBody* createBodyWithParameters(cpVect* verticesList, unsigned int verticesTotal, Vector2 pos); // creates a body with these vertices and pos, but doesn't add it to the space
//cpShape* createShapePolyWithParameters(cpVect* verticesList, unsigned int verticesTotal, Vector2 pos, Vector2 size, cpBody* bodyToAddTo);
cpBody* createBodyWithParameters(std::vector<cpVect>& verticesList, Vector2 pos);
cpShape* createShapePolyWithParameters(std::vector<cpVect>& verticesList, Vector2 pos, cpBody* bodyToAddTo);
Object* getObjectByName(std::string objectName);
bool getObjectIndexByName(std::string objectName, unsigned int& idxObjectFound);
void deleteObjectByName(std::string objectName);
////////////////////////////////
// Main ////////////////////////
////////////////////////////////
int main(void)
{
try
{
graphicsInitialize();
physicsInitialize();
std::cout << "Hit + to add object\n";
clear_keybuf();
bool cmdExit = false;
bool cmdAddObject = false;
Object* player = getObjectByName("player1");
while(!cmdExit)
{
if(key[KEY_ESC])
cmdExit = true;
if(key[KEY_PLUS_PAD])
cmdAddObject = true;
else
{
if(cmdAddObject)
{
Vector2 pos(320,10);
Vector2 dimensions(20,10);
addObjectBox(pos, dimensions, 0, false);
cmdAddObject = false;
}
}
// player controls
if(key[KEY_LEFT])
{
assert(player);
assert(player->physBody);
player->physBody->v.x = -10.0f;
//cpBodyApplyImpulse(player->physBody, cpv(-10.0f,0), cpvzero);
}
if(key[KEY_RIGHT])
{
assert(player);
assert(player->physBody);
player->physBody->v.x = 10.0f;
//cpBodyApplyImpulse(player->physBody, cpv(10.0f,0), cpvzero);
}
physicsUpdate(1);
graphicsUpdate();
//rest(100);
}
physicsTerminate();
graphicsTerminate();
}
catch (...) { // catch an error
std::cout << "Caught an exception -- value is: ";
//std::cout << i << "\n";
}
return 0;
}
END_OF_MAIN()
bool graphicsInitialize()
{
if(system_driver == NULL) // to ensure allegro is only initialed once - http://www.allegro.cc/forums/thread/591306/670840#target
{
allegro_init();
install_timer();
install_keyboard();
}
Graphics::create(640,480,16);
}
void graphicsUpdate()
{
for(unsigned int idxObject = 0; idxObject < objectList.size(); ++idxObject)
{
cpBody* body = objectList[idxObject].physBody;
//std::cout << "body "<< idxObject <<" pos:" << body->p.x <<","<< body->p.y << "\n";
cpShape* shape = objectList[idxObject].physShape;
if(shape == 0)
continue;
//std::cout << "AAAA\n";
assert(shape);
// draw to screen
switch(shape->klass->type)
{
case CP_CIRCLE_SHAPE:
{
float radius = cpCircleShapeGetRadius(shape);
Vector2 pos(body->p.x, body->p.y);
Graphics::getPtr()->drawCircle(pos,radius,Graphics::getPtr()->getColor(Graphics::Colors::Blue));
}
break;
case CP_SEGMENT_SHAPE:
break;
case CP_POLY_SHAPE:
{
Vector2 shapeOffset = objectList[idxObject].shapeOffset;
Vector2 bodyCenter(body->p.x, body->p.y);
cpVect topVect = cpPolyShapeGetVert(shape, 0);
cpVect bottomVect = cpPolyShapeGetVert(shape, 2);
Vector2 halfDims((bottomVect.x - topVect.x) * 0.5f, (bottomVect.y - topVect.y) * 0.5f),
//pos(body->p.x, body->p.y);
pos(shapeOffset.x, shapeOffset.y);
//shapeOffset = Vector2();
float angleRads = body->a;
//Graphics::getPtr()->drawAABB(pos,halfDims,Graphics::getPtr()->getColor(Graphics::Colors::Blue));
//Graphics::getPtr()->drawOBB(pos,halfDims,angleRads,Graphics::getPtr()->getColor(Graphics::Colors::Blue));
Graphics::getPtr()->drawOBB(pos,halfDims,bodyCenter,angleRads,Graphics::getPtr()->getColor(Graphics::Colors::Blue));
}
break;
}
}
//std::cout << "done drawin\n";
Graphics::getPtr()->drawToScreen();
}
bool graphicsTerminate()
{
Graphics::destroy();
allegro_exit();
}
void physicsInitialize(void)
{
cpInitChipmunk();
// Initialize a static body with infinite mass and moment of inertia
// to attach the static geometry to.
staticBody = cpBodyNew(INFINITY, INFINITY);
// Optional. Read the docs to see what this really does.
//cpResetShapeIdCounter();
// Create a space and adjust some of it's parameters.
space = cpSpaceNew();
// Lets set some parameters of the space:
// More iterations make the simulation more accurate but slower
space->iterations = 10;
// These parameters tune the efficiency of the collision detection.
// For more info: http://code.google.com/p/chipmunk-physics/wiki/cpSpace
cpSpaceResizeStaticHash(space, 30.0f, 1000);
cpSpaceResizeActiveHash(space, 30.0f, 1000);
// Give it some gravity
space->gravity = cpv(0, 90);
cpShape *shape;
Vector2 screenDimensions = Graphics::getPtr()->getScreenDimensions();
// Create some segments around the edges of the screen.
shape = cpSegmentShapeNew(staticBody, cpv(0,0), cpv(0,screenDimensions.y), 0.0f);
shape->e = 1.0; shape->u = 1.0;
cpSpaceAddStaticShape(space, shape);
shape = cpSegmentShapeNew(staticBody, cpv(0,screenDimensions.y), cpv(screenDimensions.x,screenDimensions.y), 0.0f);
shape->e = 1.0; shape->u = 1.0;
cpSpaceAddStaticShape(space, shape);
shape = cpSegmentShapeNew(staticBody,cpv(screenDimensions.x,screenDimensions.y), cpv(0,screenDimensions.y), 0.0f);
shape->e = 1.0; shape->u = 1.0;
cpSpaceAddStaticShape(space, shape);
// add player
Vector2 playerPos(200,200), playerSize(15,15);
//addObjectBox("player1", playerPos, playerSize * 2, 0, false); // setting the player as a box crashes as well
addObjectCircle("player1", playerPos, playerSize.x, false);
}
void physicsUpdate(int ticks)
{
int steps = 3; // divide velocity by this value
cpFloat dt = 1.0/60.0/(cpFloat)steps;
int i;
//for(int i=0; i<steps; i++){
for(i=0; i<steps; i++)
{
cpSpaceStep(space, dt);
}
// or:
//cpSpaceStep(space, 1.0f/60.0f);
}
void addObjectBox(Vector2 pos, Vector2 dimensions, float angleRadians, bool isStatic)
{
addObjectBox("", pos, dimensions, angleRadians, isStatic);
}
void addObjectBox(std::string objectName, Vector2 pos, Vector2 dimensions, float angleRadians, bool isStatic)
{
Object newObject;
newObject.name = objectName;
std::vector<cpVect> verticesList = getVerticesForBox(dimensions);
// Create a box and initialize some of its parameters.
//newObject.physBody = cpBodyNew(1.0, cpMomentForPoly(1.0, num, verts, cpvzero));
//newObject.physBody->p = cpv(pos.x, pos.y);
newObject.physBody = createBodyWithParameters(verticesList, pos);
cpSpaceAddBody(space, newObject.physBody);
//newObject.physShape = cpPolyShapeNew(newObject.physBody, num, verts, cpvzero);
//newObject.physShape->e = 0.0; newObject.physShape->u = 1.5;
//newObject.physShape->collision_type = 1;
newObject.physShape = createShapePolyWithParameters(verticesList, Vector2(0,0), newObject.physBody);
cpSpaceAddShape(space, newObject.physShape);
// Add a collision callback between objects of the default type and the box.
//cpSpaceAddCollisionPairFunc(space, 1, 0, &collFunc, &some_value);
cpBodySetAngle(newObject.physBody, angleRadians);
// add Object to object list
objectList.push_back(newObject);
}
void addObjectCircle(std::string name, Vector2 pos, float radius, bool isStatic)
{
Object newObject;
newObject.name = name;
// Set up the player
newObject.physBody = cpSpaceAddBody(space, cpBodyNew(1.0f, INFINITY));
//newObject.physBody = cpSpaceAddBody(space, cpBodyNew(1.0f, cpMomentForCircle(1.0f, 0, radius, cpvzero)));
newObject.physBody->p = cpv(pos.x, pos.y);
//newObject.physBody->velocity_func = playerUpdateVelocity;
newObject.physShape = cpSpaceAddShape(space, cpCircleShapeNew(newObject.physBody, radius, cpvzero));
newObject.physShape->e = 0.0f;
newObject.physShape->u = 1.0f;
//newObject.physShape->collision_type = 1;
objectList.push_back(newObject);
}
std::vector<cpVect> getVerticesForBox(Vector2 dimensions)
{
return getVerticesForBox(dimensions, Vector2(0,0));
}
std::vector<cpVect> getVerticesForBox(Vector2 dimensions, Vector2 offset)
{
std::vector<cpVect> verticesList;
verticesList.push_back(cpv((-dimensions.x * 0.5f) + offset.x, (-dimensions.y * 0.5f)+ offset.y));
verticesList.push_back(cpv((-dimensions.x * 0.5f) + offset.x, (dimensions.y * 0.5f) + offset.y));
verticesList.push_back(cpv((dimensions.x * 0.5f) + offset.x, (dimensions.y * 0.5f) + offset.y));
verticesList.push_back(cpv((dimensions.x * 0.5f) + offset.x, (-dimensions.y * 0.5f) + offset.y ));
return verticesList;
}
cpBody* createBodyWithParameters(std::vector<cpVect>& verticesList, Vector2 pos)
{
cpVect* verts = (cpVect*) malloc(sizeof(cpVect) * verticesList.size());
for(unsigned int idxVect = 0; idxVect < verticesList.size(); ++idxVect)
verts[idxVect] = verticesList[idxVect];
cpBody* physBody = cpBodyNew(1.0, cpMomentForPoly(1.0, verticesList.size(), verts, cpvzero));
//cpBody* physBody = cpBodyNew(INFINITY, INFINITY);
physBody->p = cpv(pos.x, pos.y);
return physBody;
}
cpShape* createShapePolyWithParameters(std::vector<cpVect>& verticesList, Vector2 pos, cpBody* bodyToAddTo)
{
cpVect* verts = (cpVect*) malloc(sizeof(cpVect) * verticesList.size());
for(unsigned int idxVect = 0; idxVect < verticesList.size(); ++idxVect)
verts[idxVect] = verticesList[idxVect];
//cpShape* physShape = cpPolyShapeNew(bodyToAddTo, verticesList.size(), verts, cpvzero);
cpShape* physShape = cpPolyShapeNew(bodyToAddTo, verticesList.size(), verts, cpv(pos.x, pos.y));
physShape->e = 0.0;
physShape->u = 1.5;
physShape->collision_type = 1;
return physShape;
}
Object* getObjectByName(std::string objectName)
{
unsigned int idxObject = 0;
bool objectFound = getObjectIndexByName(objectName, idxObject);
if(objectFound)
return &objectList[idxObject];
else
return 0;
}
bool getObjectIndexByName(std::string objectName, unsigned int& idxObjectFound)
{
for(unsigned int idxObject = 0; idxObject < objectList.size(); ++idxObject)
{
if(objectList[idxObject].name == objectName)
{
idxObjectFound = idxObject;
return true;
}
}
return false;
}
void deleteObjectByName(std::string objectName)
{
unsigned int idxObject = 0;
if(getObjectIndexByName(objectName, idxObject))
{
Object* obj = &objectList[idxObject];
//if(obj->physBody != 0)
if(obj->physShape != 0)
{
cpSpaceRemoveShape(space, obj->physShape);
//cpSpaceRemoveBody(space, obj->physBody);
cpShapeFree(obj->physShape);
//cpBodyFree(obj->physBody);
obj->physShape = 0;
//obj->physBody = 0;
std::cout << "removed\n";
}
//objectList.erase(objectList.begin() + idxObject);
//delete obj;
}
else
std::cout << "object "<< objectName <<" not found, not removed\n";
}
void physicsTerminate(void)
{
cpSpaceFreeChildren(space);
cpSpaceFree(space);
cpBodyFree(staticBody);
}