int CParticle::Bounce (int nThread) { if (!gameOpts->render.particles.bCollisions) return 1; if (!CollideWithWall (nThread)) { m_nBounce = ((m_nType == BUBBLE_PARTICLES) || (m_nType == WATERFALL_PARTICLES)) ? 1 : 2; return 1; } if (!--m_nBounce) return 0; fix dot = CFixVector::Dot (m_vDrift, *wallNorm [nThread]); if (dot < I2X (1) / 100) { m_nLife = -1; return 0; } m_vDrift += m_vDrift + *wallNorm [nThread] * (-2 * dot); return 1; }
void GameView::UpdateMonsters(float dt) { for (std::size_t index = 0; index < m_monsters.size(); ++index) { const MonsterPtr& monster = m_monsters[index]; if (monster) { CollideWithWall(*monster); monster->Update(dt); CollideWithCatchers(*monster); m_trails[index]->posX = monster->GetPosition().x; m_trails[index]->posY = monster->GetPosition().y; if (monster->IsDead()) { m_trails[index]->Finish(); m_shadow = m_effects.AddEffect("Shadow"); m_shadow->posX = monster->GetPosition().x; m_shadow->posY = monster->GetPosition().y; m_monsterPool.set(std::move(monster)); std::swap(m_monsters[index], m_monsters.back()); std::swap(m_trails[index], m_trails.back()); m_monsters.resize(m_monsters.size() - 1); m_trails.resize(m_trails.size() - 1); m_shadow->Reset(); } } } }
int CParticle::Update (int nCurTime) { int j, nRad; short nSegment; fix t, dot; CFixVector vPos, drift; fix drag = (m_nType == BUBBLE_PARTICLES) ? I2X (1) : F2X ((float) m_nLife / (float) m_nTTL); if ((m_nLife <= 0) /*|| (m_color [0].alpha < 0.01f)*/) return 0; t = nCurTime - m_nMoved; if (m_nDelay > 0) m_nDelay -= t; else { vPos = m_vPos; drift = m_vDrift; if ((m_nType == SMOKE_PARTICLES) /*|| (m_nType == BUBBLE_PARTICLES)*/) { drift [X] = ChangeDir (drift [X]); drift [Y] = ChangeDir (drift [Y]); drift [Z] = ChangeDir (drift [Z]); } for (j = 0; j < 2; j++) { if (t < 0) t = -t; m_vPos = vPos + drift * t; //(I2X (t) / 1000); if (m_bHaveDir) { CFixVector vi = drift, vj = m_vDir; CFixVector::Normalize (vi); CFixVector::Normalize (vj); // if (CFixVector::Dot (drift, m_vDir) < 0) if (CFixVector::Dot (vi, vj) < 0) drag = -drag; // VmVecScaleInc (&drift, &m_vDir, drag); m_vPos += m_vDir * drag; } if ((m_nType == BUBBLE_PARTICLES) || (m_nTTL - m_nLife > I2X (1) / 16)) { nSegment = FindSegByPos (m_vPos, m_nSegment, 0, 0, 1); if (nSegment < 0) { #if DBG if (m_nSegment == nDbgSeg) nSegment = FindSegByPos (m_vPos, m_nSegment, 1, 0, 1); #endif nSegment = FindSegByPos (m_vPos, m_nSegment, 0, 1, 1); if (nSegment < 0) return 0; } if ((m_nType == BUBBLE_PARTICLES) && (SEGMENTS [nSegment].m_nType != SEGMENT_IS_WATER)) return 0; m_nSegment = nSegment; } if (gameOpts->render.particles.bCollisions && CollideWithWall ()) { //Reflect the particle if (m_nType == BUBBLE_PARTICLES) return 0; if (j) return 0; else if (!(dot = CFixVector::Dot (drift, *wallNorm))) return 0; else { drift = m_vDrift + *wallNorm * (-2 * dot); //VmVecScaleAdd (&m_vPos, &vPos, &drift, 2 * t); m_nBounce = 3; continue; } } else if (m_nBounce) m_nBounce--; else { break; } } m_vDrift = drift; if (m_nTTL >= 0) { #if SMOKE_SLOWMO m_nLife -= (int) (t / gameStates.gameplay.slowmo [0].fSpeed); #else m_nLife -= t; #endif if ((m_nType == SMOKE_PARTICLES) && (nRad = m_nRad)) { if (m_bBlowUp) { if (m_nWidth >= nRad) m_nRad = 0; else { m_nWidth += nRad / 10 / m_bBlowUp; m_nHeight += nRad / 10 / m_bBlowUp; if (m_nWidth > nRad) m_nWidth = nRad; if (m_nHeight > nRad) m_nHeight = nRad; m_color [0].alpha *= (1.0f + 0.0725f / m_bBlowUp); if (m_color [0].alpha > 1) m_color [0].alpha = 1; } } else { if (m_nWidth <= nRad) m_nRad = 0; else { m_nRad += nRad / 5; m_color [0].alpha *= 1.0725f; if (m_color [0].alpha > 1) m_color [0].alpha = 1; } } } } } m_nMoved = nCurTime; return 1; }