void PackageCanvas::prepare_for_move(bool on_resize) { if (! on_resize) { DiagramCanvas::prepare_for_move(on_resize); Q3CanvasItemList l = collisions(TRUE); Q3CanvasItemList::ConstIterator it; Q3CanvasItemList::ConstIterator end = l.end(); DiagramItem * di; BrowserNode * p = get_bn(); for (it = l.begin(); it != end; ++it) { if ((*it)->visible() && // at least not deleted !(*it)->selected() && ((di = QCanvasItemToDiagramItem(*it)) != 0) && di->move_with_its_package()) { BrowserNode * bn = di->get_bn(); do bn = (BrowserNode *) bn->parent(); while (bn->get_type() != UmlPackage); if (bn == p) { the_canvas()->select(*it); di->prepare_for_move(FALSE); } } } } }
Q3CanvasItem * UmlCanvas::collision(const QPoint & p) const { Q3CanvasItemList l = collisions(p); Q3CanvasItemList::ConstIterator it; Q3CanvasItemList::ConstIterator end = l.end(); ArrowCanvas * arrow = 0; for (it = l.begin(); it != end; ++it) if (((*it)->visible()) && // at least not deleted !isa_alien(*it) && !isa_col_msg_dirs(*it)) { switch ((*it)->rtti()) { case RTTI_ARROW: if (arrow == 0) arrow = (ArrowCanvas *) *it; break; case RTTI_LABEL: return (arrow == 0) ? *it : arrow; default: // isa DiagramCanvas return ((arrow == 0) || (small_element(((DiagramCanvas *) *it)->rect()) && ((DiagramCanvas *) *it)->attached_to(arrow))) ? *it : arrow; } } return arrow; }
void VerletShapeTests::sphereMissesCapsule() { // non-overlapping sphere and capsule float radiusA = 1.5f; float radiusB = 2.3f; float totalRadius = radiusA + radiusB; float halfHeightB = 1.7f; float axialOffset = totalRadius + 1.1f * halfHeightB; float radialOffset = 1.2f * radiusA + 1.3f * radiusB; // create points for the sphere + capsule VerletPoint points[3]; for (int i = 0; i < 3; ++i) { points[i]._position = glm::vec3(0.0f); } // give the points to the shapes VerletSphereShape sphereA(radiusA, points); VerletCapsuleShape capsuleB(radiusB, points+1, points+2); capsuleB.setHalfHeight(halfHeightB); // give the capsule some arbitrary transform float angle = 37.8f; glm::vec3 axis = glm::normalize( glm::vec3(-7.0f, 2.8f, 9.3f) ); glm::quat rotation = glm::angleAxis(angle, axis); glm::vec3 translation(15.1f, -27.1f, -38.6f); capsuleB.setRotation(rotation); capsuleB.setTranslation(translation); CollisionList collisions(16); // walk sphereA along the local yAxis next to, but not touching, capsuleB glm::vec3 localStartPosition(radialOffset, axialOffset, 0.0f); int numberOfSteps = 10; float delta = 1.3f * (totalRadius + halfHeightB) / (numberOfSteps - 1); for (int i = 0; i < numberOfSteps; ++i) { // translate sphereA into world-frame glm::vec3 localPosition = localStartPosition + ((float)i * delta) * yAxis; sphereA.setTranslation(rotation * localPosition + translation); // sphereA agains capsuleB if (ShapeCollider::collideShapes(&sphereA, &capsuleB, collisions)) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: sphere and capsule should NOT touch" << std::endl; } // capsuleB against sphereA if (ShapeCollider::collideShapes(&capsuleB, &sphereA, collisions)) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: sphere and capsule should NOT touch" << std::endl; } } if (collisions.size() > 0) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: expected empty collision list but size is " << collisions.size() << std::endl; } }
/** create an animated cell from pixmaps at position row,col */ GraphicalCell::GraphicalCell( int row, int col , QCanvas *canvas) : QCanvasSprite( ImageTheme.cells, canvas ) { collisions( true ); setFrame( 0 ); move( _size*col, _size*row ); setZ( CAN_GROUND ); show(); }
void load_game(void) { update_background(); update_content(); collisions(); update_stats(); display_content(); draw(); }
//============================================================================= // Call repeatedly by the main message loop in WinMain //============================================================================= void Game::run(HWND hwnd) { if(graphics == NULL) // if graphics not initialized return; // calculate elapsed time of last frame, save in frameTime QueryPerformanceCounter(&timeEnd); frameTime = (float)(timeEnd.QuadPart - timeStart.QuadPart ) / (float)timerFreq.QuadPart; // Power saving code, requires winmm.lib // if not enough time has elapsed for desired frame rate if (frameTime < MIN_FRAME_TIME) { sleepTime = (DWORD)((MIN_FRAME_TIME - frameTime)*1000); timeBeginPeriod(1); // Request 1mS resolution for windows timer Sleep(sleepTime); // release cpu for sleepTime timeEndPeriod(1); // End 1mS timer resolution return; } if (frameTime > 0.0) fps = (fps*0.99f) + (0.01f/frameTime); // average fps if (frameTime > MAX_FRAME_TIME) // if frame rate is very slow frameTime = MAX_FRAME_TIME; // limit maximum frameTime timeStart = timeEnd; // update(), ai(), and collisions() are pure virtual functions. // These functions must be provided in the class that inherits from Game. if (!paused) // if not paused { update(); // update all game items ai(); // artificial intelligence collisions(); // handle collisions input->vibrateControllers(frameTime); // handle controller vibration } //for FPS on the title char windowtext[255]; sprintf(windowtext,"frameTime = %f, FPS= %f",frameTime, fps); SetWindowText(hwnd, windowtext); renderGame(); // draw all game items // input->readCoSntrollers(); // read state of controllers // if Alt+Enter toggle fullscreen/window if (input->isKeyDown(ALT_KEY) && input->wasKeyPressed(ENTER_KEY)) setDisplayMode(graphicsNS::TOGGLE); // toggle fullscreen/window // if Esc key, set window mode if (input->isKeyDown(ESC_KEY)) setDisplayMode(graphicsNS::WINDOW); // set window mode // Clear input // Call this after all key checks are done input->clear(inputNS::KEYS_PRESSED); }
void VerletShapeTests::sphereMissesSphere() { // non-overlapping spheres of unequal size float radiusA = 7.0f; float radiusB = 3.0f; float alpha = 1.2f; float beta = 1.3f; glm::vec3 offsetDirection = glm::normalize(glm::vec3(1.0f, 2.0f, 3.0f)); float offsetDistance = alpha * radiusA + beta * radiusB; // create points for the sphere centers VerletPoint points[2]; // give pointers to the spheres VerletSphereShape sphereA(radiusA, (points + 0)); VerletSphereShape sphereB(radiusB, (points + 1)); // set the positions of the spheres by slamming the points directly points[0]._position = origin; points[1]._position = offsetDistance * offsetDirection; CollisionList collisions(16); // collide A to B... { bool touching = ShapeCollider::collideShapes(&sphereA, &sphereB, collisions); if (touching) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: sphereA and sphereB should NOT touch" << std::endl; } } // collide B to A... { bool touching = ShapeCollider::collideShapes(&sphereB, &sphereA, collisions); if (touching) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: sphereA and sphereB should NOT touch" << std::endl; } } // also test shapeShape { bool touching = ShapeCollider::collideShapes(&sphereB, &sphereA, collisions); if (touching) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: sphereA and sphereB should NOT touch" << std::endl; } } if (collisions.size() > 0) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: expected empty collision list but size is " << collisions.size() << std::endl; } }
// ================================================================== // WinMain内のメインのメッセージループで繰り返し呼び出される // ================================================================== void Game::run(HWND hwnd) { if(graphics == NULL) // グラフィックスが初期化されていない場合 return; // エスケープキーで終了 if(input->isKeyDown(ESC_KEY)) { PostQuitMessage(0); return; } // 最後のフレームからの経過時間を計算、frameTimeに保存 QueryPerformanceCounter(&timeEnd); frameTime = (float)(timeEnd.QuadPart - timeStart.QuadPart) / (float)timeFreq.QuadPart; // 省電力コード(winmm.libが必要) // 希望するフレームレートに対して経過時間が短い場合 if(frameTime < MIN_FRAME_TIME) { sleepTime = (DWORD)((MIN_FRAME_TIME - frameTime) * 1000); timeBeginPeriod(1); // 1ミリ秒の分解能をWindowsタイマーに要求 Sleep(sleepTime); // sleepTimeの間、CPUを解放 timeEndPeriod(1); // 1ミリ秒のタイマー分解能を終了 return; } if(frameTime > 0.0) fps = (fps * 0.99f) + (0.01f / frameTime); // 平均fps if(frameTime > MAX_FRAME_TIME) // フレームレートが非常に遅い場合 frameTime = MAX_FRAME_TIME; // 最大frameTimeを制限 timeStart = timeEnd; input->readControllers(); // コントローラの状態を読み取る // update()、ai()、collisions()は純粋仮想関数です // これらの関数は、Gameを継承しているクラス側で記述する必要があります if(!paused) // 一時停止中でない { update(); // すべてのゲームアイテムを更新 ai(); // 人工知能 collisions(); // 衝突を処理 input->vibrateControllers(frameTime); //コントローラの振動を処理 } renderGame(); // すべてのゲームアイテムを描画 // 入力をクリア // すべてのキーチェックが行われた後これを呼び出す input->clear(inputNS::KEYS_PRESSED); }
/** add comments here */ GraphicalFightUnit::GraphicalFightUnit( QCanvas * canvas ) : QCanvasSprite( (*ImageTheme.creatures[0])[0], canvas ) { collisions( true ); setFrame( 0 ); setZ( CAN_LORD ); show(); /*QBrush brush( yellow ); _numBox = new QCanvasRectangle( canvas ); _numBox->setBrush( brush ); _numBox->collisions( true ); _numBox->setZ( CAN_ARROW ); _numBox->setSize( 50, 25 ); _numBox->show();*/ }
void Floater::moveBy(double dx, double dy) { if (!isEnabled()) return; QCanvasItemList l = collisions(false); for (QCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it) { CanvasItem *item = dynamic_cast<CanvasItem *>(*it); if (!noUpdateZ && item && item->canBeMovedByOthers()) item->updateZ(this); if ((*it)->z() >= z()) { if (item && item->canBeMovedByOthers() && collidesWith(*it)) { if ((*it)->rtti() == Rtti_Ball) { //((Ball *)(*it))->setState(Rolling); (*it)->moveBy(dx, dy); if (game && game->hasFocus() && !game->isEditing() && game->curBall() == (Ball *)(*it)) game->ballMoved(); } else if ((*it)->rtti() != Rtti_Putter) (*it)->moveBy(dx, dy); } } } point->dontMove(); point->move(x() + width(), y() + height()); // this call must come after we have tested for collisions, otherwise we skip them when saving! // that's a bad thing QCanvasRectangle::moveBy(dx, dy); // because we don't do Bridge::moveBy(); topWall->move(x(), y()); botWall->move(x(), y() - 1); leftWall->move(x(), y()); rightWall->move(x(), y()); if (game && game->isEditing()) game->updateHighlighter(); }
void FixedSet::Init(const std::vector<int>& elements) { int size = elements.size(); std::vector<std::vector <int> > collisions(size); buckets_.resize(size); function_ = GenerateUniversalHashFunctor(PRIME_NUMBER); for (auto iterator = elements.begin(); iterator != elements.end(); ++iterator) { int element = AdjustElement(*iterator); int index = GetIndex(element); collisions[index].push_back(element); } for (int bucket_index = 0; bucket_index != size; ++bucket_index) { buckets_[bucket_index].Init(collisions[bucket_index]); } }
void ShapeColliderTests::sphereMissesSphere() { // non-overlapping spheres of unequal size float radiusA = 7.f; float radiusB = 3.f; float alpha = 1.2f; float beta = 1.3f; glm::vec3 offsetDirection = glm::normalize(glm::vec3(1.f, 2.f, 3.f)); float offsetDistance = alpha * radiusA + beta * radiusB; SphereShape sphereA(radiusA, origin); SphereShape sphereB(radiusB, offsetDistance * offsetDirection); CollisionList collisions(16); // collide A to B... { bool touching = ShapeCollider::collideShapes(&sphereA, &sphereB, collisions); if (touching) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: sphereA and sphereB should NOT touch" << std::endl; } } // collide B to A... { bool touching = ShapeCollider::collideShapes(&sphereB, &sphereA, collisions); if (touching) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: sphereA and sphereB should NOT touch" << std::endl; } } // also test shapeShape { bool touching = ShapeCollider::collideShapes(&sphereB, &sphereA, collisions); if (touching) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: sphereA and sphereB should NOT touch" << std::endl; } } if (collisions.size() > 0) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: expected empty collision list but size is " << collisions.size() << std::endl; } }
void Game::Draw() { //SFML is a polling based system, This is why we call pollEvent. //If there is an event, it returns true, and is set equall to currentEvent. if(player1score > 9) { cout<<"Player 1 Wins!!! "<<endl; _gameState = GameOver; } if(player2score > 9) { cout<<"Player 2 Wins!!! "<<endl; _gameState = GameOver; } sf::Event event; while(ballMoving && !ballGoal){ //cout<<"ball moving"<<endl; _mainWindow.clear(sf::Color(0,0,0));//Clears the stuff drawn to the screen. ball.move(); playerUpdate(); ball.update(_mainWindow); collisions();//check collisions with the ball. // playerUpdate(); _mainWindow.display(); while(_mainWindow.pollEvent(event)) { movement();//Update the movement of the paddles playerUpdate(); ball.update(_mainWindow); _mainWindow.display(); switch(event.type) { case sf::Event::Closed: _gameState = Game::Exiting; break; } } } }
//============================================================================= // Call repeatedly by the main message loop in WinMain //============================================================================= void Game::run(HWND hwnd) { if(graphics == NULL) // if graphics not initialized return; // calculate elapsed time of last frame, save in frameTime QueryPerformanceCounter(&timeEnd); frameTime = (float)(timeEnd.QuadPart - timeStart.QuadPart ) / (float)timerFreq.QuadPart; // Power saving code, requires winmm.lib // if not enough time has elapsed for desired frame rate if (frameTime < MIN_FRAME_TIME) { sleepTime = (DWORD)((MIN_FRAME_TIME - frameTime)*1000); timeBeginPeriod(1); // Request 1mS resolution for windows timer Sleep(sleepTime); // release cpu for sleepTime timeEndPeriod(1); // End 1mS timer resolution return; } if (frameTime > 0.0) fps = (fps*0.99f) + (0.01f/frameTime); // average fps if (frameTime > MAX_FRAME_TIME) // if frame rate is very slow frameTime = MAX_FRAME_TIME; // limit maximum frameTime timeStart = timeEnd; // update(), ai(), and collisions() are pure virtual functions. // These functions must be provided in the class that inherits from Game. if (!paused) // if not paused { update(); // update all game items ai(); // artificial intelligence collisions(); // handle collisions input->vibrateControllers(frameTime); // handle controller vibration } renderGame(); // draw all game items input->readControllers(); // read state of controllers // Clear input // Call this after all key checks are done input->clear(inputNS::KEYS_PRESSED); }
void PhysicsEntity::disableCurrentSelfCollisions() { CollisionList collisions(10); int numShapes = _shapes.size(); for (int i = 0; i < numShapes; ++i) { const Shape* shape = _shapes.at(i); if (!shape) { continue; } for (int j = i+1; j < numShapes; ++j) { if (!collisionsAreEnabled(i, j)) { continue; } const Shape* otherShape = _shapes.at(j); if (otherShape && ShapeCollider::collideShapes(shape, otherShape, collisions)) { disableCollisions(i, j); collisions.clear(); } } } }
void FragmentCanvas::prepare_for_move(bool on_resize) { if (!on_resize) { DiagramCanvas::prepare_for_move(on_resize); QRect r = rect(); Q3CanvasItemList l = collisions(TRUE); Q3CanvasItemList::ConstIterator it; Q3CanvasItemList::ConstIterator end = l.end(); DiagramItem * di; for (it = l.begin(); it != end; ++it) { if ((*it)->visible() && // at least not deleted !(*it)->selected() && ((di = QCanvasItemToDiagramItem(*it)) != 0) && r.contains(di->rect(), TRUE) && di->move_with(UmlFragment)) { the_canvas()->select(*it); di->prepare_for_move(FALSE); } } } }
void Bullet::checkCollision() { QCanvasItem* item; QCanvasItemList l=collisions(FALSE); for (QCanvasItemList::Iterator it=l.begin(); it!=l.end(); ++it) { item = *it; if ( (item->rtti()== 1500) && (item->collidesWith(this)) ) { Man* deadman = (Man*)item; if (deadman->frame() != 5) return; deadman->done(); emit score(10); setShotCount(shotcount+1); setAnimated(false); nobullets--; delete this; return; } else if ( (item->rtti()==1900) && (item->collidesWith(this)) ) { Helicopter* deadchopper = (Helicopter*) item; deadchopper->done(); emit score(50); setAnimated(false); nobullets--; delete this; return; } } //check shot is not out of bounds if ( (y() < 0) || (x() < 0) || (y() > canvas()->height()) || ( x() > canvas()->width())) { setAnimated(false); nobullets--; delete this; return; } }
//============================================================================= // Call repeatedly by the main message loop in WinMain //============================================================================= void Game::run(HWND hwnd) { if(graphics == NULL) // if graphics not initialized return; // calculate elapsed time of last frame, save in frameTime QueryPerformanceCounter(&timeEnd); frameTime = (float)(timeEnd.QuadPart - timeStart.QuadPart ) / (float)timerFreq.QuadPart; // Power saving code, requires winmm.lib // if not enough time has elapsed for desired frame rate if (frameTime < MIN_FRAME_TIME) { sleepTime = (DWORD)((MIN_FRAME_TIME - frameTime)*1000); timeBeginPeriod(1); // Request 1mS resolution for windows timer Sleep(sleepTime); // release cpu for sleepTime timeEndPeriod(1); // End 1mS timer resolution return; } if (frameTime > 0.0) fps = (fps*0.99f) + (0.01f/frameTime); // average fps if (frameTime > MAX_FRAME_TIME) // if frame rate is very slow frameTime = MAX_FRAME_TIME; // limit maximum frameTime timeStart = timeEnd; // update(), ai(), and collisions() are pure virtual functions. // These functions must be provided in the class that inherits from Game. if (!paused) // if not paused { update(); // update all game items ai(); // artificial intelligence collisions(); // handle collisions input->vibrateControllers(frameTime); // handle controller vibration } renderGame(); // draw all game items //check for console key if (input->getCharIn() == CONSOLE_KEY) { input->clearCharIn(); // clear last char console->showHide(); paused = console->getVisible(); // pause game when console is visible } consoleCommand(); // process user entered console command input->readControllers(); // read state of controllers messageDialog->update(); inputDialog->update(); audio->run(); // perform periodic sound engine tasks // if Alt+Enter toggle fullscreen/window if (input->isKeyDown(ALT_KEY) && input->wasKeyPressed(ENTER_KEY)) setDisplayMode(graphicsNS::TOGGLE); // toggle fullscreen/window // if Esc key, set window mode if (input->isKeyDown(ESC_KEY)) setDisplayMode(graphicsNS::WINDOW); // set window mode // if Pause key if (input->wasKeyPressed(VK_PAUSE)) paused = !paused; // Clear input keys pressed // Call this after all key checks are done input->clear(inputNS::KEYS_PRESSED); }
void ShapeColliderTests::sphereTouchesSphere() { // overlapping spheres of unequal size float radiusA = 7.f; float radiusB = 3.f; float alpha = 0.2f; float beta = 0.3f; glm::vec3 offsetDirection = glm::normalize(glm::vec3(1.f, 2.f, 3.f)); float offsetDistance = alpha * radiusA + beta * radiusB; float expectedPenetrationDistance = (1.f - alpha) * radiusA + (1.f - beta) * radiusB; glm::vec3 expectedPenetration = expectedPenetrationDistance * offsetDirection; SphereShape sphereA(radiusA, origin); SphereShape sphereB(radiusB, offsetDistance * offsetDirection); CollisionList collisions(16); int numCollisions = 0; // collide A to B... { bool touching = ShapeCollider::collideShapes(&sphereA, &sphereB, collisions); if (!touching) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: sphereA and sphereB should touch" << std::endl; } else { ++numCollisions; } // verify state of collisions if (numCollisions != collisions.size()) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: expected collisions size of " << numCollisions << " but actual size is " << collisions.size() << std::endl; } CollisionInfo* collision = collisions.getCollision(numCollisions - 1); if (!collision) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: null collision" << std::endl; } // penetration points from sphereA into sphereB float inaccuracy = glm::length(collision->_penetration - expectedPenetration); if (fabs(inaccuracy) > EPSILON) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: bad penetration: expected = " << expectedPenetration << " actual = " << collision->_penetration << std::endl; } // contactPoint is on surface of sphereA glm::vec3 AtoB = sphereB.getPosition() - sphereA.getPosition(); glm::vec3 expectedContactPoint = sphereA.getPosition() + radiusA * glm::normalize(AtoB); inaccuracy = glm::length(collision->_contactPoint - expectedContactPoint); if (fabs(inaccuracy) > EPSILON) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: bad contactPoint: expected = " << expectedContactPoint << " actual = " << collision->_contactPoint << std::endl; } } // collide B to A... { bool touching = ShapeCollider::collideShapes(&sphereB, &sphereA, collisions); if (!touching) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: sphereA and sphereB should touch" << std::endl; } else { ++numCollisions; } // penetration points from sphereA into sphereB CollisionInfo* collision = collisions.getCollision(numCollisions - 1); float inaccuracy = glm::length(collision->_penetration + expectedPenetration); if (fabs(inaccuracy) > EPSILON) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: bad penetration: expected = " << expectedPenetration << " actual = " << collision->_penetration << std::endl; } // contactPoint is on surface of sphereA glm::vec3 BtoA = sphereA.getPosition() - sphereB.getPosition(); glm::vec3 expectedContactPoint = sphereB.getPosition() + radiusB * glm::normalize(BtoA); inaccuracy = glm::length(collision->_contactPoint - expectedContactPoint); if (fabs(inaccuracy) > EPSILON) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: bad contactPoint: expected = " << expectedContactPoint << " actual = " << collision->_contactPoint << std::endl; } } }
void ShapeColliderTests::capsuleTouchesCapsule() { // overlapping capsules float radiusA = 2.f; float halfHeightA = 3.f; float radiusB = 3.f; float halfHeightB = 4.f; float totalRadius = radiusA + radiusB; float totalHalfLength = totalRadius + halfHeightA + halfHeightB; CapsuleShape capsuleA(radiusA, halfHeightA); CapsuleShape capsuleB(radiusB, halfHeightB); CollisionList collisions(16); int numCollisions = 0; { // side by side capsuleB.setPosition((0.99f * totalRadius) * xAxis); if (!ShapeCollider::collideShapes(&capsuleA, &capsuleB, collisions)) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: capsule and capsule should touch" << std::endl; } else { ++numCollisions; } if (!ShapeCollider::collideShapes(&capsuleB, &capsuleA, collisions)) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: capsule and capsule should touch" << std::endl; } else { ++numCollisions; } } { // end to end capsuleB.setPosition((0.99f * totalHalfLength) * yAxis); if (!ShapeCollider::collideShapes(&capsuleA, &capsuleB, collisions)) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: capsule and capsule should touch" << std::endl; } else { ++numCollisions; } if (!ShapeCollider::collideShapes(&capsuleB, &capsuleA, collisions)) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: capsule and capsule should touch" << std::endl; } else { ++numCollisions; } } { // rotate B and move it to the side glm::quat rotation = glm::angleAxis(PI_OVER_TWO, zAxis); capsuleB.setRotation(rotation); capsuleB.setPosition((0.99f * (totalRadius + capsuleB.getHalfHeight())) * xAxis); if (!ShapeCollider::collideShapes(&capsuleA, &capsuleB, collisions)) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: capsule and capsule should touch" << std::endl; } else { ++numCollisions; } if (!ShapeCollider::collideShapes(&capsuleB, &capsuleA, collisions)) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: capsule and capsule should touch" << std::endl; } else { ++numCollisions; } } { // again, but this time check collision details float overlap = 0.1f; glm::quat rotation = glm::angleAxis(PI_OVER_TWO, zAxis); capsuleB.setRotation(rotation); glm::vec3 positionB = ((totalRadius + capsuleB.getHalfHeight()) - overlap) * xAxis; capsuleB.setPosition(positionB); // capsuleA vs capsuleB if (!ShapeCollider::collideShapes(&capsuleA, &capsuleB, collisions)) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: capsule and capsule should touch" << std::endl; } else { ++numCollisions; } CollisionInfo* collision = collisions.getCollision(numCollisions - 1); glm::vec3 expectedPenetration = overlap * xAxis; float inaccuracy = glm::length(collision->_penetration - expectedPenetration); if (fabs(inaccuracy) > EPSILON) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: bad penetration: expected = " << expectedPenetration << " actual = " << collision->_penetration << std::endl; } glm::vec3 expectedContactPoint = capsuleA.getPosition() + radiusA * xAxis; inaccuracy = glm::length(collision->_contactPoint - expectedContactPoint); if (fabs(inaccuracy) > EPSILON) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: bad contactPoint: expected = " << expectedContactPoint << " actual = " << collision->_contactPoint << std::endl; } // capsuleB vs capsuleA if (!ShapeCollider::collideShapes(&capsuleB, &capsuleA, collisions)) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: capsule and capsule should touch" << std::endl; } else { ++numCollisions; } collision = collisions.getCollision(numCollisions - 1); expectedPenetration = - overlap * xAxis; inaccuracy = glm::length(collision->_penetration - expectedPenetration); if (fabs(inaccuracy) > EPSILON) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: bad penetration: expected = " << expectedPenetration << " actual = " << collision->_penetration << std::endl; } expectedContactPoint = capsuleB.getPosition() - (radiusB + halfHeightB) * xAxis; inaccuracy = glm::length(collision->_contactPoint - expectedContactPoint); if (fabs(inaccuracy) > EPSILON) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: bad contactPoint: expected = " << expectedContactPoint << " actual = " << collision->_contactPoint << std::endl; } } { // collide cylinder wall against cylinder wall float overlap = 0.137f; float shift = 0.317f * halfHeightA; glm::quat rotation = glm::angleAxis(PI_OVER_TWO, zAxis); capsuleB.setRotation(rotation); glm::vec3 positionB = (totalRadius - overlap) * zAxis + shift * yAxis; capsuleB.setPosition(positionB); // capsuleA vs capsuleB if (!ShapeCollider::collideShapes(&capsuleA, &capsuleB, collisions)) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: capsule and capsule should touch" << std::endl; } else { ++numCollisions; } CollisionInfo* collision = collisions.getCollision(numCollisions - 1); glm::vec3 expectedPenetration = overlap * zAxis; float inaccuracy = glm::length(collision->_penetration - expectedPenetration); if (fabs(inaccuracy) > EPSILON) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: bad penetration: expected = " << expectedPenetration << " actual = " << collision->_penetration << std::endl; } glm::vec3 expectedContactPoint = capsuleA.getPosition() + radiusA * zAxis + shift * yAxis; inaccuracy = glm::length(collision->_contactPoint - expectedContactPoint); if (fabs(inaccuracy) > EPSILON) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: bad contactPoint: expected = " << expectedContactPoint << " actual = " << collision->_contactPoint << std::endl; } } }
void ShapeColliderTests::capsuleMissesCapsule() { // non-overlapping capsules float radiusA = 2.f; float halfHeightA = 3.f; float radiusB = 3.f; float halfHeightB = 4.f; float totalRadius = radiusA + radiusB; float totalHalfLength = totalRadius + halfHeightA + halfHeightB; CapsuleShape capsuleA(radiusA, halfHeightA); CapsuleShape capsuleB(radiusA, halfHeightA); CollisionList collisions(16); // side by side capsuleB.setPosition((1.01f * totalRadius) * xAxis); if (ShapeCollider::collideShapes(&capsuleA, &capsuleB, collisions)) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: capsule and capsule should NOT touch" << std::endl; } if (ShapeCollider::collideShapes(&capsuleB, &capsuleA, collisions)) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: capsule and capsule should NOT touch" << std::endl; } // end to end capsuleB.setPosition((1.01f * totalHalfLength) * xAxis); if (ShapeCollider::collideShapes(&capsuleA, &capsuleB, collisions)) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: capsule and capsule should NOT touch" << std::endl; } if (ShapeCollider::collideShapes(&capsuleB, &capsuleA, collisions)) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: capsule and capsule should NOT touch" << std::endl; } // rotate B and move it to the side glm::quat rotation = glm::angleAxis(PI_OVER_TWO, zAxis); capsuleB.setRotation(rotation); capsuleB.setPosition((1.01f * (totalRadius + capsuleB.getHalfHeight())) * xAxis); if (ShapeCollider::collideShapes(&capsuleA, &capsuleB, collisions)) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: capsule and capsule should NOT touch" << std::endl; } if (ShapeCollider::collideShapes(&capsuleB, &capsuleA, collisions)) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: capsule and capsule should NOT touch" << std::endl; } if (collisions.size() > 0) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: expected empty collision list but size is " << collisions.size() << std::endl; } }
void VerletShapeTests::capsuleMissesCapsule() { // non-overlapping capsules float radiusA = 2.0f; float halfHeightA = 3.0f; float radiusB = 3.0f; float halfHeightB = 4.0f; float totalRadius = radiusA + radiusB; float totalHalfLength = totalRadius + halfHeightA + halfHeightB; // create points for the shapes VerletPoint points[4]; for (int i = 0; i < 4; ++i) { points[i]._position = glm::vec3(0.0f); } // give the points to the shapes VerletCapsuleShape capsuleA(radiusA, points+0, points+1); VerletCapsuleShape capsuleB(radiusB, points+2, points+3); capsuleA.setHalfHeight(halfHeightA); capsuleA.setHalfHeight(halfHeightB); CollisionList collisions(16); // side by side capsuleB.setTranslation((1.01f * totalRadius) * xAxis); if (ShapeCollider::collideShapes(&capsuleA, &capsuleB, collisions)) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: capsule and capsule should NOT touch" << std::endl; } if (ShapeCollider::collideShapes(&capsuleB, &capsuleA, collisions)) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: capsule and capsule should NOT touch" << std::endl; } // end to end capsuleB.setTranslation((1.01f * totalHalfLength) * xAxis); if (ShapeCollider::collideShapes(&capsuleA, &capsuleB, collisions)) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: capsule and capsule should NOT touch" << std::endl; } if (ShapeCollider::collideShapes(&capsuleB, &capsuleA, collisions)) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: capsule and capsule should NOT touch" << std::endl; } // rotate B and move it to the side glm::quat rotation = glm::angleAxis(PI_OVER_TWO, zAxis); capsuleB.setRotation(rotation); capsuleB.setTranslation((1.01f * (totalRadius + capsuleB.getHalfHeight())) * xAxis); if (ShapeCollider::collideShapes(&capsuleA, &capsuleB, collisions)) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: capsule and capsule should NOT touch" << std::endl; } if (ShapeCollider::collideShapes(&capsuleB, &capsuleA, collisions)) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: capsule and capsule should NOT touch" << std::endl; } if (collisions.size() > 0) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: expected empty collision list but size is " << collisions.size() << std::endl; } }
//============================================================================= // Call repeatedly by the main message loop in WinMain //============================================================================= void Game::run(HWND hwnd) { if(graphics == NULL) // if graphics not initialized return; // calculate elapsed time of last frame, save in frameTime QueryPerformanceCounter(&timeEnd); frameTime = (float)(timeEnd.QuadPart - timeStart.QuadPart ) / (float)timerFreq.QuadPart; // Power saving code, requires winmm.lib // if not enough time has elapsed for desired frame rate if (frameTime < MIN_FRAME_TIME) { sleepTime = (DWORD)((MIN_FRAME_TIME - frameTime)*1000); timeBeginPeriod(1); // Request 1mS resolution for windows timer Sleep(sleepTime); // release cpu for sleepTime timeEndPeriod(1); // End 1mS timer resolution return; } if (frameTime > 0.0) fps = (fps*0.99f) + (0.01f/frameTime); // average fps if (frameTime > MAX_FRAME_TIME) // if frame rate is very slow frameTime = MAX_FRAME_TIME; // limit maximum frameTime timeStart = timeEnd; //PAUSE and UNPAUSE the game if(input->isStartPressed() && (currentState == OVERWORLD || currentState == BATTLE)) { if(paused) { paused = false; if(currentState == BATTLE) { audio->stopCue(NOSTRINGS); audio->playCue(BATTLELOOP); } else if (currentState == OVERWORLD) { audio->stopCue(BATTLELOOP); audio->playCue(NOSTRINGS); } } else { audio->stopCue(NOSTRINGS); audio->stopCue(BATTLELOOP); paused = true; } } // update(), ai(), and collisions() are pure virtual functions. // These functions must be provided in the class that inherits from Game. if (!paused) // if not paused { update(); // update all game items ai(); // artificial intelligence collisions(); // handle collisions input->vibrateControllers(frameTime); // handle controller vibration } renderGame(); // draw all game items input->readControllers(); // read state of controllers audio->run(); // perform periodic sound engine tasks // if Alt+Enter toggle fullscreen/window if (input->isKeyDown(ALT_KEY) && input->wasKeyPressed(ENTER_KEY)) setDisplayMode(graphicsNS::TOGGLE); // toggle fullscreen/window // if Esc key, set window mode //if (input->isKeyDown(ESC_KEY)) // setDisplayMode(graphicsNS::WINDOW); // set window mode // Clear input // Call this after all key checks are done input->clear(inputNS::KEYS_PRESSED); }
void BouncyLogo::advance(int stage) { switch ( stage ) { case 0: { double vx = xVelocity(); double vy = yVelocity(); if ( vx == 0.0 && vy == 0.0 ) { // stopped last turn initSpeed(); vx = xVelocity(); vy = yVelocity(); } double nx = x() + vx; double ny = y() + vy; if ( nx < 0 || nx >= canvas()->width() ) vx = -vx; // 換反方向 if ( ny < 0 || ny >= canvas()->height() ) vy = -vy; // 換反方向 for (int bounce=0; bounce<4; bounce++) { QCanvasItemList l=collisions(FALSE); // 沒有那麼精準的傳回所有有碰撞的canvas item for (QCanvasItemList::Iterator it=l.begin(); it!=l.end(); ++it) { QCanvasItem *hit = *it; if ( hit->rtti()==logo_rtti && hit->collidesWith(this) ) { switch ( bounce ) { case 0: vx = -vx; break; case 1: vy = -vy; vx = -vx; break; case 2: vx = -vx; break; case 3: // Stop for this turn vx = 0; vy = 0; break; } setVelocity(vx,vy); break; } } } if ( x()+vx < 0 || x()+vx >= canvas()->width() ) vx = 0; if ( y()+vy < 0 || y()+vy >= canvas()->height() ) vy = 0; setVelocity(vx,vy); } break; case 1: QCanvasItem::advance(stage); break; } }
/**Moves the objects in the game*/ void Game::animate() { //updates score gScene->removeItem(sAmount); score += 10; QString temp = QString::number(score); sAmount = new QGraphicsSimpleTextItem(temp); sAmount->setPos(400, 450); sAmount->setFont(fontT); sAmount->setZValue(2); gScene->addItem(sAmount); //moves all other things for(int l=0; l<things.size(); l++) { things[l]->move(yoshi->getLocx(), yoshi->getLocy()); if(things[l]->type == Thing::kamekEnemy && things[l]->frame == 4) { int mod = levelCnt % 3; if(mod == 0 || levelCnt >= 3) mod = 3; if(things[l]->right) { int y = things[l]->getLocy(); int x = things[l]->getLocx() +3; switch(rand()%mod){ case 0: newMagic(x, y, 0); break; case 1: newBolt(x, y, 0); break; case 2: newWind(x, y, 0); break; } } else { int y = things[l]->getLocy(); int x = things[l]->getLocx() -28; switch(rand()%mod){ case 0: newMagic(x, y, 1); break; case 1: newBolt(x, y, 1); break; case 2: newWind(x, y, 1); break; } } } if(things[l]->del) { gScene->removeItem(things[l]); things.pop(l); } } if(timeCnt >= 1000) { interval -= (interval/16); timer->setInterval(interval); timeCnt = 0; goombaMax-=goombaMax*1/4; koopaMax-=koopaMax*1/4; kamekMax-=kamekMax*1/4; billMax-=billMax*1/4; background->move(0, 0); levelCnt++; gScene->removeItem(levelAmount); temp = QString::number(levelCnt); levelAmount = new QGraphicsSimpleTextItem(temp); levelAmount->setPos(400, 480); levelAmount->setFont(fontT); levelAmount->setZValue(2); gScene->addItem(levelAmount); } else timeCnt++; //collisions collisions(); }
void SdDurationCanvas::menu(const QPoint & p) { Q3PopupMenu m(0); Q3CanvasItemList items = collisions(TRUE); Q3PtrList<SdDurationCanvas> l; Q3CanvasItemList::ConstIterator it; Q3CanvasItemList::ConstIterator end = items.end(); for (it = items.begin(); it != end; ++it) { if ((*it)->visible()) { DiagramItem * di = QCanvasItemToDiagramItem(*it); if ((di != 0) && (di->type() == UmlActivityDuration) && (((SdDurationCanvas *) di)->support == support)) l.append((SdDurationCanvas *) di); } } m.insertItem(new MenuTitle(TR("Activity bar"), m.font()), -1); m.insertSeparator(); m.insertItem(TR("Upper"), 0); m.insertItem(TR("Lower"), 1); m.insertItem(TR("Go up"), 9); m.insertItem(TR("Go down"), 10); m.insertSeparator(); m.insertItem((coregion) ? TR("Draw as activity bar") : TR("Draw as a coregion"), 7); m.insertItem(TR("Edit drawing settings"), 2); m.insertSeparator(); m.insertItem(TR("Select linked items"), 3); m.insertSeparator(); m.insertItem(TR("Remove from diagram"), 4); m.insertSeparator(); m.insertItem(TR("Cut here"), 5); if (!l.isEmpty()) m.insertItem(TR("Merge juxtaposed activity bars"), 6); if (support->isaDuration()) m.insertItem(TR("Collapse in parent bar"), 8); switch (m.exec(QCursor::pos())) { case 0: upper(); modified(); return; case 1: lower(); modified(); return; case 9: z_up(); modified(); // call package_modified() return; case 10: z_down(); modified(); // call package_modified() return; case 2: edit_drawing_settings(); return; case 3: select_associated(); break; case 4: delete_it(); package_modified(); break; case 5: cut(p); package_modified(); break; case 6: merge(l); package_modified(); break; case 7: coregion = !coregion; modified(); return; case 8: { SdDurationCanvas * d = (SdDurationCanvas *) support; d->collapse(this); d->update_hpos(); // update sub duration and msg hpos d->update_self(); } package_modified(); break; default: return; } canvas()->update(); }
void ShapeColliderTests::sphereTouchesCapsule() { // overlapping sphere and capsule float radiusA = 2.f; float radiusB = 1.f; float totalRadius = radiusA + radiusB; float halfHeightB = 2.f; float alpha = 0.5f; float beta = 0.5f; float radialOffset = alpha * radiusA + beta * radiusB; SphereShape sphereA(radiusA); CapsuleShape capsuleB(radiusB, halfHeightB); CollisionList collisions(16); int numCollisions = 0; { // sphereA collides with capsuleB's cylindrical wall sphereA.setPosition(radialOffset * xAxis); if (!ShapeCollider::collideShapes(&sphereA, &capsuleB, collisions)) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: sphere and capsule should touch" << std::endl; } else { ++numCollisions; } // penetration points from sphereA into capsuleB CollisionInfo* collision = collisions.getCollision(numCollisions - 1); glm::vec3 expectedPenetration = (radialOffset - totalRadius) * xAxis; float inaccuracy = glm::length(collision->_penetration - expectedPenetration); if (fabs(inaccuracy) > EPSILON) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: bad penetration: expected = " << expectedPenetration << " actual = " << collision->_penetration << std::endl; } // contactPoint is on surface of sphereA glm::vec3 expectedContactPoint = sphereA.getPosition() - radiusA * xAxis; inaccuracy = glm::length(collision->_contactPoint - expectedContactPoint); if (fabs(inaccuracy) > EPSILON) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: bad contactPoint: expected = " << expectedContactPoint << " actual = " << collision->_contactPoint << std::endl; } // capsuleB collides with sphereA if (!ShapeCollider::collideShapes(&capsuleB, &sphereA, collisions)) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: capsule and sphere should touch" << std::endl; } else { ++numCollisions; } // penetration points from sphereA into capsuleB collision = collisions.getCollision(numCollisions - 1); expectedPenetration = - (radialOffset - totalRadius) * xAxis; inaccuracy = glm::length(collision->_penetration - expectedPenetration); if (fabs(inaccuracy) > EPSILON) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: bad penetration: expected = " << expectedPenetration << " actual = " << collision->_penetration << std::endl; } // contactPoint is on surface of capsuleB glm::vec3 BtoA = sphereA.getPosition() - capsuleB.getPosition(); glm::vec3 closestApproach = capsuleB.getPosition() + glm::dot(BtoA, yAxis) * yAxis; expectedContactPoint = closestApproach + radiusB * glm::normalize(BtoA - closestApproach); inaccuracy = glm::length(collision->_contactPoint - expectedContactPoint); if (fabs(inaccuracy) > EPSILON) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: bad contactPoint: expected = " << expectedContactPoint << " actual = " << collision->_contactPoint << std::endl; } } { // sphereA hits end cap at axis glm::vec3 axialOffset = (halfHeightB + alpha * radiusA + beta * radiusB) * yAxis; sphereA.setPosition(axialOffset * yAxis); if (!ShapeCollider::collideShapes(&sphereA, &capsuleB, collisions)) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: sphere and capsule should touch" << std::endl; } else { ++numCollisions; } // penetration points from sphereA into capsuleB CollisionInfo* collision = collisions.getCollision(numCollisions - 1); glm::vec3 expectedPenetration = - ((1.f - alpha) * radiusA + (1.f - beta) * radiusB) * yAxis; float inaccuracy = glm::length(collision->_penetration - expectedPenetration); if (fabs(inaccuracy) > EPSILON) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: bad penetration: expected = " << expectedPenetration << " actual = " << collision->_penetration << std::endl; } // contactPoint is on surface of sphereA glm::vec3 expectedContactPoint = sphereA.getPosition() - radiusA * yAxis; inaccuracy = glm::length(collision->_contactPoint - expectedContactPoint); if (fabs(inaccuracy) > EPSILON) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: bad contactPoint: expected = " << expectedContactPoint << " actual = " << collision->_contactPoint << std::endl; } // capsuleB collides with sphereA if (!ShapeCollider::collideShapes(&capsuleB, &sphereA, collisions)) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: capsule and sphere should touch" << std::endl; } else { ++numCollisions; } // penetration points from sphereA into capsuleB collision = collisions.getCollision(numCollisions - 1); expectedPenetration = ((1.f - alpha) * radiusA + (1.f - beta) * radiusB) * yAxis; inaccuracy = glm::length(collision->_penetration - expectedPenetration); if (fabs(inaccuracy) > EPSILON) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: bad penetration: expected = " << expectedPenetration << " actual = " << collision->_penetration << std::endl; } // contactPoint is on surface of capsuleB glm::vec3 endPoint; capsuleB.getEndPoint(endPoint); expectedContactPoint = endPoint + radiusB * yAxis; inaccuracy = glm::length(collision->_contactPoint - expectedContactPoint); if (fabs(inaccuracy) > EPSILON) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: bad contactPoint: expected = " << expectedContactPoint << " actual = " << collision->_contactPoint << std::endl; } } { // sphereA hits start cap at axis glm::vec3 axialOffset = - (halfHeightB + alpha * radiusA + beta * radiusB) * yAxis; sphereA.setPosition(axialOffset * yAxis); if (!ShapeCollider::collideShapes(&sphereA, &capsuleB, collisions)) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: sphere and capsule should touch" << std::endl; } else { ++numCollisions; } // penetration points from sphereA into capsuleB CollisionInfo* collision = collisions.getCollision(numCollisions - 1); glm::vec3 expectedPenetration = ((1.f - alpha) * radiusA + (1.f - beta) * radiusB) * yAxis; float inaccuracy = glm::length(collision->_penetration - expectedPenetration); if (fabs(inaccuracy) > EPSILON) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: bad penetration: expected = " << expectedPenetration << " actual = " << collision->_penetration << std::endl; } // contactPoint is on surface of sphereA glm::vec3 expectedContactPoint = sphereA.getPosition() + radiusA * yAxis; inaccuracy = glm::length(collision->_contactPoint - expectedContactPoint); if (fabs(inaccuracy) > EPSILON) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: bad contactPoint: expected = " << expectedContactPoint << " actual = " << collision->_contactPoint << std::endl; } // capsuleB collides with sphereA if (!ShapeCollider::collideShapes(&capsuleB, &sphereA, collisions)) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: capsule and sphere should touch" << std::endl; } else { ++numCollisions; } // penetration points from sphereA into capsuleB collision = collisions.getCollision(numCollisions - 1); expectedPenetration = - ((1.f - alpha) * radiusA + (1.f - beta) * radiusB) * yAxis; inaccuracy = glm::length(collision->_penetration - expectedPenetration); if (fabs(inaccuracy) > EPSILON) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: bad penetration: expected = " << expectedPenetration << " actual = " << collision->_penetration << std::endl; } // contactPoint is on surface of capsuleB glm::vec3 startPoint; capsuleB.getStartPoint(startPoint); expectedContactPoint = startPoint - radiusB * yAxis; inaccuracy = glm::length(collision->_contactPoint - expectedContactPoint); if (fabs(inaccuracy) > EPSILON) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: bad contactPoint: expected = " << expectedContactPoint << " actual = " << collision->_contactPoint << std::endl; } } if (collisions.size() != numCollisions) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: expected " << numCollisions << " collisions but actual number is " << collisions.size() << std::endl; } }