カテゴリー : プログラミング

LG G Watch購入とアプリ作成まで

どうも、hide92795です

テスト勉強よりアプリ開発がはかどる今日このごろです。

そしてどうやらOculusRift DK2も配送が始まり、第一陣が既に日本に到着しているようで。

羨ましい限りです。

(夏終わりまでには届いてほしいなぁ・・・)

ーーー

さて、タイトルの通り、LG G Watchを買いました。

本当はmoto360を買う予定でしたが、1つ作ってみたいアプリが出来てしまったため、思わずポチってしまいました

画像はおそらく自分が撮るよりいい感じに撮られているのがたくさん存在するのでそちらを

また、LG G Watch購入に合わせてAndroidWearを動かす環境であるAndroid4.3位上の端末が必要になったため、Nexus5(レッド)も購入しました。

(Nexus7があるので、そっちでも動かせはしますが、持ち運びする際にはやっぱり軽い方がいいというのと、スマホサイズのリファレンス機が欲しかったという理由で買いました。)

ーーー

作りたかったアプリというのは、コミケ用のアプリで、マップ表示と道順表示をしてくれるという感じのやつです。

去年の夏コミはコミケ雲ができるほど暑くなり、カタロムから印刷していったマップは汗でインクが滲み、最後の方はもうぐっちゃぐちゃでした。

Android用のカタロムビューワーとしてはAndCCVがありますが、まぁ、あの環境で歩きスマホできるわけもなく。(見かけた人の中には首からタブレットを下げてる人もいました。)

というわけで、開発期間3週間弱(+バイトで時間半減)というタイムリミットの中アプリを作ろうじゃないかということになりました。

ーーー

既に色々なサイトでAndroid Wear用のアプリの作り方は紹介されているとおり、Android Wearから開発環境は大きく変わることになりそうです。

まず、eclipseのプラグインとしてのADTの開発は続けられているものの、現時点ではWear向けに最適化されているとは言えない感じです。

公式のページにもあるように、AndroidStudioを使って開発する感じになります。

もちろん、Androidアプリの開発専用にカスタムされているので、その面で不自由することはほとんどありませんが、

まぁ、eclipse使っていた身としては急に「こっち使ってね」と言われたようなものであります。

ーーー

そんなわけでAndroidStudioをインストールし使い始めたわけですが、AndroidStudioを使っていてきっついなぁと思ったのが

1. Mavenスタイルのプロジェクト配置

2. 全部英語

です。

まぁ、両方慣れろで済まされる話ですが・・・ どうもMavenのファイル配置に慣れません。。。

逆に良かったなと思う点は、レイアウトいじる時にエラーが出なくなったってことですかね

ADTは毎回起動するたびに何らかのエラーで描画できないことがあったので

それがなくなっただけでも非常に快適です。

ーーー

肝心のアプリ作成ですが、プロジェクト作成時にWearにチェックを入れれば、Wear同梱アプリとしてひな形を作ってくれます。

ただし、WearのメインのActivityがエラーを吐いてくれるので、継承元をInsetActivityにした上で、onReadyForContentにonCreateの中身を全部移動させれば問題ありません。

また、少し引っかかった点としては、WatchViewStubに対して設定したリスナーのonLayoutInflated内部じゃないとfindViewByIdが出来ないっていう点ですかね

他の部分は今までのAndroidアプリとほぼおなじ感覚で作れる感じがしました。

ーーー

作ったアプリは公開するとしたらおそらく夏コミ後です。

現状だと、サークルリストのデータ作成に人の手間がめっちゃ掛かる仕組みになりそうなので、、、

ではノシ

[Java][Android]角丸なウィジェットの背景色を変える

どうも、hide92795です

ウィジェットを作っている時に、角が四角だとどうしても刺々しさが出てしまうので、丸角にすることにしました。

初めはWidgetのレイアウトの背景にxmlで作ったShapeを指定していたのですが、その背景色をユーザーが自由に変えられるようにしようとしたところ案外ハマってしたのでメモ


Xmlで作成したShapeなDrawableはGradientDrawableとして取得することが出来ます。

しかし、基本的にDrawableはそれを作成したContextと結びついているため、ウィジェットで使うRemoteViewには適用できません。

(BitmapDrawableは内部にBitmapを持っているのでgetBitmap()で取得することが出来ます。)

悩んだ挙句、ImageViewのColorFilterという方法を思いつきました。

ただし、ColorFilterをxmlリソースのDrawableに適用するには結局Drawableをセットしなければいけないので、画像リソースのものを用意する必要があります。

また、この方法で出来るのは単色指定のみです。グラデーションの指定はできないと思います。

background_widget.9

↑が今回背景に使用する9Patch画像です。

ウィジェットのレイアウトxmlはこちら

RelativeLayoutを使用し、再背面に背景として使用するImageViewを設置します。

そして、RemoteViewを作成する部分で

このように透明度と色を指定します。

setAlpha(int color)はAPI11から非推奨になっていますが、引数がfloatの方が何故か動いてくれなかったので仕方なくこちらを


ひとまずはこれでうまく行ったので良しとしましょう

しかし、RemoteViewはなんとも言えない使いにくさが(´Д`)

ではノシ

 

JavaとJavaScriptでRSA鍵交換とAES暗号化

どうも、hide92795です。

Bukkit RemoteControllerのBukkitDev上に「iPhone(WinPhone)のも作ってくれ」という要望が結構あったので、本来は来年にMacを買ってからネイティブアプリとして作る予定でしたが、なんか審査に通らない気がしてきたので、Webアプリとして作ることにしました。

JavaScriptなにこれ?おいしいの?状態からのスタートでしたが、なんとか1週間でメインの通信可能な状態まで持って行くことが出来ました。

というわけで、今回はそこでやっていたJavaとJavaScript間での暗号化について書いていこうと思います。


自分の実装ではサーバー側がJava、クライアント側がJavaScript、

Java側でRSA鍵を生成、RSA公開鍵をJavascriptへ送信、Javascriptで生成したAES共通鍵をRSAで暗号化して送信、Java側でそれを復号という手順になっています。

また、通信の方法はWebSocket(Java側はTooTallNate/Java-WebSocket、JavaScript側はデフォルトのもの)を使っています。

まず、Java側でのRSA鍵の生成から

WebSocketで通信する際には、普通の文字(String)で送信できるので、ModulesとPublicExponentを16進数の文字列表現に変換して、コロンでつなげています。

次に、JavaScript側でのAES鍵作成とそれの暗号化へ

JavaScript側での暗号化では、RSA暗号化に以下のものを使用します。

  1. RSA and ECC in JavaScript : http://www-cs-students.stanford.edu/~tjw/jsbn/
    • jsbn.js, jsbn2.js, prng4.js, rng.js, base64.jsを使用
  2. A Client-Side JavaScript RSA Encrypter : http://www.peterrowntree.com/?d0=papers/clientRSA
    • rsa.jsを使用
  3. crypto-js : http://code.google.com/p/crypto-js/
    • aes.js, pbkdf2.jsを使用

AESキーはPBKDF2でランダムに生成(random_strは指定された文字数の英数字文字列を返す関数)

受信した文字列をコロンで区切って、それからRSAKeyを作成。

rsa.encryptで返されるのは、16進数文字列なので、crypto-jsでBase64に変換

Base64に変換したものをJava側に送り返します。

ちなみに、この部分をJavaで行うと、こんな感じになります。

違いは、AES鍵を生成する際にUUIDを使用しているくらいですかね

次はJava側での復号化

ここで出てきたbyte[] keyがAES暗号鍵です。


ここからはAESを使った暗号化です。

まず、Java側での暗号化はこんな感じです

モードがAES/CBC/PKCS5なので、IVを送る必要があります。

このIVを送るために、IVと暗号化したデータをそれぞれBase64で符号化、連結しているので多少ややこしくなってしまっています。

(Java同士の実装だと、byte[]を連結させればよかったのですが、JSと組み合わせた時にIVの長さが15byteになったりと不都合があったのでこうなりました)

次に、Java側での復号化

まぁ、暗号化とは逆な感じですね。

最初にコロンで区切ってあるIVと暗号文を分け、それぞれを復号、交換したAES鍵を使用して復号化といった感じです。

次はこれを作り始めて一番時間がかかったJavaScript側の実装です。

まずは暗号化のほうから

やっている事は

  1. 暗号化するデータをWordArrayに変換
  2. IVをランダムに生成
  3. データを暗号化
  4. IVと暗号化したデータをそれぞれBase64化
  5. それらをコロンでつなげる

と言った感じです。

最後は復号化の部分です

一番の謎は、CryptoJS.AES.decryptに渡すencryptedの中身にivとkeyを渡さないとエラーが出るということです。


JavaScriptは引数にどのクラス?の変数を渡していいのかがわかりにくいのでもう大変でしたw

あとthisの仕組みが未だによくわからん(´・ω・`)

まぁ、とりあえずは動いているので、細かな修正は色々組み上げて大分わかってきてからにしましょうかね

ではノシ

トランジションをどうするか

どうも、hide92795です。
自作ゲームフェスの方は残念ながら落選となってしまいました。
どうやらツール部門は受賞なしだそうで驚いていますw
今回のお題は「トランジション(画面遷移エフェクト)」です。
デフォルトでもフェードだったりの基本的なものは搭載しますが、既存のノベルゲームエンジンで有名な吉里吉里さんの方では、画像を用いたトランジションが出来るようになっています。
白黒の画像(ルール画像)の濃淡で順番に表示・非表示する といったものですね。
この機能は非常に優秀なので是非リスペクトしたいと思っていますが、なんせどう実装すればいいのかわからない・・・
個人的な決め事で「既存のノベルゲームエンジンのソースは(出来る限り)見ない」というのを決めているので・・・
というわけで色々考えてみたわけですが、一番しっくりした方法を書いてみようと思います
パフォーマンスは非常に悪そうで、さらにサンプルソースすら書いてませんけどねwww


①ルール画像の濃淡を8bitに直し、0.0~1.0の間に割り当てる
②全ピクセルの濃淡だけを抽出し、Client用に保存
③Client側で、②で保存したものを読み取り、①の数字をZ軸にしてVBOを作成
④トランジション実行中にVBOをデプスバッファのみ有効で書き込む
⑤フォグで指定範囲より奥にあるピクセルに霧をかけ、アルファ値が下がってるような感じをする
⑥指定範囲の閾値を時間ごとに変えていく
これが1週間ほど悩んだ結果に出された案です
非常に気がかりなのが③のVBO作成時に頂点数がバカにならない数になってしまう(800*600で48万)ということです
アルファテストとかでがんばろうかと思いましたが、閾値から完全に見えなくなるまでの範囲の濃淡をどうするか
という問題にぶち当たり没になりましたw
サンプルソースでパフォーマンスが非常によろしくなかった場合には禁じ手のソース閲覧を使うしかないのかなぁ・・・・
(ちなみに今まで見たことありません)
サンプル書くのも非常に大変・・・・
けどそれが楽しいんだけどねww
ではノシ

 

[Java&LWJGL]OGGをストリーム再生出来ない時がある

どうも、hide92795です
エンジンの作成を進めていた時にBGMなどの長めの音声を生成する際にやけに処理が重くなっているのに気づきました。
(ちなみにSoundlyという外部APIを使っています)
調べてみたところ1-2秒も処理がかかっていました・・・
①この時の仕組みはCipherInputStreamから内容すべてをbyte[]に格納
②ローダーに渡してXSound生成
という感じでした(考えてみればMB級のファイルをすべて読み込むというのはすごく非効率)
1は別スレッドで行なっているので問題なかったのですが、2で時間がかかっている模様・・・
Javadocを眺めているとXStreamingSoundというクラスが有り、URL指定でストリーミング再生が出来るとのこと
実際にそちらの方で簡単にプログラムを作ってみたところ0.002秒ほどで2と同等の処理が終わりました
しかし、実際に使うとなるとCipherInputStreamをかませなければ暗号化されているので読み込めない・・・
というわけでSoundlyを改造してInputStreamも引数に取れるように改造しましたw
SoundlyはGPLv3なのでこちらで公開しています。
しかし、ここで新たな問題に直面しました
特定のOGGファイルだけ再生が開始できなくなってしまうという現象が発生するようになってしまいました(´・ω・`)
そのファイルとは
softalk及び棒読みちゃんなどのゆっくりボイスです
テスト用に適当に見繕ったのですが、自作・ニコニコモンズ上のもの両方でダメでした
また、改変したInputStreamの引数ではなく元々のURL指定でもダメでした。
ちなみにストリーミングせず従来の方式ではちゃんと再生されました
変換には同じソフト同じ設定でやっているので差異は無いはずなんですが(そもそも従来方式では再生できていたので再生自体は出来るはずなのに。。。。)
誰か情報を知っている人がいれば教えていただけると助かります><
とりあえずデフォルトはストリーミング、ファイル作成時にユーザーが従来方式のも選べるようにしておきますかね・・・
ではノシ

[Java]LWJGLで動画再生

どうも、hide92795です
ゲームエンジンの作成にあたり、結構悩んでいたのが動画再生についてです。
Javaで動画再生といえばJMFを使用したものが有名ですが、プラットホームごとのインストーラーがあったり、プラットホームに依存しないバージョンだと対応フォーマットが皆無に等しかったりといろいろと難点があったのです。
さらにLWJGLではSwing上にて動作自体はできるものの、JMF用のPanelに切り替えた時にどんな問題が発生するかわからないなど結構なリスクがありました。
そこでグーグル先生で色々調べていたところ、
http://www.java-gaming.org/index.php?topic=24846.30
↑のサイトを見つけました。この中の画像が貼り付けられている投稿に書かれているURL
http://www.java-gaming.org/?action=pastebin&id=23
こちらにはソースコードが書かれています。
投稿があったスレッド名は「VLCJ in OpenGL / LWJGL」です。
このVLCJというのはVLCPlayerの機能をJavaで使えるようにしているライブラリです。
VLCJ – http://www.capricasoftware.co.uk/vlcj/
ではまず下準備から
今回はWindows&Eclipse使用を前提としています。
1.必要なライブラリ等
・LWJGL
・VLCJ(↑のURLからDL出来ます)
・JNA(jna.jar, platform.jar)(VLCJのダウンロードページにリンクがあります。)
・libvlc.dll&libvlccore.dll(VLCのインストールディレクトリにあります)
2.ソースコード
基本的には先程のURLのソースですが、一部修正をしてあります。

修正箇所はmainのはじめに書かれている行です。
jarに対してネイティブライブラリの登録をしたのですが、何故かダメだったので直接ソースコードに。
あとは、再生したい動画ファイルをクラスパス直下において、

のop00.mpgの名前を変え、フィールドの一番上にあるWIDTHとHEIGHTの値を変えるだけです。
lwjgl_movie
↑RewriteのOPを拝借して再生してみましたが、問題ありませんでした。
基本的にVLCで再生出来るものなら問題ないと見て大丈夫でしょう。
ではノシ

[Java]暗号化しながらストリームで書き出し&読み込み

どうも,hide92795です
夏休みの補習っていうのがね(´・ω・`)
ホント辛いですよw
今回はノベルゲームのエンジンに搭載予定の暗号化システムについて
使用する暗号化方式はAES、モードはPCBCです。
PCBCというわけで、復号化の際にはIVというのが必要になります。
IVは暗号化の際に取得できるのでそれをどうにか復号化の際に使える状態にしなければいけないのですが、
今回はこちらのサイトにて紹介されている方法である
「ファイルの先頭にIVを引っ付ける」
という方法で行きたいと思います。
まずは暗号化

上から順に解説すると
1.暗号化するファイルのFileInputStreamを生成
2.暗号化に用いるKeyを作成(鍵は16文字のStringみたいです)
3.AES/PCBC/PKCS5PaddingにてChiperを作成&初期化
4.出力先のFileOutputStreamを作成
5.↑をCipherOutputStreamで包む
6.FileOutputStreamにIVを書き込む
7.CipherOutputStreamに暗号化するデータを書き込む
となります。
今回はIVを平文の状態で書かなければいけないのでFileOutputStreamの方に書き込みます。
続いて復号化

こちらも上から順に
1.Keyの生成
2.暗号化したファイルのFileInputStreamの生成
3.IV用のbyte配列を作成
4.FileInputStreamからIV部分を3の配列に読み込み
5.Chiperを生成
6.4で読み込んだIVからIvParameterSpecを生成
7.6を使ってChiperを初期化
8.CipherInputStreamでFileInputStreamを包む
残りはChiperInputStreamで読みこむなりまた別のStreamに渡すなりしておkです
実際に暗号化してみたのが下の画像
crypt_sample
左が暗号化前、右が暗号化後
JPEGなので左ではExif情報があらわになっていますが、右では全く読めなくなっていますw
ファイルサイズは殆ど変わらず、暗号化後が8バイト増えただけでした
ちなみに、ファイルを圧縮したい場合は、FileOutputStreamをZipOutputStreamで包んだ(new ZipOutputStream(fis)みたいに)ほうが圧縮率がいいらしいです。
ではノシ

マイクラのMODとか

どうも、hide92795です
とあるマルチ鯖で出会った人たちとわいわいがやがややってるのですが、実況しようぜということになり、鯖を作ることになりました。
最初は工業御三家くらいと少なめの構成だったのですが、Wikiを見てこれを入れてみようあれを入れてみようとやっているうちに導入MODの総計が50を超えましたw
その時に自分が体験した予想外のMOD干渉について書こうと思います。
①MODを増やしても減らしてもいないのに突然起動しなくなった
普通は設定だったりワールド破壊らへんを想像する(実際そうだと思ってた)のですが、
再度1から全部揃えるとちゃんと起動する
その設定を前のに移したら起動しない
学校でずっと考えてましたわ(´・ω・`)
ちなみに正解は「ファイルの順番」でした
modsに入れたzipのファイルの順番が違うだけで起動できなくなることがあるようです・・・
②BlockIDを拡張分に移すと起動しない
これはよくある話ですね
大抵は別のMODのブロックのIDをずらしてそこに埋め込む
というのが基本的な解決方法だと思います。
まぁ、エラーが起きなくてもおいた瞬間に別のブロックに化けたり
SunLightMODではブロックを置いた瞬間にそのブロックの下から核発電機が登場したり
初めて見た時はビビりましたって(´・ω・`)


MOD制作について少し
自分が非公式に更新しているHangableMapsというMODを作っていての経験談を

これはMapを右クリックで壁に貼り付ける時のソースです
ただし、このソースにはバグがあるようなのです。
ちゃんとしたソースはこちら

上のソースだとシングルで複数枚のMapを持っていた時に一気に全部消費します。
なんかもう何がなんやらという感じです。(ちなみにまだ間違っている箇所はわかっていませんw)
他にもSecretRoomsModのOne-WayBlockにて、
このブロックは一面だけが近くにあるブロックの対応する面のテクスチャに化けます。
ただし内側から見た時はテクスチャが見えなくなります。
つまり一方通行(OneWay)的に見えるブロックということです。
このMODのフォーラムでは、Forgeの最新版を使えと書いてあるのですが、DLリンクを見るに3.1.3.105が推奨バージョンのようです。
しかし、このバージョンは既に古く、他の様々なMODがModLoader、AudioMod,4096ブロック対応化MODなどの機能を搭載している3.3.7.***が必須になってきたりしています。
このMODにもその影響が及んだらしく、最新版のForgeではOne-Wayブロックの一方通行的な見え方がしなくなってしまいます。(内側から見ても透過されない)
早速修正に取り掛かって原因(?)を発見(もしかしたら別のところかもしれないけどとりあえず治った)、早速再導入してみたところ
やっぱり透過されない
けど、Forgeオンリーの環境に入れるとちゃんと動作する
つまりは他のMODとの干渉だなと思い、MODを1つづつ追加しながら検証
結局最後のMODを入れた後もちゃんと動作しちゃったよ
最初と違うのは「ワールドを新しく作っている」という点
結局それで解決しましたww
まだ近くにいると透過されないとかのバグがあるからそれも直さないとね
なんかだらだら書いた割にはどうだっていいことばっかりな気がしますがw
ではノシ

プラグインはほどほどに

どうも、hide92795です
Java系のプログラムの開発にはEclipseという開発環境(IDE)を使っています
自分の環境では、エディタ部分のフォントに「MS ゴシック」を使っています
「プログラミングには等幅フォント」って言われている(?)ように、
フォントがプロポーショナル(可変幅)だとなんとなく落ち着かないのですww
というわけで、Eclipseを使い始めてからずっとMS ゴシックを使っています。
等幅フォントなのでちゃんと縦に見た時に揃っていてくれていたはずなのですが・・・
何故かずれているorz
というわけでぐぐったところ、
エディタ内部に太字の文字(new, classとか)があるとずれるらしい
たしかに太字のところでずれている・・・
というわけで解決策として出ていたJStyleというプラグインを導入
そこまでは良かったのですよ・・・・
JStyle導入後、Eclipseを起動させようとするとやけに時間が掛かる(-cleanのせいだと思ってた)
数分待っても起動しないのでスプラッシュ画面をクリックしたら白い靄がかかった!?(つまりは反応なしww)
数回やっても起動しないのでJStyleのプラグインを抜くことに
READMEの通りに抜いても起動しねぇ・・・orz
というわけで泣く泣く旧環境を捨て、新しく環境を揃えることに・・・
ちょうど新しいバージョン(3.7.2 旧環境は3.7.1)が来てたのでまぁいっかと思ってたら
6月くらいにバージョン3.8が来るらしい(´・ω・`)
まぁ、仕方ないねw
教訓として「プラグインはほどほどに」というわけですw
(JStyleが既存のファイル書き換え型だったっていうのもあるけどねw)


これより先は自分の環境やら入れているおすすめのプラグインやらの紹介なのですー
(ちなみにまっさらな状態のEclipseにJStyleだけ入れても起動しなかったよ(´・ω・`))
基本環境はEclipseの公式サイトでDL出来る
「Eclipse IDE for Java Developers」
http://www.eclipse.org/downloads/packages/eclipse-ide-java-developers/indigosr2
ってやつに日本語化プラグインである
「Pleiades」
http://mergedoc.sourceforge.jp/
の単体版を導入したもの
フォントは「Consolas」に
「Miguフォント(Migu 1P)」
http://mix-mplus-ipa.sourceforge.jp/migu/
をフォントリンクさせたもの
(ただし、EclipseでConsolasにフォントリンクさせるにはなぜかMicrosoft Sans Serifに対して
フォントを登録させないといけないみたい。
さらに、ただ登録させただけだと、日本語フォントが小さくなってしまうので
登録させる時に「migu-1p-regular.ttf,Migu 1P,128,85」のようにスケーリングをさせないとダメだった)
フォントリンクの方法に関しては、レジストリをいじる作業なのでここでは書きません。
ここからがEclipseへのプラグインの紹介です
説明としては簡単にしか書いていないので、使い方やその他もろもろは自分で調べてください。
「更新サイトに登録」とあるものは「新規ソフトウェアのインストール」からインストール出来るもの
「自分で追加」とある物は自分でプラグインをダウンロードして「plugins」フォルダに入れるものです
1.Android 開発ツール
更新サイトに登録

http://dl-ssl.google.com/android/eclipse/

Androidアプリの開発には欠かせないものです。
2.FindBugs
更新サイトに登録

http://findbugs.cs.umd.edu/eclipse/

ソース内にあるバグを見つけてくれる。
3.QuickREx
更新サイトに登録

http://www.bastian-bergerhoff.com/eclipse/features/

正規表現のテストを行える
4.Explore It
更新サイトに登録

http://www.strippers.jp/eclipse/updates

パッケージ・エクスプローラーから右クリックで対象のフォルダを開ける
5.AnyEditTools
更新サイトに登録

http://andrei.gmxhome.de/eclipse/

エディタ上で様々な変換(半→全などなど)を行える
6.FileBookmark Plugin for Eclipse
自分で追加

http://sourceforge.jp/projects/filebookmark/wiki/FrontPage

Webサイトやファイルへのリンクをブックマーク風に登録できる
今の環境はこんな感じです
ではノシノシ

 

アプリの現状とか

どうも、お久しぶりです。
hide92795です
テストやらなんやらで久々の更新となりますww
まず、Twit Syncの新バージョンについて
GUIを1から作りなおしたので、だいぶ時間がかかりましたが、9割がた完成といったところです。
ただ、Twitter4jの仕様変更で、今まで使ってたメソッドがDeprecatedになってしまったので、代替メソッドを使おうと思っているのですが、それが見つからず・・・・
おそらくgetFriendsIds()でIDsを取って、それをlookUpUsers()にぶち込めばいいはずなんですけど、なぜかエラー。。。。。
どうしてもわからなければT4Jのメーリングにポストすることにします。。。。
次、Twit Time for Android Pro
こちらも9割方完成ですが、LVLの仕組みが全く理解出来ない・・・・・orz
別にLVLは搭載しなくてもいいのですが、Pro版に手を出したのもこのLVLの勉強の一環だからね・・・
最後、ノベルゲームのエンジン
こちらはすこしずつですが進行しておりますww
今はウェイトカーソル(1ページ分の文字を表示し終えたあとに表示されるアレ)が完成したところですww
https://github.com/hide92795/NovelEngine-Client
に時々プッシュしてるので、暇があったら見てみてくださいww
ではノシノシ