お気に入りのゲーム固有のコーディングの宝石は何ですか?[閉まっている]


24

まず、Quake IIIのJohn Carmackの Fast Inverse Square Root から始めます。

float Q_rsqrt(float number) {

  long i;
  float x2, y;
  const float threehalfs = 1.5F;

  x2 = number * 0.5F;
  y = number;
  i = * ( long * ) &y;
  i = 0x5f3759df - ( i >> 1 );
  y = * ( float * ) &i;
  y = y * ( threehalfs - ( x2 * y * y ) );

  return y;

}

6
それは本当に質問ではありません-少なくとも、これをコミュニティwikiページと宣言するかもしれません...
レイチェルブラム

完了、コミュニティ化。
ギャック

3
それをねじ込む!すばらしいJCによって作成されたすべてのコードを使用してください。
アダムネイラー

3
0x5f375a86(:ところで、より正確な「マジックナンバー」は平方根関数、逆高速で使用することがありますのでご注意を行うen.wikipedia.org/wiki/...
Ricket

8
また、John Carmackのものではないことに注意してください。
カイ

回答:


25

mapValue関数:

float mapValue( float inVal, float inFrom, float inTo, float outFrom, float outTo )
{
    float inScale = (inFrom != inTo) 
        ? ( ( inVal - inFrom ) / ( inTo - inFrom ) ) 
        : 0.0f;
    float outVal = outFrom + ( inScale * ( outTo - outFrom ) );
    outVal = (outFrom < outTo ) 
        ? clamp( outVal, outFrom, outTo ) 
        : clamp( outVal, outTo, outFrom );
    return outVal;
}

値を取得し、それをある範囲内の割合に変換してから、別の範囲に比例してスケーリングします。二倍のように。

あなたはそれを使ってものを正規化できます:

float minDamage = 0.0f; float maxDamage = 300.0f;
float normalisedDamage = mapValue(damange, minDamage, maxDamage, 0.0f, 1.0f);

または、ある範囲から別の範囲に変換できます。

float brakeStrength = mapValue(timeToCollision, 
    0.0f, 10.0f, // seconds
    1.0f, 0.2f // brake values 
    );

2番目の例では、出力範囲は入力範囲とは異なる順序であることに注意してください。

それは多くのように見えませんが、私はあちこちでこの小さなフェラを使用しています。


14

ゲームコードでピタゴラスの定理を何回使用したか、まだ信じられません。私にとって、この単純な式はゲーム開発の宝石です。

a ^ 2 + b ^ 2 = c ^ 2
(ソース:mathurl.com

または

代替テキスト
(ソース:mathurl.com

相対的な距離のみが重要な場合は、高価な平方根演算なしで使用できます

代替テキスト
(ソース:mathurl.com


正直に言って、ピタゴラスの数学はゲームコード、特に物理コード、レンダリングコード、AIなどのエンジン全体で使用されます。
ニックベッドフォード

1
本当です。それが宝石である理由です。;)
MrValdez

4
興味深いバリエーションは、相対的な距離のみを考慮する場合です。その後、潜在的に高価なsqrt呼び出しをスキップして、単に計算することができますdistance2 = x^2 + y^2
mmyers

@mmyers-別の素晴らしいこと:x ^ 2スペースで作業している場合、距離は単なる相対距離ではありません。
スティーブンエバーズ

相対距離ビットについて言及していただきありがとうございます。あまり正確ではないものを使用する必要があるときにA *を使用するのと同じように、不必要な平方根演算が非常に多く見られました。
リケット

13

私からの最大のものは、Scott BilasのGameObjectシステムについて読んでいたことです。私は彼のようにデータベースシステムを使用していませんが、6レベルの継承ツリーを作成するのをやめ、管理しやすく再利用可能なコンポーネントシステムを作成しました。


10

私はDuffのDeviceを使用する必要があります。文字通り私のあごを落としたコードの最初のブロックでした。 "出来るよ?!?"


ああ、神様。ゴーグル!彼らは何もしません!
ラウル

「switch-case」内の入れ子になった「do-while」により、常に点滅します。20年後でも...
アンドレアス

1
-1。私はこれが好きではありません。今日はあまり役に立ちません(memcpy他の人にコードを読み取らせたい場合は、代わりに使用します)
-bobobobo

1
@JoeWreschnigどうして?Memcpyは常により読みやすく、ポータブルで、おそらくより最適化されます。
kaoD

1
@kaoD:memcpyはDuffのデバイスと同等ではないため、同じことをしない場合でも「読みやすく、移植性があり、おそらくより最適化されている」とは関係ありません。現代のCPUのパイプラインは、おそらく分岐予測と命令キャッシュのそれよりもダフのデバイスなしに有利になるだろうが、それは持っていない、何もして行うにはmemcpy

7

私が長年書き戻したゲームの小さなC / C ++スニペット:

(fill ? FillRect : DrawRect) (x, y, w, h, colour);

最初のゲーム(これ)では、1Mb以上のRAMにアクセスする必要がありましたが、これはインターネットが普及する前のことであり、DOSアプリが追加のRAMにアクセスするために使用するXMSおよびEMSのドキュメントがありませんでした。

そのため、私は386でセグメントレジスタに関して機能していた小さな「バックドア」を使用することになりました。通常、リアルモードでは、アドレスはseg*16+off1Mbに制限されるように計算されました。

ただし、保護モードに切り替えて、4Mbのアドレスにセグメントを設定し、元に戻すことができます。セグメントレジスタに書き込みを行わなければ(DOSは8086セグメントレジスタのみを使用するので問題ありません)、全体にアクセスできますフラットアドレススペースとして4Mb。DOSサービスを使用する場合は、リアルモードに戻す必要がありました。

使用可能なDPMIエクステンダーも多くありませんでした。


ほとんどC#で動作します(デリゲート型を宣言し、少なくとも1つのキャストを挿入する必要があります)
finnw

リアルモードでの32ビットアドレッシングモードとはどういう意味ですか?(つまり、アドレスサイズのプレフィックスが必要です)。セグメント記述子を設定する必要があり、実際には通常の16 * FS +としてセグメントレジスタを使用していないことは確かですか?セグメントは16ビットモードでは制限がなく、ベースアドレス(16 *それらの値)だけであるとは思わなかったので、FSを16ビットモードで何かに設定することはできませんでした[fs:esi]。欲しかった?
ピーターコーデス

私はこれを試していないか、16ビットモード用の実際のコードを32ビットと64ビットのasmだけで作成しましたが、奇妙に聞こえます。うーん、もっともらしい。現代のCPUは間違いなくセグメントのものを内部的にキャッシュし、セグメントregに書き込むときにのみそれらのキャッシュをリロードするため、それがプロテクトモードのベース+制限を維持する方法である可能性があります(実際に起こったので、 16 * FSから4MB)。
ピーターコーデス

5

個人的には、予測可能な乱数のメルセンヌツイスターの大ファンです。特に、複数の異なるシードのRandのインスタンスを作成する必要がある場合は

http://en.wikipedia.org/wiki/Mersenne_twister


Mersenne Twisterは、優れた乱数ジェネレーターであるという意味で優れていますが、特にエレガントでもクールでもありません(または高速で実装が簡単ではありません)。そのためには、en.wikipedia.org/wiki/Rule_30をご覧ください

1
WELL ..ほとんどの用途のために、一般的に良くMTよりもen.wikipedia.org/wiki/Well_equidistributed_long-period_linear
ヤリKomppa

5

以下は、Chris Crawfordが言及した(そして明らかにAtariによって使用された)彼が「A Graphics Trick」と呼んでいるものです。

LDA FIRST
EOR SECOND
AND CONTROL
EOR SECOND
STA OUTPUT

説明については記事全体をお読みください。


1
そのリンクは現在壊れているので、ここで説明が役立つと思います。
finnw

ありがとう。彼は去り、ウェブサイトを再び変更しました。リンクを更新しました。
アンソニー

4

何らかの理由で、人々はしばしばゲームのデザインパターンの力を過小評価しています。私は、ほぼすべてのGoFパターンがゲームに適用されるのを見てきました。


1
ゲームプログラミングで気に入っていることの1つは、標準的なGoFの「正確さ」の方法から離れて、純粋に美しい速度に焦点を合わせていることです。とはいえ、MVCの実装は、ゲームよりも害が多いという点で多くの悪い例があります。
イアン

デザインパターンには場所があると思います。ゲームではそれほどではありませんが。
blissfreak

@blissfreak:ゲームプログラミングには、パターンが一般的ではない、ある種のワイルドウェストになるような特別なものはありません。それらは途方もなく一般的であり、ここにいくつかの例があります。
スティーブンエバーズ14年

4

Math.atan2()は非常に便利です(すべてのtrigとともに)。


それは、まあ!私は多くの3Dを実行しましたが、実際には必要ありませんでした。
スキズ

+1、これはx + yベクトル成分からラジアン方向に進む唯一の方法です。
RCIX

1
@RCIX:私のポイントは、変換が不要であるということです。つまり、(x、y)->角度、角度の問題にはベクトル解があります。
スキズ

6
裸の標準ライブラリ関数を「gem」と実際に呼ぶつもりはありません。

1
@Skizz:3Dかもしれませんが、正規化されたベクトルを取得してラジアン方向の値を抽出する他の方法はありません。これは2Dゲームでかなりの価値があります。
RCIX

3

上記...ピタゴラス宝石に追加するには
:私は常に3Dプログラミングのために、彼らは知っている唯一の必要があることを人々に伝える
^ 2 + B ^ 2 = C ^ 2 -
- soscastoa(罪=側/傾斜面に対向し、COS =結合した側を/傾斜側、tan =反対側/取り付け側)-a
。b = | a | * | b | * cos alpha
-a * b = | a | * | b | * sin alpha * unit vector
ゲーム開発で遭遇する3D(または2D)の問題を解決できます-4つのルール。
確かに、もっと良い方法はありますが、これはemをすべて解決できます。


5
re:soscastoa私はほとんどの人がそれをsohcahtoaとして知っていると思います(「傾斜した側」を、より明確で、はっきりしない場合は「hypotenuse」に置き換えます)。舌から流れ出しやすくなり、覚えやすいと思います。
アスモール

1
中学(高校時代)が私の脳に刻印されているので、私は常に「彼のラクダと遠ledえの上の古いアラブの土」を好むでしょう。
ジョージダケット

あります" S青梅O LD H ippy C AME A ND H広告TはリッピングO N Aは、 CID"
blissfreak

3

私のお気に入りの1つは、アセンブリ言語版の 'Life'と、Michael Abrashによる「The Zen of Code Optimization」の最適化の全説明です。

コーディングの宝石を探している人には彼の本をお勧めします。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.