Skip to content

テキスト表示

Reputeless edited this page Mar 14, 2017 · 2 revisions

メッセージボックス

# include <Siv3D.hpp>

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

	const Font font(18);

	const Array<String> messages = 
	{
		L"かがくの ちからって すげー!\nSiv3D を つかうと みじかい コードで",
		L"えや もじを ひょうじしたり\nおんがくを ならしたり できるんだ!"
	};

	const Rect frame(20, 320, 600, 120);

	const int32 duration = 80;

	Stopwatch stopwatch(true);

	size_t messageIndex = 0;

	while (System::Update())
	{
		const String& message = messages[messageIndex];

		const int32 index = stopwatch.ms() / duration;

		const bool all = index >= message.length;

		if (Input::MouseL.clicked)
		{
			if (all)
			{
				++messageIndex;

				messageIndex %= messages.size();

				stopwatch.restart();
			}
			else
			{
				stopwatch.set(100000ms);
			}
		}

		frame.stretched(2).drawFrame(0, 2, Palette::Black);

		frame.stretched(-2).drawFrame(0, 2, Palette::Black);

		font(message.substr(0, index)).draw(frame.pos + Point(30, 20), Palette::Black, 1.2);

		if (all && stopwatch.ms() % 1000 < 500)
		{
			Triangle(frame.br - Point(30, 40), 20, 180_deg).draw(Palette::Black);
		}
	}
}

異なるサイズの文字のベースラインをそろえる

# include <Siv3D.hpp>

void Main()
{
	const Font fontS(12), fontM(24), fontL(36);

	while (System::Update())
	{
		fontS(L"Siv3D").draw(50, 100 - fontS.ascent);

		fontM(L"Siv3D").draw(150, 100 - fontM.ascent);

		fontL(L"Siv3D").draw(300, 100 - fontL.ascent);
	}
}

ボックス内にテキストを収める

# include <Siv3D.hpp>

void Main()
{
	const Font font(16);

	const String text = L"Lorem ipsum dolor sit amet, consectetur adipiscing elit,\
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.";

	Rect rect(50, 50, 100, 100);

	while (System::Update())
	{
		const int32 w = Max(Mouse::Pos().x - 50, 80);
		const int32 h = Max(Mouse::Pos().y - 50, font.height + 20);
		
		rect.setSize(w, h);

		rect.draw();

		Array<String> texts;

		size_t pos = 0;

		while (pos < text.length)
		{
			const size_t n = Max<size_t>(font.drawableCharacters(text, w - 20), 1);

			texts.push_back(text.substr(pos, n));

			pos += n;
		}

		for (size_t i = 0; i < texts.size(); ++i)
		{
			const int32 y = static_cast<int32>(rect.y + 10 + i * font.height);

			const bool overflow = (i + 1 < texts.size())
				&& (y + font.height * 2 + 10 > rect.y + rect.h);

			if (overflow)
			{
				if (texts[i].length > 2)
				{
					texts[i].resize(texts[i].length - (texts[i].length > 2 ? 2 : 1));
				}

				texts[i].append(L"...");
			}

			font(texts[i]).draw(rect.x + 10, y, Palette::Black);

			if (overflow)
			{
				break;
			}
		}	
	}
}

文字を点滅させる

# include <Siv3D.hpp>

void Main()
{
	const Font font(40, Typeface::Bold);

	const String text = L"Siv3D";

	const int32 cycle = 1200;

	while (System::Update())
	{
		const int32 t = Time::GetMillisec();

		if (t % cycle < (cycle / 2))
		{
			font(text).draw(100, 100);
		}

		const double a1 = (cycle - t % cycle) / static_cast<double>(cycle);

		font(text).draw(100, 200, AlphaF(a1));

		const double a2 = Sin(t % cycle / static_cast<double>(cycle) * TwoPi) * 0.3 + 0.7;

		font(text).draw(100, 300, AlphaF(a2));
	}
}

文字を揺らす

# include <Siv3D.hpp>

void Main()
{
	Graphics::SetBackground(Palette::Black);

	const Font font(8, L" ", FontStyle::BitmapBold);
	const String message = L"In this world, it's\nC++ or BE C++ed.";
	const Rect frame(100, 100, 220, 115);

	Array<Point> offsets(100, Point(0, 0));
	Stopwatch stopwatch(true);
	int32 previous = 0;

	while (System::Update())
	{
		if (Input::MouseL.clicked)
		{
			stopwatch.restart();

			previous = 0;
		}

		if (stopwatch.ms() - previous > 30)
		{
			previous = stopwatch.ms();

			for (auto& offset : offsets)
			{
				offset = RandomPoint(1, 2);
			}
		}

		RoundRect(frame, 15).draw(Palette::White);

		const auto animation = [&](KineticTypography& k)
		{
			k.pos += offsets[k.index % offsets.size()];
		};

		const int32 index = stopwatch.ms() / 80;

		font(message.substr(0, index)).drawKinetic(frame.pos + Point(15, 15), animation, Palette::Black, 1.4);
	}
}

文字を短時間だけ出す

# include <Siv3D.hpp>

struct TextEffect : IEffect
{
	const Font m_font;

	const int32 m_value;

	const Vec2 m_from;

	TextEffect(const Font& font, const int32 value, const Vec2& from)
		: m_font(font)
		, m_value(value)
		, m_from(from) {}

	bool update(const double t) override
	{
		// 1.0 秒で消える
		if (t >= 1.0)
		{
			return false;
		}

		const double alpha = 1.0 - t;

		m_font(m_value).drawCenter(m_from + Vec2(0, -40 * t), HSV(60 - m_value).toColorF(alpha));

		return true;
	}
};

void Main()
{
	const Font font(24, Typeface::Black);

	const int32 duration = 1500;

	Circle circle(Window::Center(), 50);

	int32 combo = 0;

	Effect effect;

	Stopwatch stopwatch(true);

	while (System::Update())
	{
		const int32 ms = stopwatch.ms();

		if (ms < duration)
		{
			circle.r = 50 * (duration - ms) / static_cast<double>(duration);
		}

		if (ms >= duration || circle.leftClicked)
		{
			if (circle.leftClicked)
			{
				effect.add<TextEffect>(font, ++combo, circle.center);
			}
			else
			{
				combo = 0;
			}

			stopwatch.restart();

			circle.set(RandomVec2(Window::ClientRect().stretched(-40)), 50);
		}

		circle.draw();

		effect.update();
	}
}

文字を右揃えする

# include <Siv3D.hpp>

void Main()
{
	const Font font(24);

	const Array<String> texts =
	{
		L"a",
		L"ab",
		L"abcd",
		L"abcdefgh",
		L"abcdefghijkl",
	};

	const int32 right = 280;

	while (System::Update())
	{
		int32 i = 0;

		for (const auto& text : texts)
		{
			const int32 w = font(text).region().w;

			font(text).draw(right - w, 100 + i * font.height);

			++i;
		}
	}
}

文字を少しずつ大きくする

# include <Siv3D.hpp>

void Main()
{
	const Font font(80, Typeface::Bold, FontStyle::Outline);
	font.changeOutlineStyle({ HSV(40, 0.8, 1.0), Alpha(0), 4.0 });

	while (System::Update())
	{
		const double s = 0.2 + Time::GetMillisec() % 3000 / 1000.0;

		Graphics2D::SetTransform(Mat3x2::Scale(s, Window::Center()));

		const double alpha = Saturate(2.0 - s * 0.8);

		font(L"CLEARED!").drawCenter(Window::Center(), AlphaF(alpha));
	}
}

文字に光彩をつける

# include <Siv3D.hpp>

class GlowText
{
private:

	Font m_font;

	String m_text;

	Texture m_texture;

	Point m_offset = { 0,0 };

public:

	GlowText() = default;

	GlowText(const Font& font, const String& text, int32 blur, double gamma = 2.0)
		: m_font(font)
		, m_text(text)
		, m_offset(blur + 4, blur + 4)
	{
		const Size region = font(text).region().stretched(blur + 4).size;
		
		Image image(region, Color(0, 0));

		font(text).write(image, m_offset, Palette::White);

		image.gaussianBlur(blur, blur).gammaCorrect(gamma);

		for (auto& pixel : image)
		{
			pixel.a = pixel.r;

			pixel.r = pixel.g = pixel.b = 255;
		}

		m_texture = Texture(image);
	}

	const Texture& getGlowTexture() const
	{
		return m_texture;
	}

	RectF draw(const Vec2& pos, const Color& glow = Palette::White, const Color& text = Palette::White) const
	{
		m_texture.draw(pos, glow);

		return m_font(m_text).draw(pos + m_offset, text);
	}

	RectF drawCenter(double y, const Color& glow = Palette::White, const Color& text = Palette::White) const
	{
		return drawCenter(Vec2(Window::Width() / 2, y), glow, text);
	}

	RectF drawCenter(const Vec2& pos, const Color& glow = Palette::White, const Color& text = Palette::White) const
	{
		return draw(pos - m_texture.size / 2, glow, text);
	}

	RectF region(const Vec2& pos = Vec2(0, 0)) const
	{
		return RectF(pos, m_texture.size).stretched(-m_offset);
	}

	RectF regionCenter(double y) const
	{
		return regionCenter(Vec2(Window::Width() / 2, y));
	}

	RectF regionCenter(const Vec2& pos) const
	{
		return region(pos - m_texture.size / 2);
	}
};

void Main()
{
	const Font font(20, Typeface::Medium);

	const Array<GlowText> texts =
	{
		GlowText(font, L"CONTINUE", 10),
		GlowText(font, L"NEW GAME", 10),
		GlowText(font, L"CONFIG", 10),
		GlowText(font, L"EXIT", 10)
	};

	while (System::Update())
	{
		int32 i = 0;

		for (const auto& text : texts)
		{
			const bool mouseOver = text.regionCenter(260 + i * 50).mouseOver;

			text.drawCenter(260 + i * 50, 
				AlphaF(mouseOver ? 1.0 : 0.0),
				AlphaF(mouseOver ? 1.0 : 0.9));

			++i;
		}
	}
}

文字を上から登場させる

# include <Siv3D.hpp>

void Main()
{
	const Font font(18);

	const String message = L"Lorem ipsum dolor sit amet, consectetur\n\
adipiscing elit, sed do eiusmod tempor\n\
incididunt ut labore et dolore magna aliqua. ";

	Stopwatch stopwatch(true);

	while (System::Update())
	{
		if (Input::MouseL.clicked)
		{
			stopwatch.restart();
		}

		const double index = stopwatch.ms() / 80.0;

		const auto animation = [=](KineticTypography& k)
		{
			const double t = index - k.index;

			k.col.a = AlphaF(Saturate(t / 6)).toColor().a;

			k.pos.y -= EaseIn<Easing::Quad>(Saturate(1 - t / 4)) * 20.0;
		};

		font(message).drawKinetic(40, 100, animation, Palette::White, 1.2);
	}
}

文字の間隔を広げる

# include <Siv3D.hpp>

void Main()
{
	const Font font(20);

	while (System::Update())
	{
		for (auto i : step(10))
		{
			auto ty = [=](KineticTypography& k)
			{
				k.pos.x += k.index * (i * 2);
			};

			font(L"The quick brown fox").drawKinetic(20, 20 + 40 * i, ty);
		}
	}
}

Siv3D について

  1. Siv3D の基本
  2. 図形を描く
  3. テクスチャを描く
  4. テキストを描く
  5. 文字列と数値の変換
  6. キーボード入力
  7. マウス入力
  8. サウンドの再生
  9. MIDI の再生
  10. ウィンドウと背景
  11. 図形のあたり判定
  12. 乱数
  13. ダイアログ
  14. ドラッグ & ドロップ
  15. アプリの状態
  16. テキストファイル
  17. INI, CSV, JSON
  18. バイナリファイル
  19. GUI
  20. アセット管理
  21. 画像編集
  22. Web カメラ
  23. マイク入力
  24. 経過時間の測定
  25. HSV カラー
  26. ファイルダウンロード
  27. 3D 描画
  28. 2D のレンダーステート
  29. 3D のレンダーステート
  30. パーティクル
  31. スクリーンショット
  32. アプリケーションの公開
  33. さらに学ぶには

表現テクニック集

入出力デバイス

開発のヒント

Clone this wiki locally