0

I try to model some game with RxJS. but I found some troubles with circular dependencies. So, I simplified my game to a simple simulation(I left only 'move' action). You can find code below(I omitted some parts, you can find the repo here)

const rx = require('rx')
const math = require('mathjs')
const _ = require('underscore')

const FIELD_SIZE = 10

const ctx = require('axel');

let getInitialState = () => {
  return {
    size: FIELD_SIZE,
    people: [
      { x: 0, y: 0 },
      { x: 9, y: 9 },
      { x: 5, y: 5 }
    ]
  }
}

var drawWorld = ({size, people}) => {
  // draw world logic
}


let getMove = (index)=> {
  let [xOffset, yOffset] = [[0,1], [1,0]][math.pickRandom([0, 1])]
  let direction = math.pickRandom([-1, 1])
  return (state) => {
    let {people} = state
    let p = people[index]
    people[index] = {
      x: math.max(
          0,
          math.min(p.x + xOffset * direction, FIELD_SIZE-1)),
      y: math.max(
          0,
          math.min(p.y + yOffset * direction, FIELD_SIZE-1))
    }
    return _.extend({}, state, {people})
  }
}

var POOL = []

var produceActions = (state) => {
  _.range(state.people.length).forEach((i) => {
    POOL.push(getMove(i))
  })
}

var stateObservable = rx.Observable
  .interval(100)
  .timeInterval()
  .map(()=> {
    var x = POOL.slice()
    POOL.splice(0, POOL.length)
    return x
  })
  .scan(
      (state, ops) => ops.reduce(
        (st, o) => o(st),
        state
      ),
      getInitialState()
  )

stateObservable.subscribe(drawWorld)
stateObservable.tap(produceActions).subscribe()

Is there a way to rewrite this ugly `produceActions' part which relies on global variable? Like proposed in the @user3743222 answer

user3743222
  • 18,345
  • 5
  • 69
  • 75
kharandziuk
  • 12,020
  • 17
  • 63
  • 121

2 Answers2

4

This is a question which has been dealt with a number of times here.

Three ways I can mention (might be others) :

Community
  • 1
  • 1
user3743222
  • 18,345
  • 5
  • 69
  • 75
  • I edited my question and provided a working sample. I read the articles which you provide but actually I don't find a solution. Please, help me with rewriting this sample? – kharandziuk Jan 27 '16 at 18:36
1

Following your updated question and request for an example, this is untested but here is my try, based on the provided link on the subject technique. Check if it works, I'll post some explanations after that if it does. Also, please check the syntax, I don't know so much about ES6.

Using a proxy subject for POOL:

var POOL_proxyS = new Rx.BehaviorSubject([]); // instead of var POOL = []

var stateObservable = rx.Observable
  .interval(100)
  .timeInterval()
  .combineLatest(POOL_proxyS, (_, POOL) => POOL.slice() )
  .scan(
      (state, ops) => ops.reduce(
        (st, o) => o(st),
        state
      ),
      getInitialState()
  );

var produceActions = (state) => _.range(state.people.length).map((i) => getMove(i));

stateObservable
  .do(drawWorld)
  .map(produceActions)
  .subscribe(POOL_proxyS);
user3743222
  • 18,345
  • 5
  • 69
  • 75
  • maybe offtopic but I want to ask. Is it a normal practice to use scan with some notion of state? There is really a small amount of examples in the net which describes something bigger then handling a stream of mouseclicks:( – kharandziuk Feb 04 '16 at 11:21
  • 1
    no worries. You can find a more meaningful example here : https://gist.github.com/staltz/868e7e9bc2a7b8c1f754. You also have a lot of examples here : https://github.com/Reactive-Extensions/RxJS/blob/master/examples/community.md. One is http://aaronstacy.com/writings/reactive-programming-and-mvc/. You will have to investigate and see what is useful for you. About `scan`, the question comes time to times. No, you are not breaking any purity or functional rules by using the `scan` operator. And it is actually quite used, as it is one of the very few ways to implement x_n+1 = f(x_n, y_n) – user3743222 Feb 04 '16 at 13:32
  • The introduction to Reactive Programming you've been missing – actually is a sample of useless example:) I read it few month ago and it is a nice motivation paper But thanks for http://aaronstacy.com/writings/reactive-programming-and-mvc/ it's really nice. And it uses similar scan https://github.com/aaronj1335/frp-mvc-and-other-tlas/blob/master/lib/common.js#L81 – kharandziuk Feb 04 '16 at 14:21
  • 1
    I thought you might like it as this is about a game, like in your question. – user3743222 Feb 05 '16 at 00:11