#include "gameobject.h" #include "renderer.h" #include "explosions.h" GameObject* gameObjects[100]; int nGameObjects = 0; void render(GameObject* this) { if( this->status != DEAD) renderGfxObject(&this->gfxObj, this->pos.x, this->pos.y, this->angle, this->scale); } void updateAllGameObjects() { // Update our object(s) for(int i=0; i < nGameObjects; i++) gameObjects[i]->update(gameObjects[i]); } void renderAllGameObjects() { // Render our object(s) - background objects first, and then forward objects for(int i=0; i < nGameObjects; i++) gameObjects[i]->render(gameObjects[i]); } static Circle getCircle(GameObject* pObj) { Circle c; c.center = pObj->pos; c.radius = sqrt(pObj->gfxObj.outputHeight*pObj->gfxObj.outputHeight + pObj->gfxObj.outputWidth*pObj->gfxObj.outputWidth) * 0.5; return c; } static bool collide(GameObject* pObj1, GameObject* pObj2) { Circle c1, c2; c1 = getCircle(pObj1); c2 = getCircle(pObj2); float distance = vec2fLength( vec2fSub(c1.center, c2.center) ); return ( distance <= c1.radius + c2.radius) ? true : false; } void collisionDetection() { for(int i=0; i < nGameObjects; i++) { if( !(gameObjects[i]->props & COLLIDABLE) ) continue; if(gameObjects[i]->status == DEAD) continue; if((gameObjects[i]->status == TERMINATING) && !(gameObjects[i]->props & COLLIDES_ON_TERMINATING)) continue; // Do collision detection against the rest of the objects for(int j=i+1; j < nGameObjects; j++) { if(gameObjects[i]->type == gameObjects[j]->type) continue; // we skip collision testing objects of same type if( !(gameObjects[j]->props & COLLIDABLE) ) continue; if(gameObjects[j]->status == DEAD) continue; if((gameObjects[j]->status == TERMINATING) && !(gameObjects[j]->props & COLLIDES_ON_TERMINATING)) continue; if(collide(gameObjects[i], gameObjects[j])){ // Alternatively we could inform each object whom it is colliding with and // let them do the logic. But managing it here is often easier and clearer // (but less object oriented) // loop over both the i and j object for (int k=0; k<2; k++) { int o1, o2; o1 = (k==0) ? i : j; o2 = (k==0) ? j : i; // Manage score if( (gameObjects[o1]->props & RECEIVES_SCORE) && (gameObjects[o2]->props & (GIVES_PICK_POINTS | GIVES_KILL_POINTS)) ) gameObjects[o1]->score += gameObjects[o2]->points; if( (gameObjects[o2]->props & LETHAL_ON_HIT) && (gameObjects[o1]->status == LIVE) ) { gameObjects[o1]->status = TERMINATING; // sends message that object should die if( gameObjects[o1]->onCollision == EXPLODES ) { // Use a standard explosion animation GameObject* pExpl = getExplosion1(); gameObjects[o1]->frame = pExpl->frame; gameObjects[o1]->frameSpeed = pExpl->frameSpeed; gameObjects[o1]->numFrames = pExpl->numFrames; // Maintain original screen sizes int outputWidth, outputHeight; outputWidth = gameObjects[o1]->gfxObj.outputWidth; outputHeight = gameObjects[o1]->gfxObj.outputHeight; gameObjects[o1]->gfxObj = pExpl->gfxObj; // set image data gameObjects[o1]->gfxObj.outputWidth = outputWidth; gameObjects[o1]->gfxObj.outputHeight = outputHeight; gameObjects[o1]->update = updateExplosions; // new update method } if( gameObjects[o1]->onCollision == DISAPPEARS ) { gameObjects[o1]->status = DEAD; } } } } } } } void removeDeadObjects() { int j = 0; for(int i=0; i < nGameObjects; i++) { if( gameObjects[i]->status == DEAD ) continue; gameObjects[j++] = gameObjects[i]; } nGameObjects = j; }