🎰
Siv3D | ゲーム UI テンプレート集
1. プログレスバー
# include <Siv3D.hpp> // OpenSiv3D v0.4.3
namespace GameUIToolkit
{
class ProgressBar
{
private:
RectF m_rect = Rect(0);
ColorF m_backgroundColor = ColorF(0.25);
Array<std::pair<double, ColorF>> m_barColors = {
{ 1.0, ColorF(0.1, 0.8, 0.2) }
};
double m_round = 0.0;
ColorF getBarColor(double progress) const
{
ColorF result = m_barColors.front().second;
for (auto& c : m_barColors)
{
if (progress < c.first)
{
result = c.second;
}
else
{
break;
}
}
return result;
}
public:
ProgressBar() = default;
explicit ProgressBar(const RectF& rect, double round = 0.0)
: ProgressBar(rect, ColorF(0.25), { { 1.0, ColorF(0.1, 0.8, 0.2) } }, round) {}
ProgressBar(const RectF& rect, const ColorF& backgroundColor, const ColorF& barColor, double round = 0.0)
: ProgressBar(rect, backgroundColor, { { 1.0, barColor } }, round) {}
ProgressBar(const RectF& rect, const ColorF& backgroundColor, const Array<std::pair<double, ColorF>>& barColors, double round = 0.0)
: m_rect(rect)
, m_backgroundColor(backgroundColor)
, m_barColors(barColors)
, m_round(round)
{
m_barColors.sort_by([](const auto& a, const auto& b) { return a.first > b.first; });
}
// バーを描く
const ProgressBar& draw(double value, double maxValue) const
{
const double progress = maxValue ? Math::Saturate(value / maxValue) : 1.0;
const RectF innnerRect = m_rect.stretched(-1);
const RectF innnerRectBar(innnerRect.pos, innnerRect.w * progress, innnerRect.h);
if (m_round == 0.0)
{
m_rect.draw(m_backgroundColor);
innnerRectBar.draw(getBarColor(progress));
}
else
{
m_rect.rounded(m_round).draw(m_backgroundColor);
if (innnerRectBar.w)
{
const Polygon bar = innnerRectBar.asPolygon();
const RoundRect innnerRoundRect = innnerRect.rounded(m_round - 1);
const Polygon clip = innnerRoundRect.asPolygon();
if (const auto g = Geometry2D::And(bar, clip))
{
g.front().draw(getBarColor(progress));
}
}
}
return *this;
}
// 中央揃えでテキストを描く
const ProgressBar& withText(const SDFDrawableText& drawableText, double fontSize, const ColorF& textColor, const Vec2& textPosOffset = Vec2(0, 0)) const
{
const Size textSize = drawableText.region(fontSize).size;
const auto& font = drawableText.font;
const Point textPos = (m_rect.pos + (m_rect.size - textSize) / 2 + textPosOffset).asPoint();
Graphics2D::SetSDFParameters(font.pixelRange(), 0.2);
drawableText.draw(fontSize, textPos, ColorF(0.1));
Graphics2D::SetSDFParameters(font.pixelRange(), 0.0);
drawableText.draw(fontSize, textPos, textColor);
return *this;
}
// 左揃えでテキストを描く
const ProgressBar& withLabel(const SDFDrawableText& drawableText, double fontSize, const ColorF& textColor, double offsetX, const Vec2& textPosOffset = Vec2(0, 0)) const
{
const Size textSize = drawableText.region(fontSize).size;
const auto& font = drawableText.font;
const Point textPos = (Vec2(m_rect.x + offsetX, m_rect.y + (m_rect.h - textSize.y) / 2) + textPosOffset).asPoint();
Graphics2D::SetSDFParameters(font.pixelRange(), 0.2);
drawableText.draw(fontSize, textPos, ColorF(0.1));
Graphics2D::SetSDFParameters(font.pixelRange(), 0.0);
drawableText.draw(fontSize, textPos, textColor);
return *this;
}
};
}
void Main()
{
Window::Resize(1280, 720);
Scene::SetBackground(ColorF(0.5, 0.4, 0.6));
const SDFFont font1(40, Typeface::Bold);
const SDFFont font2(32, U"example/font/LogoTypeGothic/LogoTypeGothic.otf", FontStyle::Bold);
// 進度に応じたバーの表示色のカスタマイズ
const Array<std::pair<double, ColorF>> barColors = {
{ 0.15, ColorF(0.8, 0.2, 0.0) }, // 15 % 未満は赤
{ 0.5, ColorF(0.8, 0.6, 0.1) }, // 50 % 未満はオレンジ
{ 1.0, ColorF(0.1, 0.8, 0.2) }, // それ以外は緑
};
// バーの背景色
constexpr ColorF barBackgroundColor(0.2, 0.8);
// テキストの色
constexpr ColorF textColor(1.0, 0.95, 0.9);
while (System::Update())
{
const int32 hp = static_cast<int32>(Periodic::Triangle0_1(12s) * 4800);
GameUIToolkit::ProgressBar(Rect(40, 40, 320, 25), ColorF(0.5), ColorF(0.1, 0.8, 0.2))
.draw(15, 100);
GameUIToolkit::ProgressBar(Rect(40, 80, 320, 25), ColorF(0.5), ColorF(0.1, 0.8, 0.2))
.draw(40, 100);
GameUIToolkit::ProgressBar(Rect(40, 120, 320, 25), ColorF(0.5), ColorF(0.1, 0.8, 0.2))
.draw(90, 100);
GameUIToolkit::ProgressBar(Rect(40, 180, 320, 25), barBackgroundColor, barColors)
.draw(600, 4800);
GameUIToolkit::ProgressBar(Rect(40, 220, 320, 25), barBackgroundColor, barColors)
.draw(2000, 4800);
GameUIToolkit::ProgressBar(Rect(40, 260, 320, 25), barBackgroundColor, barColors)
.draw(3200, 4800);
GameUIToolkit::ProgressBar(Rect(440, 40, 320, 25), barBackgroundColor, ColorF(0.1, 0.8, 0.2))
.draw(15, 100)
.withText(font1(U"15%"), 20, textColor);
GameUIToolkit::ProgressBar(Rect(440, 80, 320, 25), barBackgroundColor, ColorF(0.1, 0.8, 0.2))
.draw(40, 100)
.withText(font1(U"40%"), 20, textColor);
GameUIToolkit::ProgressBar(Rect(440, 120, 320, 25), barBackgroundColor, ColorF(0.1, 0.8, 0.2))
.draw(90, 100)
.withText(font1(U"90%"), 20, textColor);
GameUIToolkit::ProgressBar(Rect(440, 180, 320, 25), barBackgroundColor, barColors)
.draw(600, 4800)
.withText(font1(U"600/4800"), 24, textColor);
GameUIToolkit::ProgressBar(Rect(440, 220, 320, 25), barBackgroundColor, barColors)
.draw(2000, 4800)
.withText(font1(U"2000/4800"), 24, textColor);
GameUIToolkit::ProgressBar(Rect(440, 260, 320, 25), barBackgroundColor, barColors)
.draw(hp, 4800)
.withText(font1(U"{}/4800"_fmt(hp)), 24, textColor);
GameUIToolkit::ProgressBar(Rect(840, 40, 320, 25), barBackgroundColor, ColorF(0.2, 0.9, 0.3), 12.5)
.draw(1, 100)
.withText(font2(U"1%"), 20, textColor, Vec2(0, 1));
GameUIToolkit::ProgressBar(Rect(840, 80, 320, 25), barBackgroundColor, ColorF(0.2, 0.9, 0.3), 12.5)
.draw(80, 100)
.withText(font2(U"80%"), 20, textColor, Vec2(0, 1));
GameUIToolkit::ProgressBar(Rect(840, 120, 320, 25), barBackgroundColor, ColorF(0.2, 0.9, 0.3), 12.5)
.draw(99, 100)
.withText(font2(U"99%"), 20, textColor, Vec2(0, 1));
GameUIToolkit::ProgressBar(Rect(840, 180, 320, 25), barBackgroundColor, barColors, 12.5)
.draw(600, 4800)
.withText(font2(U"600/4800"), 25, textColor, Vec2(0, 1));
GameUIToolkit::ProgressBar(Rect(840, 220, 320, 25), barBackgroundColor, barColors, 12.5)
.draw(2000, 4800)
.withText(font2(U"2000/4800"), 25, textColor, Vec2(0, 1));
GameUIToolkit::ProgressBar(Rect(840, 260, 320, 25), barBackgroundColor, barColors, 12.5)
.draw(hp, 4800)
.withText(font2(U"{}/4800"_fmt(hp)), 25, textColor, Vec2(0, 1));
GameUIToolkit::ProgressBar(Rect(120, 320, 320, 25), barBackgroundColor, barColors)
.draw(600, 4800)
.withText(font1(U"600/4800"), 24, textColor)
.withLabel(font1(U"Lv.50"), 24, textColor, -80);
GameUIToolkit::ProgressBar(Rect(120, 360, 320, 25), barBackgroundColor, barColors)
.draw(2000, 4800)
.withText(font1(U"2000/4800"), 24, textColor)
.withLabel(font1(U"Lv.50"), 24, textColor, -80);
GameUIToolkit::ProgressBar(Rect(120, 400, 320, 25), barBackgroundColor, barColors)
.draw(hp, 4800)
.withText(font1(U"{}/4800"_fmt(hp)), 24, textColor)
.withLabel(font1(U"Lv.50"), 24, textColor, -80);
GameUIToolkit::ProgressBar(Rect(660, 327, 320, 12), barBackgroundColor, barColors)
.draw(600, 4800)
.withLabel(font2(U"600/4800"), 14, textColor, 335)
.withLabel(font2(U"Lv.50"), 25, textColor, -100, Vec2(0, 1));
GameUIToolkit::ProgressBar(Rect(660, 367, 320, 12), barBackgroundColor, barColors)
.draw(2000, 4800)
.withLabel(font2(U"2000/4800"), 14, textColor, 335)
.withLabel(font2(U"Lv.50"), 25, textColor, -100, Vec2(0, 1));
GameUIToolkit::ProgressBar(Rect(660, 407, 320, 12), barBackgroundColor, barColors)
.draw(hp, 4800)
.withLabel(font2(U"{}/4800"_fmt(hp)), 14, textColor, 335)
.withLabel(font2(U"Lv.50"), 25, textColor, -100, Vec2(0, 1));
GameUIToolkit::ProgressBar(Rect(100, 460, 320, 15), barBackgroundColor, barColors)
.draw(600, 4800)
.withText(font1(U"600/4800"), 16, textColor)
.withLabel(font1(U"Lv.50"), 16, textColor, -60);
GameUIToolkit::ProgressBar(Rect(100, 500, 320, 15), barBackgroundColor, barColors)
.draw(2000, 4800)
.withText(font1(U"2000/4800"), 16, textColor)
.withLabel(font1(U"Lv.50"), 16, textColor, -60);
GameUIToolkit::ProgressBar(Rect(100, 540, 320, 15), barBackgroundColor, barColors)
.draw(hp, 4800)
.withText(font1(U"{}/4800"_fmt(hp)), 16, textColor)
.withLabel(font1(U"Lv.50"), 16, textColor, -60);
GameUIToolkit::ProgressBar(Rect(660, 467, 480, 12), barBackgroundColor, barColors, 6)
.draw(600, 4800)
.withText(font2(U"600/4800"), 14, textColor)
.withLabel(font2(U"Lv.50"), 25, textColor, -100, Vec2(0, 1));
GameUIToolkit::ProgressBar(Rect(660, 507, 480, 12), barBackgroundColor, barColors, 6)
.draw(2000, 4800)
.withText(font2(U"2000/4800"), 14, textColor)
.withLabel(font2(U"Lv.50"), 25, textColor, -100, Vec2(0, 1));
GameUIToolkit::ProgressBar(Rect(660, 547, 480, 12), barBackgroundColor, barColors, 6)
.draw(hp, 4800)
.withText(font2(U"{}/4800"_fmt(hp)), 14, textColor)
.withLabel(font2(U"Lv.50"), 25, textColor, -100, Vec2(0, 1));
}
}
2. プログレスバー (カスタム形状)
# include <Siv3D.hpp> // OpenSiv3D v0.4.3
namespace GameUIToolkit
{
class CustomShapeProgressBar
{
private:
Polygon m_shape;
Polygon m_shrinkedShape;
ColorF m_backgroundColor = ColorF(0.25);
Array<std::pair<double, ColorF>> m_barColors = {
{ 1.0, ColorF(0.1, 0.8, 0.2) }
};
double m_shearedX = 0.0;
ColorF getBarColor(double progress) const
{
ColorF result = m_barColors.front().second;
for (auto& c : m_barColors)
{
if (progress < c.first)
{
result = c.second;
}
else
{
break;
}
}
return result;
}
public:
CustomShapeProgressBar() = default;
explicit CustomShapeProgressBar(const Polygon& polygon, double shearedX = 0.0)
: CustomShapeProgressBar(polygon, ColorF(0.25), { { 1.0, ColorF(0.1, 0.8, 0.2) } }, shearedX) {}
CustomShapeProgressBar(const Polygon& polygon, const ColorF& backgroundColor, const ColorF& barColor, double shearedX = 0.0)
: CustomShapeProgressBar(polygon, backgroundColor, { { 1.0, barColor } }, shearedX) {}
CustomShapeProgressBar(const Polygon& polygon, const ColorF& backgroundColor, const Array<std::pair<double, ColorF>>& barColors, double shearedX = 0.0)
: m_shape(polygon)
, m_shrinkedShape(polygon.calculateBuffer(-1))
, m_backgroundColor(backgroundColor)
, m_barColors(barColors)
, m_shearedX(shearedX)
{
m_barColors.sort_by([](const auto& a, const auto& b) { return a.first > b.first; });
}
// バーを描く
const CustomShapeProgressBar& draw(double value, double maxValue) const
{
const double progress = maxValue ? Math::Saturate(value / maxValue) : 1.0;
const RectF innnerRect = m_shrinkedShape.boundingRect();
const RectF innnerRectBar(innnerRect.pos, innnerRect.w * progress, innnerRect.h);
if (m_shearedX == 0.0)
{
m_shape.draw(m_backgroundColor);
if (innnerRectBar.w)
{
const Polygon bar = innnerRectBar.asPolygon();
if (const auto g = Geometry2D::And(bar, m_shrinkedShape))
{
g.front().draw(getBarColor(progress));
}
}
}
else
{
const Vec2 center = m_shape.boundingRect().center();
Transformer2D tr(Mat3x2::Translate(-center).shearedX(m_shearedX).translated(center));
m_shape.draw(m_backgroundColor);
if (innnerRectBar.w)
{
const Polygon bar = innnerRectBar.asPolygon();
if (const auto g = Geometry2D::And(bar, m_shrinkedShape))
{
g.front().draw(getBarColor(progress));
}
}
}
return *this;
}
// 中央揃えでテキストを描く
const CustomShapeProgressBar& withText(const SDFDrawableText& drawableText, double fontSize, const ColorF& textColor, const Vec2& textPosOffset = Vec2(0, 0)) const
{
const Size textSize = drawableText.region(fontSize).size;
const auto& font = drawableText.font;
const auto& rect = m_shape.boundingRect();
const Point textPos = (rect.pos + (rect.size - textSize) / 2 + textPosOffset).asPoint();
Graphics2D::SetSDFParameters(font.pixelRange(), 0.2);
drawableText.draw(fontSize, textPos, ColorF(0.1));
Graphics2D::SetSDFParameters(font.pixelRange(), 0.0);
drawableText.draw(fontSize, textPos, textColor);
return *this;
}
// 左揃えでテキストを描く
const CustomShapeProgressBar& withLabel(const SDFDrawableText& drawableText, double fontSize, const ColorF& textColor, double offsetX, const Vec2& textPosOffset = Vec2(0, 0)) const
{
const Size textSize = drawableText.region(fontSize).size;
const auto& font = drawableText.font;
const auto& rect = m_shape.boundingRect();
const Point textPos = (Vec2(rect.x + offsetX, rect.y + (rect.h - textSize.y) / 2) + textPosOffset).asPoint();
Graphics2D::SetSDFParameters(font.pixelRange(), 0.2);
drawableText.draw(fontSize, textPos, ColorF(0.1));
Graphics2D::SetSDFParameters(font.pixelRange(), 0.0);
drawableText.draw(fontSize, textPos, textColor);
return *this;
}
};
}
void Main()
{
Window::Resize(1280, 720);
Scene::SetBackground(ColorF(0.5, 0.4, 0.6));
const SDFFont font(32, U"example/font/LogoTypeGothic/LogoTypeGothic.otf", FontStyle::Bold);
// 進度に応じたバーの表示色のカスタマイズ
const Array<std::pair<double, ColorF>> barColors = {
{ 0.15, ColorF(0.8, 0.2, 0.0) }, // 15 % 未満は赤
{ 0.5, ColorF(0.8, 0.6, 0.1) }, // 50 % 未満はオレンジ
{ 1.0, ColorF(0.1, 0.8, 0.2) }, // それ以外は緑
};
// バーの背景色
constexpr ColorF barBackgroundColor(0.2, 0.8);
// テキストの色
constexpr ColorF textColor(1.0, 0.95, 0.9);
// 六角形
const Polygon shape1({ {0, 12}, {12, 0}, {308, 0}, {320, 12}, {308, 24}, {12, 24} });
// だんだん大きく
const Polygon shape2({ {0, 10}, {320, 0}, {320, 24}, {0, 24} });
// ラベルの場所を細く
const Polygon shape3({ {-6, 0}, {314, 0}, {314, 16}, {160, 16}, {160, 24}, {6, 24} });
// 右端だけ丸く
const Polygon shape4 = Rect(320, 24).rounded(0, 12, 12, 0);
// 六角形(細長)
const Polygon shape5({ {0, 6}, {6, 0}, {614, 0}, {620, 6}, {614, 12}, {6, 12} });
while (System::Update())
{
const int32 hp = static_cast<int32>(Periodic::Triangle0_1(12s) * 4800);
GameUIToolkit::CustomShapeProgressBar(Rect(40, 40, 320, 25).asPolygon(), ColorF(0.5), ColorF(0.1, 0.8, 0.2))
.draw(600, 4800);
GameUIToolkit::CustomShapeProgressBar(Rect(40, 120, 320, 25).stretched(-12, 0).asPolygon(), ColorF(0.5), ColorF(0.1, 0.8, 0.2), 1.0)
.draw(1200, 4800);
GameUIToolkit::CustomShapeProgressBar(shape1.movedBy(40, 200), ColorF(0.5), ColorF(0.1, 0.8, 0.2))
.draw(1800, 4800);
GameUIToolkit::CustomShapeProgressBar(shape2.movedBy(40, 280), ColorF(0.5), ColorF(0.1, 0.8, 0.2))
.draw(2400, 4800);
GameUIToolkit::CustomShapeProgressBar(shape3.movedBy(40, 360), ColorF(0.5), ColorF(0.1, 0.8, 0.2), 0.5)
.draw(3000, 4800);
GameUIToolkit::CustomShapeProgressBar(shape4.movedBy(40, 440), ColorF(0.5), ColorF(0.1, 0.8, 0.2))
.draw(3400, 4800);
GameUIToolkit::CustomShapeProgressBar(Rect(410, 40, 320, 25).asPolygon(), barBackgroundColor, barColors)
.draw(hp, 4800)
.withText(font(U"{}/4800"_fmt(hp)), 20, textColor, Vec2(0, 1));
GameUIToolkit::CustomShapeProgressBar(Rect(410, 120, 320, 25).stretched(-12, 0).asPolygon(), barBackgroundColor, barColors, 1.0)
.draw(hp, 4800)
.withText(font(U"{}/4800"_fmt(hp)), 20, textColor, Vec2(0, 1));
GameUIToolkit::CustomShapeProgressBar(shape1.movedBy(410, 200), barBackgroundColor, barColors)
.draw(hp, 4800)
.withText(font(U"{}/4800"_fmt(hp)), 20, textColor, Vec2(0, 1));
GameUIToolkit::CustomShapeProgressBar(shape2.movedBy(410, 280), barBackgroundColor, barColors)
.draw(hp, 4800)
.withLabel(font(U"{}/4800"_fmt(hp)), 20, textColor, 180, Vec2(0, 2));
GameUIToolkit::CustomShapeProgressBar(shape3.movedBy(410, 360), barBackgroundColor, barColors, 0.5)
.draw(hp, 4800)
.withLabel(font(U"{}/4800"_fmt(hp)), 20, textColor, 180, Vec2(0, 15));
GameUIToolkit::CustomShapeProgressBar(shape4.movedBy(410, 440), barBackgroundColor, barColors)
.draw(hp, 4800)
.withText(font(U"{}/4800"_fmt(hp)), 20, textColor, Vec2(0, 1));
GameUIToolkit::CustomShapeProgressBar(Rect(840, 40, 320, 25).asPolygon(), barBackgroundColor, barColors)
.draw(hp, 4800)
.withLabel(font(U"{}/4800"_fmt(hp)), 14, textColor, 330)
.withLabel(font(U"Lv.50"), 25, textColor, -85, Vec2(0, 1));
GameUIToolkit::CustomShapeProgressBar(Rect(840, 120, 320, 25).stretched(-12, 0).asPolygon(), barBackgroundColor, barColors, 1.0)
.draw(hp, 4800)
.withLabel(font(U"{}/4800"_fmt(hp)), 14, textColor, 330 - 12)
.withLabel(font(U"Lv.50"), 25, textColor, -85 - 12, Vec2(0, 1));
GameUIToolkit::CustomShapeProgressBar(shape1.movedBy(840, 200), barBackgroundColor, barColors)
.draw(hp, 4800)
.withLabel(font(U"{}/4800"_fmt(hp)), 14, textColor, 330)
.withLabel(font(U"Lv.50"), 25, textColor, -85, Vec2(0, 1));
GameUIToolkit::CustomShapeProgressBar(shape2.movedBy(840, 280), barBackgroundColor, barColors)
.draw(hp, 4800)
.withLabel(font(U"{}/4800"_fmt(hp)), 14, textColor, 330)
.withLabel(font(U"Lv.50"), 25, textColor, -85, Vec2(0, 1));
GameUIToolkit::CustomShapeProgressBar(shape3.movedBy(840, 360), barBackgroundColor, barColors, 0.5)
.draw(hp, 4800)
.withLabel(font(U"{}/4800"_fmt(hp)), 20, textColor, 180, Vec2(0, 15))
.withLabel(font(U"Lv.50"), 25, textColor, -85 + 6, Vec2(0, 1));
GameUIToolkit::CustomShapeProgressBar(shape4.movedBy(840, 440), barBackgroundColor, barColors)
.draw(hp, 4800)
.withLabel(font(U"{}/4800"_fmt(hp)), 14, textColor, 330)
.withLabel(font(U"Lv.50"), 25, textColor, -85, Vec2(0, 1));
GameUIToolkit::CustomShapeProgressBar(shape5.movedBy(320, 540), barBackgroundColor, barColors)
.draw(hp, 4800)
.withText(font(U"{}/4800"_fmt(hp)), 17, textColor, Vec2(0, 1))
.withLabel(font(U"Lv.50"), 25, textColor, -100, Vec2(0, 1));
}
}
3. タイル型のボタン
- 事前準備: knapsack.png を https://game-icons.net/1x1/lorc/knapsack.html からダウンロード
# include <Siv3D.hpp> // OpenSiv3D v0.4.3
namespace GameUIToolkit
{
class TileButton
{
private:
static constexpr double Border = 3.0;
TextureRegion m_icon;
int32 m_iconSize = 0;
Font m_font;
String m_text;
RectF m_rect;
Transition m_transitionPressed{ 0.09s, 0.12s };
ColorF m_color1, m_color2, m_color3, m_color4;
bool m_pressed = false;
void drawTile(double t) const
{
m_rect.draw(m_color1.lerp(m_color2, t));
m_rect.stretched(Math::Lerp(-Border, 0, t))
.drawFrame(0.1, Math::Lerp(1, 3, t), m_color3.lerp(m_color4, t));
}
void drawIcon(double padding, double t) const
{
const Point iconPos = Vec2(m_rect.x + (m_rect.w - m_icon.size.x) / 2,
m_rect.y + Border + padding + (m_iconSize - m_icon.size.y) / 2.0).asPoint();
m_icon.draw(iconPos, m_color2.lerp(m_color1, t));
}
void drawLabel(double padding, double t) const
{
const Size textSize = m_font(m_text).region().size;
const Point textPos = Vec2(m_rect.x + (m_rect.w - textSize.x) / 2,
m_rect.y + Border + padding + m_iconSize + padding).asPoint();
m_font(m_text).draw(textPos, m_color2.lerp(m_color1, t));
}
public:
TileButton() = default;
// アルファ透過した画像からアイコンを作成
TileButton(const FilePath& path, int32 iconSize, const Font& font, StringView text, const RectF& rect, const ColorF& color1, const ColorF& color2, const ColorF& color3, const ColorF& color4)
: TileButton(Texture(path, TextureDesc::Mipped), iconSize, font, text, rect, color1, color2, color3, color4) {}
// Image からアイコンを作成
TileButton(const Image& image, int32 iconSize, const Font& font, StringView text, const RectF& rect, const ColorF& color1, const ColorF& color2, const ColorF& color3, const ColorF& color4)
: TileButton(Texture(image, TextureDesc::Mipped), iconSize, font, text, rect, color1, color2, color3, color4) {}
// Icon コードからアイコンを作成
TileButton(uint32 iconCode, int32 iconSize, const Font& font, StringView text, const RectF& rect, const ColorF& color1, const ColorF& color2, const ColorF& color3, const ColorF& color4)
: TileButton(Texture(Icon::CreateImage(iconCode, iconSize), TextureDesc::Mipped), iconSize, font, text, rect, color1, color2, color3, color4) {}
// Texture からアイコンを作成
TileButton(const TextureRegion& textureRegion, int32 iconSize, const Font& font, StringView text, const RectF& rect, const ColorF& color1, const ColorF& color2, const ColorF& color3, const ColorF& color4)
: m_icon(textureRegion)
, m_iconSize(iconSize)
, m_font(font)
, m_text(text)
, m_rect(rect)
, m_color1(color1)
, m_color2(color2)
, m_color3(color3)
, m_color4(color4) {}
bool update()
{
const bool mouseOver = m_rect.mouseOver();
bool pushed = false;
if (mouseOver)
{
Cursor::RequestStyle(CursorStyle::Hand);
}
if (!m_pressed)
{
if (m_rect.leftClicked())
{
m_pressed = true;
}
}
else
{
if (m_rect.leftReleased())
{
m_pressed = false;
pushed = true;
}
else if (!m_rect.mouseOver())
{
m_pressed = false;
}
}
m_transitionPressed.update(m_pressed);
return pushed;
}
void draw() const
{
const double padding = (m_rect.h - m_iconSize - m_font.ascent() - (Border * 2)) / 3.0;
const double t = m_transitionPressed.value();
const Transformer2D tr(Mat3x2::Scale((1 + t * 0.06), m_rect.center()));
drawTile(t);
drawIcon(padding, t);
drawLabel(padding, t);
}
};
}
void Main()
{
Window::Resize(1280, 720);
const Font font1(21, U"example/font/LogoTypeGothic/LogoTypeGothic.otf", FontStyle::Bold);
const Font font2(14, U"example/font/LogoTypeGothic/LogoTypeGothic.otf", FontStyle::Bold);
const Font font3(24, Typeface::Heavy);
constexpr int32 iconSize1 = 65;
constexpr int32 iconSize2 = 40;
constexpr int32 iconSize3 = 60;
constexpr ColorF c1(0.3, 0.2, 0.0);
constexpr ColorF c2(1.0, 0.95, 0.75);
constexpr ColorF c3(1.0, 0.4);
constexpr ColorF c4(1.0, 0.8, 0.4);
Array<GameUIToolkit::TileButton> buttons = {
{ 0xf279, iconSize1, font1, U"マップ", Rect(40, 40, 130), c1, c2, c3, c4 },
{ 0xf14e, iconSize1, font1, U"イベント", Rect(180, 40, 130), c1, c2, c3, c4 },
// knapsack.png は https://game-icons.net/1x1/lorc/knapsack.html からダウンロード
{ Image(Palette::White, U"knapsack.png").scaled(iconSize1, iconSize1), iconSize1, font1, U"バッグ", Rect(320, 40, 130), c1, c2, c3, c4 },
{ 0xf02d, iconSize1, font1, U"冒険の記録", Rect(460, 40, 130), c1, c2, c3, c4 },
{ 0xf091, iconSize1, font1, U"実績", Rect(600, 40, 130), c1, c2, c3, c4 },
{ 0xf013, iconSize1, font1, U"設定", Rect(740, 40, 130), c1, c2, c3, c4 },
{ 0xf279, iconSize2, font2, U"マップ", Rect(40, 200, 80), c1, c2, c3, c4 },
{ 0xf14e, iconSize2, font2, U"イベント", Rect(130, 200, 80), c1, c2, c3, c4 },
{ Image(Palette::White, U"knapsack.png").scaled(iconSize2, iconSize2), iconSize2, font2, U"バッグ", Rect(220, 200, 80), c1, c2, c3, c4 },
{ 0xf02d, iconSize2, font2, U"冒険の記録", Rect(310, 200, 80), c1, c2, c3, c4 },
{ 0xf091, iconSize2, font2, U"実績", Rect(400, 200, 80), c1, c2, c3, c4 },
{ 0xf013, iconSize2, font2, U"設定", Rect(490, 200, 80), c1, c2, c3, c4 },
{ 0xf2e7, iconSize3, font3, U"メニュー", Rect(40, 360, 150, 120), HSV(25, 1, 0.8), Palette::White, c3, HSV(25, 0.5, 1) },
{ 0xf7fb, iconSize3, font3, U"具材", Rect(200, 360, 150, 120), HSV(75, 1, 0.8), Palette::White, c3, HSV(75, 0.5, 1) },
{ 0xf816, iconSize3, font3, U"調味料", Rect(360, 360, 150, 120), HSV(125, 1, 0.8), Palette::White, c3, HSV(125, 0.5, 1) },
{ 0xf07a, iconSize3, font3, U"仕入れ", Rect(520, 360, 150, 120), HSV(175, 1, 0.8), Palette::White, c3, HSV(175, 0.5, 1) },
{ 0xf517, iconSize3, font3, U"設備", Rect(680, 360, 150, 120), HSV(225, 1, 0.8), Palette::White, c3, HSV(225, 0.5, 1) },
{ 0xf0a1, iconSize3, font3, U"宣伝", Rect(840, 360, 150, 120), HSV(275, 1, 0.8), Palette::White, c3, HSV(275, 0.5, 1) },
{ 0xf201, iconSize3, font3, U"売り上げ", Rect(1000, 360, 150, 120), HSV(325, 1, 0.8), Palette::White, c3, HSV(325, 0.5, 1) },
};
while (System::Update())
{
Rect(0, 0, Scene::Width(), 320).draw(ColorF(0.8, 0.7, 0.6));
Rect(0, 320, Scene::Width(), 200).draw(ColorF(0.3));
for (auto& button : buttons)
{
button.update();
}
for (const auto& button : buttons)
{
button.draw();
}
}
}
Discussion