BOOL Game::checkForCollisions() { // NOTE: Things happen here in a specific order. Collisions between non-wall objects // MUST MUST MUST happen before wall collisions. The reason is that the player could // collide with a dragon and thus bounce off. If this were to occur after wall collisions were // calculated, the player would more easily bounce through a wall. UINT i; SimpleArray *walls = itsPlayer->getRoom()->getWalls(); GameObject *bridge = itsPlayer->getRoom()->searchRoom(GameObject::GAMEOBJECT_TYPE_BRIDGE); // TODO: clean this up SimpleArray *objects = itsWorld->getObjects(); for (i=0;i<objects->length();i++) { GameObject *object = (GameObject *)(objects->elementAt(i)); if (object->getType() == GameObject::GAMEOBJECT_TYPE_WALL) continue; for (UINT j=1;j<objects->length();j++) { GameObject *object2 = (GameObject *)(objects->elementAt(j)); if (object2->getType() == GameObject::GAMEOBJECT_TYPE_WALL) continue; if (object->isColliding(object2)) { object->collision(itsLastTickTime,object2); object2->collision(itsLastTickTime,object); } } } RECT playerRect; itsPlayer->getRect(&playerRect); BOOL onBridge = FALSE; for (i=0;i<walls->length();i++) { Wall *thisWall = (Wall *)(walls->elementAt(i)); if (thisWall->isColliding(itsPlayer)) { // If the player's rect is colliding with the bridge, but not their actual pixels // (in other words, inside the bridge's rect, but not touching the bridge itself) if ( (bridge != NULL) && (ON_BRIDGE(bridge,itsPlayer,playerRect)) ) { onBridge = TRUE; } else { itsPlayer->collision(itsLastTickTime,thisWall); } } } itsPlayer->setOnBridge(onBridge); return TRUE; }
BOOL Game::update() { BOOL updateObjects = FALSE; BOOL checkForWinning = FALSE; BOOL checkForLosing = FALSE; BOOL checkCollisions = FALSE; BOOL stopMovement = TRUE; switch (itsCurrentState) { case GAMESTATE_PREGAME : // since the pregame section is so different, we will call our own method pregameUpdate(); break; case GAMESTATE_INPROGRESS : updateObjects = TRUE; checkForWinning = TRUE; checkForLosing = TRUE; checkCollisions = TRUE; stopMovement = FALSE; break; case GAMESTATE_WON : { updateObjects = TRUE; Room *room = itsPlayer->getRoom(); // we need to change the walls a color for that ending flashiness if (itsLastTickTime - itsWinTime >= theWinAnimationLength) { for (UINT i=0;i<room->getWalls()->length();i++) { Wall *wall = (Wall *)(room->getWalls()->elementAt(i)); wall->setChangesColor(FALSE); } } else { // since the player will be holding the chalice, we can tell // the walls to change colors, and they will change to the color // of the chalice, which will make them appear to animate for (UINT i=0;i<room->getWalls()->length();i++) { Wall *wall = (Wall *)(room->getWalls()->elementAt(i)); wall->setChangesColor(TRUE,1); } } // hack to put the player in the right place for the ending itsPlayer->setX(Game::theScreenHeight-64); itsPlayer->setY(Game::theScreenWidth/2-16); } break; case GAMESTATE_LOST : updateObjects = TRUE; stopMovement = FALSE; break; case GAMESTATE_PAUSED : stopMovement = FALSE; break; } theEventDispatcher.update(itsLastTickTime); if (updateObjects) { SimpleArray *objects = NULL; if (itsWorld != NULL) objects = itsWorld->getObjects(); for (UINT i=0;i<objects->length();i++) { ((GameObject *)(objects->elementAt(i)))->update(itsLastTickTime); if (stopMovement) { ((GameObject *)(objects->elementAt(i)))->stopMoving(itsLastTickTime); } } for (i=0;i<itsWorld->getRooms()->length();i++) { ((Room *)(itsWorld->getRooms()->elementAt(i)))->checkForObjectsLeaving(); } } if (checkForWinning && gameWon()) { itsNewStateRequest.itsNewState = GAMESTATE_WON; itsNewStateRequest.isActiveRequest = TRUE; } if (checkForLosing && gameLost()) { itsNewStateRequest.itsNewState = GAMESTATE_LOST; itsNewStateRequest.isActiveRequest = TRUE; } if (checkCollisions) return checkForCollisions(); else return TRUE; }