void BallMap::removeBall() { // make sequence remove m_isAnimationing = true; std::list<BallSprite *>::iterator itList; for (itList = m_readyRemoveList.begin(); itList != m_readyRemoveList.end(); itList++) { BallSprite *ball = dynamic_cast<BallSprite*>(*itList); if (!ball) { continue; } if (ball->getIsNeedRemove()) { m_isNeedFillVacancies = true;//需要掉落 m_isNeedCheckSelf = true; explodeBall(ball); } } m_readyRemoveList.clear(); }
void Ball::animateBall(float interval) { bool collision = false; Vector3 normal(0.0f, 0.0f, 0.0f); Vector3 ball; Vector3 step; mVelocity = add(mVelocity, scale(MOVE_FORCE / mMass * interval, mPushDirection)); mVelocity.z -= GRAVITY * interval; /* collision detection */ step = scale(interval, mVelocity); ball = mPos + step; /* check only fields near by the ball. check field under ball first!!! */ QuadList list = getFieldSphereIntersection(ball, BALL_RADIUS); while (list.next()) { Quad quad = *list; const Vector3* q = quad.mVertices; const Vector3& dir = quad.mNormals[0]; Vector3 a1 = closestPointTriangle(ball, q[0], q[1], q[2]); Vector3 a2 = closestPointTriangle(ball, q[2], q[3], q[0]); float d1 = (ball - a1).len(); float d2 = (ball - a2).len(); Vector3 a = (d1 <= d2) ? a1 : a2; if ((a - ball).len() <= BALL_RADIUS) { /* dist = vector from ball center to quad */ Vector3 dist = a - ball; float l = dist.len(); /* move = vector to move the ball out of quad */ Vector3 move = scale(-((mRadius - l) / l), dist); /* some rotation for a better look */ Vector3 right = norm(cross(dir, step)); Vector3 forward = norm(cross(right, dir)); mAngularRate = scale(dot(sub(ball, mPos), forward) / (2.0f * M_PI * mRadius) * 360.0f / interval, right); ball = add(ball, move); normal = add(normal, move); collision = true; } } mPos = ball; normal = norm(normal); mHasBallHitGoal = false; /* contact to surface? */ if (collision) { float vn = dot(mVelocity, normal); Vector3 rebound = scale(-(1 + ELASTICITY) * vn, normal); if (len(rebound) > 3.0f * JUMP_FORCE * interval) { /* collision was to havy */ explodeBall(); } else { mVelocity = add(mVelocity, rebound); if (mJump) { mVelocity = add(mVelocity, scale(JUMP_FORCE / mMass * interval, normal)); } } int x = (int) floor(ball.x - sgLevel.origin.x); int y = (int) floor(ball.y - sgLevel.origin.y); if (x == sgLevel.finish.x && y == sgLevel.finish.y) { /* hit goal */ mHasBallHitGoal = true; } } /***/ /* damping */ mVelocity = scale(DAMPING, mVelocity); Quaternion rotation = mkQuaternion(len(mAngularRate) * interval, mAngularRate); mOrientation = mulQuaternion(rotation, mOrientation); /* falling to infinity */ if (mPos.z < -1.0f) { explodeBall(); } /* reset through user */ if (wasKeyPressed(KEY_ENTER)) { explodeBall(); } mPushDirection = Vector3(0.0f, 0.0f, 0.0f); mJump = false; }