示例#1
0
文件: World.cpp 项目: eggw/xviii
void World::turnlyUpdate(){
    boost::random::uniform_int_distribution<int> dist(1, 100);

    incrementElapsedTurns();
    getCurrentTime().increment();

    //The weather will tend to change every ~8 hours, or 480 minutes.
    //Ideally, something like this:

    //1 hour  (60)  -> 4%
    //2 hours (120) -> 6%
    //3 hours (180) -> 8%
    //4 hours (240) -> 12.5%
    //5 hours (300) -> 16%
    //6 hours (360) -> 24%
    //7 hours (420) -> 30%
    //8 hours (480) -> 40%

    for(auto& effect : weatherEffects){
        effect.second += minutesPerTurn;
    }

    auto effect = std::begin(weatherEffects);
    while(effect != std::end(weatherEffects)){

        int removeEffect{dist(masterManager.randomEngine)};
        //For instance, if the effect has been there for 240 minutes, it will have an
        //40% chance of being removed. There is a hard cap of 80%.

        int totalChance = effect->second / 15;
        if(totalChance > 50){
            totalChance = 50;
        }

        if(removeEffect <= totalChance){
            effect = weatherEffects.erase(effect);
        }
        else{
            effect++;
        }

    }

    int hourlyChance = 20;
    int turnlyChance = hourlyChance / (60/minutesPerTurn);

    int randomRoll{dist(masterManager.randomEngine)};

    if (randomRoll <= turnlyChance){
        addWeather();
    }


    ////////////////////////////////////////////////////////////////////////////////
    //////////////////MUD CREATION AND REMOVAL//////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////


    //Firstly, depending on whether the rain is heavy or light, there will be a varying
    //amount of mud formations per turn.


    bool rain{false};
    int minimumMudFormations{0};

    for(auto& effect : weatherEffects){

        if(effect.first == World::Weather::HEAVY_RAIN){
            rain = true;
            minimumMudFormations = 4;
            break;
        }
        else if(effect.first == World::Weather::LIGHT_RAIN){
            rain = true;
            minimumMudFormations = 2;
            break;
        }

    }

    //A random tile on the map that we call the origin is converted to mud (if possible).

    if(rain){

        for (int i{0}; i < minimumMudFormations; ++i){
            boost::random::uniform_int_distribution<int> randomIndexDist(0, getDimensions().x * getDimensions().y);
            int randomIndex{randomIndexDist(masterManager.randomEngine)};

            sf::Vector2i originPosition{cartesianPosAtIndex(randomIndex)};
            TerrainTile* origin = terrainAtCartesianPos(originPosition);

            bool originConvertedToMud{false};

            if(origin->getTerrainType() == TerrainTile::TerrainType::MEADOW){
                toggleMud(origin);
                originConvertedToMud = true;
            }

            if(!originConvertedToMud){
                break;
            }

            //There is then an 4/5 chance that a neighboring tile is also converted, if possible...

            int randomNumber{0};
            do{
                boost::random::uniform_int_distribution<int> randomDist(1, 5);
                randomNumber = randomDist(masterManager.randomEngine);

                if(randomNumber >= 2){
                    boost::random::uniform_int_distribution<int> randomDisplacementDist(-1, 1);
                    int randomDisplacementX{randomDisplacementDist(masterManager.randomEngine)};
                    int randomDisplacementY{randomDisplacementDist(masterManager.randomEngine)};

                    sf::Vector2i newPosition{originPosition.x + randomDisplacementX, originPosition.y + randomDisplacementY};
                    TerrainTile* newTerrain = terrainAtCartesianPos(newPosition);

                    if(newTerrain != nullptr){
                        if(newTerrain->getTerrainType() == TerrainTile::TerrainType::MEADOW){
                            toggleMud(newTerrain);
                        }
                    }
                }

            //... and a 3/5 chance for this process to repeat.
            }while(randomNumber >= 3);

        }


        //While new mud tiles are formed, every old mud tile has a 1/8 chance to spread to a neighboring tile, if possible

        //IMPORTANT NOTE: here we use an integer-based index rather than a foreach loop, because toggleMud()
        //itself actually erases a mud tile from mudTiles. So if we do a foreach mudTiles loop, we end up with
        //messy dangling pointers and, in my case, days of debugging crashes.

        for(std::vector<Mud*>::size_type i{0}; i < mudTiles.size(); i++){
            boost::random::uniform_int_distribution<int> randomDist(1, 8);
            int randomNumber = randomDist(masterManager.randomEngine);

            if(randomNumber == 1){
                    boost::random::uniform_int_distribution<int> randomDisplacementDist(-1, 1);
                    int randomDisplacementX{randomDisplacementDist(masterManager.randomEngine)};
                    int randomDisplacementY{randomDisplacementDist(masterManager.randomEngine)};

                    sf::Vector2i originPosition = mudTiles[i]->getCartesianPos();
                    sf::Vector2i newPosition{originPosition.x + randomDisplacementX, originPosition.y + randomDisplacementY};
                    TerrainTile* newTerrain = terrainAtCartesianPos(newPosition);

                    if(newTerrain != nullptr){
                        if(newTerrain->getTerrainType() == TerrainTile::TerrainType::MEADOW){
                            toggleMud(newTerrain);
                        }
                    }
                }
        }

    }

    //Finally, after the rain has stopped, each mud tile has a 9/10 chance to dry up.

    else if (!rain){

        //IMPORTANT NOTE: here we use an integer-based index rather than a foreach loop, because toggleMud()
        //itself actually erases a mud tile from mudTiles. So if we do a foreach mudTiles loop, we end up with
        //messy dangling pointers and, in my case, days of debugging crashes.

        for(std::vector<Mud*>::size_type i{0}; i < mudTiles.size(); i++){
            boost::random::uniform_int_distribution<int> randomDryingChanceDist(1, 10);
            int randomDryingChance{randomDryingChanceDist(masterManager.randomEngine)};

            if(randomDryingChance <= 9){
                toggleMud(mudTiles[i]);
            }
        }

    }

    unhighlightVisibleTiles();
    visibleTiles.clear();
}
示例#2
0
void GameState_Setup::getInput(){
	sf::Event event;

	while (game->mWindow.pollEvent(event)){

		switch (event.type){

		case sf::Event::MouseMoved:
			game->mousePos.x = event.mouseMove.x;
			game->mousePos.y = event.mouseMove.y;
			break;

		case sf::Event::Resized:
			handleResize();
			break;

		case sf::Event::MouseButtonPressed:
			if (event.mouseButton.button == sf::Mouse::Middle){
				middleButtonHeld = true;
				middleButtonCoords = {event.mouseButton.x, event.mouseButton.y};
			}

			else if (event.mouseButton.button == sf::Mouse::Left && drawUI){

				//If no menu item was selectedSpawnableUnit, select it

				if (selectedSpawnableUnit == nullptr){
					sf::Vector2f worldCoords{game->mWindow.mapPixelToCoords(game->mousePos, *game->currentView)};
					sf::Vector2f uiCoords{game->mWindow.mapPixelToCoords(game->mousePos, setupUI.uiView)};

					std::vector<SpawnableUnit> current{game->currentPlayer->getSpawnableUnits()};

					for (size_t i{0}; i < current.size(); ++i){
						if (uiCoords.x > current[i].left() && uiCoords.x < current[i].right()
							&&
							uiCoords.y > current[i].top() && uiCoords.y < current[i].bottom()){

							selectedSpawnableUnit = std::move(std::unique_ptr<SpawnableUnit>(new SpawnableUnit(current[i])));
							break;

						}
					}


					if (uiCoords.x >= setupUI.getButton().left() && uiCoords.x <= setupUI.getButton().right()
						&&
						uiCoords.y >= setupUI.getButton().top() && uiCoords.y <= setupUI.getButton().bottom()){

						//As long as the player has at least one non-general unit
						if (game->currentPlayer->getDeploymentPoints() <= game->currentPlayer->getMaxDeploymentPoints() - 1){
							game->currentPlayer->setReady(true);
						}

					}

					if(selectedSpawnableUnit == nullptr){
						middleButtonHeld = true;
						middleButtonCoords = {event.mouseButton.x, event.mouseButton.y};
					}
				}

				//Spawn a unit on the tile:

				else{
					sf::Vector2i mouseCoords{event.mouseButton.x, event.mouseButton.y};
					sf::Vector2i worldCoords{game->mWindow.mapPixelToCoords(mouseCoords, *game->currentView)};

					TerrainTile* terrain = game->mWorld->terrainAtPixelPos(worldCoords);

					if (terrain != nullptr){

                        if(terrain->getTerrainType() != TerrainTile::TerrainType::WATER){
                            game->currentPlayer->spawnUnit(selectedSpawnableUnit->unitID, worldCoords);
                        }

					}

					selectedSpawnableUnit = nullptr;
					break;
				}
			}


			else if (event.mouseButton.button == sf::Mouse::Right && drawUI){

				//Deselect the currently selectedSpawnableUnit icon:

				if (selectedSpawnableUnit != nullptr){
					selectedSpawnableUnit = nullptr;
					break;
				}

				//Delete a unit from a tile:

				else{
					sf::Vector2i mouseCoords{event.mouseButton.x, event.mouseButton.y};
					sf::Vector2i worldCoords{game->mWindow.mapPixelToCoords(mouseCoords, *game->currentView)};

					auto removed = game->currentPlayer->removeUnit(worldCoords);

					if(removed != nullptr){
                        game->currentPlayer->setDeploymentPoints(game->currentPlayer->getDeploymentPoints() + removed.get()->getCost());
					}

					break;
				}

			}

			break;

		case sf::Event::MouseButtonReleased:

			if (event.mouseButton.button == sf::Mouse::Middle){
				middleButtonHeld = false;
			}
			else if(event.mouseButton.button == sf::Mouse::Left){
				middleButtonHeld = false;
			}

			break;

		case sf::Event::Closed:
			game->exitGame(false);
			break;

		case sf::Event::KeyPressed:

			switch (event.key.code){

			case Key::UP_KEY:
				cameraVelocity = {0.f, -2.f};
				break;

			case Key::RIGHT_KEY:
				cameraVelocity = {2.f, 0.f};
				break;

			case Key::DOWN_KEY:
				cameraVelocity = {0.f, 2.f};
				break;

			case Key::LEFT_KEY:
				cameraVelocity = {-2.f, 0.f};
				break;

			case Key::RESETZOOM_KEY:
				game->currentView->setSize(game->mWindow.getSize().x, game->mWindow.getSize().y);
				break;

            case Key::ZOOMIN_KEY:
				game->currentView->setSize(game->currentView->getSize().x - xResolution / 10, game->currentView->getSize().y - yResolution / 10);
                break;

            case Key::ZOOMOUT_KEY:
				game->currentView->setSize(game->currentView->getSize().x + xResolution / 10, game->currentView->getSize().y + yResolution / 10);
                break;

            case sf::Keyboard::Escape:
            {
                game->setGameState(game->SetupPauseMenuState.get());
            }

            break;

			case Key::HIDE_UI_KEY:
				if (drawUI){
					drawUI = false;
				}
				else if (!drawUI){
					drawUI = true;
				}
				break;

			default: break;
			}

			break;

		case sf::Event::MouseWheelMoved:
			smoothZoom_zooming = true;
			smoothZoom_lerpFactor = 0.0085f;

			if (event.mouseWheel.delta > 0 && game->currentView->getSize().x > xResolution && game->currentView->getSize().y > yResolution){
                //zoom in
                //std::cout << game->currentView->getSize().x << ',' << game->currentView->getSize().y << std::endl;
				//game->currentView->setSize(game->currentView->getSize().x - xResolution / 12, game->currentView->getSize().y - yResolution / 12);
				smoothZoom_targetZoom = 0.8f;
			}
			else if (event.mouseWheel.delta < 0 && game->currentView->getSize().x < xResolution * 4 && game->currentView->getSize().y < yResolution * 4){
			    //zoom out
			    //std::cout << game->currentView->getSize().x << ',' << game->currentView->getSize().y << std::endl;
				//game->currentView->setSize(game->currentView->getSize().x + xResolution / 12, game->currentView->getSize().y + yResolution / 12);
				smoothZoom_targetZoom = 1.2f;
			}

			smoothZoom_currentZoom = 1.0f;
			smoothZoom_previousZoom = smoothZoom_currentZoom;

			smoothZoom_currentCenter = game->currentView->getCenter();

			if(smoothZoom_targetZoom >= 1.f){
				smoothZoom_targetCenter = game->mWindow.mapPixelToCoords(game->mousePos, *(game->currentView));
				auto dist = smoothZoom_targetCenter - smoothZoom_currentCenter;
				dist.x /= 2;
				dist.y /= 2;
				smoothZoom_targetCenter = smoothZoom_currentCenter - dist;
			}
			else{
				smoothZoom_targetCenter = game->mWindow.mapPixelToCoords(game->mousePos, *(game->currentView));
				auto dist = smoothZoom_targetCenter - smoothZoom_currentCenter;
				dist.x /= 2;
				dist.y /= 2;
				smoothZoom_targetCenter = smoothZoom_targetCenter - dist;
			}

			break;

		default: break;
		}

	}

}