C++20 framework for creative coding 🎮🎨🎹 / Cross-platform support (Windows, macOS, Linux, and the Web)
MIT License
Siv3D (OpenSiv3D) is a C++20 framework for creative coding (2D/3D games, media art, visualizers, and simulators). Siv3D applications run on Windows, macOS, Linux, and the Web.
Point
, Float2
, Vec2
, Float3
, Vec3
, Float4
, Vec4
, Mat3x2
, Mat3x3
, Mat4x4
, SIMD_Float4
, Quaternion
)Line
, Circle
, Ellipse
, Rect
, RectF
, Triangle
, Quad
, RoundRect
, Polygon
, MultiPolygon
, LineString
, Spline2D
, Bezier2
, Bezier3
)Plane
, InfinitePlane
, Sphere
, Box
, OrientedBox
, Ray
, Line3D
, Triangle3D
, ViewFrustum
, Disc
, Cylinder
, Cone
)Color
, ColorF
, HSV
)HalfFloat
, int128
, uint128
, BigInt
, BigFloat
)String
, StringView
){fmt}
style text formattingArray
, Grid
)* Some features are limited to specific platforms
v0.6.15 | released 3 July 2024 | Release Notes
Platform | SDK | Requirements |
---|---|---|
Windows | Download SDK /**SDK ** | - Windows 10 / 11 (64-bit)- Microsoft Visual C++ 2022 17.10- Windows 10 SDK- Intel / AMD CPU |
macOS | Download SDK /**SDK ** | - macOS Big Sur / Monterey / Ventura- Xcode 12.5 or newer- Intel CPU / Apple Silicon (Rosetta mode)*- OpenGL 4.1 compatible hardware |
Linux | Compiling for Linux /**Linux ** | - GCC 9.3.0 (with Boost 1.71.0) / GCC 11.2 (with Boost 1.74.0)- Intel / AMD CPU- OpenGL 4.1 compatible hardware |
Web (experimental**) | Compiling for Web /**Web ** | Web browser with WebAssembly and WebGL2 support |
* Native Apple Silicon support will be added in the future release. You can build and run Siv3D in Rosetta mode** Some functionality may be missing or limited
The next major update, Siv3D v0.8, is under development in the following repository.
If you would like to support the project financially, visit my GitHub Sponsors page. Your support will accelerate the development of this exciting framework.
https://github.com/sponsors/Reputeless
# include <Siv3D.hpp>
void Main()
{
// | Set the background color
Scene::SetBackground(ColorF{ 0.6, 0.8, 0.7 });
// | Create a texture from an image file
const Texture texture{ U"example/windmill.png" };
// | Create a texture from an emoji
const Texture emoji{ U""_emoji };
// | Create a bold font with MSDF method
const Font font{ FontMethod::MSDF, 48, Typeface::Bold };
// font | Create a font for emojis in text and add it to font as a fallback
const Font emojiFont{ 48, Typeface::ColorEmoji };
font.addFallback(emojiFont);
// | Number of button presses
int32 count = 0;
// | Checkbox state
bool checked = false;
// | Player's movement speed
double speed = 200.0;
// X | Player's X position
double playerPosX = 400;
// | Whether player is facing right
bool isPlayerFacingRight = true;
while (System::Update())
{
// | Draw the texture
texture.draw(20, 20);
// | Draw text
font(U"Hello, Siv3D!").draw(64, Vec2{ 20, 340 }, ColorF{ 0.2, 0.4, 0.8 });
// | Draw text within a specified area
font(U"Siv3D () C++ ")
.draw(18, Rect{ 20, 430, 480, 200 }, Palette::Black);
// | Draw a rectangle
Rect{ 540, 20, 80, 80 }.draw();
// | Draw a rounded rectangle
RoundRect{ 680, 20, 80, 200, 20 }.draw(ColorF{ 0.0, 0.4, 0.6 });
// | Draw a circle
Circle{ 580, 180, 40 }.draw(Palette::Seagreen);
// | Draw an arrow
Line{ 540, 330, 760, 260 }.drawArrow(8, SizeF{ 20, 20 }, ColorF{ 0.4 });
// | Draw a semi-transparent circle
Circle{ Cursor::Pos(), 40 }.draw(ColorF{ 1.0, 0.0, 0.0, 0.5 });
// | Button
if (SimpleGUI::Button(U"count: {}"_fmt(count), Vec2{ 520, 370 }, 120, (checked == false)))
{
// | Increase the count
++count;
}
// | Checkbox
SimpleGUI::CheckBox(checked, U"Lock \U000F033E", Vec2{ 660, 370 }, 120);
// | Slider
SimpleGUI::Slider(U"speed: {:.1f}"_fmt(speed), speed, 100, 400, Vec2{ 520, 420 }, 140, 120);
// | If left key is pressed
if (KeyLeft.pressed())
{
// | Player moves left
playerPosX = Max((playerPosX - speed * Scene::DeltaTime()), 60.0);
isPlayerFacingRight = false;
}
// | If right key is pressed
if (KeyRight.pressed())
{
// | Player moves right
playerPosX = Min((playerPosX + speed * Scene::DeltaTime()), 740.0);
isPlayerFacingRight = true;
}
// | Draw the player
emoji.scaled(0.75).mirrored(isPlayerFacingRight).drawAt(playerPosX, 540);
}
}
# include <Siv3D.hpp>
void Main()
{
// 1 | Size of a single block
constexpr Size BrickSize{ 40, 20 };
// / | Ball speed (pixels / second)
constexpr double BallSpeedPerSec = 480.0;
// | Ball velocity
Vec2 ballVelocity{ 0, -BallSpeedPerSec };
// | Ball
Circle ball{ 400, 400, 8 };
// | Array of bricks
Array<Rect> bricks;
for (int32 y = 0; y < 5; ++y)
{
for (int32 x = 0; x < (Scene::Width() / BrickSize.x); ++x)
{
bricks << Rect{ (x * BrickSize.x), (60 + y * BrickSize.y), BrickSize };
}
}
while (System::Update())
{
// | Paddle
const Rect paddle{ Arg::center(Cursor::Pos().x, 500), 60, 10 };
// | Move the ball
ball.moveBy(ballVelocity * Scene::DeltaTime());
// | Check bricks in sequence
for (auto it = bricks.begin(); it != bricks.end(); ++it)
{
// | If block and ball intersect
if (it->intersects(ball))
{
// | If ball intersects with top or bottom of the block
if (it->bottom().intersects(ball) || it->top().intersects(ball))
{
// Y | Reverse the sign of the Y component of the ball's velocity
ballVelocity.y *= -1;
}
else //
{
// X | Reverse the sign of the X component of the ball's velocity
ballVelocity.x *= -1;
}
// | Remove the block from the array (the iterator becomes invalid)
bricks.erase(it);
// | Do not check any more
break;
}
}
// | If the ball hits the ceiling
if ((ball.y < 0) && (ballVelocity.y < 0))
{
// Y | Reverse the sign of the Y component of the ball's velocity
ballVelocity.y *= -1;
}
// | If the ball hits the left or right wall
if (((ball.x < 0) && (ballVelocity.x < 0))
|| ((Scene::Width() < ball.x) && (0 < ballVelocity.x)))
{
// X | Reverse the sign of the X component of the ball's velocity
ballVelocity.x *= -1;
}
// | If the ball hits the left or right wall
if ((0 < ballVelocity.y) && paddle.intersects(ball))
{
// | Change the direction (velocity vector) of the ball depending on the distance from the center of the paddle
ballVelocity = Vec2{ (ball.x - paddle.center().x) * 10, -ballVelocity.y }.setLength(BallSpeedPerSec);
}
// | Draw all the bricks
for (const auto& brick : bricks)
{
// Y | Change the color of the brick depending on the Y coordinate
brick.stretched(-1).draw(HSV{ brick.y - 40 });
}
// | Hide the mouse cursor
Cursor::RequestStyle(CursorStyle::Hidden);
// | Draw the ball
ball.draw();
// | Draw the paddle
paddle.rounded(3).draw();
}
}
# include <Siv3D.hpp>
void Main()
{
// Resize the window and scene to 1280x720
Window::Resize(1280, 720);
// Background color (remove SRGB curve for a linear workflow)
const ColorF backgroundColor = ColorF{ 0.4, 0.6, 0.8 }.removeSRGBCurve();
// Texture for UV check (mipmapped. treat as SRGB texture in a linear workflow)
const Texture uvChecker{ U"example/texture/uv.png", TextureDesc::MippedSRGB };
// Multisample RenderTexture for a linear workflow
const MSRenderTexture renderTexture{ Scene::Size(), TextureFormat::R8G8B8A8_Unorm_SRGB, HasDepth::Yes };
// 3D debug camera (free camera)
// Vertical FOV: 30, Eye position: (10, 16, -32)
// Move: [W][S][A][D][E][X], View: [arrow keys]
DebugCamera3D camera{ renderTexture.size(), 30_deg, Vec3{ 10, 16, -32 } };
while (System::Update())
{
// Update a camera
camera.update(2.0);
// Set up a camera in the current 3D scene
Graphics3D::SetCameraTransform(camera);
// [3D rendering]
{
// Clear renderTexture with the background color,
// then make renderTexture the render target for the current 3D scene
const ScopedRenderTarget3D target{ renderTexture.clear(backgroundColor) };
// Draw a floor
Plane{ 64 }.draw(uvChecker);
// Draw a box
Box{ -8,2,0,4 }.draw(ColorF{ 0.8, 0.6, 0.4 }.removeSRGBCurve());
// Draw a sphere
Sphere{ 0,2,0,2 }.draw(ColorF{ 0.4, 0.8, 0.6 }.removeSRGBCurve());
// Draw a cylinder
Cylinder{ 8, 2, 0, 2, 4 }.draw(ColorF{ 0.6, 0.4, 0.8 }.removeSRGBCurve());
}
// [2D rendering]
{
// Flush 3D rendering commands before multisample resolve
Graphics3D::Flush();
// Multisample resolve
renderTexture.resolve();
// Transfer renderTexture to the current 2D scene (default scene)
Shader::LinearToScreen(renderTexture);
}
}
}