与FRP战斗

iof*_*sli 6 javascript frp reactive-programming bacon.js

我读过FRP,非常兴奋.它看起来很棒,所以你可以编写更多高级代码,一切都更具可组合性等.

然后我试图用普通的js到Bacon重写我自己的小游戏.

我发现不是编写高级逻辑代码,而是使用Bacon.js并遵守原则.

我遇到了一些令人头痛的问题,主要是干扰代码

  1. .take(1)

我应该创造丑陋的结构,而不是获得价值.

  1. 循环依赖

有时它们应该是逻辑的.但在FRP中实施它是可怕的

  1. 活跃的状态

即使是bacon.js的创造者也会遇到麻烦.


这里的例子是代码的和平来证明问题:

任务是不允许两名球员留在同一个地方

用bacon.js实现

http://jsbin.com/zopiyarugu/2/edit?js,console

function add(a) {return function(b){return a + b}}
function nEq(a) {return function(b){return a !== b}}
function eq(a) {return function(b){return a === b}}
function always(val) {return function(){return val}}
function id(a){return a}

var Player = function(players, movement, initPos){
    var me = {};
    me.position = movement
        .flatMap(function(val){
            return me.position
                .take(1)
                .map(add(val))
        })
        .flatMap(function(posFuture){
            var otherPlayerPositions = players
                .filter(nEq(me))
                .map(function(player){return player.position.take(1)})
            return Bacon
                .combineAsArray(otherPlayerPositions)
                .map(function(positions){
                    return !positions.some(eq(posFuture));
                })
                .filter(id)
                .map(always(posFuture))
        })
        .log('player:' + initPos)
        .toProperty(initPos);
    return me;
}

var moveA = new Bacon.Bus();
var moveB = new Bacon.Bus();

var players = [];
players.push(new Player(players, moveA, 0));
players.push(new Player(players, moveB, 10));

moveA.push(4);
moveB.push(-4);
moveA.push(1);
moveB.push(-1);
moveB.push(-1);
moveB.push(-1);
moveA.push(1);
moveA.push(-1);
moveB.push(-1);
Run Code Online (Sandbox Code Playgroud)

我要展示的是:

  1. me.positions 依赖自己
  2. 理解这段代码并不容易.是必要的实施.它看起来更容易理解.我花了很多时间用培根实施.结果我不确定它会按预期工作.

我的问题:

可能我会错过一些基本的东西.也许我的实施在FRP风格中并非如此?

也许这段代码看起来不错,它只是不习惯新的编码风格?

或者这个众所周知的问题,我应该选择最好的邪恶?如此描述的FRP的麻烦,或OOP的麻烦.

rai*_*ska 4

我在尝试使用 Bacon 和 RxJs 编写游戏时也有过类似的经历。具有独立性的事物(例如玩家的位置)很难以“纯 FRP”方式处理。

例如,在我早期的 Worzone 游戏中,我包含了一个可变目标对象,可以查询玩家和怪物的位置。

另一种方法是像 Elm 人那样:将完整的游戏状态建模为单个属性(或在 Elm 中称为信号),并根据该完整状态计算下一个状态。

到目前为止,我的结论是 FRP 不太适合游戏编程,至少在“纯粹”的方式上是这样。毕竟,对于某些事情来说,可变状态可能是更可组合的方法。在一些游戏项目中,例如 Hello World 公开赛车比赛,我使用了可变状态,例如用于存储状态的 DOM 和用于传递事件的 EventStreams。

所以,Bacon.js 并不是灵丹妙药。我建议您自己去了解一下,哪些地方适合使用FRP,哪些地方不适合!