サンプル集
プログラムをクリップボードにコピーするには、コード欄左上の「cpp」にカーソルを重ねて「Copy」を押します
Windows の場合、Visual Studio のメニューでビルド設定を「Debug」から「Release」に変えておくとプログラムが早くなるので、変えておきます
サンプル 1. 文字列で物理演算
テキストを入力してエンターキーで落下開始
右クリックでリセット
右クリックやホイールでカメラ移動
code:cpp
# include <Siv3D.hpp>
# include <HamFramework.hpp>
MultiPolygon MakePolygons(const Font& font, const String& text)
{
Image image(1200, 200, Color(0, 0));
font(text).overwrite(image, 0, 0, Palette::White);
return image.alphaToPolygons().simplified(1).movedBy(-400, -500).scaled(0.025);
}
void Main()
{
Window::Resize(1280, 720);
Graphics::SetBackground(ColorF(0.94, 0.91, 0.86));
P2World world;
const P2Body line = world.createLine(Vec2(0, 0), Line(-16, 0, 16, 0), P2Material(1, 0.1, 1.0), none, P2BodyType::Static);
Array<P2Body> bodies;
Camera2D camera(Vec2(0, -5), 38);
camera.enableKeyControl(false);
const Font font(100, Typeface::Bold);
String text;
int32 generation = 0;
HashTable<P2BodyID, int32> table;
while (System::Update())
{
TextInput::UpdateText(text);
world.update(System::DeltaTime(0.05), 30, 10);
camera.update();
auto t = camera.createTransformer();
for (const auto& body : bodies)
{
body.draw(HSV(tablebody.id() * 45 + 30, 0.75, 0.85)); }
line.draw(Palette::Green);
{
Transformer2D trans(Mat3x2::Scale(0.025));
font(text + TextInput::GetEditingText()).draw(-400, -500, ColorF(0.5));
}
if (text.includes(U'\n'))
{
for (const auto& poly : MakePolygons(font, text))
{
const Vec2 centroid = poly.centroid();
bodies << world.createPolygon(centroid, poly.movedBy(-centroid), P2Material(1, 0.0, 0.4));
}
text.clear();
++generation;
}
if (MouseR.down())
{
bodies.clear();
}
camera.draw(Palette::Orange);
}
}
サンプル 2. 音声波形可視化
クリックでランダムに音を生成
code:cpp
# include <Siv3D.hpp>
void Main()
{
Window::Resize(1280, 720);
const Font font(40, Typeface::Medium);
String text;
Audio audio;
Wave wave;
LineString lines(2560);
while (System::Update())
{
font(text).draw(20, 20, Palette::Orange);
if (MouseL.down())
{
const uint8 inst = static_cast<uint8>(Random(0, 127)); // See SoundFont.hpp
const uint8 key = static_cast<uint8>(Random(50, 80)); // See SoundFont.hpp
text = U"Instrument: {}\nKey: {}"_fmt(inst, key);
wave = Wave(inst, key, 1.0s, 1.0);
audio = Audio(wave);
audio.play();
}
if (audio.isPlaying())
{
const int64 pos = audio.posSample();
const int64 beginPos = pos - lines.size();
size_t lineIndex = 0;
for (int64 i = beginPos; i < pos; ++i)
{
if (i < 0)
{
lineslineIndex = Vec2(lineIndex * 0.5, 360.0); }
else
{
lineslineIndex = Vec2(lineIndex * 0.5, 360 - f * 360); }
++lineIndex;
}
lines.draw(3, ColorF(0.0, 1.0, 1.0));
}
else
{
Line(0, 360, 1280, 360).draw(3, ColorF(0.0, 1.0, 1.0));
}
}
}
サンプル 3. ピアノ
Tab キーから 1, Q, W, ... とピアノの鍵盤に対応
code:cpp
# include <Siv3D.hpp>
void Main()
{
constexpr int32 NumKeys = 20;
std::array<Audio, NumKeys> sounds;
const uint8 inst = Random(0, 127);
for (auto i : step(NumKeys))
{
soundsi = Audio(Wave(inst, static_cast<uint8>(PianoKey::A3 + i), 0.5s)); }
const std::array<Key, NumKeys> keys =
{
KeyTab, Key1, KeyQ,
KeyW, Key3, KeyE, Key4, KeyR, KeyT, Key6, KeyY, Key7, KeyU, Key8, KeyI,
KeyO, Key0, KeyP, KeyMinus, KeyGraveAccent,
};
const std::array<int32, NumKeys> keyOffset =
{
0, 1, 2, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14, 15, 16, 18, 19, 20, 21, 22
};
while (System::Update())
{
for (auto i : step(NumKeys))
{
{
soundsi.playOneShot(0.5); }
}
for (auto i : step(NumKeys))
{
{
Rect(keyOffseti / 2 * 54, 0, 52, 400) .draw(keysi.pressed() ? Palette::Pink : Palette::White); }
}
for (auto i : step(NumKeys))
{
{
Rect(37 + keyOffseti / 2 * 54, 0, 32, 250) .draw(keysi.pressed() ? Palette::Pink : Palette::Black); }
}
}
}
サンプル 4. どうぶつタワーバトル
クリックで動物落下
code:cpp
# include <Siv3D.hpp>
# include <HamFramework.hpp>
void Main()
{
P2World world;
const P2Body line = world.createLine(Vec2(0, 0), Line(-12, 0, 12, 0), P2Material(1, 0.1, 1.0), none, P2BodyType::Static);
Array<P2Body> bodies;
Array<MultiPolygon> polys;
Array<Texture> textures;
HashTable<P2BodyID, size_t> table;
for (const auto& animal : { U"🐘", U"🐧", U"🐐", U"🐤" })
{
polys << Emoji::LoadImage(animal).alphaToPolygons()
.moveBy(-Emoji::ImageSize / 2).simplified(0.8).scale(0.04);
textures << Texture(Emoji(animal), TextureDesc::Mipped);
}
Camera2D camera(Vec2(0, -8), 20);
size_t index = 0;
while (System::Update())
{
world.update();
camera.update();
auto t = camera.createTransformer();
if (MouseL.down())
{
bodies << world.createPolygons(Cursor::PosF(), polysindex, P2Material(0.1, 0.0, 1.0)); table.emplace(bodies.back().id(), std::exchange(index, Random(polys.size() - 1)));
}
for (const auto& body : bodies)
{
textures[tablebody.id()].scaled(0.04).rotated(body.getAngle()).drawAt(body.getPos()); }
line.draw(Palette::Green);
texturesindex.scaled(0.04).drawAt(Cursor::PosF()); camera.draw(Palette::Orange);
}
}
サンプル 5. ブロックくずし
マウスでバーを移動
code:cpp
# include <Siv3D.hpp>
void Main()
{
const Size blockSize(40, 20);
Array<Rect> blocks = Iota2D(Window::Width() / blockSize.x, 5).asArray()
.map(=(Point p) { return Rect(p * blockSize, blockSize).moveBy(0, 60); }); Circle ball(320, 400, 8);
const double speed = 8.0;
Vec2 ballSpeed(0, -speed);
while (System::Update())
{
const Rect bar(Arg::center(Cursor::Pos().x, 420), 60, 10);
ball.moveBy(ballSpeed * (System::DeltaTime() / 0.01667));
for (auto it = blocks.begin(); it != blocks.end(); ++it)
{
if (it->intersects(ball))
{
(it->bottom().intersects(ball) || it->top().intersects(ball) ? ballSpeed.y : ballSpeed.x) *= -1;
blocks.erase(it);
break;
}
}
if (ball.y < 0 && ballSpeed.y < 0)
{
ballSpeed.y *= -1;
}
if ((ball.x < 0 && ballSpeed.x < 0) || (Window::Width() < ball.x && ballSpeed.x > 0))
{
ballSpeed.x *= -1;
}
if (ballSpeed.y > 0 && bar.intersects(ball))
{
ballSpeed = Vec2((ball.x - bar.center().x) / 8, -ballSpeed.y).setLength(speed);
}
blocks.each([](const Rect& b) { b.stretched(-1).draw(HSV(b.y - 40)); });
ball.draw();
bar.draw();
}
}
サンプル 6. リアルタイム QR エンコード
code:cpp
# include <Siv3D.hpp>
void Main()
{
Window::Resize(1280, 720);
const Font font(40, Typeface::Bold);
DynamicTexture texture;
QRCode qr;
String text, previous;
while (System::Update())
{
TextInput::UpdateText(text);
const String current = text + TextInput::GetEditingText();
if (current != previous)
{
// 入力したテキストを QR コードに変換
if (QR::EncodeText(qr, current))
{
texture.fill(qr.image.border(4).scaled(500, 500, Interpolation::Nearest));
}
}
previous = current;
font(current).draw(60, 50);
texture.drawAt(640, 400);
}
}
サンプル 7. ライフゲーム
code:cpp
# include <Siv3D.hpp>
struct Cell
{
bool previous : 1;
bool current : 1;
};
void RandomFill(Grid<Cell>& grid)
{
grid.fill({ 0,0 });
for (auto y : Range(1, grid.height() - 2))
{
for (auto x : Range(1, grid.width() - 2))
{
gridyx = { 0, RandomBool(0.5) }; }
}
}
void Update(Grid<Cell>& grid)
{
for (auto& cell : grid)
{
cell.previous = cell.current;
}
for (auto y : Range(1, grid.height() - 2))
{
for (auto x : Range(1, grid.width() - 2))
{
const int32 c = gridyx.previous; int32 n = 0;
gridyx.current = (c == 0 && n == 3) || (c == 1 && (n == 2 || n == 3)); }
}
}
void CopyToImage(const Grid<Cell>& grid, Image& image)
{
for (auto y : step(image.height()))
{
for (auto x : step(image.width()))
{
? Color(0, 255, 0) : Palette::Black;
}
}
}
void Main()
{
Window::Resize(800, 600);
constexpr int32 width = 60;
constexpr int32 height = 60;
Grid<Cell> grid(width + 2, height + 2, { 0,0 });
Image image(width, height, Palette::Black);
DynamicTexture texture(image);
Stopwatch s(true);
bool autoStep = false;
double speed = 0.5;
bool showGrid = true;
bool updated = false;
while (System::Update())
{
if (SimpleGUI::ButtonAt(U"Random", Vec2(700, 40), 170))
{
RandomFill(grid);
updated = true;
}
if (SimpleGUI::ButtonAt(U"Clear", Vec2(700, 80), 170))
{
grid.fill({ 0, 0 });
updated = true;
}
if (SimpleGUI::ButtonAt(autoStep ? U"Pause" : U"Auto", Vec2(700, 160), 170))
{
autoStep = !autoStep;
}
SimpleGUI::SliderAt(U"Speed", speed, 1.0, 0.1, Vec2(700, 200), 70, 100);
if (SimpleGUI::ButtonAt(U"Step", Vec2(700, 240), 170)
|| (autoStep && s.sF() >= (speed * speed)))
{
Update(grid);
updated = true;
s.restart();
}
SimpleGUI::CheckBoxAt(showGrid, U"Grid", Vec2(700, 320), 170);
if (Rect(0, 0, 599).mouseOver())
{
const Point target = Cursor::Pos() / 10 + Point(1, 1);
if (MouseL.pressed())
{
updated = true;
}
else if (MouseR.pressed())
{
updated = true;
}
}
if (updated)
{
CopyToImage(grid, image);
texture.fill(image);
updated = false;
}
{
RenderStateBlock2D sampler(SamplerState::ClampNearest);
texture.scaled(10).draw();
}
if (showGrid)
{
for (auto i : step(61))
{
Rect(0, i * 10, 600, 1).draw(ColorF(0.4));
Rect(i * 10, 0, 1, 600).draw(ColorF(0.4));
}
}
if (Rect(0, 0, 599).mouseOver())
{
Cursor::RequestStyle(CursorStyle::Hidden);
Rect(Cursor::Pos() / 10 * 10, 10).draw(Palette::Orange);
}
}
}