23. Arrays of Shapes¶
Learn how to handle shape classes like Circle and Rect in arrays.
23.1 Creating an Array of Circles¶
Array<Circle>is an array ofCircle

# include <Siv3D.hpp>
void Main()
{
Array<Circle> circles =
{
Circle{ 100, 300, 10 },
Circle{ 200, 300, 20 },
Circle{ 300, 300, 30 },
Circle{ 400, 300, 40 },
};
Print << circles;
while (System::Update())
{
}
}
23.2 Drawing All Circles¶
- Use a range-based for loop (const reference) to draw all
Circles

# include <Siv3D.hpp>
void Main()
{
Scene::SetBackground(ColorF{ 0.6, 0.8, 0.7 });
Array<Circle> circles =
{
Circle{ 100, 300, 10 },
Circle{ 200, 300, 20 },
Circle{ 300, 300, 30 },
Circle{ 400, 300, 40 },
};
while (System::Update())
{
// Draw all circles
for (const auto& circle : circles)
{
circle.draw();
}
}
}
23.3 Moving All Circles¶
- Use a range-based for loop (reference) to move all
Circles

# include <Siv3D.hpp>
void Main()
{
Scene::SetBackground(ColorF{ 0.6, 0.8, 0.7 });
Array<Circle> circles =
{
Circle{ 100, 300, 10 },
Circle{ 200, 300, 20 },
Circle{ 300, 300, 30 },
Circle{ 400, 300, 40 },
};
while (System::Update())
{
const double deltaTime = Scene::DeltaTime();
// Move all circles
for (auto& circle : circles)
{
circle.y += (deltaTime * 50.0);
}
// Draw all circles
for (const auto& circle : circles)
{
circle.draw();
}
}
}
23.4 Adding Circles by Clicking¶
- Add a
Circlewith a random radius at the clicked position

# include <Siv3D.hpp>
void Main()
{
Scene::SetBackground(ColorF{ 0.6, 0.8, 0.7 });
Array<Circle> circles;
while (System::Update())
{
// If left-clicked
if (MouseL.down())
{
// Add a circle with random radius at the clicked position
circles << Circle{ Cursor::Pos(), Random(5.0, 40.0) };
}
// Draw all circles
for (const auto& circle : circles)
{
circle.draw();
}
}
}
23.5 Removing Circles by Clicking (.remove_if() Method)¶
- Use
.remove_if()to removeCircles that are left-clicked- See Tutorial 22.17 for element removal using
.remove_if()
- See Tutorial 22.17 for element removal using
- Pass a lambda expression to
.remove_if()that determines "whether the circle was left-clicked"

# include <Siv3D.hpp>
void Main()
{
Scene::SetBackground(ColorF{ 0.6, 0.8, 0.7 });
Array<Circle> circles =
{
Circle{ 100, 300, 10 },
Circle{ 200, 300, 20 },
Circle{ 300, 300, 30 },
Circle{ 400, 300, 40 },
};
while (System::Update())
{
// Remove circles that were left-clicked
circles.remove_if([](const Circle& circle) { return circle.leftClicked(); });
// Draw all circles
for (const auto& circle : circles)
{
circle.draw();
}
}
}
23.6 Removing Circles by Clicking (Iterator Method)¶
- Remove
Circles that are left-clicked using the iterator method- See Tutorial 22.16 for element removal using iterators
- Compared to the
.remove_if()method, this approach makes it easier to write additional processing along with removal (such as adding points, stopping further removals, etc.) - Access to elements must be done before removal with
.erase()

# include <Siv3D.hpp>
void Main()
{
Scene::SetBackground(ColorF{ 0.6, 0.8, 0.7 });
const Font font{ FontMethod::MSDF, 48 };
Array<Circle> circles =
{
Circle{ 100, 300, 10 },
Circle{ 200, 300, 20 },
Circle{ 300, 300, 30 },
Circle{ 400, 300, 40 },
};
// Score
double score = 0;
while (System::Update())
{
// For each circle
for (auto it = circles.begin(); it != circles.end();)
{
// If the circle was left-clicked
if (it->leftClicked())
{
// Add radius * 10 to the score
score += (it->r * 10); // Access element before deletion
// Remove the circle
it = circles.erase(it);
}
else
{
++it;
}
}
// Draw all circles
for (const auto& circle : circles)
{
circle.draw();
}
font(U"Score: {}"_fmt(score)).draw(40, Vec2{ 40, 40 }, ColorF{ 0.1 });
}
}
23.7 Removing Circles that Reach a Certain Position¶
- Make
Circles move automatically and remove them when they reach a certain position - Pass a lambda expression to
.remove_if()that determines "whether the Y coordinate exceeded 500.0"

# include <Siv3D.hpp>
void Main()
{
Scene::SetBackground(ColorF{ 0.6, 0.8, 0.7 });
Array<Circle> circles;
for (int32 i = 0; i < 6; ++i)
{
circles << Circle{ (100 + i * 100), Random(0.0, 200.0), 30 };
}
while (System::Update())
{
const double deltaTime = Scene::DeltaTime();
for (auto& circle : circles)
{
circle.y += (deltaTime * 100.0);
}
// Remove circles whose Y coordinate exceeded 500.0
circles.remove_if([](const Circle& circle) { return (500.0 < circle.y); });
// Draw all circles
for (const auto& circle : circles)
{
circle.draw();
}
}
}
23.8 Adding Circles at Regular Intervals¶
- Apply the "doing something at regular intervals" from Tutorial 19.3 to add a
Circleevery 0.5 seconds

Add a circle every 0.5 seconds (maximum 10 circles)
# include <Siv3D.hpp>
void Main()
{
Scene::SetBackground(ColorF{ 0.6, 0.8, 0.7 });
Array<Circle> circles;
// Circle spawn interval (seconds)
const double spawnInterval = 0.5;
// Maximum number of circles
const size_t maxCircles = 10;
// Accumulated time (seconds)
double accumulatedTime = 0.0;
while (System::Update())
{
// Time elapsed since the previous frame (seconds)
const double deltaTime = Scene::DeltaTime();
// Increase accumulated time
accumulatedTime += deltaTime;
// If accumulated time exceeds the interval
if (spawnInterval < accumulatedTime)
{
// If the number of circles hasn't reached the maximum
if (circles.size() < maxCircles)
{
// Add a circle
circles << Circle{ Random(100, 700), Random(100, 500), 30 };
}
// Reduce accumulated time by the interval
accumulatedTime -= spawnInterval;
}
for (const auto& circle : circles)
{
circle.draw();
}
}
}
23.9 Arrays of Custom Classes (1)¶
- Create a
ColorCircleclass that has aCircleand a hue value, and handle them in an array

# include <Siv3D.hpp>
struct ColorCircle
{
Circle circle;
double hue;
// Function to draw the circle
void draw() const
{
circle.draw(HSV{ hue, 0.75, 0.9 });
}
};
void Main()
{
Scene::SetBackground(ColorF{ 0.6, 0.8, 0.7 });
Array<ColorCircle> circles;
while (System::Update())
{
// If left-clicked
if (MouseL.down())
{
// Add a ColorCircle
circles << ColorCircle{ Circle{ Cursor::Pos(), Random(5.0, 40.0) }, Random(0.0, 360.0) };
}
// Draw all ColorCircles
for (const auto& circle : circles)
{
circle.draw();
}
}
}
23.10 Arrays of Custom Classes (2)¶
- Create a
RectCounterclass that keeps count of how many times it has been clicked, and handle them in an array .center()ofRectreturns the center coordinates of the rectangle as aPointtype

# include <Siv3D.hpp>
struct RectCounter
{
Rect rect;
int32 count = 0;
// Function to update the counter
void update()
{
if (rect.mouseOver())
{
Cursor::RequestStyle(CursorStyle::Hand);
}
if (rect.leftClicked())
{
++count;
}
}
// Function to draw the counter
void draw(const Font& font) const
{
rect.draw();
rect.drawFrame(2, ColorF{ 0.1 });
font(U"{}"_fmt(count)).drawAt(rect.center(), ColorF{ 0.1 });
}
};
void Main()
{
Scene::SetBackground(ColorF{ 0.6, 0.8, 0.7 });
const Font font{ FontMethod::MSDF, 48, Typeface::Bold };
Array<RectCounter> rectCounters;
rectCounters << RectCounter{ Rect{ 100, 100, 100, 100 } };
rectCounters << RectCounter{ Rect{ 300, 100, 100, 100 } };
rectCounters << RectCounter{ Rect{ 500, 100, 100, 100 } };
while (System::Update())
{
// Update all RectCounters
for (auto& rectCounter : rectCounters)
{
rectCounter.update();
}
// Draw all RectCounters
for (const auto& rectCounter : rectCounters)
{
rectCounter.draw(font);
}
}
}