RxJS 的循环依赖。孢子建模
Circular Dependencies with RxJS. Modeling spores
我尝试用 RxJS 为一些游戏建模。但我发现循环依赖存在一些问题。所以,我将我的游戏简化为一个简单的模拟(我只留下 'move' 动作)。你可以在下面找到代码(我省略了一些部分,你可以找到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()
有没有办法重写这个依赖全局变量的丑陋的“produceActions”部分?
就像@user3743222 回答中提出的那样
这个问题已经在这里处理过很多次了。
我可以提及的三种方式(可能是其他方式):
- 使用主题
- 使用
expand
- Feedback loop without Subject in RX
- 使用cycle.js(如果你熟悉RxJS,学习曲线很小,如果你做很多游戏,这可能是值得的)
根据您更新的问题和示例请求,这是未经测试的,但这是我的尝试,基于所提供的 link 主题技术。检查它是否有效,如果有效,我会在之后 post 进行一些解释。另外,请检查语法,我对 ES6 了解不多。
为 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);
我尝试用 RxJS 为一些游戏建模。但我发现循环依赖存在一些问题。所以,我将我的游戏简化为一个简单的模拟(我只留下 'move' 动作)。你可以在下面找到代码(我省略了一些部分,你可以找到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()
有没有办法重写这个依赖全局变量的丑陋的“produceActions”部分? 就像@user3743222 回答中提出的那样
这个问题已经在这里处理过很多次了。
我可以提及的三种方式(可能是其他方式):
- 使用主题
- 使用
expand
- Feedback loop without Subject in RX
- 使用cycle.js(如果你熟悉RxJS,学习曲线很小,如果你做很多游戏,这可能是值得的)
根据您更新的问题和示例请求,这是未经测试的,但这是我的尝试,基于所提供的 link 主题技术。检查它是否有效,如果有效,我会在之后 post 进行一些解释。另外,请检查语法,我对 ES6 了解不多。
为 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);