今回は、リクエストがあった VS2022 の C# だけでゲームの画面表示を、どうやって実装するかの手順説明となります。簡単ではありますが、細かく説明したために少し記事が長くなっています。まあ、DirectX 使うという選択肢とかもあるんですが、簡単なゲームなら C# .NET のそのまんまでもさほど問題にはならないですね。今時の PC 能力は本当に凄いと思います。

※ シンプルでインクは大容量。印刷はそこそこ速い。プリンタはこれで十分です。インク代も安い部類だと思います。


これで登録は完了です…が、最後に画像の設定をします。今放り込んだ画像全てを、ソリューションエクスプローラから選択状態にします。するとプロパティが表示されますので、ビルドアクションを埋め込みリソースに変更します。これでリソース準備は完了です。



※大容量HDDが安くなった今、NASは普通の人には2ベイで十分です。これは比較的本格的なNASで2万円台とオトクなNASキットになります。



※Gen3で良ければ2TBでもこんなに安い。もはやシステムにHDDを使う気など全く起きないレベルで安くなりました。安心の東芝なし崩しブランドですw

やることがたくさんあるように見えますが、その実、やってる事は単純です。なお、今回はサンプルということでリソースを確保してそのまま放置してますが、実際には Dispose できっちりリソースを開放するようにしてください。
今回紹介した記事のソースコードをダウンロードできるようにしておきます。
GameTest20231010.zip
2023.10.10.1800
- 準備
Visual Studio 2022 にて Windows フォームアプリで新しいプロジェクトを作成します。プロジェクト名はここでは GameTest としておきます。フレームワークは .NET 7.0 を指定します。C# は作り始める際の最新版を選択するのが内藤流です。理由は作っているうちに古くなっていくためです。まあ、途中で .NET のバージョンを上げても良いのですが、下げることはたぶん出来ないので注意が必要かな。

最初に Form1 が表示されます。このフォームにツールボックスから Timer を選択してフォームに D&D します。ゲームエンジンを使ったり、C++の場合と異なり、C# 標準の状態では、メインループに相当する部分が作りづらい※1ので、一番手軽な方法として、Timer による呼び出しとしています。処理速度に余裕があるのであれば、この Timer ループでも十分です※2
※1 本気で作るなら Program.cs 側でメインループを回す実装が良いかと思います。
※1 本気で作るなら Program.cs 側でメインループを回す実装が良いかと思います。
※2 ギリギリを攻めたい場合は、どのみち何かしらのゲームエンジンを使うと思いますしね。
- 基本的な考え方
ワークとして画面と同じサイズの画像を2枚用意します。2枚用意するのは、作業用と表示用と分けるためです。ダブルバッファの考え方ですね。画像が1枚しかない場合は、描画中の状態が見えてしまうことがあり、低品質に見えてしまうためです。そのため、ここでは2枚用意します。
Timer によって自分や敵の動きを処理します。そして、その処理結果を作業用の画像に反映させます。全ての処理が終わったら、作業画像と表示画像を入れ替えて、画面更新の指示を出します。
画面の更新はフォームの Paint イベントで行います。表示画像を Paint のクライアントグラフィックに描画してお終いです。描画の際はストレッチや縦横比の固定などいろいろな方法がありますが、ゲーム的には縦横比固定のほうが良いかと思います。
まとめると、
- Timer で処理のタイミング毎にゲーム処理を呼び出す
- ゲーム処理で作業画像を更新する
- 作業画像と表示画像を入れ替える
- 表示画像をフォームに反映する
以上となります。
ブラザー工業(Brother Industries)
2021-09-01
- 画像の組み込み
画像データは、数千数万というオーダーでなければ、リソースとして組み込むのが良いかと思います。組み込み方はソリューションエクスプローラの GameTest を右クリックしてプロパティを選択、左側のリソースを選択して、アセンブリリソースを作成する/開くをクリックします。

さらに開いた画面上でイメージを選択します。

何もないダイアログが表示されますので、そこに登録したい画像を D&D して放り込みます。

さらに開いた画面上でイメージを選択します。

何もないダイアログが表示されますので、そこに登録したい画像を D&D して放り込みます。


これで登録は完了です…が、最後に画像の設定をします。今放り込んだ画像全てを、ソリューションエクスプローラから選択状態にします。するとプロパティが表示されますので、ビルドアクションを埋め込みリソースに変更します。これでリソース準備は完了です。
続いてリソースの読み込み処理です。ソリューションエクスプローラの Form1.cs を右クリックして、コードの表示を選択します。

コンストラクタだけのシンプルなコードが表示されます。このメンバに Bitmap配列を用意してそこに読み込んでしまいます。

コンストラクタだけのシンプルなコードが表示されます。このメンバに Bitmap配列を用意してそこに読み込んでしまいます。

これで画像の準備は完了です。
- 画面に表示する準備
Form1 クラスのプロパティに作業画像と表示画像を用意します。画像のサイズは 640x400 ドットとしましょうか。いちいち作業画面か表示画像かを判定するのも面倒なので、自動で画像が取得できるようにします。
まず、画面サイズの変更が容易なように、サイズに関しては定数定義します。その定数を使って画像を2枚配列で用意します。そして、作業画像と表示画像を切り替えるためのカウンタを用意します。このカウンタが偶数か奇数かで、作業画像と表示画像を切り替えるための参照を、bmBackBuffer と bmScreen という名前で用意しました。

これで以降は bmBackBuffer に次の画面を作成してから drawCounter を +1 の後に Paint を行うための Invalidate(); を呼び出すだけで切り替わります。

最後にコンストラクタで bmBuffer を初期化しておきます。
※ これをしないと場合によっては起動直後に一瞬ゴミが表示される可能性があります。
Synology
2023-06-29
- メイン処理の実装
Form1.cs [デザイン] の編集画面に戻ります。ウィンドウの下部に timer1 が配置されているので左クリックします。timer1 のプロパティが表示されます。

その Interval はデフォルトで 100 となっています。これは 100ms 毎に呼び出されるという設定です。60FPS で動作させたいのであれば、1000 ÷ 60 ≒ 17 を Interval に設定します。綺麗な数字にならないのが気分がわるいのであれば、20(50FPS)あたりは個人的にオススメです。今回は 20 を設定します。

その Interval はデフォルトで 100 となっています。これは 100ms 毎に呼び出されるという設定です。60FPS で動作させたいのであれば、1000 ÷ 60 ≒ 17 を Interval に設定します。綺麗な数字にならないのが気分がわるいのであれば、20(50FPS)あたりは個人的にオススメです。今回は 20 を設定します。
次にウィンドウの下部に配置されている timer1 をダブルクリックします。自動的にエントリが作成されます。

この timer1_Tick が先に設定したタイミングで自動的に呼び出されるメソッドとなります。ここにゲームの処理を記述します。本当はタイマーイベントに重い処理を記述するのはよろしくないのですが、今回は画面描画を中心の解説ですので、これでお許しください…^^;
とりあえず、プレイヤーがアニメーションする処理を書いてみます。

プレイヤーのアニメは cntPlayer で管理していますので、単純に +1 して更新します。その後、BackBuffer のグラフィックオブジェクトを取得して、描画品質を指定した後に、ゲームフィールドの色で初期化して、その後にプレイヤーの描画を呼び出しています。最後に、画面を ++drawCounter で入れ替えてから、Invalidate(); で画面の更新を指示しています。
- 実際の描画処理
Form1.cs [デザイン] の編集画面に戻ります。表示されている Form1 ウィンドウをクリックすると、プロパティがいろいろなパラメータが表示されている画面に切り変わります。とりあえず、BackColorを黒色に、ForeColor を白色に変更します。

あと、ちらつきを止めるために DoubleBuffered を True に変更します。次にこのプロパティ上部の⚡アイコンをクリックします。これも ForeColor の上にあります。

あと、ちらつきを止めるために DoubleBuffered を True に変更します。次にこのプロパティ上部の⚡アイコンをクリックします。これも ForeColor の上にあります。

イベントリストに切り替わります。

この中から Paint を見つけてダブルクリックします。自動的にエントリが作成されます。

この中から Paint を見つけてダブルクリックします。自動的にエントリが作成されます。
キオクシア(KIOXIA)
2021-07-19
- 最終調整

やることがたくさんあるように見えますが、その実、やってる事は単純です。なお、今回はサンプルということでリソースを確保してそのまま放置してますが、実際には Dispose できっちりリソースを開放するようにしてください。
今回紹介した記事のソースコードをダウンロードできるようにしておきます。
GameTest20231010.zip
2023.10.10.1800






コメント