読者です 読者をやめる 読者になる 読者になる

Play Siv3D!

ゲームとメディアアートのための C++ ライブラリ「Siv3D」

OpenWeatherMap

サンプル | OpenWeatherMap

Siv3D June 2015 v2


※ OpenWeatherMap の API 変更で現在このサンプルは利用いただけません。



OpenWeatherMap の API を利用して世界各地の天気を表示します。

# include <Siv3D.hpp>

void Main()
{
	Graphics::SetBackground(Color(230));

	const Font fontCity(36), fontSmall(18);
	GUI gui(GUIStyle::Default);
	gui.add(L"place", GUITextField::Create(18));
	gui.add(L"get", GUIButton::Create(L"現在の天気を調べる"));
	const int offset = (Window::Width() - gui.getRect().w) / 2;
	gui.setPos(offset, 20);

	Optional<bool> found;
	String cityName, countryName;
	Array<Texture> weatherIcons;
	int temperature = 0, humidity = 0, pressure = 0, windSpeed = 0, windDegree = 0;

	while (System::Update())
	{
		if (gui.button(L"get").pushed)
		{
			MemoryReader reader;
			const String url = L"http://api.openweathermap.org/data/2.5/weather?units=metric&q=" + gui.textField(L"place").text;

			if (!Internet::Download(url, reader))
			{
				found = false;
				continue;
			}

			JSONReader json(std::move(reader));

			if (json[L"cod"].getOpt<String>() == String(L"404"))
			{
				found = false;
				continue;
			}

			if (json[L"cod"].getOpt<int>() == 200)
			{
				found = true;
				countryName = json[L"sys.country"].getString();
				cityName = json[L"name"].getString();
				
				if (cityName.isEmpty)
				{
					cityName = countryName;
				}

				temperature = static_cast<int>(json[L"main.temp"].getNumber());
				humidity = static_cast<int>(json[L"main.humidity"].getNumber());
				pressure = static_cast<int>(json[L"main.pressure"].getNumber());
				windSpeed = json[L"wind.speed"].get<int>();
				windDegree = json[L"wind.deg"].get<int>();
				weatherIcons.clear();

				for (const auto& weather : json[L"weather"].getArray())
				{
					const String url = Format(PyFmt, L"http://openweathermap.org/img/w/{}.png", weather[L"icon"].getString());

					if (!Internet::Download(url, reader))
					{
						continue;
					}

					weatherIcons.emplace_back(std::move(reader));
				}
			}
		}

		if (found && found.value() == false)
		{
			fontCity(L"Not found").draw(offset + 20, 110, Color(100));
		}
		else if (found && found.value() == true)
		{
			fontCity(cityName).draw(offset + 20, 110, Color(30));

			fontSmall(countryName).draw(offset + 40 + fontCity(cityName).region().w,
				110 + (fontCity.ascent - fontSmall.ascent), Color(80));

			for (auto i : step(weatherIcons.size()))
			{
				Rect(offset + 20 + i * 120, 190, weatherIcons[i].size * 2).draw();
				weatherIcons[i].scale(2.0).draw(offset + 20 + i * 120, 190);
			}

			fontSmall(PyFmt, L"気温: {} ℃ / 湿度: {} % / 気圧: {} hPa", temperature, humidity, pressure).draw(offset + 20, 310, Color(30));
			fontSmall(PyFmt, L"風速: {} m", windSpeed).draw(offset + 20, 350, Color(30));

			const Circle circle(offset + 220, 400, 50);
			circle.drawFrame(4, 0, Palette::White);

			const Vec2 a = circle.center + Circular(circle.r * 0.8, Radians(windDegree));
			const Vec2 b = circle.center + Circular(circle.r * 0.8, Radians(windDegree - 180));
			Line(a, b).drawArrow(15.0, { 20.0, 20.0 }, Palette::Skyblue);
		}
	}
}