Implemented weather
This commit is contained in:
parent
f6a02dc850
commit
bb2ddf1374
@ -2,7 +2,6 @@
|
||||
<launchConfiguration type="org.eclipse.ui.externaltools.ProgramBuilderLaunchConfigurationType">
|
||||
<stringAttribute key="org.eclipse.debug.core.ATTR_REFRESH_SCOPE" value="${working_set:<?xml version="1.0" encoding="UTF-8"?> <resources> <item path="/Farmlands/build/Debug" type="2"/> <item path="/Farmlands/build/Release" type="2"/> </resources>}"/>
|
||||
<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_BUILD_SCOPE" value="${working_set:<?xml version="1.0" encoding="UTF-8"?> <resources> <item path="/Farmlands/CMakeLists.txt" type="1"/> </resources>}"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="/usr/bin/cmake"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_RUN_BUILD_KINDS" value="full,incremental,"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="-DCMAKE_BUILD_TYPE=${config_name:Farmlands} ../.."/>
|
||||
|
@ -21,7 +21,7 @@
|
||||
</State>
|
||||
</Sprite>
|
||||
<SpriteRenderer />
|
||||
<Plant needsWater="false" maxDaysWithoutWater="3">
|
||||
<Plant needsWater="true" maxDaysWithoutWater="3">
|
||||
<State len="1" />
|
||||
<State len="1" />
|
||||
<State len="2" />
|
||||
|
@ -7,6 +7,7 @@
|
||||
<Transform />
|
||||
<Camera scale="4" mainCamera="true" />
|
||||
<GameTime />
|
||||
<Weather />
|
||||
</GameObject>
|
||||
|
||||
<!-- Background object -->
|
||||
|
@ -13,8 +13,10 @@
|
||||
#include <model/Configuration.h>
|
||||
#include <graphics/RenderContext.h>
|
||||
#include <resources/ResourceManager.h>
|
||||
#include <utils/Random.h>
|
||||
|
||||
#include <memory>
|
||||
#include <random>
|
||||
|
||||
namespace farmlands {
|
||||
|
||||
@ -47,6 +49,9 @@ namespace farmlands {
|
||||
|
||||
float deltaTime;
|
||||
|
||||
// Misc
|
||||
utils::Random random;
|
||||
|
||||
private:
|
||||
static GameState s_current;
|
||||
};
|
||||
|
11
src/Main.cpp
11
src/Main.cpp
@ -7,9 +7,11 @@ using namespace farmlands;
|
||||
|
||||
int main()
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
try
|
||||
{
|
||||
return controller::FarmlandsGame().run();
|
||||
ret = controller::FarmlandsGame().run();
|
||||
}
|
||||
catch (utils::Exception& ex)
|
||||
{
|
||||
@ -22,4 +24,11 @@ int main()
|
||||
std::cerr << "Panic: Caught unhandled exception!\n";
|
||||
std::cerr << typeid(ex).name() << " : " << ex.what() << "\n";
|
||||
}
|
||||
|
||||
if (ret != 0)
|
||||
{
|
||||
std::cerr << "Panic: Caught non-zero exit status!\n";
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ MapLayer* MapLayer::clone()
|
||||
|
||||
Cell MapLayer::get(size_t row, size_t col) const
|
||||
{
|
||||
Assert(row < m_w && col < m_h, "Index out of bounds.");
|
||||
Assert(row < m_h && col < m_w, "Index out of bounds.");
|
||||
|
||||
return m_cells[row * m_w + col];
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
*/
|
||||
|
||||
#include <GameState.h>
|
||||
#include <components/GameTime.h>
|
||||
#include <components/environment/GameTime.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
@ -16,6 +16,7 @@
|
||||
|
||||
namespace farmlands {
|
||||
namespace components {
|
||||
namespace environment {
|
||||
|
||||
GameTime::~GameTime()
|
||||
{
|
||||
@ -51,5 +52,6 @@ void GameTime::onUpdateLogic()
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
} /* namespace components */
|
||||
} /* namespace farmlands */
|
@ -12,6 +12,7 @@
|
||||
|
||||
namespace farmlands {
|
||||
namespace components {
|
||||
namespace environment {
|
||||
|
||||
/**
|
||||
* Maintains game time.
|
||||
@ -27,6 +28,7 @@ namespace components {
|
||||
virtual void onUpdateLogic() override;
|
||||
};
|
||||
|
||||
}
|
||||
} /* namespace components */
|
||||
} /* namespace farmlands */
|
||||
|
122
src/components/environment/Weather.cpp
Normal file
122
src/components/environment/Weather.cpp
Normal file
@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Weather.cpp
|
||||
*
|
||||
* Created on: Dec 10, 2016
|
||||
* Author: tibi
|
||||
*/
|
||||
|
||||
#include <GameState.h>
|
||||
#include <assets/Ground.h>
|
||||
#include <components/environment/Weather.h>
|
||||
#include <components/plants/Plant.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace farmlands {
|
||||
namespace components {
|
||||
namespace environment {
|
||||
|
||||
Weather::Weather()
|
||||
: today(WeatherType::Sunny),
|
||||
tomorrow(WeatherType::Sunny),
|
||||
m_map(nullptr),
|
||||
m_grid(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
Weather::~Weather()
|
||||
{
|
||||
}
|
||||
|
||||
model::Component* Weather::clone()
|
||||
{
|
||||
Weather* clone = new Weather();
|
||||
clone->today = today;
|
||||
clone->tomorrow = tomorrow;
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
void Weather::dump(unsigned level)
|
||||
{
|
||||
for (unsigned i = 0; i < level; i++)
|
||||
std::cout<<" ";
|
||||
|
||||
std::cout << " .Component: Weather \n";
|
||||
}
|
||||
|
||||
void Weather::onInitialize()
|
||||
{
|
||||
model::GameObject* root = &GameState::current().scene->root;
|
||||
|
||||
// Find background object
|
||||
auto it = root->findByComponent<Map>();
|
||||
Assert(it != root->childrenEnd(), "Can't find background game object.");
|
||||
m_map = (*it)->component<Map>();
|
||||
|
||||
auto gridIt = root->findByComponent<basic::Grid>();
|
||||
Assert(gridIt != root->childrenEnd(), "Can't find grid game object.");
|
||||
m_grid = (*gridIt)->component<basic::Grid>();
|
||||
}
|
||||
|
||||
void Weather::onUpdateLogic()
|
||||
{
|
||||
if (GameState::current().isMidnight)
|
||||
{
|
||||
today = tomorrow;
|
||||
|
||||
std::cout << "Today the weather is ";
|
||||
if (today == WeatherType::Sunny)
|
||||
std::cout << "sunny\n";
|
||||
if (today == WeatherType::Cloudy)
|
||||
std::cout << "cloudy\n";
|
||||
if (today == WeatherType::Rainy)
|
||||
std::cout << "rainy\n";
|
||||
|
||||
// Pick weather for next day
|
||||
int r = GameState::current().random.getInt((int) WeatherType::_Count);
|
||||
tomorrow = (WeatherType) r;
|
||||
|
||||
// Wet/dry soil tiles
|
||||
updateSoilTiles();
|
||||
updatePlants();
|
||||
}
|
||||
}
|
||||
|
||||
void Weather::updateSoilTiles()
|
||||
{
|
||||
bool rain = (today == WeatherType::Rainy);
|
||||
Cell cellWet = assets::Ground::SoilWet;
|
||||
Cell cellDry = assets::Ground::SoilDry;
|
||||
|
||||
for (size_t row = 0; row < m_map->height; row++)
|
||||
for (size_t col = 0; col < m_map->width; col++)
|
||||
{
|
||||
Cell soil = m_map->layer(1).get(row, col);
|
||||
if (assets::groundIsSoil(soil))
|
||||
m_map->layer(1).set(row, col, (rain) ? cellWet : cellDry);
|
||||
}
|
||||
}
|
||||
|
||||
void Weather::updatePlants()
|
||||
{
|
||||
bool rain = (today == WeatherType::Rainy);
|
||||
|
||||
if (rain)
|
||||
{
|
||||
// Tell plants that they have been given water
|
||||
for (size_t row = 0; row < m_map->height; row++)
|
||||
for (size_t col = 0; col < m_map->width; col++)
|
||||
{
|
||||
model::GameObject* obj = m_grid->get(col, row);
|
||||
plants::Plant* plant = (obj != nullptr) ? obj->component<plants::Plant>() : nullptr;
|
||||
|
||||
if (plant)
|
||||
plant->onWatered();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} /* namespace environment */
|
||||
} /* namespace components */
|
||||
} /* namespace farmlands */
|
53
src/components/environment/Weather.h
Normal file
53
src/components/environment/Weather.h
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Weather.h
|
||||
*
|
||||
* Created on: Dec 10, 2016
|
||||
* Author: tibi
|
||||
*/
|
||||
|
||||
#ifndef COMPONENTS_ENVIRONMENT_WEATHER_H_
|
||||
#define COMPONENTS_ENVIRONMENT_WEATHER_H_
|
||||
|
||||
#include <components/basic/Grid.h>
|
||||
#include <components/Map.h>
|
||||
#include <model/Component.h>
|
||||
|
||||
namespace farmlands {
|
||||
namespace components {
|
||||
namespace environment {
|
||||
|
||||
enum class WeatherType
|
||||
{
|
||||
Sunny,
|
||||
Cloudy,
|
||||
Rainy,
|
||||
_Count
|
||||
};
|
||||
|
||||
class Weather: public model::Component
|
||||
{
|
||||
public:
|
||||
Weather();
|
||||
virtual ~Weather();
|
||||
|
||||
virtual model::Component* clone() override;
|
||||
virtual void dump(unsigned level) override;
|
||||
|
||||
virtual void onInitialize() override;
|
||||
virtual void onUpdateLogic() override;
|
||||
|
||||
WeatherType today, tomorrow;
|
||||
|
||||
private:
|
||||
void updateSoilTiles();
|
||||
void updatePlants();
|
||||
|
||||
Map* m_map;
|
||||
basic::Grid* m_grid;
|
||||
};
|
||||
|
||||
} /* namespace environment */
|
||||
} /* namespace components */
|
||||
} /* namespace farmlands */
|
||||
|
||||
#endif /* COMPONENTS_ENVIRONMENT_WEATHER_H_ */
|
@ -8,6 +8,7 @@
|
||||
#include <GameState.h>
|
||||
#include <assets/Ground.h>
|
||||
#include <components/items/WateringCan.h>
|
||||
#include <components/plants/Plant.h>
|
||||
#include <math/GameMath.h>
|
||||
#include <utils/Assert.h>
|
||||
|
||||
@ -54,8 +55,11 @@ void WateringCan::onInitialize()
|
||||
// Find background object
|
||||
auto it = root->findByComponent<Map>();
|
||||
Assert(it != root->childrenEnd(), "Can't find background game object.");
|
||||
|
||||
m_map = (*it)->component<Map>();
|
||||
|
||||
auto gridIt = root->findByComponent<basic::Grid>();
|
||||
Assert(gridIt != root->childrenEnd(), "Can't find grid game object.");
|
||||
m_grid = (*gridIt)->component<basic::Grid>();
|
||||
}
|
||||
|
||||
void WateringCan::performAction(float x, float y, model::Direction d)
|
||||
@ -73,23 +77,35 @@ void WateringCan::performAction(float x, float y, model::Direction d)
|
||||
Cell backCell = m_map->layer(0).get(row, col);
|
||||
Cell soilCell = m_map->layer(1).get(row, col);
|
||||
|
||||
// If there is water, fill can
|
||||
if (backCell == Ground::Water)
|
||||
{
|
||||
amountLeft = capacity;
|
||||
std::cout << "Filled can: " << amountLeft << "\n";
|
||||
}
|
||||
model::GameObject* obj = m_grid->get(col, row);
|
||||
plants::Plant* plant = (obj != nullptr) ? obj->component<plants::Plant>() : nullptr;
|
||||
|
||||
// If there is dry soil, wet it
|
||||
// Fill can
|
||||
if (backCell == Ground::Water)
|
||||
fillCan();
|
||||
|
||||
// Wet dry soil
|
||||
if (groundIsDrySoil(soilCell) && amountLeft > 0)
|
||||
{
|
||||
m_map->layer(1)[row][col] = Ground::SoilWet;
|
||||
--amountLeft;
|
||||
|
||||
// Set wet soil
|
||||
m_map->layer(1)[row][col] = Ground::SoilWet;
|
||||
|
||||
// If there is a plant, tell it we watered it
|
||||
if (plant != nullptr)
|
||||
plant->onWatered();
|
||||
|
||||
std::cout << "Watering can: " << amountLeft << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
void WateringCan::fillCan()
|
||||
{
|
||||
amountLeft = capacity;
|
||||
std::cout << "Filled can: " << amountLeft << "\n";
|
||||
}
|
||||
|
||||
} /* namespace items */
|
||||
} /* namespace components */
|
||||
} /* namespace farmlands */
|
||||
|
@ -8,6 +8,7 @@
|
||||
#ifndef COMPONENTS_ITEMS_WATERINGCAN_H_
|
||||
#define COMPONENTS_ITEMS_WATERINGCAN_H_
|
||||
|
||||
#include <components/basic/Grid.h>
|
||||
#include <components/items/IPlayerAction.h>
|
||||
#include <components/Map.h>
|
||||
#include <model/Component.h>
|
||||
@ -30,12 +31,15 @@ namespace items {
|
||||
|
||||
virtual void performAction(float x, float y, model::Direction d) override;
|
||||
|
||||
void fillCan();
|
||||
|
||||
public:
|
||||
uint32_t capacity;
|
||||
uint32_t amountLeft;
|
||||
|
||||
private:
|
||||
Map* m_map;
|
||||
basic::Grid* m_grid;
|
||||
};
|
||||
|
||||
} /* namespace items */
|
||||
|
@ -65,7 +65,10 @@ void Plant::onUpdateLogic()
|
||||
// At midnight, the plant grows
|
||||
if (GameState::current().isMidnight)
|
||||
{
|
||||
stateDays++;
|
||||
// Plant only grows when wet
|
||||
if (!needsWater || daysWithoutWater == 0)
|
||||
stateDays++;
|
||||
|
||||
daysWithoutWater++;
|
||||
|
||||
// Exceeded plant's survival time without water
|
||||
@ -94,6 +97,7 @@ void Plant::onWatered()
|
||||
void Plant::die()
|
||||
{
|
||||
// TODO: implement plant death
|
||||
std::cout << "Oh, no. Plant is dead\n";
|
||||
}
|
||||
|
||||
} /* namespace plants */
|
||||
|
@ -243,16 +243,46 @@ components::DebugController* parse<components::DebugController> (boost::property
|
||||
}
|
||||
|
||||
template <>
|
||||
components::GameTime* parse<components::GameTime> (boost::property_tree::ptree& root)
|
||||
components::environment::GameTime* parse<components::environment::GameTime> (boost::property_tree::ptree& root)
|
||||
{
|
||||
// Ensure we are on the correct node (property tree seems to add root of its own)
|
||||
if (root.front().first == "GameTime")
|
||||
root = root.front().second;
|
||||
|
||||
components::GameTime* gameTime = new components::GameTime();
|
||||
components::environment::GameTime* gameTime = new components::environment::GameTime();
|
||||
return gameTime;
|
||||
}
|
||||
|
||||
components::environment::WeatherType parseWeatherType(std::string weatherType)
|
||||
{
|
||||
boost::to_lower(weatherType);
|
||||
components::environment::WeatherType type = components::environment::WeatherType::Sunny;
|
||||
|
||||
if (weatherType == "cloudy")
|
||||
type = components::environment::WeatherType::Cloudy;
|
||||
|
||||
if (weatherType == "rainy")
|
||||
type = components::environment::WeatherType::Rainy;
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
template <>
|
||||
components::environment::Weather* parse<components::environment::Weather> (boost::property_tree::ptree& root)
|
||||
{
|
||||
// Ensure we are on the correct node (property tree seems to add root of its own)
|
||||
if (root.front().first == "Weather")
|
||||
root = root.front().second;
|
||||
|
||||
components::environment::Weather* weather = new components::environment::Weather();
|
||||
std::string today = root.get<std::string>("<xmlattr>.today", "Sunny");
|
||||
weather->today = parseWeatherType(today);
|
||||
std::string tomorrow = root.get<std::string>("<xmlattr>.tomorrow", "Sunny");
|
||||
weather->tomorrow = parseWeatherType(tomorrow);
|
||||
|
||||
return weather;
|
||||
}
|
||||
|
||||
template <>
|
||||
components::items::Axe* parse<components::items::Axe> (boost::property_tree::ptree& root)
|
||||
{
|
||||
@ -522,8 +552,12 @@ model::GameObject* parse<model::GameObject> (boost::property_tree::ptree& root)
|
||||
else if (child.first == "DebugController")
|
||||
gameObj->addComponent(parse<components::DebugController>(child.second));
|
||||
|
||||
// Environment
|
||||
else if (child.first == "GameTime")
|
||||
gameObj->addComponent(parse<components::GameTime>(child.second));
|
||||
gameObj->addComponent(parse<components::environment::GameTime>(child.second));
|
||||
|
||||
else if (child.first == "Weather")
|
||||
gameObj->addComponent(parse<components::environment::Weather>(child.second));
|
||||
|
||||
else if (child.first == "Map")
|
||||
gameObj->addComponent(parse<components::Map>(child.second));
|
||||
|
@ -13,7 +13,8 @@
|
||||
#include <components/basic/Sprite.h>
|
||||
#include <components/basic/Transform.h>
|
||||
#include <components/DebugController.h>
|
||||
#include <components/GameTime.h>
|
||||
#include <components/environment/GameTime.h>
|
||||
#include <components/environment/Weather.h>
|
||||
#include <components/items/Axe.h>
|
||||
#include <components/items/Giftable.h>
|
||||
#include <components/items/Hoe.h>
|
||||
@ -66,7 +67,10 @@ namespace storage {
|
||||
components::DebugController* parse<components::DebugController> (boost::property_tree::ptree& root);
|
||||
|
||||
template <>
|
||||
components::GameTime* parse<components::GameTime> (boost::property_tree::ptree& root);
|
||||
components::environment::GameTime* parse<components::environment::GameTime> (boost::property_tree::ptree& root);
|
||||
|
||||
template <>
|
||||
components::environment::Weather* parse<components::environment::Weather> (boost::property_tree::ptree& root);
|
||||
|
||||
template <>
|
||||
components::items::Axe* parse<components::items::Axe> (boost::property_tree::ptree& root);
|
||||
|
@ -18,10 +18,10 @@ namespace utils {
|
||||
void _AssertInternal(bool condition, const std::string& msg, const std::string& lineText, const std::string& file, int line);
|
||||
void _AssertInternalLog(bool condition, const std::string& msg, const std::string& lineText, const std::string& file, int line);
|
||||
|
||||
#ifdef BUILD_DEBUG
|
||||
#define Assert(condition, message) farmlands::utils::_AssertInternal(condition, message, #condition, __FILE__, __LINE__)
|
||||
#else
|
||||
#ifdef NDEBUG
|
||||
#define Assert(condition, message) farmlands::utils::_AssertInternalLog(condition, message, #condition, __FILE__, __LINE__)
|
||||
#else
|
||||
#define Assert(condition, message) farmlands::utils::_AssertInternal(condition, message, #condition, __FILE__, __LINE__)
|
||||
#endif
|
||||
|
||||
} /* namespace utils */
|
||||
|
32
src/utils/Random.cpp
Normal file
32
src/utils/Random.cpp
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Random.cpp
|
||||
*
|
||||
* Created on: Dec 10, 2016
|
||||
* Author: tibi
|
||||
*/
|
||||
|
||||
#include <utils/Random.h>
|
||||
|
||||
namespace farmlands {
|
||||
namespace utils {
|
||||
|
||||
float Random::getFloat()
|
||||
{
|
||||
std::uniform_real_distribution<float> distrib;
|
||||
return distrib(m_engine);
|
||||
}
|
||||
|
||||
int Random::getInt(int min, int max)
|
||||
{
|
||||
std::uniform_int_distribution<int> distrib(min, max);
|
||||
return distrib(m_engine);
|
||||
}
|
||||
|
||||
int Random::getInt(int max)
|
||||
{
|
||||
std::uniform_real_distribution<float> distrib(0, max);
|
||||
return distrib(m_engine);
|
||||
}
|
||||
|
||||
} /* namespace utils */
|
||||
} /* namespace farmlands */
|
30
src/utils/Random.h
Normal file
30
src/utils/Random.h
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Random.h
|
||||
*
|
||||
* Created on: Dec 10, 2016
|
||||
* Author: tibi
|
||||
*/
|
||||
|
||||
#ifndef UTILS_RANDOM_H_
|
||||
#define UTILS_RANDOM_H_
|
||||
|
||||
#include <random>
|
||||
|
||||
namespace farmlands {
|
||||
namespace utils {
|
||||
|
||||
class Random
|
||||
{
|
||||
public:
|
||||
float getFloat();
|
||||
int getInt(int min, int max);
|
||||
int getInt(int max);
|
||||
|
||||
private:
|
||||
std::mt19937 m_engine;
|
||||
};
|
||||
|
||||
} /* namespace utils */
|
||||
} /* namespace farmlands */
|
||||
|
||||
#endif /* UTILS_RANDOM_H_ */
|
Loading…
Reference in New Issue
Block a user