Skip to content

Instantly share code, notes, and snippets.

@sknjpn
Last active July 7, 2017 06:17
Show Gist options
  • Save sknjpn/270e9ab87939e354ddca6d05d7a2749e to your computer and use it in GitHub Desktop.
Save sknjpn/270e9ab87939e354ddca6d05d7a2749e to your computer and use it in GitHub Desktop.
# include <Siv3D.hpp> // OpenSiv3D v0.1.5
struct Bug
{
Bug() {}
Bug(const int& _type) : type(_type) {}
int type = Random(4);
Vec2 p = { -16, Random(Window::Center().y - 120, Window::Center().y + 120) };
double v = Random(1.0, 2.0);
Vec2 dv = { 0, 0 };
double t = 0;
double h = 1;
};
struct Pom
{
Vec2 p;
Vec2 v;
double t;
};
void Main()
{
Window::SetTitle(L"Be full of bugs");
Window::Resize(1280, 720);
const Vec2 launchPos(Window::Size().x, Window::Size().y);
const Texture pomTexture(Emoji(L"💣"), TextureDesc::Mipped);
const Texture popTexture(Emoji(L"💥"), TextureDesc::Mipped);
const Array<Texture> bugTextures = {
Texture(Emoji(L"🐛"), TextureDesc::Mipped),
Texture(Emoji(L"🕷"), TextureDesc::Mipped),
Texture(Emoji(L"🐜"), TextureDesc::Mipped),
Texture(Emoji(L"🐍"), TextureDesc::Mipped),
Texture(Emoji(L"🐝"), TextureDesc::Mipped),
};
const PerlinNoise noise(Random(Largest<uint32>()));
const Texture ground(Image(Window::Size(), Arg::generator = [&noise](Point p) {
return Palette::Green
.lerp(Palette::Darkgreen, Min(1.0, Max(0.0, 0.5 + 0.5*noise.octaveNoise(Vec2(p.x, p.y * 2)*0.1, 4))))
.lerp(Palette::Khaki, Min(1.0, Max(0.0, 0.4 + 0.3*noise.octaveNoise(Vec2(p.x, p.y * 2)*0.01, 4))))
.lerp(Palette::Khaki, Min(0.5, Max(0.0, 0.8 - abs(p.y - Window::Center().y) / double(Window::Center().y))));
}));
const Font font1(128, Typeface::Bold, FontStyle::Italic);
Array<Bug> bugs;
Array<Pom> poms;
Vec2 tv;
double health = 1.0;
Color gColor(Palette::Darkred, 0);
int timer = 1800;
int score = 0;
while (System::Update())
{
//時間の処理
timer--;
//バグの追加
if (timer < 0) bugs.emplace_back(5);
else if (RandomBool(0.1)) bugs.emplace_back();
//地面の描画
ground.draw();
//バグの更新
for (auto& b : bugs)
{
b.p += b.dv;
b.dv *= 0.8;
switch (b.type)
{
case 0: //ムカデ
if (RandomBool(0.01)) b.dv = RandomVec2(10);
b.t += 0.2;
b.p.x += b.v;
bugTextures[0].resize(32).mirror().rotate(0.78 + sin(b.t)*0.20).drawAt(b.p);
break;
case 1: //スパイダー
b.t = fmod(b.t + 1.0, 120);
if (b.t < 30) b.p += Vec2(b.v * 2, 0).rotated(-0.2);
if (60 < b.t&& b.t < 90) b.p += Vec2(b.v * 2, 0).rotated(0.2);
if (b.t < 60) bugTextures[1].resize(32).rotate(1.57 - 0.2).drawAt(b.p);
else bugTextures[1].resize(32).rotate(1.57 + 0.2).drawAt(b.p);
break;
case 2: //アリ
b.p.x += b.v;
bugTextures[2].resize(32).mirror().drawAt(b.p);
break;
case 3: //スネーク
b.t += 0.1;
b.p.x += 2 * b.v*(1 + sin(b.t));
bugTextures[3].resize(32).mirror().drawAt(b.p);
break;
case 4: //ハチ
b.t += 0.2;
b.p.x += b.v * 2;
b.p.y += sin(b.t) * 2;
bugTextures[4].resize(32).mirror().drawAt(b.p);
break;
case 5: //スーパームカデ
b.t = fmod(1.0 + b.t, 60.0);
b.p.x += b.v * 5;
if (b.t < 15) bugTextures[0].resize(48).mirror().rotate(0.78 + sin(b.t)*0.20).drawAt(b.p.movedBy(0, -sin(3.14*b.t / 15.0) * 32), Palette::Red);
else bugTextures[0].resize(48).mirror().rotate(0.78 + sin(b.t)*0.20).drawAt(b.p, Palette::Red);
break;
}
//ヘルスバー
Line(-12, -12, 12, -12).movedBy(b.p).draw(4, Palette::Red);
Line(-12, -12, -12 + 24 * b.h, -12).movedBy(b.p).draw(4, Palette::Green);
}
//爆弾の発射
if (Window::ClientRect().mouseOver() && health > 0 && System::FrameCount() % 15 == 0)
poms.push_back({ launchPos, ((Cursor::PosF() - launchPos) / 60.0).movedBy(RandomVec2(Random(1.5))).movedBy(0,-15), 60.0 });
//爆弾の更新
for (auto& p : poms)
{
if (p.t > 0)
{
p.p += p.v;
p.v.y += 0.5;
pomTexture.resize(48).drawAt(p.p);
}
else if (p.t > -60)
{
pomTexture.resize(48).drawAt(p.p);
Circle(p.p.movedBy(5, 5), 8).drawArc(0, 6.28*p.t / 60.0, 2, 2, Palette::Red);
}
else
{
pomTexture.resize(48).drawAt(p.p, ColorF(1.0, (p.t + 60) / 5.0 + 1.0));
popTexture.resize((-p.t - 60) * 15).drawAt(p.p, ColorF(1.0, (p.t + 60) / 5.0 + 2.0));
}
p.t -= 1.0;
}
//爆発の削除
poms.remove_if([&bugs](const Pom& p) {
if (p.t > -70) return false;
for (auto& b : bugs) if (p.p.distanceFrom(b.p) < 150) { b.h -= 75 / p.p.distanceFrom(b.p); b.dv += (b.p - p.p).normalized()*10.0; }
return true;
});
//バグの削除
bugs.remove_if([&tv, &health, &score](const Bug& b) {
if (b.p.x >= Window::Size().x + 16)
{
tv += RandomVec2(10);
health = Max(0.0, health - 0.01);
return true;
}
if (b.h <= 0)
{
score++;
return true;
}
return false;
});
//ヘルスバーの表示
{
tv = tv.rotated(Random(6.28))*0.9;
const Transformer2D t1(Mat3x2::Translate(tv));
RectF(Window::Size().x, 32).draw(Palette::Red).drawFrame(3, 0, Palette::Black);
RectF(Window::Size().x*health, 32).draw(Palette::Green).drawFrame(3, 0, Palette::Black);
}
//残り時間の表示
if (timer >= 0)
{
font1(L"time:", timer / 60, L"s").drawAt(Window::Center().movedBy(0, -240), HSV(timer, 0.5, 0.3));
}
//ゲームオーバー時
if (health == 0)
{
gColor.a = Min(255, int(gColor.a) + 2);
Window::ClientRect().draw(Color(0, gColor.a / 2));
for (int i = 32; i >= 0; --i)
{
const Transformer2D t(Mat3x2::Translate(0, i));
const Color color = i == 0 ? Color(Palette::White, gColor.a/2) : Color(Palette::Red, (gColor.a*(128 - i * 4) / 255));
font1(L"Game Over").drawAt(Window::Center().movedBy(0, 64 - gColor.a / 4 - 72), color);
font1(L"Score {}"_fmt(score)).drawAt(Window::Center().movedBy(0, 64 - gColor.a / 4 + 72), color);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment