SlideShare una empresa de Scribd logo
1 de 19
1
〜僕の初めてのリアクティブプログラミング
Reactor を使って
リアクティブに昇龍拳
を繰り出してみた!
quitada
2017/11/17
2
リアクティブプログラミングっ
て何か面白そう!すごそう!で、
何?
リアクティブプログラミングとは?
3
“In computing, reactive programming is an asynchronous
programming paradigm concerned with data streams and
the propagation of change.”
(参考訳)「コンピューター処理において、リアクティ
ブプログラミングは、データストリームとその変更内容
の伝搬を意識した非同期プログラミング方法論の一つで
ある。」
出典:Wikipedia - https://en.wikipedia.org/wiki/Reactive_programming
4
リアクティブプログラミング
のざっくりとした僕の理解
モダンな
ストリーミング
処理関数群
次々やってくる
ストリーミング
データ
なんらかの結果
とか挙動
モダンって何やねん?
5
すぐに思いついたこと
必殺技コマンド
データストリーム
処理関数群
昇龍拳コマンド
データ
ストリーム
しょ〜りゅ〜けん!
ストリートファイターの昇龍拳をモダンに
繰り出せるんじゃね?
P+
だから、モダンって何やね
ん?
ストリートファイターとは?
 1987 年よりカプコン社からリリースされている一連の対戦型格闘ゲーム
シリーズ
 1991 年リリースの二作目、ストリート
ファイター II が爆発的ヒット、各種ビデオ
ゲームプラットフォームにも次々と移植
される(任天堂スーパーファミコンとか)
– 一作目は、大人の事情でファイティング・
ストリートと名前を変えて PC-エンジン
CD-ROM2 に移植されていたりしますが…
6
昇龍拳とは?
 ストリートファイターシリーズのプレイ可能なキャラクターである、リュウ並
びにケンの必殺技の一つ。
 ゲーム中では、以下の操作を素早く行うことにより昇龍拳を繰り出すことがで
きる。対戦相手にヒットすると、比較的大ダメージを与えることができる。
 大ジャンプキックからの、アッパーカットからの昇龍拳といったいわゆるキャ
ンセル技を組み合わせることで対戦をかなり有利に進められる。
7
キャラクターの向いている方向
P+
レバー(パッド)の方向操作 最後にパンチボタン同時押し
8
ということで、リュウさんが昇
龍拳とかを繰り出すだけのアプ
リをリアクティブプログラミン
グして作ってみたので、何か報
告します。
前提とか準備とか(1/3)
 一応、僕は Java ラーなので、UI はこんな感じで JavaFX
で作ります。
– PC のキーボードからのコマンド入力前提。
– レバーの斜めは方向キー同時押しで対応。
– キーを押すと、UI 上のキー画像が押されたようなアニメーションを
する(ちょっと緑色っぽくなる)。
– 昇龍拳コマンド入力等成功すると、リュウのそれに応じたアニメー
ションが見られるだけのアプリケーション。
– 方向キー↑は “W” キー、←は “A” キー、→ は “S” キー、↓は “Z”、パ
ンチキーは “X” キー、キックキーは “C” とする。
 ついでに、波動拳、竜巻旋風脚や、(必殺技でないけ
ど)中パンチと大キックも実装。
 どうでもいいけど、BGM とか効果音もつけてみる。
9
方向キー
キックキー
リュウさん
(本人)
パンチキー
前提とか準備とか(2/3)
 必殺技コマンド入力の実装アイディア
– javafx.scene.Scene のインスタンスにキーイベントを取得するため以下のリスナーを
付与
▪ キーを押したイベントを取得: Scene#setOnKeyPressed
▪ キーを離したイベントを取得: Scene#setOnKeyReleased
– 取得したキーイベントをバッファしておく。
– 必殺技は最終的にパンチキーかキックキーを押すことで繰り出されるので、当該
キーが押された際にあらかじめバッファしておいたキー入力が各必殺技のコマンド
入力に合致しているか判断して、合致していたら対応する必殺技を繰り出す。
– バッファされたキー入力はアルファベット文字列に変換され、各必殺技に相当する
文字列と比較して入力判定する。キーを押した場合は大文字、キーを離した場合は
小文字とする。例えば昇龍拳と判断されるキー入力文字列は以下(キーを離したと
いうイベントも意識する)。
▪ “SsZzZSX” か “SsZzSZX”
10
前提とか準備とか(3/3)
 リアクティブライブラリーとして、Reactor を使います。
Java だし。最新の v3.1.x 系を使用します
(2017 年 11 月現在)。
 ところで…、Reactor?原子炉?
11
Reactor とは?
 Pivotal 社主導で Project Reactor というオープンソースプロジェクトの下
で開発されている、Reactive Streams 仕様に沿った、JVM 上でノンブ
ロッキングなアプリケーションを開発するリアクティブライブラリー。
– https://projectreactor.io/
 バージョンアップするたびに、API がかなり変遷してますが、現在
(2017 年 11 月現在)はコアライブラリーとして、Flux と Mono という
Reactive Extensions の実装が提供されています。
 Spring Framework 5 のリアクティブプログラミング向けフレームワーク
(Spring WebFlux とか)の実装として Reactor が使われいます。
12
13
デモ:
とりあえずできあがったアプリ
ケーションがどんなものかデモ
ンストレーションするよ。
【どうでも】キーイベント取得動作で分かったこと【イイネ!】
 いきなり本筋からそれますが…
 昇龍拳って、最後にレバー斜め下 + パンチボタンという同時押しするんで、今回の想定で
は [→] + [↓] + [P] と、3 キー同時押しになるんですね。
 普通の PC に付属しているキーボードって、ほとんど「2 キーロールオーバー 」というス
ペックで、特殊キーを除いて 2 キーまでしか同時押し認識しないんですね。
 私の PC も例外なく 2 キーロールオーバーだったんで、当初の仕様上、3 キー同時押しを要
求する昇龍拳はだせないんですよね…。
 なので、デモアプリを動かすには「N キーロール
オーバー」といったスペックのちょっといい外付け
キーボードを使いましょう。ちなみに僕は、HHKB
Professional BT(無刻印変態仕様)を使っています。
– それでも、PS/2 接続じゃない最近のやつは 6 キーまでしか同時
押し認識しないんですけどね。ま、それで十分ですが。
14
15
比較のため、まずはリアクティ
ブプログラミングなしでアプリ
ケーションを作ってみたよ。
さて、昇龍拳ロジックを見てみ
ましょう。
ノンリアクティブな昇龍拳ロジック
16
mainScene.setOnKeyPressed(new EventHandler<KeyEvent>() { // キー押下時に反応するリスナー付与
public void handle(KeyEvent event) {
String keyEvent = event.getCode().toString(); // キーイベントを文字列に変換
if (keyActionChecker(keyEvent)) { // 方向キーかパンチ・キックキーが押された場合のみ以下実行
commandList.add(keyEvent); // 入力キーバッファ commandList にキー文字列追加
if (keyEvent.equals(PUNCH) || keyEvent.equals(KICK)) { // パンチ・キックキーが押されたら必殺技判定
String cl = readCommand(); // 入力キーバッファの内容を文字列 cl に変換します
if (cl.contains(SYORYU_CL[0])…) { // cl に昇龍拳コマンドが含まれているか?
startAction(3, 17, “shouryuuken.mp3”); // 昇龍拳を繰り出す
} else if (cl.contains(HADOU_CL[0])...) { // cl に波動拳コマンドが含まれているか?
startAction(4, 14, “hadouken.mp3”); // 波動拳を繰り出す
} else if (cl.contains(TATSUMAKI_CL[0])…) { // cl に竜巻旋風脚コマンドが含まれているか?
startAction(5, 27, "tatsumaki_senpukyaku.mp3");
} else if (cl.contains(PUNCH)) { // cl にパンチキーイベントが含まれているか?
startAction(1, 8, “punch.mp3”); // 中パンチを繰り出す
} else {
startAction(2, 15, “kick.mp3”); // 上述のどれにも該当しなかったら、大キックを繰り出す
}
}
}
}
});
mainScene.setOnKeyReleased(new EventHandler<KeyEvent>() { // キー離した時に反応するリスナー付与
public void handle(KeyEvent event) {
String keyEvent = event.getCode().toString(); // キーイベントを文字列に変換
if (keyActionChecker(keyEvent)) { // 方向キーかパンチ・キックキーが離された場合のみ以下実行
commandList.add(keyEvent.toLowerCase()); // commandList にキー文字列を小文字にして追加
}
}
});
入力キーバッファは、異なるリス
ナーインスタンス(キーを押した
場合と話した場合)にまたがって
使用されるので、static な List 型
の変数として定義してあります。
キー押したり離したりするリス
ナーのロジックの記述は、Java 8
以降だとラムダ式使ってもいいん
ですが、ここでは使ってません。
思ったよりも、シンプルでしたが
必殺技判定ロジックの if 文ネスト
の闇がやや深いのと、リスナーの
都合でバッファを共有変数として
持っているのがキモイです。
17
そして、Reactor を使ってリアク
ティブプログラミングした方の
昇龍拳ロジックを見てみましょ
う。
リアクティブな昇龍拳ロジック
18
Flux.create(sink -> { // 複数のデータストリームを扱う Flux を採用。FluxSink でデータをバッファに入れます
mainScene.setOnKeyPressed(keyEvent -> { // キー押下時に反応するリスナーの付与
String pressedKey = keyEvent.getCode().toString(); // キーイベントを文字列に変換
sink.next(pressedKey); // 文字列をバッファに追加
});
mainScene.setOnKeyReleased(keyEvent -> { // キーを離した時に反応するリスナーの付与
String releasedKey = keyEvent.getCode().toString(); // キーイベントを文字列に変換
sink.next(releasedKey.toLowerCase()); // 文字列をバッファに追加(離した時なので小文字に変換)
});
}).filter(keyEvent -> { // 方向キーかパンチ・キックキーが押された場合のみ、バッファに追加
String key = ((String) keyEvent).toUpperCase();
return key.equals(UP) || … || key.equals(KICK);
}).bufferUntil(keyEvent -> { // パンチ・キックキーが押下されるまでデータストリームをバッファする
return ((String) keyEvent).equals(PUNCH) || …);
}).subscribe(commandList -> { // パンチキーかキックキーが押下されたら、必殺技判定ロジック実行
String[] cl = {""};
commandList.forEach(keyEvent -> cl[0] += (String) keyEvent); //入力キーバッファの内容を文字列 cl[0] に変換
if (cl[0].contains(SYORYU_CL[0]) || …) { // cl[0] に昇龍拳コマンドが含まれているか?
startAction(3, 17, “shouryuuken.mp3”); // 昇龍拳を繰り出す
} else if (cl[0].contains(HADOU_CL[0]) || …) { // cl[0] に波動拳コマンドが含まれているか?
startAction(4, 14, “hadouken.mp3”); // 波動拳を繰り出す
} else if (cl[0].contains(TATSUMAKI_CL[0]) ||…) { // cl[0] に竜巻旋風脚コマンドが含まれているか?
startAction(5, 27, “tatsumaki_senpukyaku.mp3”); // 竜巻旋風脚を繰り出す
} else if (cl[0].contains(PUNCH)){ // cl[0] にパンチキーイベントが含まれているか?
startAction(1, 8, “punch.mp3”); // 中パンチを繰り出す
} else {
startAction(2, 15, “kick.mp3”); //上述のどれにも該当しなかったら、大キックを繰り出す
}
});
各ロジックを Composable にすっ
きり記述できてうれしいですね!
ノンリアクティブ版ではバラバラ
だったストリームデータをバッ
ファにいれるロジックも、まとめ
て記述できて、バッファ用の共有
変数も特に用意しなくて良いです。
ラムダ式やメソッド参照(ここで
は使ってないですが)、Streams
など積極的に使って、リアクティ
ブストリーマーを目指しましょう
(謎)。
19
ということで、Reactor を使って
リアクティブに昇龍拳を繰り出
してみました!
個人的には、Reactor の他
JavaFX やラムダ式、メソッド参
照、Streams といった Java 技術
の勉強になりましたー。
では、またー。

Más contenido relacionado

La actualidad más candente

.NET Web プログラミングにおける非同期 IO のすべて (Build Insider OFFLINE)
.NET Web プログラミングにおける非同期 IO のすべて (Build Insider OFFLINE).NET Web プログラミングにおける非同期 IO のすべて (Build Insider OFFLINE)
.NET Web プログラミングにおける非同期 IO のすべて (Build Insider OFFLINE)Tusyoshi Matsuzaki
 
Lagopus as open flow hybrid switch
Lagopus as open flow hybrid switchLagopus as open flow hybrid switch
Lagopus as open flow hybrid switchMasaru Oki
 
x86とコンテキストスイッチ
x86とコンテキストスイッチx86とコンテキストスイッチ
x86とコンテキストスイッチMasami Ichikawa
 
Xtend30分クッキング やきに駆動
Xtend30分クッキング   やきに駆動Xtend30分クッキング   やきに駆動
Xtend30分クッキング やきに駆動Shinichi Kozake
 
Reactive Extensions v2.0
Reactive Extensions v2.0Reactive Extensions v2.0
Reactive Extensions v2.0Yoshifumi Kawai
 
Linux Performance Analysis in 15 minutes
Linux Performance Analysis in 15 minutesLinux Performance Analysis in 15 minutes
Linux Performance Analysis in 15 minutesYohei Azekatsu
 
JJUG CCC 2017 Fall オレオレJVM言語を作ってみる
JJUG CCC 2017 Fall オレオレJVM言語を作ってみるJJUG CCC 2017 Fall オレオレJVM言語を作ってみる
JJUG CCC 2017 Fall オレオレJVM言語を作ってみるKoichi Sakata
 
デバドラを書いてみよう!
デバドラを書いてみよう!デバドラを書いてみよう!
デバドラを書いてみよう!Masami Ichikawa
 

La actualidad más candente (9)

.NET Web プログラミングにおける非同期 IO のすべて (Build Insider OFFLINE)
.NET Web プログラミングにおける非同期 IO のすべて (Build Insider OFFLINE).NET Web プログラミングにおける非同期 IO のすべて (Build Insider OFFLINE)
.NET Web プログラミングにおける非同期 IO のすべて (Build Insider OFFLINE)
 
Lagopus as open flow hybrid switch
Lagopus as open flow hybrid switchLagopus as open flow hybrid switch
Lagopus as open flow hybrid switch
 
x86とコンテキストスイッチ
x86とコンテキストスイッチx86とコンテキストスイッチ
x86とコンテキストスイッチ
 
Stream2の基本
Stream2の基本Stream2の基本
Stream2の基本
 
Xtend30分クッキング やきに駆動
Xtend30分クッキング   やきに駆動Xtend30分クッキング   やきに駆動
Xtend30分クッキング やきに駆動
 
Reactive Extensions v2.0
Reactive Extensions v2.0Reactive Extensions v2.0
Reactive Extensions v2.0
 
Linux Performance Analysis in 15 minutes
Linux Performance Analysis in 15 minutesLinux Performance Analysis in 15 minutes
Linux Performance Analysis in 15 minutes
 
JJUG CCC 2017 Fall オレオレJVM言語を作ってみる
JJUG CCC 2017 Fall オレオレJVM言語を作ってみるJJUG CCC 2017 Fall オレオレJVM言語を作ってみる
JJUG CCC 2017 Fall オレオレJVM言語を作ってみる
 
デバドラを書いてみよう!
デバドラを書いてみよう!デバドラを書いてみよう!
デバドラを書いてみよう!
 

Destacado

〜Apache Geode 入門 gfsh によるクラスター構築・管理
〜Apache Geode 入門 gfsh によるクラスター構築・管理〜Apache Geode 入門 gfsh によるクラスター構築・管理
〜Apache Geode 入門 gfsh によるクラスター構築・管理Akihiro Kitada
 
はじめての Cloud Foundry: .NET アプリケーションのはじめ方
はじめての Cloud Foundry: .NET アプリケーションのはじめ方はじめての Cloud Foundry: .NET アプリケーションのはじめ方
はじめての Cloud Foundry: .NET アプリケーションのはじめ方Akihiro Kitada
 
Reactor によるデータインジェスチョン
Reactor によるデータインジェスチョンReactor によるデータインジェスチョン
Reactor によるデータインジェスチョンAkihiro Kitada
 
Apache Geode で始める Spring Data Gemfire
Apache Geode で始めるSpring Data GemfireApache Geode で始めるSpring Data Gemfire
Apache Geode で始める Spring Data GemfireAkihiro Kitada
 
20171118 jjug snappydata
20171118 jjug snappydata20171118 jjug snappydata
20171118 jjug snappydataMasaki Yamakawa
 
「黒騎士と白の魔王」gRPCによるHTTP/2 - API, Streamingの実践
「黒騎士と白の魔王」gRPCによるHTTP/2 - API, Streamingの実践「黒騎士と白の魔王」gRPCによるHTTP/2 - API, Streamingの実践
「黒騎士と白の魔王」gRPCによるHTTP/2 - API, Streamingの実践Yoshifumi Kawai
 

Destacado (6)

〜Apache Geode 入門 gfsh によるクラスター構築・管理
〜Apache Geode 入門 gfsh によるクラスター構築・管理〜Apache Geode 入門 gfsh によるクラスター構築・管理
〜Apache Geode 入門 gfsh によるクラスター構築・管理
 
はじめての Cloud Foundry: .NET アプリケーションのはじめ方
はじめての Cloud Foundry: .NET アプリケーションのはじめ方はじめての Cloud Foundry: .NET アプリケーションのはじめ方
はじめての Cloud Foundry: .NET アプリケーションのはじめ方
 
Reactor によるデータインジェスチョン
Reactor によるデータインジェスチョンReactor によるデータインジェスチョン
Reactor によるデータインジェスチョン
 
Apache Geode で始める Spring Data Gemfire
Apache Geode で始めるSpring Data GemfireApache Geode で始めるSpring Data Gemfire
Apache Geode で始める Spring Data Gemfire
 
20171118 jjug snappydata
20171118 jjug snappydata20171118 jjug snappydata
20171118 jjug snappydata
 
「黒騎士と白の魔王」gRPCによるHTTP/2 - API, Streamingの実践
「黒騎士と白の魔王」gRPCによるHTTP/2 - API, Streamingの実践「黒騎士と白の魔王」gRPCによるHTTP/2 - API, Streamingの実践
「黒騎士と白の魔王」gRPCによるHTTP/2 - API, Streamingの実践
 

Más de Akihiro Kitada

How to configure the cluster based on Multi-site (WAN) configuration
How to configure the clusterbased on Multi-site (WAN) configurationHow to configure the clusterbased on Multi-site (WAN) configuration
How to configure the cluster based on Multi-site (WAN) configurationAkihiro Kitada
 
Reactive Streams に基づく非同期処理プログラミング 〜 Reactor を使ってみた
Reactive Streams に基づく非同期処理プログラミング 〜 Reactor を使ってみたReactive Streams に基づく非同期処理プログラミング 〜 Reactor を使ってみた
Reactive Streams に基づく非同期処理プログラミング 〜 Reactor を使ってみたAkihiro Kitada
 
〜僕の初めてのリアクティブプログラミング Reactor を使ってリアクティブに昇龍拳を繰り出してみた!
〜僕の初めてのリアクティブプログラミング Reactor を使ってリアクティブに昇龍拳を繰り出してみた!〜僕の初めてのリアクティブプログラミング Reactor を使ってリアクティブに昇龍拳を繰り出してみた!
〜僕の初めてのリアクティブプログラミング Reactor を使ってリアクティブに昇龍拳を繰り出してみた!Akihiro Kitada
 
【古いスライド】〜僕の初めてのリアクティブプログラミング Reactor を使ってリアクティブに昇龍拳を繰り出してみた!
【古いスライド】〜僕の初めてのリアクティブプログラミング Reactor を使ってリアクティブに昇龍拳を繰り出してみた!【古いスライド】〜僕の初めてのリアクティブプログラミング Reactor を使ってリアクティブに昇龍拳を繰り出してみた!
【古いスライド】〜僕の初めてのリアクティブプログラミング Reactor を使ってリアクティブに昇龍拳を繰り出してみた!Akihiro Kitada
 
Apache Geode の Apache Lucene Integration を試してみた
Apache Geode の Apache Lucene Integration を試してみたApache Geode の Apache Lucene Integration を試してみた
Apache Geode の Apache Lucene Integration を試してみたAkihiro Kitada
 
Apache Calcite の Apache Geode Adapter を弄った
Apache Calcite の Apache Geode Adapter を弄ったApache Calcite の Apache Geode Adapter を弄った
Apache Calcite の Apache Geode Adapter を弄ったAkihiro Kitada
 
Grafana を使った Apache Geode クラスター監視
Grafana を使った Apache Geode クラスター監視Grafana を使った Apache Geode クラスター監視
Grafana を使った Apache Geode クラスター監視Akihiro Kitada
 
〜Apache Geode 入門 Multi-site(WAN)構成による クラスター連携
〜Apache Geode 入門 Multi-site(WAN)構成によるクラスター連携〜Apache Geode 入門 Multi-site(WAN)構成によるクラスター連携
〜Apache Geode 入門 Multi-site(WAN)構成による クラスター連携Akihiro Kitada
 
My first reactive programming - To deliver a deathblow “Shoryuken” with using...
My first reactive programming - To deliver a deathblow “Shoryuken” with using...My first reactive programming - To deliver a deathblow “Shoryuken” with using...
My first reactive programming - To deliver a deathblow “Shoryuken” with using...Akihiro Kitada
 

Más de Akihiro Kitada (9)

How to configure the cluster based on Multi-site (WAN) configuration
How to configure the clusterbased on Multi-site (WAN) configurationHow to configure the clusterbased on Multi-site (WAN) configuration
How to configure the cluster based on Multi-site (WAN) configuration
 
Reactive Streams に基づく非同期処理プログラミング 〜 Reactor を使ってみた
Reactive Streams に基づく非同期処理プログラミング 〜 Reactor を使ってみたReactive Streams に基づく非同期処理プログラミング 〜 Reactor を使ってみた
Reactive Streams に基づく非同期処理プログラミング 〜 Reactor を使ってみた
 
〜僕の初めてのリアクティブプログラミング Reactor を使ってリアクティブに昇龍拳を繰り出してみた!
〜僕の初めてのリアクティブプログラミング Reactor を使ってリアクティブに昇龍拳を繰り出してみた!〜僕の初めてのリアクティブプログラミング Reactor を使ってリアクティブに昇龍拳を繰り出してみた!
〜僕の初めてのリアクティブプログラミング Reactor を使ってリアクティブに昇龍拳を繰り出してみた!
 
【古いスライド】〜僕の初めてのリアクティブプログラミング Reactor を使ってリアクティブに昇龍拳を繰り出してみた!
【古いスライド】〜僕の初めてのリアクティブプログラミング Reactor を使ってリアクティブに昇龍拳を繰り出してみた!【古いスライド】〜僕の初めてのリアクティブプログラミング Reactor を使ってリアクティブに昇龍拳を繰り出してみた!
【古いスライド】〜僕の初めてのリアクティブプログラミング Reactor を使ってリアクティブに昇龍拳を繰り出してみた!
 
Apache Geode の Apache Lucene Integration を試してみた
Apache Geode の Apache Lucene Integration を試してみたApache Geode の Apache Lucene Integration を試してみた
Apache Geode の Apache Lucene Integration を試してみた
 
Apache Calcite の Apache Geode Adapter を弄った
Apache Calcite の Apache Geode Adapter を弄ったApache Calcite の Apache Geode Adapter を弄った
Apache Calcite の Apache Geode Adapter を弄った
 
Grafana を使った Apache Geode クラスター監視
Grafana を使った Apache Geode クラスター監視Grafana を使った Apache Geode クラスター監視
Grafana を使った Apache Geode クラスター監視
 
〜Apache Geode 入門 Multi-site(WAN)構成による クラスター連携
〜Apache Geode 入門 Multi-site(WAN)構成によるクラスター連携〜Apache Geode 入門 Multi-site(WAN)構成によるクラスター連携
〜Apache Geode 入門 Multi-site(WAN)構成による クラスター連携
 
My first reactive programming - To deliver a deathblow “Shoryuken” with using...
My first reactive programming - To deliver a deathblow “Shoryuken” with using...My first reactive programming - To deliver a deathblow “Shoryuken” with using...
My first reactive programming - To deliver a deathblow “Shoryuken” with using...
 

【古いスライド】〜僕の初めてのリアクティブプログラミング Reactor を使ってリアクティブに昇龍拳を繰り出してみた!