おもちゃバコ

中身スカスカ♡

問題のあるC++コードについて

こんにちハロ

今回はCEDEC2015で話題になったCoverityクイズについての記事です.

今更な内容ですが,見たときに直ぐに解けなかったので備忘録として残しておきます.


参考文献

この記事の元ネタです.
別の調べ物をしていた時に発見しました.
ota42y.com

同じ内容のプログラムです.
tanku.hatenablog.jp


問題

問題のバグが潜んでいるソースコードに検証を追加したもの.

実行結果

0: 0, 0, 0
1: 0, 0, 0
2: 0, 0, 0
3: 0, 0, 0
4: 0, 0, 0
5: 0, 0, 0
6: 0, 0, 0
7: 0, 0, 0
8: 0, 0, 0
9: 0, 0, 0

0: 0, 0, 1
1: 1, 2, 2
2: 3, 3, 4
3: 4, 5, 5
4: 6, 6, 7
5: 7, 8, 8
6: 9, 9, 0
7: 0, 0, 0
8: 0, 0, 0
9: 0, 0, 0

問題点

添え字と同じ数値をメンバ変数x,y,zに代入したいのに,暗黙の型変換(アップ・キャスト)によってアドレス位置がずれてしまった.

本来はこうなってほしい↓.

0: 0, 0, 0
1: 1, 1, 0
2: 2, 2, 0
...

図解

f:id:lambda410:20210815135204p:plain

解決策

横着せずに1つずつ処理する(参考文献とほぼ同じ).
根本的に解決したい場合は,参考文献を参照してください.


メモリ構造

Coverityクイズだけでは薄いので,クラスのメモリ構造について簡単な検証をして見ました.
特に解説はないですが,クラス配置ついてなんとなく理解が深まった気がします.

sizeof
int        : 4
base       : 8
derived    : 12
base_h_f   : 8
derived_h_f: 12

base_class address
    base  : 0x7ffcc71ede30
    base.x: 0x7ffcc71ede30
    base.y: 0x7ffcc71ede34

derived_class address
    derived  : 0x7ffcc71ede20
    derived.x: 0x7ffcc71ede20
    derived.y: 0x7ffcc71ede24
    derived.z: 0x7ffcc71ede28

base_have_func address
    base_h_f        : 0x7ffcc71ede10
    base_h_f.x      : 0x7ffcc71ede10
    base_h_f.y      : 0x7ffcc71ede14
    base_h_f::func  : 0x4008a2

derived_have_func address
    derived_h_f        : 0x7ffcc71ede00
    derived_h_f.x      : 0x7ffcc71ede00
    derived_h_f.y      : 0x7ffcc71ede04
    derived_h_f.z      : 0x7ffcc71ede08
    derived_h_f::func  : 0x4008a2
    derived_h_f::funcX : 0x4008d2

まとめ

C++は奥が深い.

「Effective C++ 第3版 -プログラムとデザインを改良するための55項目-」を読んだ

こんにちハルマゲドン

「Effective C++ 第3版 -プログラムとデザインを改良するための55項目-」を読んだ備忘録です.


Amazon

内容

C++でプログラムを書く時のテクニックをまとめたもの.
非常に濃い.

対象

C++を仕事に使用している人.
C++入門後の参考書を求めている人.
C++を理解したい人.

「入門書」ではないです.


要約

イントロダクション

・「プログラミング言語の基礎を学ぶこと」と「効率的なプログラムを設計・実装すること」は全く別のこと.
・この本はC++のリファレンスではない.
 プログラムやデザインを改良するアドバイスをまとめたもの.
・CとC++のどちらのものが使用されるかはインクルードヘッダによって決まる.
 C: size_t
 C++: std::size_t
・explicit
 コンストラクタの暗黙の型変換を使用できなくする.
・未定義動作
 怖い.
・コードの「クライアント」
 コードを使う「コード」や「プログラマ」を意味する.
 クライアントのことを意識しよう.

第1章 C++に慣れよう

C++のサブセット
 C: 大部分はCから来ている.
 オブジェクト指向: C++における「クラス付きC」.
 テンプレート: ジェネリックプログラミング,TMP.
 STL: STL独自のコンベンションに従おう.
プリプロセッサよりコンパイラを使おう.
 #defineは数値に置換される.
  コンパイルエラー時にシンボルが出ない.
  -> const定数に置き換えよう.
 定数の使用.
  クラスで使用する定数はstatic.
  ヘッダで宣言,ソースで定義.
 #defineにはスコープがない.
 enumハック
  宣言時の初期化が拒否られたときに使用.
  古いコンパイラ対策.
 #defineマクロよりインライン関数テンプレート.
・const
 「変更ダメ」の明示化.
 operatorのconst.
  (ab) = c; の禁止.
  if ((a
b) = c) の防止.
 mutableキーワード.
  constメンバ関数内で書き換えたいときに使用.
 「ビットレベルの不変性」
  コンパイラのconstの扱い.
  「論理的不変性」を保証するコードを書こう.
 非constメンバ関数内でconstメンバ関数呼び出し.
  コードの重複を避ける.
・オブジェクトは初期化しろ.
 自動的に保証されない.
 コンストラクタによる初期化.
  コンストラクタ内での初期化は「代入」.
  初期化は「メンバ初期化子リスト」.
   デフォルトコンストラクタに仕事に関係.
  デフォルトコンストラクタ使用時にも明示的に初期化する.
 初期化の順番は超大事.

第2章 コンストラクタ,デストラクタ,コピー代入演算子

C++が自動で書き,自動で実行するもの
 デフォルトコンストラク
 コピーコンストラク
 デストラク
 コピー代入演算子
コンパイラが自動生成することを禁止する.
 望まない自動生成は禁止しよう.
 privateに隠蔽する.
 Uncopyableクラスを作成し,継承する.
・仮想デストラク
 仮想デストラクタを持たない基底クラスのポインタにdeleteは未定義.
 仮想関数は「派生クラスでの実装のカスタマイズ」.
 理由のない仮想デストラクタは良くない.
  クラスが仮想関数を持つときに使用する.
 仮想デストラクタを持たないSTL
・デストラクタから例外を投げない.
 クライアントが問題対処できるデザインにする.
・コンストラクタやデストラクタ内では仮想関数を呼ばない.
 実行されるのは「その時のオブジェクト型」のもの.
 バグになりやすい.
・代入演算子は*this参照を返すようにする.
・operator=実装は自己代入に備える.
・コピー時はオブジェクト全体をコピー.

第3章 リソース管理

・リソース管理にオブジェクトを使う.
 リソース確保したら管理オブジェクトに渡す.
  RAII.
 リソース管理オブジェクトは解放時にデストラクタを使う.
 参照カウント型スマートポインタ: RCSP
・リソース管理クラスのコピー振る舞いはよく考える.
 Mutexの扱い.
  RAIIオブジェクトの扱い.
  リソースへの参照カウント.
  管理リソースをコピー.
  管理リソースの管理者を変更.
・リソース管理クラスはリソースへのアクセスを付ける.
 RAIIオブジェクトは生リソースにアクセスする必要が多々ある.
  管理リソースへのアクセス提供.
 明示的「get()」か非明示的「暗黙の型変換」.
・対応するnewとdeleteは同じものを使用.
 単独オブジェクトと配列オブジェクトは扱いが違う.
 new[ ]を使用したらdeleteも[ ].
・newで生成したオブジェクトのスマポ私は独立ステートメントで行う.
 例外対策.

第4章 デザインと宣言

・インタフェースは正しいときに使いやすく,間違ったときに使いにくく.
 インタフェースに一貫性を持たせ,組み込み型と同じ振る舞いをするようにすると良い.
 誤用対策には,新しく型を定義し,オブジェクトの値を宣言すると良い.
  また,クライアントにリソース管理を任せない.
 デリータの設定.
・クラスのデザインを型デザインとして考える.
 クラスのデザインとは型のデザイン.
 ★クラス設計時にこの項目を見返す.
・値渡しよりconst参照渡し.
 スライス問題.
 STLの反復子,関数オブジェクトに注意.
・オブジェクトを戻すときに参照を戻さないこと.
 存在しないオブジェクトの参照戻しに気を付ける.
・データメンバはprivate宣言.
 protectedはpublicよりカプセル化を進めるものではない.
メンバ関数より,メンバ・friendでない関数を使用する.
・全引数に型変換が必要なら,メンバでない関数を宣言する.
・例外を投げないswap.
 テンプレート特化.
 自作型のswapが非効率な場合,メンバ関数としてswapを作る.

第5章 実装

・変数の定義は可能な限り先延ばしにする.
・キャストは最小限にする.
 const_cast: オブジェクトのconst性を取り除く.
 dynamic_cast: 安全なダウンキャストに使用.
 reinterpret_cast: 実装依存の低レベルキャスト.
 static_cast: 暗黙の型変換.
 新しいスタイルのキャストは目的が限定されている.
  コンパイルエラーになるのでわかりやすい.
 dynamic_castの使用.
  遅い.
  使用時は設計ミスの可能性がある.
・オブジェクトの内部データへのハンドルを戻さない.
 ハンドル: 参照,ポインタ,反復子.
・コードを例外安全にする.
 例外安全.
  リソース漏れがない.
  データ構造が無効状態になることを防ぐ.
 保証.
  関数が例外に対し基本保証.
  関数が例外に対し強い保証.
  関数が例外に対し投げない保証.
・インラインを良く理解する.
・ファイル間のコンパイル依存性を最小限にする.
 参照やポインタで十分ならオブジェクトの使用を避ける.
 クラスの定義でなく,宣言依存なコードを書く.
 宣言と定義でヘッダを分ける.
 implとpimpl.

第6章 継承とオブジェクト指向

・public継承はis-a関係を表すようにする.
 public継承はis-a関係を意味する.
 全ソフトウェアにとって利用的なデザインはない.
 基底クラスに適用可能なものは,派生でも適用可能にする.
・継承した名前を隠蔽しない.
 using宣言の利用.
・インタフェースと実装の継承を区別する.
 protectedにデフォルト動作を作成する.
 public継承においては,派生クラスは基底クラスのインタフェースを全て継承.
 純粋仮想関数は,インタフェースのみの継承を意味.
 仮想関数は,インタフェースとデフォルトの実装の継承を意味.
・仮想関数の代わりになるもの.
 NVI: 非仮想インタフェース.
 仮想関数を置き換える.
  関数ポインタ
  tr1::function
  別クラス階層の仮想関数.
・非仮想関数を派生クラスで再定義しない.
・継承した関数のデフォルト引数を再定義しない.
 デフォルト引数: 静的結合.
 仮想関数: 動的結合.
コンポジションでhas-a, is-implemented-in-terms-of関係を作る.
・private継承は賢く使う.
 private継承はis-implemented-in-terms-of関係を意味する.
 EBOが働くことがある.
  ライブラリ開発者には重要かもしれない.
・多重継承は賢く使う.

第7章 テンプレートとジェネリックプログラミング

・暗黙のインタフェースとコンパイルポリモフィズムを理解する.
・typenameの2つの意味.
 テンプレート内でネストされた依存型名にはtypenameを使用する.
 テンプレートパラメータ宣言には,classとtypenameがある.
・テンプレート化された基底クラス内の名前へのアクセス.
・パラメータに依存しないコードはテンプレート外へ.
・すべての互換型を受け取るためにメンバ関数テンプレートを使用する.
・型変換させたいならメンバでない関数をクラステンプレート内で定義する.
・型情報に関してはtraitsクラスを使用する.
テンプレートメタプログラミングを意識する.

第8章 newとdeleteのカスタマイズ

・new-handlerを理解する.
・どういうときにnewとdeleteの定義を書くか理解する.
・自前new, deleteを用意するときはコンベンションに従う.
・プレースメントnewの定義時はdeleteも定義.

第9章 いろいろな事

コンパイラの注意を払う.
・TR1を含む標準ライブラリに慣れる.
・Boostに慣れる.


感想

const辺りの内容しか理解できませんでした(ここも怪しい).

ただ,この本はC++の基礎知識の塊なので,経験を積んでから読み返した時を楽しみにしてます.

「ゲームプログラマになる前に覚えておきたい技術」を読んだ

こんにちはかいこうさく

この記事は「ゲームプログラマになる前に覚えておきたい技術」を読んだ感想と備忘録についてです.


Amazon


内容

キャラ制御,グラフィック,メモリ管理などゲームプログラムに必要な知識がまんべんなく解説されています.
内容は古いらしいですが,ゲームプログラムの基礎が網羅されているので学習にはおススメです.

対象

新人ゲームプログラマゲームプログラマを目指す学生など


要約

Part1. 2次元のゲーム

Chapter1 はじまりのゲーム

倉庫番を題材としたゲーム開発のイントロ
・変更する気のない変数はconstをつけよう.
グローバル変数は接頭辞として[g]をつけるなど,変数名に気を使う.
・列挙型を使えるときは使おう.
・newしたらdeleteする癖をつける.また,delete時にポインタを初期化する.
プログラマ以外にもわかるようにデータを作成する. ・C++の補足(namespace,template,const,2種のdeleteなど) ・プログラムが大きくなるほどconstなどの安全装置は有効に働く.
・const char x[] = "abc"とconst char* x = "abc"の違い.
・やろうと思えばポインタを使ってclassのprivateなメンバにアクセスできる(?).
・参照はポインタの危険な扱い方を防ぐ効用がある.
・ポインタ返しと参照返し

Chapter2 点から始める2Dグラフィックス

Visual StudioのDebug/Release設定は「すべての構成」を選択すると楽.
・newしたらdeleteを徹底しろ(RAII的な).

Chapter3 描いた絵を使う

・const_castを使用する場合は設計を疑おう.
C言語のキャストはなるべく使用しない(キャストはバグになりやすく,検索に引っかからないのは面倒なため).
・アライメントの問題に気を付ける.
・「人間は間違えることが可能な状況であれば必ず間違える」ことを念頭に置く.
・単純な高速化手法として,可能ならばループ中の計算をループ外で行う.
・中途半端に透ける-->アルファブレンド
・アルファブレンドは線形補完で実現可能.
・適切なインクルード
 実体:クラス「定義」
 ポインタ:クラス「宣言」
 1. インクルードガード
 2. (可能ならば)ポインタの変数を使用
 3. 必要とするヘッダをインクルード
・式変形の段階で高速化を意識する.
 アルファブレンド

Chapter4 リアルタイムなゲーム

・固定フレームレート
 遅いときに速くできない(一番遅い秒数に合わせる).
 再現性がある.
・可変フレームレート
 処理落ちがゲーム進行速度に影響を与えない(?).

Chapter5 かんたんなシーケンス遷移

・ASSERT
・「if-elseが10個並んだらそのコードを書いた人はヤバい」
 なんとなくわかる.
・階層型シーケンス遷移でゲーム画面を管理
 Stateパターンに近いものを感じる.

Chapter6 文字の書き方

・作成しているゲームが面白いかはすぐ判断できたほうが良い.
 素材は後でいいから速く実装する.
・シングルトン
 1. グローバル変数の危険を軽減する.
 2. グローバル変数を使用したい.
著作権
 大事.

Chapter7 はじめてのアクションゲーム

・ゲーム遷移
 状態遷移図であらかじめ図示しとくのが良いと思った.
・処理の共通化
 1人用と2人用で同じ機能(ポーズ画面など)を共通化すると楽.
  ただし,ポーズ機能が違うなどが発生すると面倒になるので,一長一短.
  柔軟性を持つことが大切.
・ゲーム開発は調整とテストの繰り返し.

Chapter8 平面の衝突判定

・あたる寸前で止める
 1. 何回かに分けて判定
  遅い.
 2. いつ当たるか計算
  すでにめり込んでいる状態が面倒.
 3. めり込んだら元に戻す.
・当たり判定を小さくする.
 Unityのコリジョンのイメージ.

Chapter9 いろいろな入力装置

・ライブラリの隠蔽
 ライブラリ開発者は使用用途を知ることができない.
  必要な機能はすべて準備.
  適切に隠蔽し,無用なバグや使用を防ぐ.

Chapter10 少しマシなシーケンス遷移

・ステートマシンでシーケンス遷移する方法(?)
・dynamic_cast
 ダウンキャストは遅い
・言語機能は無理してまで使用する必要はない.
 必要になったら使用する.
・継承についての補足
 仮想関数の詳細(実装寄り)
・継承の目的
 1. 派生を隠し継承だけを教える.
  中身は関係ない.
 2. 同じコードを何度も書く必要がない.
  比較的類推しやすい.
 3. 派生を使用する人が理解しやすい.
  基底側である程度実装すれば派生側は楽.

Chapter11 音を鳴らす

・音源ファイルの処理方法について.

Chapter12 回す,伸ばす,動かす

・回転
 補完しないと点が出現する.
 線形補完と2次元補完.
・拡大縮小
・アフィン変換
・ラスタライズ

Chapter13 ハードウェアのパワー

GPUは偉大
・ハードウェアは最強だが,自力で実装する力もあったほうが良い.

Part2. 3次元のゲーム

Chapter14 立体を描く

・Zソート
 z値の大きい順にソート.
・Zバッファ
・透視変換
・座標変換
・Zバッファ精度問題

Chapter15 ライブラリの作り方

XMLでデータ管理
・ライブラリは.libにまとめると良さそう.

Chapter16 XMLモドキを読む

・std::stringは遅い.
・文法の自由度を下げればデコード側は楽.
 そうだね.
・字句解析
 状態遷移図.
・最初は速度は気にしなくていい.
 慣れてきたら気にしよう.

Chapter17 遅くないコードを書くために

・計算量/オーダ
スループット
 単位時間当たりの処理能力
・レイテンシ
 結果を見るまでの待ち時間
・メモリの問題
・キャッシュ
・配置newとoperator new()
・std::set
 赤黒木
・「速度が必要とされる度合いに応じて適切なコードを書く」

Chapter18 立体の衝突処理

平方根
 割と扱いが面倒.
・三角形と線分の交差判定

Chapter19 ロボファイトの設計

・フロントエンド
 レーダ的な奴.

Chapter20 光が当たるということ

・レイトレース
・光源処理の高速化

Chapter21 キャラクターが動き出す

・モデルビュー射影行列
木構造による親子関係の実装
・ホーナー法
・Inverse Kinetics(逆動力学)

Part3. 売り物への道

Chapter22 遅くない衝突検出

・空間分割による衝突検出
・k-d tree
・CPU命令とキャッシュ

Chapter23 ローディング

・ファイル結合による高速化
・圧縮による高速化
・LZ77
・マルチスレッドによる非同期処理
・中身を見せないための結合と圧縮

Chapter24 floatの使い方

・数値が大きいほど次の数値までの幅が大きくなる.
・誤差
・ゼロの扱い
・無限大:Inf
・非数:NaN
・非正規数

Chapter25 付属ライブラリの本番仕様

・シングルトン
 Impl
・標準のrand()
・Thread
 Semaphore, Mutex, Event

Chapter26 バグとの付き合い方

・論理バグ
 作成しようとしたものが間違い,作成しようと思った物と違うものを作成する.
 「プログラムは書いた通りにしか動かない」
・技術バグ
 プログラム・ハード的に間違い.
 無知によるミス.
・処理落ち
 遅い.
・メモリ溢れ
 メモリ使用効率が悪い.
・コメント
 三日後は他人.
C++的にはアンダーバ始まりの変数はどうなのさ?
・試作品は捨てろ
 後々悲劇を生みやすい.
・メモリ解放忘れ
 crtdbg.h

Chapter27 もっと先へ

いろいろな参考文献が書いてある.

感想

C++や数学の知識が足りていないことを再認識できた本でした.

流し見で読みましたが,今度は項目別にじっくり読みたいと思います.

「オンラインゲームを支える技術-壮大なプレイ空間の舞台裏-」を読んだ

こんにちはちみつ

「オンラインゲームを支える技術-壮大なプレイ空間の舞台裏-」を読んだ感想です.


Amazon


内容

オンラインゲーム開発の技術について,ネットワークの歴史や次世代プラットフォーム,ソケット通信などを一通り解説してます.

技術だけでなく,チート業者の目的やその対策,ハードウェアの歴史を踏まえたネットワークプログラミングについてなど,ネットワークを扱うゲームについて色々な視点から解説されているため,ネットワーク関連の業務に携わる人なら楽しく読み進められると思います.

対象

・オンラインゲーム開発を行う新人さん
・ネットワークプログラミングに興味のある人
ゲームプログラマ

個人的な感想ですが,ネットワーク関連について結構深いところに踏み込んでいるため,ネットワーク関連の書籍としては入門書と専門書の間ぐらいの内容だと思います.

ネットワークについてそこそこの知識が必要になると感じました.


要約

第0章 [速習]オンラインゲームプログラミング

ネットワークプログラミングの基礎

・インターネットプログラミングの歴史について
 TCPRFCなど.
TCPUDP
 送受信の順番・正確性を保証: TCP
 ↑が必要ないとき: UDP
・オンラインゲームではUDP
 基本はUDPで必要な時にTCP
・レイヤ5(OSI)以上はゲームごとに実装
・「UNIXネットワークプログラミング」はイイゾ
・オンラインゲームではコネクション指向のTCPを使用

ソケットプログラミング入門

・ソケットAPI
 ECHOサーバ
・同期的な呼び出しにはスレッドを使用
・オンラインゲームではC/C++が主流
 次いでJavaなど
 軽量言語としてlua, squirrelなどがある
・サーバの効率化
 C/C++は開発コストが高いのでGCがるC#Javaが使いたい.
 -> 開発サイクルは改善するが性能を犠牲に...
JavaC言語
 100MBのファイルを読むとき,Javaシステムコール前後で例外処理などを行う.
 Cのほうが約10倍ぐらい早い.

RPCの攻略

RPC: 通信に関する細かい面倒をラップし,通常の関数呼び出しと同様にホストと通信できる仕組み.
UDPの使用目的
 到達速度>信頼性の時
  FPSなど
 NATトラバーサル機能を実装する

ゲームプログラミングの基礎

・インベーダゲーム
 初期化,無限ループ,Sprite,描画
・タスクシステム
 「ミサイル1つを1フレーム進める」など,細かい単位の処理を1つの関数として定義し,ミサイル数だけ1フレーム内に順番に全て呼び出す.
・ゲームプログラミングとネットワークプログラミングの違い
 ネットワーク:全ソケットに対してselect()でポーリングし,コールバック関数を呼び出して少しずつ動作.
 ゲーム:すべての可動物に対して舞フレームポーリングし,コールバック関数を呼び出して少しずつ動作.

開発効率とプラットフォーム間の移植性の確保

・要望
 本番サーバはLinux,開発環境はWindows(VS)で開発
 サーバとクライアントで衝突判定など,同じ処理コードを使用したい
  ・C/C++/Javaの選択.
  ・ラッパでソースレベルで互換性を保つ
・ラッパの仕事
 メモリ管理:mallocは全システムで使用可能なので比較的簡単.
 ソケットAPI:WindowとUNIXではAPI仕様が違うので一通りラップする.
 スレッド:pthreadなど
 シグナル:移植性の低い方法なのでお勧めしない.
 イベント・タイマ:libeventで楽にラップ可能.
POSIX標準に近いインタフェースになるようラップすると全体の作業量が減り,楽.

オンラインゲームの歴史と進化

オンラインゲームの技術史

・1983年
 P2Pタイプのネットワーク対戦ゲームSnipesが登場
 NESのマリオやゼルダが出たころ
・1989年
 CERNにおいて,HTMLと世界初のブラウザWorldWideWebが開発される.
 1989年後半でインターネット接続ホストは約30万台.
・1990年
 SNESメガドライブ用に電話回線を使用するネットワーク対戦ゲームXBANDが登場.
  帯域速度・パケット遅延の影響で失敗に終わる.
 MMORPGでは「Meridian50」が成功.
・2000年代前半
 FF,信長の野望など,有名タイトルがオンライン化.
 NTTドコモiアプリ以降,携帯電話でもオンラインゲームが普及したがパケット代金が社会問題化した.
・2000年後半
 WebブラウザベースのMMOGの成功.
 World of Warcraftが1人用ゲームデザインで約1200万人以上の大ヒット.
 マシン性能向上によるトランザクション処理の高速化などにより課金モデルが進化.
 WiiPS3, Xbox360など,LAN接続機能が標準搭載される.

技術遍歴から見えてくるゲーム文化/経済圏

・文化圏
 ハッカー,コンソル・アーケードビジネス,Microsoftの3つの文化圏が生まれる.
 日本の会社は,自身の知識やソースコードを公開することに消極的でないため,技術レベルが衰退してしまいそう.
  CEDECの誕生.

Column

・売れるオンラインゲームプログラマの条件
 1.ゲームが好き
 2.プログラミング・実作業が好き

オンラインゲームとは何か?

「オンラインゲーム」の用語の定義

・物理的な側面
 コンピュータ
  クライアント機器:PC,家庭用ゲーム機,携帯電話,PDAなど
  サーバ機器:データセンタにあるサーバ
  ロードバランサ
 ネットワーク
  インターネットプロトコル
  ローカルエリアの物理ネットワーク:RS-232,MIDI,USBなど

オンラインゲームの概念的な側面

・概念的な側面
 ゲームプレイの基本
  認知・判断・操作の繰り返し.
 ゲームの進行
  同じゲーム進行を共有する.

オンラインゲームのビジネスとしての側面

・ビジネス的な側面
 おもしろくしたい,素早く・安く完成したい,長く・安く運営したいなど
 テストプレイヤを効果的に集めたい
  オフラインゲームよりデバッグが難しい.
  オープンベータテスト
 頻繁に更新したい
  定期パッチ,大規模パッチ,緊急メンテなど
 攻撃者を安く・素早く・確実に排除したい
  RMT業者,botの排除など
・オンラインゲームを支える技術の大区分
 C/S型とP2P
 MMO型とMO型
・ゲーム本体を支える3つの軸
 データ形式,通信形式,反応速度(レイテンシ)

開発コストを左右する技術的ポイント

データ形式
 disposable: ゲーム内容を毎回初期化して捨てる
  MO型
 persistent: ゲーム内容が永続的にサーバ側に存在
  MMO型
・通信形式
 P2P: 中央サーバが存在しない端末間直接通信方式
 C/S: クライアント・サーバ間のみ通信するスター型通信方式
・反応速度
 ゲームサイクルに大きくかかわる.
 特に,認知と認知の間の時間0.0167秒(1フレーム)を意識すること.
・ネットワーク遅延の3パターン
 25m: 格ゲーなど
 100m: FPSやストラテジーなど
 300m: MMORPGなど

オンラインゲームのアーキテクチャ

ゲームプログラムの特性

NESとCPUサイクル
PS3とCPUサイクル

オンラインゲーム特有の要素

・避けられない遅延
・通信帯域
 C/S MMO: 10kbps~100kbps
 P2P MO: 30kbps~300kbps
・チートはなぜ行われるのか
 RMTで儲かるから
 利益=チートの価値ーチート開発のコスト
・チートの内訳
 メモリハック,パケットハック,データファイルハック,DLLハック,タイマハック,UIハックなど
 チートでないがダメなもの:規約違反,バグの不正利用,サーバに過負荷など
ノイマン型コンピュータの宿命
 チートと対策のいたちごっこノイマン型(プログラム内蔵方式)のコンピュータである限り永遠に続く.

[実践]C/S MMOゲーム開発

実際のゲームを題材としたゲーム開発について.

[実践]P2P MOゲーム開発

実際のゲームを題材としたゲーム開発について.

オンラインゲームの補助的システム

負荷テストなど.

オンラインゲームの開発体制

ソースコードの規模
・プロジェクトの保守

感想

読み始める前はオンラインゲームの技術について簡単に解説されているぐらいの認識でしたが,読んでみると結構ガッツリと技術解説されていて面白かったです.

まだ薄っすらとしか理解できていないので,ネットワークプログラミングについて勉強してからもう一度読みたいと思います.

Unity: 進行方向を表示する

こんにちハルマゲドン
水太りしてきました.

Unityで進行方向を可視化したときの備忘録です.


参考文献

なし


目的

進行方向を矢印で可視化したかった.


方法

矢印の画像を使用して,入力値に応じてGameObjectを回転させます(まんま).

f:id:lambda410:20210526215350p:plain
使用した画像

手法

  1. 入力取得
    x,yともに[-1.0, 1.0].
  2. 回転角度計算
    右ベクトルを基準として,入力値との角度を計算.
    f:id:lambda410:20210526215857p:plain

スクリプト

角度の向きを状況に応じて変更してます.
必要に応じて豪華にしてください.


動作

f:id:lambda410:20210526221055g:plain


まとめ

Unityは便利ですね.

Unityで自動生成の迷路を作る

こんにちはみがきこ
網戸にカメムシの卵があったので,急いで殺虫剤を買いました.

今回はUnityで迷路を自動生成したときの備忘録です. 自動生成に使用したアルゴリズムは穴掘り法です.

参考文献

algoful.com

完成図

サイズ: 5×5
f:id:lambda410:20210424205040p:plain サイズ: 51×51
f:id:lambda410:20210424205042p:plain
サイズ: 101×101 f:id:lambda410:20210424205036p:plain

穴掘り法

すごく簡単に言うと「穴を掘り続けて迷路を作る」アルゴリズムです.(そのまんま)
今回は下記の条件でアルゴリズムを実装しました.

・制約
1.迷路の横・縦のサイズは奇数.
2.横・縦の最小サイズは「5」.

・実装したアルゴリズム
1.奇数座標(x, y)をランダムに取得し,基準座標とする.
2.基準座標の上・下・右・左の4方向から1方向をランダムに取得.
3-1.ランダムに取得した方向の2マス先が壁ならば,そのマスまで掘る.
3-2.進めないならば,その方向を除いた他の方向をランダムに取得し,手順3-1.
3-3.全方向に進めないならば,1つ前の座標に戻り,残りの方向をランダムに取得し,手順3-1.
4.既定の回数になるまで手順2,3を繰り返す.

おそらく再帰かスタックを使用すると思います.
自分はスタックで実装しました.


ソースコード

若干無駄な処理がある かつ このままでは動かない気がします.
あくまでアルゴリズムの参考までに.


まとめ

今度はスタートからゴールまでを探索するAIを書いてみたいですね.
多分生成と同じ方法で解けると思ってます.

Unity: スプライトの表示順を変更する

こんにちワンダーランド

Unityでスプライトの表示順を変更したときの備忘録です.


参考文献

この記事を読めば理解できます.
tsubakit1.hateblo.jp


設定

今回はスクリプトや面倒な設定はなしです.

[Sorting Group]をアタッチして[Order in Layer]の値を変更するだけです.
f:id:lambda410:20210524213830p:plain

「値が大きい」ならば「一番上に描画」されます.
以上.


結果

f:id:lambda410:20210524214043p:plain
f:id:lambda410:20210524214103p:plain
f:id:lambda410:20210524214333p:plain

奥行きの配置に関係なく描画順が決まります.


まとめ

本当にただの備忘録.