C#初心者の私がGUIアプリケーションに挑戦した際に参考にしたサイト等

プログラミングそのものに対しては完全な初心者ではなく、
  • C言語の知識あり
    (関数のポインタやマルチバイト文字用の関数なども使ったことがある)
  • データ構造の知識あり
    (スタック、キュー、連結リストなど勉強のためにC言語で実装した経験あり)
  • バイナリデータ処理アプリケーション制作経験あり
    (C言語、CUI、一時ファイルの利用など)
  • GUIのアプリケーション制作経験あり(C言語+Win32API)
  • GUIミニゲームの制作経験あり(HSP)
  • その他、VB、VBAでの制作経験あり
という知識・経験があるので、完全に初心者の方には参考にならないものもあるかも


全体的な参考
C# によるプログラミング入門
C# の文法についてはほぼこのサイトに頼った
 内容が難しいものも多く、項目の量も多いので、いきなりここを見ても理解しきれないかも

私自身、まだよくわからない部分が多い
今回の開発中はほぼ常にこのサイトを開いていた

C#でオブジェクト指向を活用してジャンケンゲームを作ろう
内容が難しくてまだ理解できていな部分が多いが、一通りの技法などが含まれているように思われるので、上のサイトとセットで見ると非常に勉強になる
 早い段階でこのサイトを見て、機能を細かくクラス分けできるという認識を持った状態で製作開始し、自分の知識・技術力がないために失敗した部分もある
 ただ、このサイトを見ていなかったら大皿スパゲッティになっていたと思う

一週間で身につくC#言語の基本
上2つのサイトの内容をいきなり理解するには難しすぎたので、まずはここでざっくりと勉強した

やってみて損はない Visual C#
GUI については主にここを参考にした
ただ、ここのサンプルコードはフォームクラスの中で完結している

今回は c# の勉強とオブジェクト指向設計の勉強も兼ねていたので、クラスを作る部分については本を買って勉強した

表示位置がズレてサンプル画像のようにならない
上のサイトを参考に同じコードを書いても表示される位置がサンプル画像とズレる現象が発生した
 今回、参考サイトからソースコード写経をしていて一番最初につまづいたポイント

C#_Form の内側サイズを取得、設定
Windows のバージョンの違いによるものなのか、VisualStudio のバージョンの違いによるものなのか、私の環境ではフォームのサイズはウィンドウ領域のサイズで、タイトルバーや枠も含まれていた
 しかし参考にしたサイトのサンプル画像ではフォームのサイズはクライアント領域のサイズのようで、タイトルバーや枠は含まれない

クライアント領域のサイズはプロパティウィンドに表示されないようで、ソースコードの中でサイズ指定を記載するしかなさそう

クライアント領域のサイズを変更
1.
ClientSize = new Size(x,y);

ゲームループ処理
最初に参考にしていたサイトなどでは Timer コントロールを使用する方法が紹介されていたが、ミリ秒単位の整数値でイベントを発生させるものなので 1/1000 秒が限界、割り切れないフレームレートに対して小数点以下分のズレが発生する

ゲーム向けのループ処理について
今回はこのページで紹介されている方法を採用した
 System.Environment.TickCount を使用しているのでこちらも 1/1000 秒が限界だが、次のフレームまでの時間を double 型で管理しているため小数点以下のズレは発生しにくい

が、動作確認用にサブ機で実行した際に問題が発生
 計算処理と描画処理が混ざっているメソッドなどがあり、計算処理の中でも描画処理をしてしまっていたので、ちゃんと分離してフレームスキップがちゃんと機能するように修正
 ついでにタイトル画面やゲームオーバーなどと関連して if(フラグ) の形でメソッドの実行有無を判定していたものを、デリゲートを使用してフラグ切り替え時に代入することでゲームループ中の if 文を削減

このページの本文中に記載があるものの、FPS の計測についてはサンプルコード中には記載されておらず、特にフレームスキップが発生する場合は計算回数と描画回数それぞれを計測していないと、不具合対策の方針を見誤る場合もあるため注意が必要

本文中にもあるように、計算回数が間に合っていない場合はフレームスキップでは対応できない

昔読んだ記事なのでソースを示せないが一般的なゲームループでは「計算に必要な時間よりも描画に必要な時間の方が大きい」らしいので、計算処理の中で描画処理を行っていないかを確認するのは大切

foreach 文
C では for 文をよく使っていて、foreach 文に慣れない
 勉強のためと思って使おうとしてみたものの、初期化などで一括で値を代入したい時などは制限がある

foreach の変数は読み取り専用なんですか?
ここに MSDN からの引用で、foreach 文はコレクションからの情報受け取り用で、コレクションの内容変更には使えない、といったことが書かれている
 ただ、現時点では引用で示された文章は見当たらない

C# de .NET & オブジェクト指向 - foreach
プロパティを使ったメンバーの書き換えはできるみたい

基底クラスから派生クラスのプロパティやメソッドを利用する
実体化の際に初期値を与える関係でキャラクタの種類ごとに派生クラスを作って実体化を行うが、座標の移動や描画は共通の処理のため基底クラス配列に代入してまとめて処理をしている
 しかし、一部だけ派生クラスにしかないメソッドを使いたい場合があり、基底クラスから派生クラスのメソッドを呼び出す方法がないかを調べてみた

C#で基本クラスから派生クラスのメンバーにアクセスする方法はあ...
基底クラスから、派生クラスにある(基底クラスになくても可)メソッドを呼びだす

基底クラス側に実行用のメソッドを用意しておいて、その中で this.GetType() で自分のクラスが分かって、GetMethod() で実際に呼び出したいメソッドの有無を取得して、if で有無を判定、Invoke でメソッドを実行

ソッドやプロパティの有無を確認して呼び出すには?
Invoke の使い方はここが分かり易かった

メソッドを変数に代入する方法に関連して、デリゲート(メソッド型の変数、c 言語の関数のポインタみたいなもの)やラムダ式(匿名メソッドを簡略に書ける)という機能がある

また、基底クラス配列の処理中に派生クラスの種類によって異なる処理をしたい場合もあり、typeof を使えばよいと分かった

C#で型を判別するtypeofとis演算子
クラス名やアセンブリ名を取得するには?
GetType().Name でもクラス名を取得できるが、文字列として取得するため、一致判定をする if 文を書くときに文字列の比較をするなど注意が必要

セーブデータの保存場所
AppData の Roaming と Local と LocalLow
c# というより UAC が有効な Windows 環境下での話だと思うが、一般的にソフトを入れる場所は Program Files が多いのではないかと考えている
 が、ここは UAC によりファイル操作に制限があるため、UAC 登場以降の Windows に対応しているソフトは Program Files に置いていてもセーブデータだけは別の場所に保存するようになっている

例えば設定データの保存フォルダは環境変数 %AppData% や %LocalAppData% などが示すフォルダが候補として挙げられるが、ソースコード中に %temp% などと書いてもそのままの文字列として扱われる

環境変数の値を取得するには?
Environment.GetEnvironmentVariable メソッドの引数に環境変数を指定することで、その環境変数の値を取得することができる

アプリケーション設定情報はどこに保存すべきか?
アプリケーションの設定を保存する
設定データの保存フォルダであれば、System.Windows.Forms 名前空間の Application.UserAppDataPath プロパティや Application.LocalUserAppDataPath プロパティを利用すると、自動的にプログラムの名前などを含むフォルダが作成され、そのパスを取得できる
 ただし、フォルダの構造や名前が自動的に決定されてしまうため、任意の構造、名前のフォルダにしたい場合は、Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) のようにしてフォルダのパスのみを取得して、その下に自分でフォルダを作成する

ファイルパスの最大長 260 文字、フォルダ名の最大長 248 文字、ファイル名の最大長 255 文字(実際には必ず最後に '\' 1文字分を含んだ文字数で数える)で、フォルダやファイルを作成する際にパスや名前が長すぎると例外 System.IO.PathTooLongException がスローされると思っていたが、例外をわざと発生させるテスト中に 260 文字を超えるフルパスを指定してフォルダを作成しようとしたところ System.IO.DirectoryNotFoundException がスローされた
 248 文字以下は問題なくフォルダ作成、249 - 260 文字は System.IO.PathTooLongException、260 文字以上は System.IO.DirectoryNotFoundException
 詳細な検討はしていないが、極端に長いパスになり得る場合は System.IO.PathTooLongException をキャッチするだけでは足りない?

リソース
プロジェクトのリソースとフォームのリソースがあるということを理解しておらず、フォームで追加したはずの画像がプロジェクトのリソースに含まれていたり、いなかったりで、両方に含まれている画像もあり無駄に exe ファイルサイズを大きくしていた
 リソースファイルが複数あることに気付いて、整頓しようと不用意に削除したら Image プロパティが Null になり例外が発生、元に戻せなくなった

別 PC で動作確認のためにまるごとコピーしたデータが運良くあったおかげで復元できた
 バックアップのためとかではなく、別PCでのテスト中に不具合が出て、まるごとコピーしたらどうなるかを確認するためのコピーだったので、本当に運が良かった

アイコン
アイコンのサイズと色について
ざっくりと検索して、サイズについて書かれているページは多かった印象だが、色数まで書かれているページは少なかった印象

Finder/Explorerのアイコン表示
どのサイズのアイコンが表示されているか手っ取り早く確認するなら、ここで公開されているアイコンを使って確認すると分かり易い

0 件のコメント:

コメントを投稿