こんにちは。今年は OpenSiv3D(v0.4.0) を使用して文化祭のランチャーのプログラム開発を担当したので記事にしたいと思います。
何を作ったか
# 便利だった機能 このランチャー制作で特に苦労したのがアニメーションなのですが、それを作るのに`Transition` や `Periodic::Sine0_1()`などがとても便利で、これとEasingを組み合わせてほとんどの動きを作っています。 この二つの機能は [OpenSiv3Dのサンプル](https://scrapbox.io/Siv3D/%E3%83%9E%E3%82%A6%E3%82%B9%E3%82%AA%E3%83%BC%E3%83%90%E3%83%BC%E3%81%A7%E5%9B%B3%E5%BD%A2%E3%82%92%E3%83%8F%E3%82%A4%E3%83%A9%E3%82%A4%E3%83%88) に載っているのでそちらを参考にしてください。最後は、興風祭のゲームランチャー。
— 早稲田中高PCプログラミング部 (@waseda_pcp) September 27, 2019
高1の部員2人で、デザインと本体作成を分担している。
今年のゲーム制作者たちの努力がこのランチャーに詰まっています!
ぜひ会場に来て、プレイしてください!!
(一部個人情報保護のため画像が表示されています)
使用ソフト:OpenSiv3D pic.twitter.com/zRBrtRyFZr
苦労したこと
アニメーションももちろん苦労しましたが、ランチャー制作にあたってウィンドウへの操作が必須だったので、Windows APIをかじった程度の腕だとそこに苦労しました。いくつか苦労したことを挙げていきたいと思います。
###Process機能の未実装
旧Siv3DにあったSystem::CreateProcess
にあたる機能が当時OpenSiv3Dにはありませんでした。
自分で実装するのは手間がかかるなーと思いながらSiv3DのSlackで質問したところ、
1分で参考になるリンクと共に回答が来ました。
開発者に質問しやすく対応が早いのはSiv3Dの良いところですね。
※ちなみにOpenSiv3D v0.4.1で Process
機能が公式に実装されたので現在は楽にできるようになってます。
###アクティブウィンドウ問題
ランチャーからゲームを起動している間に何らかのキー入力をするとアクティブなウィンドウがランチャーウィンドウのまま起動してしまう致命的なバグがありました。
そこでこれを解決するためにゲームウィンドウのhWndを使いアクティブ化しようと考えたのですが、プロセスIDしか保持していないため
各ウィンドウのプロセスIDを調べ、ゲームのプロセスIDと一致していたらそのhWndを返す
という関数を作り、取得したhWndを使って
SetWindowPos(processHWND, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
という風にすることで解決しました。
###フルスクリーン化問題
例年モニターにゲーム画面のみを映すゲームセンター形式なので、フルスクリーン化は必須でした。
フルスクリーン化するだけなら公式リファレンスを参考にすれば実装できる(僕の場合はSceneのサイズを変更したくなかったので Window::SetFullscreen
の第三引数にWindowResizeOption::KeepSceneSize
を指定しました)のですが、ここで問題が発生しました。
ランチャーをフルスクリーン化するとゲームウィンドウがランチャーの後ろに隠れてしまうようになりました。
困ったので Window::SetFullscreen
の内部コードを調べたところ、SetWindowPos
で HWND_TOPMOST
が指定されていました。
普通、アクティブなウィンドウが最前面にくるのですが、SetWindowPos
で HWND_TOPMOST
を指定すると、ウィンドウは常に最前面におかれ、他のウィンドウがアクティブになっても最前面ウィンドウの後ろにおかれます。そのため作成したゲームウィンドウがフルスクリーン化、つまり最前面指定されたランチャーより後ろに置かれていたのです。
これはランチャーのhWndを使って
SetWindowPos(launcher_hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
という風にすることで最前面指定を解除でき、解決しました。
###その他の問題
- ゲームを起動している最中にタスクバーとスタートボタンが見えてゲームセンター感がなかったので、タスクバー
Shell_TrayWnd
とスタートボタンButton
でFindWindow
してhWndを取得、これを使いShowWindow
でSW_HIDE
を指定して隠しました - これは別に苦労してないのですが、ゲームのプレイ動画を流したかったけど動画再生機能が実装されてなかったので連番画像を12FPSで5秒ほど流してループさせるといった形式で代用しました
感想
デザイン担当が頑張ってくれたので僕はデザインの再現と機能面の実装をするだけで済み、とても早く作業が進みました。分担は大事ですね。
文化祭当日でも特にバグはでなかったのでなんとかうまくいって良かったです。
おわりに
これからランチャーを制作したい人は OpenSiv3Dサンプルのゲームランチャー をぜひ読んでみてください。僕の場合はキーボードのみで動作させる、フルスクリーン表示させるという前提があったのでやや苦労しましたが、その辺にこだわりがなければほぼサンプルだけでも制作できると思います。がんばってください。