开发者

How to detect konami code with Rx.js (reactive extensions for javascript)?

开发者 https://www.devze.com 2023-01-28 05:15 出处:网络
I want to start learning Rx.js and I\'m looking for a cool example to start the ball rolling. How do I detect konami code with Rx.js?

I want to start learning Rx.js and I'm looking for a cool example to start the ball rolling. How do I detect konami code with Rx.js?

I want to dete开发者_如何学Goct a sequence of key press events (up up down down left right left right B A) and display an image if this happens.


Here is my version:

<html>
<head>
<script type="text/javascript" src="jquery-1.4.4.min.js"></script>
<script type="text/javascript" src="rx.js"></script>
<script type="text/javascript" src="rx.jQuery.js"></script>
</head>
<body>
<p id="result"></p>
<script type="text/javascript">
    $(function() {
        var konami = $(document).toObservable("keyup").Select(function(e) {
            return e.keyCode
        }).SkipWhile(function(k) {
            return (k != 38)
        }).BufferWithCount(
            10
        ).Where(function(ks) {
            return ks.length == 10 &&
                ks[0] == 38 && ks[1] == 38 &&
                ks[2] == 40 && ks[3] == 40 &&
                ks[4] == 37 && ks[5] == 39 &&
                ks[6] == 37 && ks[7] == 39 &&
                ks[8] == 66 && ks[9] == 65
        })

        var konamisub = konami.Subscribe(function(e) {
            $("#result").text("KONAMI!")
            $("#result").fadeIn().fadeOut()
        })
    })
</script>
</body>
</html>

I convert the stream of keyup events into a stream of keycodes with the Select, then ignoring keypresses until the user press up (keycode 38) with the SkipWhile, then collecting 10 keystrokes with the BufferWithCount, then checking the keystrokes with the Where.

I tried using BufferWithTime, but it tends to cut in the middle of keystrokes.

If somebody can suggest improvements, I would love to hear them.


I don't want to spoil the answer for you since you're learning, but I would try to think of the problem as, "How can I transform the Key up event into the sequence of the last 10 characters that were recently pressed", and compare that list to the constant list of "UUDDLRLRBA". (Hint: Buffer, Where, Select, Take, Repeat are your friends here)


To update the answer from Endy (in RxJS 7) (with sequenceEqual from rxjs sample, because, smart usage of it :D)

const table: {[key: string]: number} = {
    ArrowUp: 38,
    ArrowDown: 40,
    ArrowLeft: 37,
    ArrowRight: 39,
    KeyB: 66,
    // Azerty compat
    KeyQ: 65,
    KeyA: 65,
};

const knownSequence = from([38, 38, 40, 40, 37, 39, 37, 39, 66, 66]);

const konami$ = fromEvent<KeyboardEvent>(document, 'keyup').pipe(
    map((e) => table[e.code] ? table[e.code] : -1),
    skipWhile((k) => k !== 38),
    bufferCount(10, 1),
    mergeMap((x) => {
        return from(x).pipe(sequenceEqual(knownSequence));
    }),
    filter((sequenceEqual) => sequenceEqual),
    switchMap((_) => of('konami'))
);

// Basic usage (promisified)
await firstValueFrom(konami$);
// Do Konami thing
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号