/** return a list of data objects where all dependencies appear earlier in the list */ ObjectList<DataObject> Document::sortedDataObjectList() { ObjectList<DataObject> sorted; ObjectList<DataObject> raw = objectStore()->getObjects<DataObject>(); sorted.clear(); // set the flag for all primitives: not strictly necessary // since it should have been done in the constructor, but... PrimitiveList all_primitives = objectStore()->getObjects<Primitive>(); int n = all_primitives.size(); for (int i=0; i<n; i++) { all_primitives[i]->setFlag(true); } // now unset the flags of all output primitives to indicate their parents haven't been // put in the sorted list yet n = raw.size(); for (int i=0; i<n; i++) { raw[i]->setOutputFlags(false); } // now place into the sorted list all data objects whose inputs haven't got parents // or whose inputs have parents which are already in the sorted list. // do this at most n^2 times, which is worse than worse case. int i=0; while (!raw.isEmpty() && (++i <= n*n)) { DataObjectPtr D = raw.takeFirst(); if (D->inputFlagsSet()) { D->setOutputFlags(true); sorted.append(D); } else { raw.append(D); // try again later } } if ((i== n*n) && (n>1)) { qDebug() << "Warning: loop detected, File will not be able to be loaded correctly!"; while (!raw.isEmpty()) { DataObjectPtr D = raw.takeFirst(); sorted.append(D); } } return sorted; }
/* Move the object pointed to to postion where(in asc11 spaces) */ int WorldManager::moveObject(Object *p_o, Position where){ GraphicsManager &graphics_manager = GraphicsManager::getInstance(); if (p_o->isSolid()){ //collisions only matter for solid objects bool doMove = true; //Get collisions ObjectList list = isCollision(p_o, where); //if we have collided with something if (!list.isEmpty()){ //Itereate accross list ObjectListIterator li = ObjectListIterator(&list); while (!li.isDone()){ Object *p_temp_o = li.currentObject(); //Create collision event EventCollision collision(p_o, p_temp_o, where); //send to both objects p_o->eventHandler(&collision); p_temp_o->eventHandler(&collision); //if both objects are hard move fails if (p_o->getSolidness() == HARD && p_temp_o->getSolidness() == HARD){ doMove = false; } li.next(); }// end iterator while if (!doMove){ return -1; } }// end list is not empty ( no collision }//Object not solid p_o->setPosition(where); //Check to see if moving out of bounds if (where.getX() < 0 || (where.getX() >= graphics_manager.getHorizontal()) || where.getY() < 0 || (where.getY() >= graphics_manager.getVertical())){ EventOut ov = EventOut(); p_o->eventHandler(&ov); } return 0; }
//Move Object //If no collision with solid, move okay, else don't move //If p_o is Spectral, move ok. //Return 0 if move ok, else -1 if collision is solid int WorldManager::moveObject(Object *p_o, Position where) { if (p_o->isSolid()) { //Need to be solid for collisions //Get Collisions ObjectList list = isCollision(p_o, where); if (!list.isEmpty()) { boolean do_move = true; //Assume we can move ObjectListIterator li = ObjectListIterator(&list); li.first(); while (!li.isDone()) { Object *p_temp_o = li.currentObject(); //Create Collision event EventCollision c(p_o, p_temp_o, where); //Send to both objects p_o->eventHandler(&c); p_temp_o->eventHandler(&c); //If both Hard, then cannot move if (p_o->getSolidness() == HARD && p_temp_o->getSolidness() == HARD) do_move = false; //Can't move //If object won't move onto soft objects, check for that if (p_o->getNoSoft() && p_temp_o->getSolidness() == SOFT) do_move = false; li.next(); } //End while if (do_move == false) return -1; } } //Get world bounds GraphicsManager &gp_m = GraphicsManager::getInstance(); int maxHori = boundary.getHorizontal(); int maxVert = boundary.getVertical(); //Check if object is moving out of world if ((p_o->getPos().getX() > 0) && (p_o->getPos().getX() < maxHori) // X is within bounds AND && (p_o->getPos().getY() > 0) && (p_o->getPos().getY() < maxVert) //Y is within bounds AND && (where.getX() < 0 || where.getX() > maxHori || where.getY() < 0 || where.getY() > maxVert)) //Any part of new location is out of bounds { EventOut ov = EventOut(); p_o->eventHandler(&ov); } //No collision between 2 hard objects, so move object p_o->setPos(where); if (p_view_following == p_o) setViewPosition(p_o->getPos()); return 0; }
int CCollector::Reclamation () { ObjectList lstDestructed; // destructed object list // step 401 - determine unreachable objects do for (ObjectList::Iterator iter (getWhiteList ()); iter;) { CPouch *pPouch = iter; iter.next (); if (pPouch->isDestructed ()) { getWhiteList ().remove (pPouch); lstDestructed.pushTail (pPouch); } else { pPouch->getFlags ()->bitwiseOR (F_UNREACHABLE); } } while (0); // step 402 - invoke OnReclaim routine of all unreachable objects bool bResurr = false; do for (ObjectList::Iterator iter (getWhiteList ()); iter; iter.next ()) { CPouch *pPouch = iter; CDeclarator dcl (&bResurr, pPouch, pPouch); pPouch->onreclaim (&dcl); // call OnReclaim routine for // each unreachable object to give them a chance to resurrect. } while (0); if (bResurr) { // 1. clear the D-List CDependence *pRec; while ((pRec = m_lstDependences.popNode ()) != 0) { delete pRec; } // 2. unmark unreachabe objects do for (ObjectList::Iterator iter (getWhiteList ()); iter; iter.next ()) { CPouch *pPouch = iter; pPouch->getFlags ()->bitwiseAND (~F_UNREACHABLE); } while (0); // 3. move back destructed objecs getWhiteList ().pushTail (lstDestructed); // return back and continue traversal again. return 1; } // note - From now, unreachable objects can be dropped to ZRC or/and // be explicitly destructed. ObjectList lstStandby; // objects that is depended by others ObjectList *pDestructing = &getWhiteList (); ObjectList *pStandby = &lstStandby; uint_flags nColorDestructing = 0; // identify Q-Destructing or Q-Standby for (;;) { // note - Q-Standby is empty at beginning for every loop // step 403 - scan D-List do for (DRecList::Iterator iter (m_lstDependences); iter;) { CPouch *pDepender = iter->m_pDepender; // note - D-List records have been limited to among unreachable // objects, others are discarded in CCollector::OnReclaimDeclare. if (pDepender->isDestructed ()) { CDependence *pRec = iter; iter.remove (); delete pRec; continue; } // move dependee from Q-Destructing to Q-Standby CPouch *pDependee = iter->m_pDependee; if (pDependee->getFlags ()->bitwiseCompareExchange ( F_DEPENDENCE, nColorDestructing, F_DEPENDENCE & (~nColorDestructing) ) == nColorDestructing) { // this ensures a dependee would only move once from // Q-Destructing to Q-Standby pDestructing->remove (pDependee); pStandby->pushTail (pDependee); } iter.next (); } while (0); // step 404 - check Q-Destructing if (pDestructing->isEmpty ()) { // No destruction can be taken, no depender will vanish break; } // step 405 - destructing objects in Q-Destructing CPouch *pPouch; while ((pPouch = pDestructing->popHead ()) != 0) { // previous nesting HandleZRC function may have destructed the object DestructObject (pPouch); lstDestructed.pushTail (pPouch); } // step 407 - remove records in D-List that the depender of the // record has been destructed. (emerged into step 403) // step 408 - switch Q-Destructing and Q-Standby ObjectList *pTemp = pDestructing; pDestructing = pStandby; pStandby = pTemp; nColorDestructing = F_DEPENDENCE & ~nColorDestructing; } // loop back D-List scanning // // Destructions of objects have done // if (!pStandby->isEmpty ()) { // circular-depended relationship found! all objects are moved // from Q-Destructing to Q-Standby. // 1. clear D-List do for (DRecList::Iterator iter (m_lstDependences); iter;) { CDependence *pRec = iter; iter.remove (); delete pRec; } while (0); // 2. TODO: log these circular-depended objects // 3. skip app-level reclamation of Q-Standby objects. lstDestructed.pushTail (*pStandby); } // step 406 - System-level reclamation // all unreachable objects are destructed (or skipped for the reason of // circular depending relationship), there is neither live objects nor // any destructor refering them. CPouch *pPouch; while ((pPouch = lstDestructed.popHead ()) != 0) { // RC should be zero, but cannot guaranteed for some bad-behavor // application does not drop reference at destruction, or existing // some circular-depended objects. // ASSERT(pPouch->getLECount()->isZero()); pPouch->destroy (); } // By now, Q-Destructed, Q-Destructing, D-List, Q-Standby should be empty ASSERT (pDestructing->isEmpty ()); ASSERT (pStandby->isEmpty ()); ASSERT (lstDestructed.isEmpty ()); ASSERT (m_lstDependences.isEmpty ()); return 0; }
void Platform::hit(EventCollision *p_c) { if (((p_c->getObject1()->getType()) == "Hero") || ((p_c->getObject2()->getType()) == "Hero")) { auto heroPtr = (Object*)nullptr; auto platformPtr = (Object*)nullptr; if ((p_c->getObject1()->getType()) == "Hero") { heroPtr = p_c->getObject1(); platformPtr = p_c->getObject2(); } else { heroPtr = p_c->getObject2(); platformPtr = p_c->getObject1(); } WorldManager &world_manager = WorldManager::getInstance(); auto heroPos = heroPtr->getPosition(); auto platformPos = platformPtr->getPosition(); int xOffset = 0; int yOffset = 0; if (heroPtr->getPosition().getY() <= (this->getPosition().getY() + this->getHeight())) { if (getXVelocity() > 0) { xOffset = this->lastXDisplacement; } else if (getXVelocity() < 0) { xOffset = this->lastXDisplacement; } } if (getYVelocity() > 0) { //only adjust hero position when platform goes up //yOffset = 1; } else if (getYVelocity() < 0) { yOffset = this->lastYDisplacement; } float xCD; float yCD; bool xChanged; if (xOffset || yOffset) { heroPos = Position(heroPos.getX(), heroPos.getY()); platformPos = Position(platformPos.getX(), platformPos.getY()); xCD = platformPtr->getXVelocityCountdown(); xChanged = xCD > prevXCD; yCD = platformPtr->getYVelocityCountdown(); heroPos.setX(heroPos.getX() + xOffset); platformPos.setX(platformPos.getX()); if (!xChanged) { heroPos.setX(heroPos.getX() - xOffset); //platformPos.setX(platformPos.getX() - xOffset); } prevXCD = xCD; if (yCD <= 0) { heroPos.setY(heroPos.getY() + yOffset); platformPos.setY(platformPos.getY() + yOffset); } } if (yOffset > 0) { world_manager.moveObject(platformPtr, platformPos); world_manager.moveObject(heroPtr, heroPos); } else if (yOffset < 0) { ObjectList list = world_manager.isCollision(heroPtr, heroPos); if (!list.isEmpty()) { world_manager.markForDelete(heroPtr); } else { world_manager.moveObject(heroPtr, heroPos); world_manager.moveObject(platformPtr, platformPos); } } if (xOffset) { ObjectList list = world_manager.isCollision(heroPtr, heroPos); if (list.isEmpty()) { world_manager.moveObject(heroPtr, heroPos); world_manager.moveObject(platformPtr, platformPos); } else { world_manager.moveObject(platformPtr, platformPos); list = world_manager.isCollision(heroPtr, heroPos); if (list.isEmpty()) { world_manager.moveObject(heroPtr, heroPos); } else { //world_manager.markForDelete(heroPtr); } } } } else { // monster, trap, etc. will stop the platform completely //setXVelocityCountdown(getXVelocityCountdown() + fabs(getXVelocity())); //setYVelocityCountdown(getYVelocityCountdown() + fabs(getYVelocity())); } }