8

私はNetwireに入ろうとしています.ドキュメンテーション、紹介、チュートリアルなどを探しましたが、ほぼすべてのチュートリアルと既存のコードはNetwire 5に関しては時代遅れであり、もはや使用されていないNetwire 4の機能を使用しています.我ら。READMEはある程度役に立ちますが、すべてがコンパイルされるわけではなく、開始するのに十分な情報がほとんど提供されません。

ゲームループを実行してイベントに応答できるようにするためだけに説明または例を求めているので、最終的に知ることができるように情報を求めています。

  1. 基本構造 (reactive-banana で、ハンドラーを消費し、動作を定義し、イベントに反応するネットワーク記述を作動させる方法など)。
  2. それが最終的にどうなるかmain
  3. IO イベント (マウスクリック、キーダウン、ゲームループ コールバックなど) の処理方法、セッションでのイベントの発生方法など。

そして、その他の関連するもの。

そこから何かを実行できると考えているので、実験によって残りを学ぶことができます (第 5 バージョンのドキュメントとチュートリアルの状態は恐ろしく存在しないため、すぐにいくつかが表示されることを願っています)。

ありがとうございました!

4

2 に答える 2

10

免責事項: 私は Netwire を使用する大規模なプログラムを見つけることができなかったので、Netwire を使用した私自身の経験に基づいているため、私がこれから書くことはすべて慎重に考えてください。ここで使用する例は、ほとんどが自分のライブラリから取得したもので、 FRP を使用してゲームを作成しようとするものであり、「正しい方法」ではない可能性があります。


質問 1: 基本構造 (reactive-banana で、ハンドラーを消費し、動作を定義し、イベントに反応するネットワーク記述を起動する方法など)。

セッション: netwire ライブラリの作成者は、netwire プログラムの基本構造について非常に優れた回答を提供しました。少し古いので、ここでいくつかのポイントを概説します。ワイヤを調べる前に、まず、FRP の根底にあるドライバーである netwire が時間を処理する方法を見てみましょう。テスト ハーネスを使用せずに時間を進める唯一の方法は、タイム デルタをステートフルに返すtestWireを生成することです。保存状態がその型にカプセル化されるSession方法:Sessions

newtype Session m s = Session { stepSession :: m (s, Session m s) }

ここで、 aSessionは Monad (通常はIO) 内にあり、評価されるたびに type の「時間状態」値sと newを返しますSession。通常、有用な状態は、 のインスタンスを返すことができる値sとして記述できます。TimedReal t

data Timed t s
class (Monoid s, Real t) => HasTime t s | s -> t where
    -- | Extract the current time delta.
    dtime :: s -> t
instance (Monoid s, Real t) => HasTime t (Timed t s)

たとえば、ゲームでは通常、更新呼び出しを行うために固定のタイムステップが必要です。netwire は、この概念を次のようにエンコードします。

countSession_ :: Applicative m => t -> Session m (Timed t ())

AcountSession_は入力としてタイムステップ (この場合は type の固定値) を取り、状態値がtypetである を生成します。これは、 type の単一の値のみをエンコードし、値に追加の状態を持たないことを意味します。ワイヤについて説明した後、ワイヤを評価する際にこれがどのように役割を果たすかを見ていきます。SessionTimed t ()t()

ワイヤ: Netwire の「ワイヤ」の主なタイプは次のとおりです。

Wire s e m a b

このワイヤは、次のことを行うタイプのリアクティブ値を記述します。b

  • タイプのリアクティブ値を入力として受け取りますa
  • モナド内で動作するm
  • タイプの阻害値を生成して、値を阻害するか生成しない可能性がありますe
  • によって与えられる時間状態を仮定します。s

リアクティブな値であるという性質上、ワイヤは時変関数と考えることができます。したがって、各ワイヤは時間 (または時間状態s) の関数としてエンコードされ、その時点で type の新しい値と、 typebの次の入力を評価するための新しいワイヤが生成されaます。値と新しいワイヤを返すことにより、関数は関数定義を通じて状態を伝達することで状態を包含することができます。

さらに、ワイヤは値を抑制したり、生成しない場合があります。これは、計算が定義されていない場合 (マウスがアプリケーション ウィンドウの外にある場合など) に役立ちます。switchこれにより、ワイヤーを別のワイヤーに変更して実行を継続する (プレーヤーがジャンプを終了するなど) などを実装できます。

これらのアイデアを使用すると、ネットワイヤのワイヤの主な原因がわかります。

stepWire :: Monad m => Wire s e m a b -> s -> Either e a -> m (Either e b, Wire s e m a b)

stepWire wire timestate input前に言ったことを正確に行います: を取り、wireそれに電流timestateinput前のワイヤから渡します。次に、基礎となる Monadmで、 の値を生成するか、 の値でRight b抑制しLeft e、計算に使用する次のワイヤーを提供します。

質問 2: 最終的にどのようにメインになるか。

タイプSessionとの値をWire使用して、2 つのことを繰り返し実行するループを作成できます。

  1. セッションをステップ実行して、新しい時間状態を受け取ります
  2. 新しい時間状態を使用してワイヤをステップします

以下は、固定カウンターを変更して永久に 2 でカウントするプログラムの例です。

import Control.Wire

-- My countLoop operates in the IO monad and takes two parameters:
--   1. A session that returns time states of type (Timed Int ())
--   2. A wire that ignores its input and returns an Int
countLoop :: Session IO (Timed Int ()) -> Wire (Timed Int ()) () IO a Int -> IO ()
countLoop session wire = do
  (st, nextSession) <- stepSession session
  (Right count, nextWire) <- stepWire wire st (Right undefined)
  print count
  countLoop nextSession nextWire

-- Main just initializes the procedure:
main :: IO ()
main = countLoop (countSession_ 1) $ time >>> (mkSF_ (*2))

質問 3: IO イベント (マウス クリック、キーダウン、ゲーム ループ コールバックなど) の処理方法、イベントがセッションでどのように発生するかなど。

これをどのように行うかについては、多少の議論があります。mこの状況では、基になる Monad を利用して、現在の状態のスナップショットを関数に渡すのが最善だと思いstepWireます。そうすることで、私の入力ワイヤのほとんどは次のようになります。

mousePos :: Wire s e (State Input) a (Float, Float)

ワイヤーへの入力は無視され、マウス入力はStateモナドから読み取られます。Stateキーのデバウンスを適切に処理するためにand notを使用しReaderます (UI をクリックしても UI の下の何かをクリックしないようにするため)。状態はmain関数で設定され、 に渡されrunStateます。これにより、ワイヤ ステップも実行されます。このようなワイヤの抑制動作は、洗練されたコードを作成できます。たとえば、キーが押された場合に値を生成し、それ以外の場合は禁止するワイヤrightと矢印キーがあるとします。left次のようなワイヤーでキャラクターの動きを作成できます。

(right >>> moveRight) <|> (left >>> moveLeft) <|> stayPut

ワイヤは のインスタンスであるため、禁止されている場合はAlternativeright次の可能なワイヤに移動します。a <|> b両方ab阻害する場合にのみ阻害します。

netwire のシステムを利用するコードを書くこともできますが、 usingEventを返す独自のワイヤを作成する必要があります。そうは言っても、この抽象化が単純な抑制よりも有用であるとはまだ思っていません。EventControl.Wire.Unsafe.Event

于 2014-08-16T12:42:25.187 に答える