In my previous posting I ranted a bit about the WTFs related to RxJs hot and cold Observables and didn't come up with a very good workaround.
This time I have one. Use Bacon.js. That would be my homemade reactive library for Javascript. It solves the hot/cold problem by replacing Observable with two distinct abstractions:
- EventStream: an observable stream of events. Never emits the same event twice. Always emits the same event to all subscribers.
- Property: like a stream with current value. Any new subscriber will immediately be called back with the current value if there is any.
I'll use my earlier game development examples again, converted into bacon.js, to show how the new library works. I assume some RxJs knowhow.
So if you have some events (say keyboard events) and you want to map them into some domain events (like game character movement), you can start with the source events and use
The following functions allow you to create a keyUp or keyDown stream for a given keyCode.
map
, filter
and merge
.The following functions allow you to create a keyUp or keyDown stream for a given keyCode.
var allKeyUps = $(document).asEventStream("keyup")
var allKeyDowns = $(document).asEventStream("keydown")
function always(value) { return function(_) { return value } }
function keyCodeIs(keyCode) { return function(event) { return event.keyCode == keyCode} }
function keyUps(keyCode) { return allKeyUps.filter(keyCodeIs(keyCode)) }
function keyDowns(keyCode) { return allKeyDowns.filter(keyCodeIs(keyCode)) }
When you want to accumulate some state (like player position), you can use
toProperty
or scan
to get a stateful Property. These things have a meaningful "current value", unlike streams like "keyup events".
The following creates keyState property from keyups and keydowns of each arrow key, then combines them into a single "direction" property usin
toProperty
:function concat(a1, a2) {
return a1.concat(a2)
}
function keyState(keyCode, value) {
return keyDowns(keyCode).map(always([value])).
merge(keyUps(keyCode).map(always([]))).toProperty([])
}
var direction = keyState(38, new Vector2D(0, -1))
.combine(keyState(40, new Vector2D(0, 1)), concat)
.combine(keyState(37, new Vector2D(-1, 0)), concat)
.combine(keyState(39, new Vector2D(1, 0)), concat)
.map(head)
The direction property will start with the empty array []. When you press an arrow key, the value will change to an array containing the corresponding direction vector. The
combine
method of Property is used to combine multiple properties into one.
The
Property.sample
method can be used to sample the current value of a Property each 50 milliseconds. The result will be an EventStream, because these are now distincts events (no current value, see?). So if you sample the direction each 50 milliseconds, you'll get a "movements" stream:var startPos = new Vector2D(50, 50)
function head(array) { return array[0] }
function id(x) { return x }
var movements = direction.sample(50).filter(id)
Now we can further accumulate the movements into the current position:
var position = movements
.scan(startPos, function(pos, move) { return pos.add(move) })
And voila, we are able to control our game character with the keyboard.
For a live demo of the same, see my slideshow, especially the last slide.
Bacon.js has quite good test coverage, it's open-source, it has at least some level of documentation and I'm a nice guy, so please try it out and let me know how the Bacon suits you.
All help is also appreciated also, so please contribute.
sample(50).filter(id) does not work but filter(id).sample(50) works fine
ReplyDeleteThanks for sharing this amazing post with us.
ReplyDeleteHadoop Training Institute in Noida
Best Hadoop Training in Noida
I enjoyed your blog Thanks for sharing such an informative post. We are also providing the best services click on below links to visit our website.
ReplyDeletedigital marketing company in nagercoil
digital marketing services in nagercoil
digital marketing agency in nagercoil
best marketing services in nagercoil
SEO company in nagercoil
SEO services in nagercoil
social media marketing in nagercoil
social media company in nagercoil
PPC services in nagercoil
digital marketing company in velachery
digital marketing company in velachery
digital marketing services in velachery
digital marketing agency in velachery
SEO company in velachery
SEO services in velachery
social media marketing in velachery
social media company in velachery
PPC services in velachery
online advertisement services in velachery
online advertisement services in nagercoil
web design company in nagercoil
web development company in nagercoil
website design company in nagercoil
website development company in nagercoil
web designing company in nagercoil
website designing company in nagercoil
best web design company in nagercoil
web design company in velachery
web development company in velachery
website design company in velachery
website development company in velachery
web designing company in velachery
website designing company in velachery
best web design company in velachery
Thanks for Sharing - ( Groarz branding solutions )
thanks for sharing we at SynergisticIT offer the best aws certification training
ReplyDelete