関数型言語でゲームを書くことの課題と利点は何ですか?


81

関数型言語はゲームの作成に最も一般的に使用されるわけではないことは知っていますが、プログラミング言語では興味深いと思われる多くの利点があります。特に焦点がますます多くのプロセッサに向かっているため、並列化の容易さは非常に役立つと思います。

また、.NETファミリの新しいメンバーとしてF#を使用すると、XNAで直接使用できます。たとえば、LISP、Haskell、Erlangなどを使用するのではなく、しきい値をかなり下げることができます。

機能的なコードを使ってゲームを書いた経験がある人なら、何が良い面と悪い面があるのでしょうか?それは何に適していましたか?

編集:これに対する単一の良い答えがあると判断するのが難しいと思うので、おそらくコミュニティwiki投稿としてより適しています。


3
私のお気に入りのゲーム(Rogue)の1つがLISPで記述されているため、この質問(およびその答えの可能性)は非常に興味深いものです。
ジャスティンL.

RogueがLISPで書かれていることを知りませんでしたが、それは興味深いものです。古典的なゲーム。:)
マクマトンズ

2
何を言っているのかわかりません。RogueはCで作成
Mason Wheeler

2
オリジナルのRogueがUnixで書かれているので、あなたは正しいと確信していますが、Lisp には確かにいくつかのRogue クローンがあります:cl-user.net/asp/root-dir(直接のゲームリンクではありません) 、非常に多くの特殊文字が含まれていたため、リンケージが壊れているようです)。
サイクロプス

回答:


57

現在、Haskellでゲームを開発しています。一般的な関数型プログラミングについて話すことはできませんが、具体的にはHaskellについては:

いいもの

これらは、Haskellを本当に際立たせる素晴らしいものです。

  • 純度とは、コードについての推論がはるかに簡単であることを意味します。変数の「現在の」値を心配する必要はありません。また、特定の関数を使用すると、何らかの方法でグローバル状態と競合するかどうかを心配する必要はありません。また、並列処理と同時実行性の処理がはるかに簡単になります(多くの場合、些細なことです)。これらのことは、ゲーム開発者にとって天の恵みとなります。
  • Haskellを使用すると、独自の作成の抽象化を使用して、非常に高いレベルで非常に簡単に記述できます。多くの場合、Haskellの専用コードよりも非常に汎用的なコードを記述する方が簡単です。この利点は、開発時間の短縮とコードの理解の容易さに現れます。私が知っている他のどの言語よりもHaskellの方が真実です。インターフェースを使用することは、まったく新しい言語を使用することに似ています(Haskellエコシステムの残りの利点を維持します)。ほとんどの言語は言語機能と呼んでいますが、Haskellはライブラリと呼んでいますが、強制されているとは感じません。psuedocodeでゲームについての推論を見つけた場合は、おそらく単純なインターフェイスを作成して実際のコードにすることができますが、通常はその価値があります。
  • これは他の答えと矛盾するかもしれませんが、Haskellは私が知っている他のどの言語よりも命令型コードの処理が優れています。純度の制約は、Haskellが「評価」(表現を減らす)と「実行」(副作用を実行する)の概念を分離していることを意味します。いわゆる「命令型」言語とは比べ物にならないほど簡単に副作用をいつ、どのように実行するかを制御できます。以前に純度について述べたことにもかかわらず、いくつかのCバインディングは依然として非常に命令的です(OpenGL、私はあなたを見ています)。したがって、命令的コードに対するこのきめ細かい制御は大歓迎です。最も熟練したCプログラマーでさえ、慣れればそれを高く評価するでしょう。
  • GHCは非常に高速なバイナリを生成します。これらは一般的なCコンパイラから生成されたバイナリほど高速ではありませんが、1桁以内であり、インタプリタ言語で達成するよりもはるかに高速です。Pythonのような他の高水準言語でゲームを書くことができなくても、それは遅すぎるので、Haskellでできる可能性は十分にあります。
  • Haskellにはゲーム関連のライブラリはあまりありませんが、以下の「悪い点」で説明しているように、Haskellの外部関数インターフェイスは私が今まで使った中で最も簡単です。Haskellでほぼ排他的に記述することで、Cにバインドできます。

悪い人

これらは良くありませんが、あまり手間をかけずに対処できます。

  • Haskellを習得するのに必要な時間と労力は、非機能言語での作業に非常に慣れている場合、かなり高くなる可能性があります。言語自体はそれほど難しくありませんが、共通の言語拡張機能と膨大な量のライブラリを考慮すると(他の言語の言語機能を考慮する多くのことはHaskellのライブラリであることに注意してください)、より不吉に見えます。私の意見では、それはそれだけの価値がありますが、他の人は反対するかもしれません。
  • 一部の人々は怠について多くの不満を述べています。あなたが何をしているのかを知っていれば、追跡するのが難しいスペースリークを引き起こすことはありません(私はここ数年でスペースリークを作成していません)が、初心者はこれに関して多くの問題を抱えています これらの人々を撃shootし、これが問題ではないと主張するのは愚かでしょうが、経験によって簡単に解決できる問題だと断言します。
  • Haskellでゲームを作成するための優れたライブラリはあまりなく、Haskellerでゲームを作成しているHaskellerも多くないため、この問題に関するリソースを見つけて支援することは困難です。

ぶさいく

これらは、克服するためにかなりの努力を要するものです。

  • リソースを集中的に使用するゲームを作成している場合、GHCのガベージコレクターはあなたを一生懸命噛むかもしれません。これは、世代を超えた世界のGCであるため、ときどきいくつかのフレームをドロップすることがあります。一部のゲームでは問題ありませんが、他のゲームでは大きな問題です。私とHaskellを使用する他の一部のゲーム開発者は、GHC用に実装されたソフトリアルタイムGCを見たいと思っていますが、私の知る限り、まだ努力は費やされていません。現在、私はこの問題を回避することを心配していません(まだフレームがドロップされているのを見たことはありません)が、少なくとも1つの他のチームがメインレンダリングループをCに入れています。

2
FRPについてどう思いますか?
Hu胡

4
@Wei Hu:私はFRPのアイデアの大ファンであり、いくつかの異なるセマンティクスの作成やいくつかの実装の作成など、FRPをかなり広範囲に研究しています。最良の実装には、依然として重大なセマンティックおよび/または実装のバグがあります。それらはゲーム開発には実行可能ですが、従来のアプローチに比べて多くの利点は(まだ)ありません。
ジェイクマッカーサー

1
匿名ユーザーが、この回答を編集して「lyい」部分を消去しようとしました。「ハスケルにガベージコレクタは(今、同時並行、及び2011などの世代であるghc.haskell.org/trac/ghc/blog/new-gc-preview)」
ヤリKomppa

1
残念ながら、実際にはそうではありません。コンカレントGCは、小さな全体的な改善を正当化するにはあまりにも複雑であることが判明した、それがでマージされていない。
ジェイクマッカーサー

1
@ Hi-Angel Cを生成した古いGHCバックエンドがありますが、ネイティブコードジェネレーターまたはLLVMバックエンドと違いはありません。それでもGHCランタイムが必要です。また、ガベージコレクターを回避しやすくするCバックエンドについて特別なものはありません。GCを排除するのが非常に簡単で安価な場合、他のバックエンドもおそらくそれを行うでしょう。
ジェイクマッカーサー

19

昨年はHaskellで商用ゲームエンジンの開発に費やしましたが、私たちにとって、この経験は非常に前向きでした。私たちのゲームの世界は複雑であり、Haskellはエディター形式からゲームエンジン形式への変換プロセスのモデル化を容易にしました。そのコードが命令型言語でどのように見えるかを考えるのは嫌です。

スペースリークは時々発生しますが、多少のトラブルを引き起こしましたが、一般的なスキームでは少量でした(たとえば、同じサイズのJavaプロジェクトでデッドロックを見つけるのに比べて)。 、彼らは固定されたままでした。

Yampaに似たFRPを使用しており、それに関連する学習曲線は確かにありますが、それが終わったら、経験は非常にポジティブです。ライブラリは私たちにとって問題ではありませんでした-私たちが必要としていたものはすべて利用可能です。ガベージコレクションの遅延は、組み込みプラットフォームのためであるため、特定の問題でした。アニメーションの管理にC ++を使用しました。組み込みプラットフォーム(=低速プロセッサ)であるため、パフォーマンスも問題になりました。私たちはいくつかのCを実行しましたが、アクセラレータなどの新しいHaskellテクノロジーも検討しています。C ++アニメーターは初期の設計上の決定であり、コードが遅すぎる場所はごく小さな領域です。長期的には、すべてのCをHaskellに変換したいと考えています。

Haskellは困難な仕事を容易にし、先ほど述べたすべての困難は、クリーンで保守可能で非常に壊れにくい大量の複雑なコードを作成するのに比べて小さいことです。並列処理はゲーム開発においてすぐに問題となるでしょう、そして私たちはそれに対処するために非常にうまく配置されています。私が言ったことの一部は小さなプロジェクトには当てはまらないかもしれません。なぜなら私たちは長い間これに携わっているからです。そのため、学習曲線やライブラリサポートなどの起動コストはそれほど問題ではありません。


7
この回答を投稿してから5年近くになります。あなたはそれを更新しても構わないと思いますか?市販のゲームエンジンはどのように機能しましたか?どの部分が価値があると判明しましたか?希望どおりに並列処理を利用できましたか?
レヴィ・モリソン

17

デイブはいくつかの優れた点に言及していますが、Haskellが両方の問題を解決したことを指摘する必要があります。ステートレス性は、Stateモナドを使用してバイパスすることができ(EDIT:実際ではありません-詳細は以下を参照)、IOモナドを使用してシーケンスを処理できます(EDIT:またはその他のモナド、その点で...)

あなたが抱える課題(そして、私はゲームプログラミングとHaskellの両方を学ぼうとしていました)は、これらの方針に沿ったものです。(これらはすべてHaskell固有のものです。私はまだ他のFP言語に深く関わっていないためです。)

  • FP学習曲線: FPでは、反復プログラミングから考え方を完全に変える必要があります。ループではなくマップとフォールドの観点から考えることを学ぶには、慣れていない場合はメンタルトレーニングが必要です。
  • Mathyの学習曲線: Haskellは、デザイナーの数学的な洗練に恵まれ、呪われています。FPの基本を学習した後、モナド、射、矢、その他の多くの考慮事項に固執しているためです。それ自体は非常に抽象的なものです。
  • モナド:これらの子犬は、特に「関数構成を関数呼び出しの順序付けを強制する方法に変えるハック」であるというエリック・レイモンドの声明を受け入れた場合、あなたの心を包むのは特に難しくありません。残念ながら(これはHaskellの人気が高まるにつれて良くなっていますが)、モナドの多くの説明は、ほとんどのプログラマーの頭上を狙っています(「エンドファンクターのカテゴリーのモノイドです!」)、またはまったく役に立たないアナロジー(例えば、 、ブレントYorgeyの痛ましい正確たとえば、「モナドはブリトーのようなものです!」あなたは、彼は冗談だと思いますか?誰もが今までのチュートリアルでは、このような間抜けなアナロジーを思い付くことができなかったこと?もう一度考えてみて。)
  • エコシステム:道路の他のすべての段差を乗り越えることができた場合、まだ大部分は実験的な言語で作業するという現実的な日々の現実に気付くでしょう。あなたがここに着いたとき、神はあなたを助けます。ここで、Scala、F#、または他のライブラリとの相互運用性が少なくともある程度保証されている他の言語を真剣に探し始めました。むかし、私はHaskellにWindowsのOpenGLライブラリをリンクしてロードさせました。それは私をかなり気分が良くした。その後、OpenGLバインディングが再リリースされ、私がやったことすべてを壊しました。それがハスケルランドでの生活です。正直なところ、それは痛みになる可能性があります。Bulletエンジンのラッパーが必要ですか?Hackageにあります- 放棄されたウェアとして昨年の11月から。Ogre3dが好きですか?ハッキングには、ライブラリのサブセットのみへのバインディングがあります。要するに、ゲーム開発のbeat地から離れた言語に固執すると、群れを追ってC ++に固執した場合よりも、基本的な配管作業に多くの時間を費やすことになります。

これの裏側は、物事が急速に改善されているということです。そして、それは本当にあなたが経験から何を望んでいるかに依存します。ゲームを構築し、それをあなたのウェブサイトに載せて名声と富を求めたいですか?C ++またはPythonに固執します。しかし、プロセスを革新する必要がある新しい何かを学びたい場合は、関数型言語を試してください。あなたが学習している間、自分自身に多くの忍耐を持っているだけです。

Antti Salonenには、Haskellのゲームプログラミングとの関係を詳しく述べた興味深いブログがあります。読む価値があります。

編集(1年後):状態モナドをさらに研究したので、特定の機能の外に永続化することを目的とする状態のソリューションとしてはあまり良いとは言えません。ステートレスの本当の解決策は、IOVar、ST、MVar(スレッドセーフティ用)のHaskell、または開発者から隠されている内部状態を管理するためにArrowsとFRPを使用するYampaのようなものを通じて見つかります。(このリストは難易度順になっていますが、最初の3つはモナドを理解すれば特に難しくありません。)


1
そこでの良い考えは、たとえHaskell特有のものであっても、ほとんどの周辺言語に当てはまる考えだと思います。簡単に述べたように、ここでF#のような言語が輝く可能性があると思います。たとえば、C#で状態/ UIを処理し、次いで等潜在パス発見、AI、などアルゴリズムのためのF#で論理モジュールを持っている
McMuttons

5

客観的なCaml!

関数型言語を使用することは、ほとんどのタイプのソフトウェア開発で大きな利点となります。これは主に、開発時間を大幅に短縮するためです。ゲームへのサーバーバックエンド、または関数型言語でクライアントのAIおよびロジック層を作成する大きな可能性があります。そして誰もが知っているように、LISPはNPCスクリプトに使用されています。

ゲームのフロントエンドを関数型言語で記述しようとすると、ハイブリッド言語であるObjective Camlに間違いなく行きます。MLの子孫であり、反復スタイルと機能スタイルを混在させることができ、ステートフルオブジェクトを備えた客観的なシステムを備えています。(CamlはF#がモデル化されている言語です。)

OpenGLバインディングは問題なく動作するようで、人々は長い間OCamlでゲームを作っています。この言語はコンパイル可能で、潜在的に非常に高速です(昔、いくつかのベンチマークでCに勝っていることは有名ですが、今の状況ではありません)。

ライブラリもたくさんあります。コンピューターサイエンスのものから、あらゆる種類のライブラリへのバインディングまで、あらゆるものがあります。


4

-そうでもないものへの答えが、私は関数型言語でのゲームプログラミングの議論のように感じる官能性反応プログラミング(FRP)の言及なしで不完全であるhttp://www.haskell.org/frp/ -そしてその最も一般的な実装( YAMPA- http: //www.haskell.org/yampa/ 。


3

利点については、Clean Game Library(http://cleangl.sourceforge.net/)をチェックして、プラットフォーマーゲームをチェックしてください。構文を理解したら(試してみることをお勧めします)、構造の優雅さと、ソースが表現している概念にどれだけ近いかがわかります。追加のボーナスとして、状態の抽象化、および状態を明示的に渡す必要性により、コードははるかにマルチコアフレンドリーになります。

一方で、大きなパラダイムシフトが必要です。あなたがそれについて考えずに行うことの多くは、突然存在しなくなり、間違ったパターンで考えているという理由だけで、あなたはそれを解決する方法を戸惑うでしょう。


2

私の観点からの最大の課題は次のとおりです。

  • 関数型言語のステートレス性:ゲームの考え方は、各エンティティに状態があり、この状態はフレームごとに変更されるというものです。一部の言語ではその動作を模倣するメカニズムがありますが(たとえば、pltスキームで「!」を使用する関数)、不自然に感じます。
  • 実行の順序:ゲームでは、一部のコードパーツは、実行前に終了する他のコードパーツに依存します。関数型言語は一般に、関数の引数の実行順序について何も保証しません。この動作を模倣する方法があります(たとえば(begin...、pltスキームの" ")。

このリストを自由に拡張してください(そして肯定的な点を追加することもできます^^)。


1
Haskellのような非厳密な言語では実行順序が異なる場合がありますが、他のコードパーツに依存するコードパーツで問題が発生することはありません。オンデマンドの評価と考えることができます。結果が必要になるまで、計算は実行されません。悲しみを引き起こす唯一の方法は、パフォーマンスの面だと思います。たとえば、計算間の依存関係を指定する以外に評価の順序を制御できないため、場合によっては適切なキャッシュを取得するのが難しくなる場合があります。
ジェイソンダジット

1

C / C ++でコードを記述し、スクリプトにEmbedded Common Lispなどの埋め込み言語を使用できます。これらを別のプラットフォームでコンパイルするのは難しいかもしれませんが。独自のスクリプト言語の作成方法を学ぶために、Lisp In Small Piecesをご覧ください。時間があれば、それほど難しくありません。


0

LISPで簡単なゲームを作成しましたが、楽しかったのですが、お勧めするものではありませんでした。関数型プログラミングはすべて最終結果です。そのため、データの処理と意思決定には非常に便利ですが、基本的な制御ループのような単純でクリーンなコードを実行するのは困難でした。

私はF#を学んでいないので、作業がずっと簡単になるかもしれません。


私の最初の考えは、足場と状態処理を命令型言語で記述し、ゲームロジックなどを機能ビットで行うことです。.NETとC#/ F#を使用すると、たとえば同じライブラリを使用し、私が知っている本当のペナルティなしで互いに通信できるため、これは非常に簡単です。
マクマトンズ

-1

肯定的なものはパフォーマンス移植性であり、否定的なものは複雑さの管理です。今日のゲームは非常に複雑で、オブジェクト指向の方法論や関数型プログラミングでは実装が難しい汎用プログラミングなど、複雑さをよりうまく管理できるツールまたはプログラミング言語が必要です言語。


11
私をからかってるの?FPは、ステロイドに関する一般的なプログラミングです。データ型機能の両方を一般化できることにより、FPは複雑さを管理するための強力な力を与えます。
rtperson

FPの最大の強みの1つは、汎用コードを実行できることです。
マクマトン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.