Last active
December 7, 2019 15:59
-
-
Save falrnd/75d750a225e125369575a1b01f09092d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//based on https://siv3d.github.io/ja-jp/reference/2d-particle/ | |
# include <Siv3D.hpp> | |
const String siv3d_kun_path = U"example/siv3d-kun.png"; | |
Polygon CreateSiv3D_kunPolygon() | |
{ | |
return Image(siv3d_kun_path) | |
.alphaToPolygonCentered().simplified(1); | |
} | |
auto CreateParticleTexture() | |
{ | |
Image image{ 128,128 }; | |
Shape2D::NStar(5, 64, 32, image.size() / 2).asPolygon().overwrite(image, Palette::White); | |
return Texture{ image }; | |
}; | |
void Main() | |
{ | |
Window::Resize(1280, 720); | |
bool debugMode = false; | |
bool whiteBackground = false; | |
const std::array<BlendState, 4> blends = { | |
BlendState::Default, BlendState::Additive, BlendState::Opaque, BlendState::Subtractive | |
}; | |
size_t blendIndex = 0; | |
CircleEmitter2D circleEmitter; | |
ArcEmitter2D arcEmitter; | |
RectEmitter2D rectEmitter; | |
PolygonEmitter2D polygonEmitter(CreateSiv3D_kunPolygon()); | |
enum EmitterType : size_t { | |
Circle, Arc, Rect, Polygon, | |
}; | |
size_t emitterIndex = EmitterType::Arc; | |
Vec2 position{ 300, 340 }; | |
Vec2 force{ 0.0, 0.0 }; | |
ParticleSystem2D particleSystem(position, force); | |
particleSystem.setEmitter(arcEmitter); | |
particleSystem.setTexture(CreateParticleTexture()); | |
particleSystem.prewarm(); | |
ParticleSystem2DParameters parameters; | |
HSV startColor{ ColorF(1.0) }; | |
const Texture texture = Texture(siv3d_kun_path); | |
bool drawTexture = false; | |
while (System::Update()) | |
{ | |
SimpleGUI::CheckBox(debugMode, U"Debug", Vec2(40, 660), 120); | |
SimpleGUI::CheckBox(whiteBackground, U"White", Vec2(160, 660), 120); | |
SimpleGUI::CheckBox(drawTexture, U"Texture", Vec2(280, 660), 140, (emitterIndex == EmitterType::Polygon)); | |
Scene::SetBackground(whiteBackground ? Color(250, 252, 255) : Palette::DefaultBackground); | |
{//particleSystem,parametersの設定 | |
const int32 x = 560, labelw = 120, sliderw = 200; | |
SimpleGUI::Slider(U"Rate", parameters.rate, 1.0, 500.0, { x, 20 }, labelw, sliderw); | |
SimpleGUI::Slider(U"Max", parameters.maxParticles, 50.0, 2500.0, Vec2(x, 60), labelw, sliderw); | |
SimpleGUI::Slider(U"LifeTime", parameters.startLifeTime, 0.0, 5.0, Vec2(x, 100), labelw, sliderw); | |
SimpleGUI::Slider(U"Speed", parameters.startSpeed, 0.0, 320.0, Vec2(x, 140), labelw, sliderw); | |
SimpleGUI::ColorPicker(startColor, Vec2(x, 180)); | |
SimpleGUI::Slider(U"Size", parameters.startSize, 0.0, 150.0, Vec2(x, 300), labelw, sliderw); | |
SimpleGUI::Slider(U"Rotation", parameters.startRotationDeg, -180, 180, Vec2(x, 340), labelw, sliderw); | |
SimpleGUI::Slider(U"AngularVel", parameters.startAngularVelocityDeg, -720, 720, Vec2(x, 380), labelw, sliderw); | |
SimpleGUI::Slider(U"Force X", force.x, -320.0, 320.0, Vec2(x, 420), labelw, sliderw); | |
SimpleGUI::Slider(U"Force Y", force.y, -320, 320.0, Vec2(x, 460), labelw, sliderw); | |
SimpleGUI::RadioButtons(blendIndex, { U"Default", U"Additive", U"Opaque", U"Subtractive" }, Vec2(x, 500), 320); | |
SimpleGUI::CheckBox(parameters.randomStartRotation, U"randomRotation", Vec2(x, 660), 220); | |
SimpleGUI::CheckBox(parameters.randomAngularVelocity, U"randomAngularVelocity", Vec2(x + 200, 660), 280); | |
parameters.blendState = blends[blendIndex]; | |
parameters.startColor = startColor; | |
particleSystem.setParameters(parameters); | |
particleSystem.setForce(force); | |
if (MouseR.pressed()) | |
particleSystem.setPosition(position = Cursor::Pos()); | |
} | |
{//emitterの設定 | |
const int32 x = 900, labelw = 120, sliderw = 200; | |
bool emitterChanged = false; | |
emitterChanged = SimpleGUI::RadioButtons(emitterIndex, { U"Circle", U"Arc", U"Rect", U"Polygon" }, Vec2(x, 20), 360); | |
switch (emitterIndex) | |
{ | |
case EmitterType::Circle: | |
emitterChanged |= SimpleGUI::Slider(U"Source Radius", circleEmitter.sourceRadius, 0.0, 40.0, Vec2(x, 180), 160, 200); | |
emitterChanged |= SimpleGUI::Slider(U"R", circleEmitter.r, 0.0, 320.0, Vec2(x, 220), 160, 200); | |
emitterChanged |= SimpleGUI::CheckBox(circleEmitter.randomDirection, U"Random Direction", Vec2(x, 260), 360); | |
emitterChanged |= SimpleGUI::CheckBox(circleEmitter.fromShell, U"From Shell", Vec2(x, 300), 300); | |
if (emitterChanged) // setEmitter は重い処理なので、変更があった時だけ | |
particleSystem.setEmitter(circleEmitter); | |
break; | |
case EmitterType::Arc: | |
emitterChanged |= SimpleGUI::Slider(U"Source Radius", arcEmitter.sourceRadius, 0.0, 40.0, Vec2(x, 180), 160, 200); | |
emitterChanged |= SimpleGUI::Slider(U"R", arcEmitter.r, 0.0, 320.0, Vec2(x, 220), 160, 200); | |
emitterChanged |= SimpleGUI::Slider(U"Direction", arcEmitter.direction, -180, 180, Vec2(x, 260), 160, 200); | |
emitterChanged |= SimpleGUI::Slider(U"Angle", arcEmitter.angle, 0.0, 360, Vec2(x, 300), 160, 200); | |
emitterChanged |= SimpleGUI::CheckBox(arcEmitter.randomDirection, U"Random Direction", Vec2(x, 340), 360); | |
emitterChanged |= SimpleGUI::CheckBox(arcEmitter.fromShell, U"From Shell", Vec2(x, 380), 360); | |
if (emitterChanged) // setEmitter は重い処理なので、変更があった時だけ | |
particleSystem.setEmitter(arcEmitter); | |
break; | |
case EmitterType::Rect: | |
emitterChanged |= SimpleGUI::Slider(U"Source Radius", rectEmitter.sourceRadius, 0.0, 40.0, Vec2(x, 180), 160, 200); | |
emitterChanged |= SimpleGUI::Slider(U"Width", rectEmitter.width, 0, 720, Vec2(x, 220), 160, 200); | |
emitterChanged |= SimpleGUI::Slider(U"Height", rectEmitter.height, 0, 720, Vec2(x, 260), 160, 200); | |
emitterChanged |= SimpleGUI::CheckBox(rectEmitter.randomDirection, U"Random Direction", Vec2(x, 300), 360); | |
emitterChanged |= SimpleGUI::CheckBox(rectEmitter.fromShell, U"From Shell", Vec2(x, 340), 360); | |
if (emitterChanged) // setEmitter は重い処理なので、変更があった時だけ | |
particleSystem.setEmitter(rectEmitter); | |
break; | |
case EmitterType::Polygon: | |
if (emitterChanged) // setEmitter は重い処理なので、変更があった時だけ | |
particleSystem.setEmitter(polygonEmitter); | |
break; | |
} | |
} | |
particleSystem.update(); | |
if (debugMode) | |
particleSystem.drawDebug(); | |
else | |
particleSystem.draw(); | |
if (emitterIndex == EmitterType::Polygon && drawTexture) | |
texture.drawAt(position); | |
ClearPrint(); | |
Print << U"{} particles"_fmt(particleSystem.num_particles()); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment