//---------------------------------------------------------------------------- Smoke2D::Smoke2D (Renderer* renderer, float x0, float y0, float x1, float y1, float dt, float denViscosity, float velViscosity, int imax, int jmax, int numGaussSeidelIterations, int numVortices) : mX0(x0), mY0(y0), mX1(x1), mY1(y1), mDt(dt), mDenViscosity(denViscosity), mVelViscosity(velViscosity), mIMax(imax), mJMax(jmax), mNumGaussSeidelIterations(numGaussSeidelIterations), mNumVortices(numVortices), mNumActive(0), mGravity(Vector2f::ZERO), mRenderer(renderer), mIP(0), mUseVortexOverlay(false) { mIMaxM1 = mIMax - 1; mJMaxM1 = mJMax - 1; mIMaxP1 = mIMax + 1; mJMaxP1 = mJMax + 1; mNumPixels = mIMaxP1*mJMaxP1; mDx = (mX1 - mX0)/(float)mIMax; mDy = (mY1 - mY0)/(float)mJMax; mDxDx = mDx*mDx; mDyDy = mDy*mDy; mHalfDivDx = 0.5f/mDx; mHalfDivDy = 0.5f/mDy; mDtDivDx = mDt/mDx; mDtDivDy = mDt/mDy; mDtDivDxDx = mDt/mDxDx; mDtDivDyDy = mDt/mDyDy; mEpsilon0 = 0.5f*mDxDx*mDyDy/(mDxDx + mDyDy); mEpsilonX = mEpsilon0/mDxDx; mEpsilonY = mEpsilon0/mDyDy; mDenLambdaX = mDenViscosity*mDtDivDxDx; mDenLambdaY = mDenViscosity*mDtDivDyDy; mVelLambdaX = mVelViscosity*mDtDivDxDx; mVelLambdaY = mVelViscosity*mDtDivDyDy; mDenGamma0 = 1.0f/(1.0f + 2.0f*(mDenLambdaX + mDenLambdaY)); mDenGammaX = mDenLambdaX*mDenGamma0; mDenGammaY = mDenLambdaY*mDenGamma0; mVelGamma0 = 1.0f/(1.0f + 2.0f*(mVelLambdaX + mVelLambdaY)); mVelGammaX = mVelLambdaX*mVelGamma0; mVelGammaY = mVelLambdaY*mVelGamma0; mTime = 0.0f; mVortexCenter = new1<Vector2f>(mNumVortices); mVortexVariance = new1<float>(mNumVortices); mVortexAmplitude = new1<float>(mNumVortices); mTimelessDensity = new2<float>(mIMaxP1, mJMaxP1); mTimelessVortex = new3<Vector2f>(mNumVortices, mIMaxP1, mJMaxP1); mTimelessWind = new2<Vector2f>(mIMaxP1, mJMaxP1); mTimelessVelocity = new2<Vector2f>(mIMaxP1, mJMaxP1); int v; for (v = 0; v < mNumVortices; ++v) { mVortexCenter[v][0] = Mathf::UnitRandom(); mVortexCenter[v][1] = Mathf::UnitRandom(); mVortexVariance[v] = Mathf::IntervalRandom(0.001f, 0.01f); mVortexAmplitude[v] = Mathf::IntervalRandom(128.0f, 256.0f); if (Mathf::SymmetricRandom() < 0.0f) { mVortexAmplitude[v] *= -1.0f; } } for (int j = 0; j <= mJMax; ++j) { float y = mY0 + mDy*(float)j; for (int i = 0; i <= mIMax; ++i) { float x = mX0 + mDx*(float)i; // density source float dx = x - 0.25f; float dy = y - 0.75f; float arg = -(dx*dx + dy*dy)/0.01f; mTimelessDensity[j][i] = 2.0f*Mathf::Exp(arg); // density sink dx = x - 0.75f; dy = y - 0.25f; arg = -(dx*dx + dy*dy)/0.01f; mTimelessDensity[j][i] -= 2.0f*Mathf::Exp(arg); // velocity vortex source for (v = 0; v < mNumVortices; ++v) { dx = x - mVortexCenter[v][0]; dy = y - mVortexCenter[v][1]; arg = -(dx*dx + dy*dy)/mVortexVariance[v]; Vector2f vortex(dy, -dx); vortex *= mVortexAmplitude[v]*Mathf::Exp(arg); mTimelessVortex[j][i][v] = vortex; } // velocity wind source float diff = y - 0.5f; float ampl = 32.0f*Mathf::Exp(-diff*diff/0.001f); Vector2f wind(ampl, 0.0f); mTimelessWind[j][i] = wind; mTimelessVelocity[j][i] = wind; } } }
Smoke2D<Real>::Smoke2D (Real x0, Real y0, Real x1, Real y1, Real dt, Real denViscosity, Real velViscosity, int imax, int jmax, int numGaussSeidelIterations, bool densityDirichlet, int numVortices) : FLUIDBASE(x0, y0, x1, y1, dt, denViscosity, velViscosity, imax, jmax, numGaussSeidelIterations, densityDirichlet), mNumVortices(numVortices), mNumActive(0), mGravity((Real)0) { mVortexCenter = new1<Vector2<Real> >(mNumVortices); mVortexVariance = new1<Real>(mNumVortices); mVortexAmplitude = new1<Real>(mNumVortices); mTimelessDensity = new2<Real>(mIMaxP1, mJMaxP1); mTimelessVortex = new3<Vector2<Real> >(mNumVortices, mIMaxP1, mJMaxP1); mTimelessWind = new2<Vector2<Real> >(mIMaxP1, mJMaxP1); int v; for (v = 0; v < mNumVortices; ++v) { mVortexCenter[v][0] = Math<Real>::UnitRandom(); mVortexCenter[v][1] = Math<Real>::UnitRandom(); mVortexVariance[v] = Math<Real>::IntervalRandom((Real)0.001, (Real)0.01); mVortexAmplitude[v] = Math<Real>::IntervalRandom((Real)128, (Real)256); if (Math<Real>::SymmetricRandom() < (Real)0) { mVortexAmplitude[v] *= (Real)-1; } } for (int j = 0; j <= mJMax; ++j) { Real y = mY[j]; for (int i = 0; i <= mIMax; ++i) { Real x = mX[i]; // density source Real dx = x - (Real)0.25; Real dy = y - (Real)0.75; Real arg = -(dx*dx + dy*dy)/(Real)0.01; mTimelessDensity[j][i] = ((Real)2)*Math<Real>::Exp(arg); // density sink dx = x - (Real)0.75; dy = y - (Real)0.25; arg = -(dx*dx + dy*dy)/(Real)0.01; mTimelessDensity[j][i] -= ((Real)2)*Math<Real>::Exp(arg); // velocity vortex source for (v = 0; v < mNumVortices; ++v) { dx = x - mVortexCenter[v][0]; dy = y - mVortexCenter[v][1]; arg = -(dx*dx + dy*dy)/mVortexVariance[v]; Vector2<Real> vortex(dy, -dx); vortex *= mVortexAmplitude[v]*Math<Real>::Exp(arg); mTimelessVortex[j][i][v] = vortex; } // velocity wind source Real diff = y - (Real)0.5; Real ampl = ((Real)32)*Math<Real>::Exp(-diff*diff/(Real)0.001); Vector2<Real> wind(ampl, (Real)0); mTimelessWind[j][i] = wind; } } }
void playLevel(SDL_Renderer* renderer, SDL_Window* window) { TextureStorage::getInstance().setDifficultyBackground(renderer); bool isScoreRecording = false; bool isHighScore = false; bool isPaused = false; std::random_device rd; std::mt19937 eng(rd()); std::uniform_int_distribution<> randomX(2 * WALL_WIDTH, SCREEN_WIDTH - (2 * WALL_WIDTH)); std::uniform_int_distribution<> randomY(2 * WALL_WIDTH, SCREEN_HEIGHT - (2 * WALL_WIDTH)); std::uniform_int_distribution<> randomVortex(0, VORTEX_LIMIT); std::string inputText = ""; SDL_Event e; Player player(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, PLAYER_WIDTH, PLAYER_HEIGHT, PLAYER_VEL); Collectible collectible(randomX(eng), randomY(eng), resolveCoinWidth(), COIN_HEIGHT, 0); Skull skull(0, 0, SKULL_WIDTH, SKULL_HEIGHT, 0); std::vector<SDL_Rect> walls = getBoundaries(); SoundPlayer::getInstance().playMusic(); while (!isQuitting) { if (player.isDead) { SoundPlayer::getInstance().stopMusic(); if (!isScoreRecording) { isScoreRecording = HighScore::getInstance().checkAndAddNewScore(score, gameDifficulty); if (isScoreRecording) { isHighScore = true; SoundPlayer::getInstance().playHighScore(); } } } while (SDL_PollEvent(&e) != 0) { if (!isPaused) SDL_EventState(SDL_KEYUP, SDL_ENABLE); if (e.type == SDL_QUIT) { isQuitting = true; isResetting = false; reset(); } else if (e.type == SDL_KEYDOWN && e.key.keysym.sym == SDLK_ESCAPE) toggleFullscreen(window); else if (e.type == SDL_KEYDOWN && e.key.keysym.sym == SDLK_RETURN && !player.isDead) { SoundPlayer::getInstance().pauseMusic(); SoundPlayer::getInstance().playPause(); if (isPaused) isPaused = false; else { isPaused = true; SDL_EventState(SDL_KEYUP, SDL_IGNORE); } } if (isPaused) SDL_EventState(SDL_KEYDOWN, SDL_IGNORE); if (!player.isDead) { if (!isPaused) player.handleEvent(e); } else { if (e.type == SDL_TEXTINPUT) { if (inputText.size() < 3 && e.text.text[0] != ',') inputText += e.text.text; } else if (e.type == SDL_KEYDOWN) { if (e.key.keysym.sym == SDLK_n && !isHighScore) { isResetting = false; reset(); return; } else if (e.key.keysym.sym == SDLK_y && !isHighScore) { isResetting = true; reset(); return; } else if (e.key.keysym.sym == SDLK_BACKSPACE) { if (inputText.size() != 0) inputText.pop_back(); } else if (e.key.keysym.sym == SDLK_RETURN) { if (isHighScore) HighScore::getInstance().addInitials(inputText); isHighScore = false; } } } SDL_EventState(SDL_KEYDOWN, SDL_ENABLE); } if (!isPaused) { if (!player.isDead) player.move(walls, enemies, skull); else skull.move(walls); for (std::vector<Enemy>::iterator it = enemies.begin(); it != enemies.end(); ++it) { it->move(walls); } if (!collectible.isHit) { prevX = collectible.getX(); prevY = collectible.getY(); } collectible.move(player, randomX(eng), randomY(eng)); } SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF); SDL_RenderClear(renderer); TextureStorage::getInstance().bgTexture.render(0, 0, renderer); renderWalls(renderer, walls); for (std::vector<Enemy>::iterator it = enemies.begin(); it != enemies.end(); ++it) { it->render(renderer); } collectible.render(renderer); if (!player.isDead) player.render(renderer); else skull.render(renderer); TextDraw::getInstance().renderHUD(renderer); if (collectible.isHit) { time++; TextDraw::getInstance().renderScoreGain(prevX, prevY, renderer); prevX++; prevY--; if (time == 20) { time = 0; Enemy enemy(randomX(eng), randomY(eng), ENEMY_WIDTH, ENEMY_HEIGHT, ENEMY_VEL * (int)gameDifficulty, EnemyType::SPIKEBALL); if (randomVortex(eng) > VORTEX_LIMIT / (int)gameDifficulty) { Enemy vortex(randomX(eng), randomY(eng), ENEMY_WIDTH, ENEMY_HEIGHT, 0, EnemyType::VORTEX); while (checkCollision(vortex.getHitbox(), player.getHitbox())) { vortex.setX(randomX(eng)); vortex.setY(randomY(eng)); vortex.setHitbox(); } enemies.push_back(vortex); } while (checkCollision(enemy.getHitbox(), player.getHitbox())) { enemy.setX(randomX(eng)); enemy.setY(randomY(eng)); enemy.setHitbox(); } enemies.push_back(enemy); collectible.isHit = false; } } if (player.isDead) TextDraw::getInstance().renderGameOver(renderer, isHighScore, inputText); if (isPaused)TextDraw::getInstance().renderPause(renderer); SDL_RenderPresent(renderer); frameCount++; if (frameCount == DISPLAY_LIMIT) frameCount = 0; } }