Edited at
Siv3DDay 20

Siv3D実装会で作ったサンプルプログラム

この記事は Siv3D Advect Calendar 2018 の20日目の記事です。

こんにちは。去年 Siv3D/OpenSiv3Dの便利な機能 を書いたleafです。

今回は、OpenSiv3D実装会でできたサンプル的なプログラムが2つほどあるので、紹介したいと思います。


注意

OpenSiv3D v0.3.0からデフォルトの解像度が 640*480 → 800*600 になったので、支障が出ないようにWindowの大きさを 640*480 に設定しています。時間があったらWindowの大きさが変わっても支障がでないようにしたいと思います


シューティングゲーム


code.cpp


# include <Siv3D.hpp>

void Main()
{
Window::Resize(640, 480);

int32 level = 0;

Graphics::SetBackground(ColorF(0.8, 1.0, 0.8));

const Texture textureA(Emoji(U"🛩"), TextureDesc::Mipped);

const Texture textureB(Emoji(U"👾"), TextureDesc::Mipped);

Stopwatch time1(true);

Stopwatch time2(true);

Array<Vec2> bullets, enemies;

Vec2 playerPos = Window::Center();

while (System::Update())
{
const double speed = System::DeltaTime() * 100;

playerPos.moveBy(Vec2(KeyRight.pressed() - KeyLeft.pressed(), KeyDown.pressed() - KeyUp.pressed())
.setLength(6 * speed))
.clamp(Window::ClientRect());

if (time1 >= 250ms - 1ms * Min(level, 180)) {
enemies.emplace_back(680, Random(40, 440));
++level;
time1.restart();
}
if (KeyZ.pressed() && time2 >= 40ms) {
bullets.push_back(playerPos);
time2.restart();
}

bullets.each([=](Vec2& bullet) { bullet.x += 9.0 * speed; });
enemies.each([=](Vec2& enemy) { enemy.x -= 3.0 * speed; });

bullets.remove_if([](const Vec2& b) { return b.x > 664.5; });
enemies.remove_if([&](const Vec2& e)
{
for (auto it = bullets.begin(); it != bullets.end(); ++it)
{
if (it->distanceFrom(e) < 35.0)
{
bullets.erase(it);
return true;
}
}
return e.x < -35.0;
});

bullets.each([](const Vec2& b) { Circle(b, 4).draw(Palette::Orange); });

textureA.resized(150).drawAt(playerPos);

enemies.each([&](const Vec2& e) { textureB.resized(70).drawAt(e); });

}
}


OpenSiv3Dのサンプルに新しいシューティングゲームがなかったので作った、横に動くタイプのシューティングゲームです。

フレームレートが変化してもできるだけ動作の速さはできるだけ変わらないようになってます。

是非スコアを表示するなり背景をつけたりするなりなんなりしてください。


High & low


code.cpp

# include <Siv3D.hpp>

# include <HamFramework.hpp>

std::pair<PlayingCard::Card, PlayingCard::Card> ChoiceTwoCards(const Array<PlayingCard::Card>& cards)
{
const Array<PlayingCard::Card> cardPair = cards.shuffled().take(2);

return{ cardPair[0], cardPair[1] };
}

int32 Reorder(int32 var)
{
return (var + 12) % 14;
}

void Main()
{
Window::Resize(640, 480);
Graphics::SetBackground(Palette::Darkgreen);
const Font font(65, Typeface::Bold);
const RectF lowButton(Arg::center(Window::Center().movedBy(-130, 100)), 200, 90);
const RectF highButton(Arg::center(Window::Center().movedBy(130, 100)), 200, 90);

const PlayingCard::Pack pack(100, Palette::Red);
const Array<PlayingCard::Card> cards = PlayingCard::CreateDeck(0);

int32 combo = 0;
bool selected = false, correct = false;

auto cardPair = ChoiceTwoCards(cards);
cardPair.first.flip();

while (System::Update())
{
if (MouseL.down())
{
if (!selected)
{
if (lowButton.mouseOver())
{
cardPair.first.flip();
correct = (Reorder(cardPair.first.rank) <= Reorder(cardPair.second.rank));
selected = true;
}
else if (highButton.mouseOver())
{
cardPair.first.flip();
correct = (Reorder(cardPair.first.rank) >= Reorder(cardPair.second.rank));
selected = true;
}
}
else
{
cardPair = ChoiceTwoCards(cards);
cardPair.first.flip();
selected = false;
combo = correct ? (combo + 1) : 0;
}
}

if (lowButton.mouseOver() || highButton.mouseOver())
{
Cursor::RequestStyle(CursorStyle::Hand);
}

RectF(Arg::center(Window::Center().movedBy(-130, -60)), pack.size()).drawShadow(Vec2(6, 6), 12, 0);
pack(cardPair.first).drawAt(Window::Center().movedBy(-130, -60));

RectF(Arg::center(Window::Center().movedBy(130, -60)), pack.size()).drawShadow(Vec2(6, 6), 12, 0);
pack(cardPair.second).drawAt(Window::Center().movedBy(130, -60));

lowButton.rounded(25).draw(HSV(Palette::Lightblue) - HSV(0, lowButton.mouseOver()*0.15, 0)).drawFrame(2, 2, ColorF(0.6));
highButton.rounded(25).draw(HSV(Palette::Orange) - HSV(0, highButton.mouseOver()*0.4, 0)).drawFrame(2, 2, ColorF(0.6));

if (selected)
{
font(correct ? U"Win" : U"Lose")
.drawAt(Window::Center().movedBy(0, -110),
correct ? Palette::Red : Palette::Blue);
}

font(U"Low").drawAt(lowButton.center());
font(U"High").drawAt(highButton.center());

if (combo)
{
font(combo).drawAt(Window::Center().movedBy(0, -180), Palette::Gold);
}
}
}


せっかくSiv3Dにはトランプ描画機能があるのに、公式サンプルがないということで、トランプを使った簡単なゲームです。

ハイアンドロー(ハイロー)と呼ばれる、カジノとかにありそうなゲームです。(というか多分あります)

2つ裏のカードがあるので、片方を表にして数字を見て、裏になっているもう片方のカードにかかれている数字が表になったカードの数字より高い(High)か低い(Low)か当てるゲームです。

何連続正解かが黄色い字ででるのでわかるようになっています。

ハイスコア機能をつけたりするといいかもしれません。


さいごに

上にある二つのプログラムは (https://scrapbox.io/Siv3Dbyleaf/ )にあります

新しくサンプルを作ったらここにあげられるかもしれません。

試験や文化祭のゲームづくりなんかで忙しかったので最近は実装会に行けてませんでしたが、そろそろ行きたいですね。