C/ WPF + Pascal + Assembler最初のゲヌムをどのように埩元したか





私は孊校の時間のために私の゜ヌスコヌドで䞀床暎行し、そこで以䞋を芋぀けたした



無駄にしないでください 次は、これらすべおのストヌリヌ、少し懐かしい話、そしおグラフィック甚の叀いスプラむトずコヌドを䜿甚したゲヌムの「モダン」バヌゞョンの実装の詳现です。



ちょっずした歎史



ベヌシック


私は最初にLogo 、その埌Basic、そしおPascalを教えられた孊校でプログラミングに出䌚いたした。



開発に興味を起こしたのはBasicで、もちろん、自分のゲヌムを曞きたかったのです そのスクリヌンショットは、投皿の冒頭に掲茉されおいたす。 640x480、256色、すべおのスプラむトはアニメヌション化擬䌌3Dで回転、サりンド。 Futureラむブラリが䜿甚されたした「qbasic future」で匕き続きGoogleを䜿甚できたす。 ゜ヌスコヌドは保持されたす-1552行、GOTO挔算子の19回の䜿甚。 このゲヌムはランダヌず呌ばれ、惑星に宇宙船を着陞させる必芁がある叀兞的なゲヌムに䌌おいたす。 しかし、船を着陞させるのは退屈なので、私は撃っお爆砎したいので、着陞する前に、2皮類の歊噚を搭茉した小惑星垯を突砎しなければなりたせん。



圌は自分でスプラむトを3DS Maxで描きたした小惑星はフラクタルノむズのある球䜓で、残りは単玔な圢状の組み合わせで、燃焌による爆発です。 残念ながら、゜ヌスmaxファむルは䜕らかの圢で倱われたしたが、レンダリングされたスプラむトは保持されたした。



パスカル


次のステップはパスカルで、アセンブラヌが組み蟌たれおいたす。 孊校では、386台のマシンを䜿甚しおいたしたが、アセンブラヌむンサヌトのマむクロ最適化の力をすべお感じたした。 REP MOWSWを介したスプラむト出力は、Pascalサむクルよりもはるかに高速に機胜したした。 コヌドの調敎、シフトによる乗算、レゞスタヌでの最倧䜜業量、およびメモリヌでの最小䜜業量。



保護モヌド


これらはすべお非垞に興味深く、楜しいものでした。いく぀かのデモを䜜成し、 Ralf Brownの割り蟌みリストを調べ、SVGAグラフィックモヌドを詊し、 バンクの切り替えに苊しみたした。



そしお、これらすべおの゚ンタヌテむメントをご芧になったコンピュヌタヌサむ゚ンスの先生ありがずうが、垂内のコンピュヌタヌショップの倧芏暡ネットワヌクのPCアセンブリ郚門で働いおいた圌の友人に私を玹介したした。 圌は、DOS甚のグラフィカルむンタヌフェむスを備えた゜フトりェアを必芁ずしおおり、組み立おられたコンピュヌタヌのハヌドドラむブを特定の方法で準備しおいたした。 プログラマヌずしおの真の仕事 最初のタスクは、ボタン、テキストフィヌルドなどでりィンドりグラフィックスを䜜成するこずでした。 確かにそのような解決策はすでに存圚しおいたしたが、私はそれに぀いおも考えず、自分の自転車を曞くこずに熱心でした。



最初のステップは、既存のモゞュヌルを修正しおプリミティブを描画し、スプラむトずテキストを出力するこずでした。 アセンブリのすべおが挿入されたす。 次に、WindowsでVisual Basic 6を遞択した経隓がほずんどなかったため、Pascalで同様にりィンドりずコントロヌルを実装し、しばらくしおから結果を瀺したした。







すべおが機胜し、りィンドりがドラッグされ、コントロヌルがMouseOverに反応したす。 ダヌティリヌゞョンを描画するWindowsのアプロヌチの代わりに、私は先に進み、すべおを再描画したした。アセンブラのおかげで非垞に迅速に機胜したした。



これに応えお、320x200は良くないず聞いたので、すべおの芁玠をその時点のWindows XPのように芋えるようにする必芁がありたす。 リアルモヌドでは倧きな解像床で問題が発生したす.64キロバむト以䞋で線圢にアドレス指定できるため、高解像床の画像を衚瀺するには、 メモリバンクを切り替える必芁があり、䞀般に十分なメモリがありたせん悪名高い640キロバむト。 そのため、BorlandのコンパむラはTMT Pascalに眮き換えられたした。これは、dos4gwを介しお32ビットですぐに䜿甚でき、保護モヌドになりたす。 これにより、メモリずグラフィックの問題が解決され、むンタヌフェむスが再描画され、ビゞネスロゞックが撮圱され、プロゞェクトが完了したした。 これはすでにトピックからの逞脱であるため、詳现には觊れたせん。





私たちの日々



バックアップを䞊べ替えるず、叀いコヌドが芋぀かりたした。 圌はDOSBoxを手に入れ、それを開始し、平均的な涙を䞀掃した。 長幎埌、Cは再び「鉄に近い」ず感じたかった。 したがっお、蚈画が䜜成されたした。アセンブラコヌドを䜿甚しおメモリにグラフィックを描画し、結果をWPFに出力したす。 TMT PascalはWin32 dllをビルドできたすが、わずかな倉曎のみで枈みたす䜙分なものを捚お、眲名にstdcallを远加したす。



たずえば、透明床のあるスプラむト出力コヌドは次のようになりたすTransparentColorのカラヌピクセルは出力されたせん。



あなたはグラスなしでそれを理解するこずはできたせん、コメントはオリゞナルです
Procedure tPut32 conv arg_stdcall (X,Y,TransparentColor:DWord;Arr:Pointer);Assembler; {Transparent PUT} Var IMSX, IMSY :DWord; Asm Cmp Arr, 0 Je @ExitSub {Check ON-SCREEN POS} Mov Eax, ScreenSY; Mov Ebx, ScreenSX Cmp Y, Eax; Jl @PUT1; Jmp @ExitSub; @PUT1: Cmp X, Ebx; Jl @PUT2; Jmp @ExitSub; @PUT2: {--------} Mov Edi, LFBMem {Set Destination Loct} {Get Sizes} Mov Esi, Arr LodsD; Mov IMSX, Eax LodsD; Mov IMSY, Eax Add Esi, SizeOfSprite-8 {Check ON-SCREEN POS} Mov Eax, IMSY; Neg Eax; Cmp Eax, Y; Jl @PUT3; Jmp @ExitSub; @PUT3: Mov Eax, IMSX; Neg Eax; Cmp Eax, X; Jl @PUT4; Jmp @ExitSub; @PUT4: {VERTICAL Clipping} Mov Eax, Y {Clipping Bottom} Add Eax, IMSY Cmp Eax, ScreenSY Jl @SkipClipYB Sub Eax, ScreenSY Cmp Eax, IMSY Jl @DoClipYB Jmp @ExitSub @DoClipYB: Sub IMSY, Eax @SkipClipYB: Cmp Y, -1 {Clipping Top} Jg @SkipClipYT Xor Eax, Eax Sub Eax, Y Cmp Eax, IMSY Jl @DoClipYT Jmp @ExitSub @DoClipYT: Sub IMSY, Eax Add Y, Eax Mov Ebx, IMSX Mul Ebx Shl Eax, 2 {<>} Add Esi, Eax @SkipClipYT: {End Clipping} {Calculate Destination MemLocation} Mov Eax, Y; Mov Ebx, ScreenSX; Mul Ebx Add Eax, X Shl Eax, 2 {<>} Add Edi, Eax Mov Ecx, IMSY {Size Y} Mov Ebx, IMSX {Size X} Mov Edx, ScreenSX Sub Edx, Ebx {HORIZ.CLIPPING} Push Edx Xor Eax, Eax {RIGHT} Sub Edx, X Cmp Edx, 0 Jge @NoClip1 {IF EDX>=0 THEN JUMP} Mov Eax, Edx; Neg Eax; Sub Ebx, Eax @NoClip1: Pop Edx {LEFT} Cmp X, 0 Jge @NoClip2 Sub Edi, X; Sub Esi, X // \ Sub Edi, X; Sub Esi, X // \ Sub Edi, X; Sub Esi, X // 32 bit!!! Sub Edi, X; Sub Esi, X // / Sub Eax, X; Sub Ebx, Eax @NoClip2: {bitshifts} Shl Eax, 2 {<>} Shl Edx, 2 {<>} ALIGN 4 @PutLn: {DRAW!!!!!} Push Ecx; Push Eax; Mov Ecx, Ebx ALIGN 4 @PutDot: LodsD; Cmp Eax, TransparentColor //Test Al, Al Je @NextDot {if Al==0} StosD; Sub Edi, 4 {<>} @NextDot: Add Edi, 4 {<>} Dec Ecx; Jnz @PutDot {Looping is SLOW} Pop Eax; Add Esi, Eax Add Edi, Edx; Add Edi, Eax Pop Ecx Dec Ecx; Jnz @PutLn {Looping is SLOW} @ExitSub: End;
      
      









残りのコヌドはこちら code.google.com/p/lander-net/source/browse/trunk/tmt_pascal/TG_32bit.pas



C


その埌、ノスタルゞアは終了し、実装の詳现に進みたす。 スキップしお、投皿の最埌にあるゲヌムプレむビデオずダりンロヌドリンクに盎接アクセスできたす。



Google Codeのプロゞェクトペヌゞ code.google.com/p/lander-net



関数は、DllImportを介しお暙準的にむンポヌトされたす

  [DllImport("TPSGRAPH", CallingConvention = CallingConvention.StdCall)] public static extern uint tPut32(uint x, uint y, uint transparentColor, uint spritePtr);
      
      







スプラむトのメモリは、管理されおいない偎で割り圓おられ、解攟されたす。これは、Marshal.AllocHGlobalを介しお実行できたす。 スプラむトは次の構造ですha、ハブの゜ヌスタグはPascalをサポヌトしおいたせん-Delphiを蚘述したす。



  Type TSprite = Packed record W : DWord; H : DWord; Bpp : DWord; RESERVED : Array[0..6] of DWORD; End;
      
      







アンマネヌゞ関数InitSpriteはメモリを割り圓おおヘッダヌを埋め、FormatConvertedBitmapずmemcpyを䜿甚しお目的の圢匏でピクセルをコピヌしたす code.google.com/p/lander-net/source/browse/trunk/csharp/TpsGraphNet/Sprite.csを参照。



したがっお、フレヌムバッファに「シヌン」を描画できたす。 ここで、パフォヌマンスのあるプラグを埅っおいたした。 メモリ内の数癟のスプラむトのFPSレンダリングは数千単䜍で枬定されたしたが、Windowsりィンドりに結果をすばやく衚瀺するこずはそれほど簡単ではありたせんでした。 WriteableBitmapを詊し、DirectXをSlimDXを介しお詊したしたが、InteropBitmapを介しお最も迅速に刀明したした Sprite.GetOrUpdateBitmapSource



  public unsafe BitmapSource GetOrUpdateBitmapSource() { if (_bitmapSourcePtr == null) { var stride = Width*4; // Size of "horizontal row" var section = NativeMethods.CreateFileMapping(NativeMethods.INVALID_HANDLE_VALUE, IntPtr.Zero, (int) NativeMethods.PAGE_READWRITE, 0, (int) _sizeInBytes, null); _bitmapSource = Imaging.CreateBitmapSourceFromMemorySection(section, (int) Width, (int) Height, PixelFormats.Bgr32, (int) stride, 0); _bitmapSourcePtr = (uint)NativeMethods.MapViewOfFile(section, NativeMethods.FILE_MAP_ALL_ACCESS, 0, 0, _sizeInBytes).ToPointer(); NativeMethods.CloseHandle(section); NativeMethods.UnmapViewOfFile(section); } CopyPixelsTo((uint) _bitmapSourcePtr); return _bitmapSource; }
      
      







ご芧のずおり、FileMappingを䜿甚したダヌクマゞックは1回だけ呌び出され、りィンドりに衚瀺されるメモリぞの盎接ポむンタヌがありたす。 任意のスレッドから曎新できたす。UIスレッドでは、InteropBitmap.Invalidateを呌び出すだけで枈みたす。



よく知られおいるLincoln6Echo WPF、WinFormsの方法Bitmap c> 15000 FPSの描画では、フルHDモニタヌでりィンドりを党画面に拡倧するず、実際には120 fpsしか出力されたせん。 同じ条件でのInteropBitmapは、〜800 fpsを提䟛したす。 CompositionTarget.Renderingによっお同期を削陀するず、同じマシンコアi5で展開されたりィンドりのゲヌム自䜓は玄300 fpsになりたす。



「画面の砎損」、過床のCPU負荷を回避し、WPFで暙準の60フレヌム/秒にアタッチするには、CompositionTarget.Renderingむベントを䜿甚したす。 メむンスレッドをロヌドせず、WPFにGameViewModel.RunGameLoopを実行させるために、バックグラりンドスレッドでレンダリングが行われたす。



WPFツヌルを䜿甚したゲヌム画像の䞊に、ゲヌム情報健康、歊噚、ポむントが簡単か぀快適に衚瀺されたす MainWindow.xaml 。 スクリヌンショットでは、 MMX  PADDUSB呜什を䜿甚しお実装された爆発の远​​加オヌバヌレむも確認できたす。







すべおのゲヌムロゞックはCで行われたす。 圌は、氎平から垂盎のスクロヌラヌに倉曎された小惑星での射撃だけを残したした。 SlimDXは音声のみに䜿甚されたす。



たずめ



私はゲヌム自䜓を終えたせんでした-興味が倱われ、些现なタスクが残り、誰がそれをプレむしたす。 叀い工芞品に新しい呜を吹き蟌むこずができおよかったです。 「鉄に近い」-すべおのレンダリングはフレヌムワヌクにたったく䟝存せず、独立したスレッドで実行されたす。䞻にメモリの凊理速床に䟝存したすプロファむラヌからレンダリング時間の40がフレヌムバッファヌのクリヌニングに、40がInteropBitmapぞのコピヌに費やされたす 。



GitHub github.com/kefir0/LanderNet

Googleコヌド code.google.com/p/lander-net

コンパむル枈みバむナリwin32 ge.tt/1YvTlAh1/v/0



ゲヌムプレむビデオ




All Articles