Vue.js+VuexでFlashメッセージコンポーネントのサンプルを書いてみました
今回はVuexのお勉強もかねて、FlashメッセージをVue.js+Vuexで書いてみました。 というのも、今開発をすすめている「みんなでつくるダンジョン」はVue.jsを使って作っているのですが、「保存しました!」とか「通信中です」などのメッセージを出したくなったのでした。
つくったもののデモは以下にあります。リンク先に「Show Flash Message」ボタンが3つあるので押してみてください。
https://piyoppi.github.io/samples/vue-flash-message-sample/
このようなメッセージはいろいろなコンポーネントから呼び出したくなったりするのですが、各コンポーネントから$emit
して値のやり取りをするのは大変です。
ということで、Vuexに慣れる意味も込めてVuexで作ってみることにしました。
Vuexについては本家日本語版ドキュメントに詳しくあるので、これを読んで理解しました。(日本語ドキュメントありがたや~)。 Vue.jsはコンポーネントに状態を持てますが、ものによっては状態を共有したい場合も出てきます。propsやemitをつかっての状態共有もできないことはないですが、規模が大きくなると状態の紐づきを管理するのが大変になるので、共有すべき状態について管理するためにつかうライブラリがVuex(という理解)です。
Vuexには「State」「Getter」「Mutation」「Action」の4つの要素があり、それぞれ以下のような役割があります(という理解をしています)。
- State: 共有したい状態(変数)を保持するところ
- Getter: Stateを加工して返すことができるもの(Stateを足したり割ったり文字列連結したりした値を欲しい時に使う)
- 特に加工が必要ない場合は直接Stateから値をとることもできる
- 今回は使っていません
- Mutation: Stateを更新することができるメソッドたち
- こいつが唯一Stateを更新できる
- 更新したいときは
this.$store.commit('Mutation名', 値);
みたいにする
- Action: Mutationを呼び出して何らかの処理をするためのメソッドたち
- Action内でMutationを呼び出して状態を更新したりする
- Actionを呼び出すときは
this.$store.dispatch('Action名', 値);
みたいにする - Mutationでは非同期処理ができないが、Actionではできる(ここがポイントみたい)
- 単純なStateの更新ならMutation経由でもできるし、複雑な(?)処理を経てStateを更新したいときはMutationを呼び出す命令を書いたActionを実行する
基本的にVuexのこれらの要素にはどのコンポーネントからも簡単にアクセスできるようにすることができます。 また、Stateが変更されれば各コンポーネントでStateを参照している箇所も更新されるので、State(状態)の共有ができます。
今回のサンプルソースはこちら。 github.com
VuexのActionをつかって表示メッセージを受け取る
FlashメッセージにつかうState,Mutation,Actionはこのように定義しました。showFlashMessage
をディスパッチすることで、必要な値がmutation経由でstateに反映されます。
# src/components/noticeMessageBox/noticeMessageBoxStore.js export default { state: { text: '', mode: 'processing', visible: false, timeoutId: -1, }, mutations: { setMessage: (state, payload) => { state.text = payload.text; state.mode = payload.mode; state.visible = true; }, setMessageVisible: (state, value) => state.visible = value, setMessageTimeoutId: (state, value) => state.timeoutId = value, clearMessageTimeoutId: (state) => state.timeoutId = -1, }, actions: { showFlashMessage: ({state, commit}, message) => new Promise((resolve, reject) => { //timeoutId !== 1 のときはVisibleを変更するsetTimeoutが生きているのでキャンセルする if( state.timeoutId !== -1 ) { clearTimeout(state.timeoutId); commit('clearMessageTimeoutId'); } commit('setMessage', message); if( message.duration > 0 ) { //durationだけ時間が経ったらVisible=falseとする(メッセージを隠す) const timeoutId = setTimeout( () => { commit('clearMessageTimeoutId'); commit('setMessageVisible', false); return resolve(); }, message.duration); commit('setMessageTimeoutId', timeoutId); } else { return resolve(); } }) } }
上記定義をVuexオブジェクトをインスタンス化する際に読み込んであげます。
# src/main.js import Vue from 'vue' import Vuex from "vuex" Vue.use(Vuex); import noticeMessageBoxStore from "./components/noticeMessageBox/noticeMessageBoxStore.js" import appOptions from './main.vue' let store = new Vuex.Store({ modules: { noticeMessageBoxStore } }); // src/main.vueをdist/index.htmlのapp-entrypointにマウントします window.addEventListener("load", ()=>{ const app = Object.assign(appOptions, { el: '#app-entrypoint', store: store //storeを注入する(後述) }); new Vue(app); }, false);
使うときのイメージはこんな感じ。textにメッセージを設定し、Durationに表示時間(ミリ秒)を設定します。modeは見た目を変更するための文字列(後述)です。
this.$store.dispatch('showFlashMessage', {text: 'Message!', duration: 4000, mode: 'done'});
Flashメッセージコンポーネントの定義はこんな感じ。先ほどのstoreを見て、変更がリアルタイムにコンポーネントに反映されるようにしています。表示・非表示切り替えはcomputedに記したスタイルで定義します。 (this.$storeをつかうには、ルートコンポーネントでstoreを注入する必要があります。)
storeのmodeに応じて適用するスタイルシートのクラスを変えることで、Notice、Warning、Errorなどの見た目を変えることができます。
# src/components/noticeMessageBox/noticeMessageBox.vue <template> <div class="msgbox-outer" :class="outerClass"> {{ $store.state.noticeMessageBoxStore.text }} </div> </template> <script> export default { computed: { mode: function() { return this.$store.state.noticeMessageBoxStore.mode; }, visible: function() { return this.$store.state.noticeMessageBoxStore.visible; }, outerClass: function() { return { darkblue: this.mode === "processing", lightblue: this.mode === "done", red: this.mode === "error", hidden_bottomside: !this.visible && !this.isTopside, hidden_topside: !this.visible && this.isTopside, show_bottomside: this.visible && !this.isTopside, show_topside: this.visible && this.isTopside, topside: this.isTopside } }, //(以下略) </script>
あとは、コンポーネントのテンプレートに以下のように書き、componentsにコンポーネントを登録してあげればどのコンポーネントからもFlashメッセージを表示させることができるようになります。
# src/main.vue <notice-messagebox></notice-messagebox>
こんなかんじにVuexとVue.jsをくみあわせて作ることができました。もうちょいとVuexと戯れて、開発の効率が良くなると良いなぁとおもっています。 ではではー。
「ここちがうよ!」とか「ここはこうじゃないの?」みたいな建設的な技術的ツッコミは歓迎しますので、ぜひー。(わたしも自信があるわけではないので。。。)
マップ同士の接続をどうするか問題を考えてみた
みんなでつくるダンジョン(仮称)はマップ同士の接続によって無限に広がるマップを楽しめるよ!!というのがコンセプトなわけですが、ここで じぶんのマップと他の人のマップをどのように結べばよいかという点が難しいなと思った次第です。
ここでいう難しさとは、プログラミング的に難しいなどの実装面の話ではなく、どのようにユーザー同士で合意をとってマップを接続してもらうかというところ。
基本的に、マップAとマップBは以下のように相互に行き来できるようにするので、マップAにマップBの接続設定をすると、それはマップBからマップAに接続設定をするのと 同じことになります。このとき、マップAとマップBの持ち主が異なるとき、どのように合意を取ってもらい相互に接続してもらうかが問題になります。
たとえば以下のような案が考えられそうです。
マップの持ち主に許可をもらって接続する(承認制)
マップAの所有者がマップBの所有者に「接続したいぞー」とリクエストを出し、マップBの所有者が許可を出した場合に接続を許可するというもの。 これでもよさそうなのですが、マップAの所有者が断られてしまうと面白くないだろうし、マップBの所有者も断りづらくなって、いろいろと 上手くいかなくなるのではないかなという気持ちもします。
先着順で自由に接続できるようにする
マップAの所有者は、マップBが空いていたら許可などを経なくても接続できてしまうというもの。ただ、マップBの所有者が他のマップと 繋ぎたいと思っていた場合に、マップAの持ち主に勝手に繋がれてしまうと面白くないかもしれません。
みんなでつくるダンジョンのコンセプト的には、基本的にはマップはどんどん相互接続されて広くなっていってほしいので、これくらいの接続の気軽さや自由さが欲しいところですが、 マップはいわば制作者の作品でもあるので、それらを勝手に接続されてしまうというのはイマイチなのかもしれません。
んー、むずかしいですね。。。
「接続用のマップ」を用意して自由に接続できるようにする
じぶんの作ったマップが他のマップと気軽につなげられるように、「接続用のマップ」を用意してあげる方法です。接続用のマップはいくつかの「コネクタ」を持っていて、 空いているコネクタとじぶんのマップを自由に接続できるようにするというものです。
このようにすることで、「気軽に接続したい!」という要望と、「勝手に接続されては困る」という点をなんとか解決できるのではないかなぁと思っています。 はじめのうちは接続用マップは運営側で用意してあげる方向でよいかなと思っていますが、ゆくゆくはユーザーのみなさんで「接続用マップ」も作られるようになればいいなと 考えています。
もちろん、マップAの所有者とマップBの所有者が合意して相互に接続できる、みたいな機能も欲しいところなので、その辺は別途考えるとします。 (コネクタにパスワードをかけられるようにして、接続の際にパスワードを要求するなどを考えています)
開発報告(5/11)
おひさしぶりです。相変わらずちまちまと開発しているので、進捗報告をばをば。 先月からの大きな進捗は概ね以下のような感じです。
「みんなでつくるダンジョン」の進捗報告
ほかのマップへ移動できるようになった
ほかのマップに移動できるようになって、ようやくやりたいことの骨組みができ始めてきたぞー、という気持ち。 こんなかんじにマップに「コネクタ(仮称)」とよばれるブロックを置き、接続先のコネクタを選んであげるとマップ間移動ができるようになります。
まだまだ作り立てほやほやなこともあり、UIは微妙な感じですが、これからもうちょっとカッコ良くしていきたいなと思っています。
いまは自分のつくったマップのみ接続先として設定できるようになっていますが、これから他の人が作ったマップとも接続できるようにしていきます。
あたり判定を改善した
あたり判定を改善して、アバターの位置補正処理(壁や床に当たったときに止めたりする処理)がよくなりました。
いままでは、以下のように接触部分をバネ・ダンパーモデルっぽくしてあげて、マップに拘束された(動かない)物体にめり込まないように アバターの跳ね返り処理を行っていました。めり込み量とばね定数からなるばねの反発力を使って、アバターなどの「固定されていないオブジェクト」の 位置を補正します。
こうすることで、複数の物体が重なったり押し込まれたりした場合についても、ばねの反発力が作用しあうことで位置補正が自然と行われることが期待できるため、このようにしています。
しかしながら、めり込み量が大きいとアバターが跳ねてしまうほか、ばね定数が小さいとめり込みから復帰しなかったりとなかなか調整が難しいなぁという感じでした。 そこで、新たに「拘束条件を求める処理」を追加して、壁に接触している場合のめり込み方向の速度を補正してあげる処理を追加しました。こうすることで、めり込みすぎを防止したりできるので、 ばね定数の調整などもしやすくなると考えました。
こんな感じに接触ツリーをあたり判定時に構築し、壁や天井などの「マップに拘束されている」部分からツリーを辿り、接触面の法線ベクトルと力の向きから修正すべき速度の方向や大きさを決定します。
これである程度はマシになったので、しばらく様子見をしてみようかなーという感じです。
ロゴを試しに描いてみた
やっぱり見た目がある程度ちゃんとしていないと開発のモチベーションが維持できないなという気持ちになったので、(サービス名も決まっていないのにというツッコミはありつつ)とりあえずロゴでも書いてみました。
いろいろなマップを組み合わせてつくられた空間を動き回るというイメージです。(そのまんまじゃないか)
ロゴ、以下の理由から描くの難しいなーって思います。個人開発なのでよいじゃないかといえばそうなのですが、やっぱりもうすこしこの辺のスキルも欲しいなと思うのでした。
- ぱっとみてわかる図にしなければならないこと
- ある程度大きさの変更に耐えうること(特に小さくしたときでも見づらくならないこと)
- (デザインにもよるけど)シンプルなほうが良い場合が多いこと
ロゴは「Inkscape」というベクトル画像をつくれるソフトウェアで描いたのですが、このソフトを使っている人をあまり周りで見ないなぁという気持ちになったので、いつか使い方記事でも書いてみようかな。
雑記
進捗報告だけのブログだと、どうしてもネタがあれでなかなか筆が重くなってしまうので、もうちょっとどうでもいいことを書いてもいいかなと思い始めています。 というのも、こうして進捗報告記事を書くときに「あれ、なに実装したっけ?」となりがちなので。。。
継続はなんとやら、ということで、文章書くのに慣れて(というか面倒くさがりな部分を直して)もうちょっとこまめに開発報告できるといいなぁ。
ではでは。
さいきんの開発報告など
ちょっといろいろありまして、開発作業などが滞っており、現在スローペースで開発しています。
みんなでつくるダンジョンの開発状況
ブラウザでマップをつくって探検できる予定のウェブサービス「みんなでつくるダンジョン」のほうは、こんな感じに進捗しています。
キャラが歩くようになった
キャラが歩くようになりました。これであたり判定などのデバッグがしやすくなったので良かったなぁという感じです。
※床や壁などの画像は「@bunaguchi様」、キャラクターは「墨cm」様からお借りしました。ありがとうございます。
まだまだキャラと地面とのあたり判定が微妙だったりするところなどがあり、そのへんはこれから詰めていかないといけないのですが、画面上で動かせる環境ができたのでバシバシ試しながら作っていければよいですな。
キャラクターと地面天井などの各種オブジェクトとの跳ね返り処理は、ばねとダンパーをモデルに計算してみているのですが、条件がそろうとキャラクターが勝手に飛び跳ねてしまったりしてしまいます。 計算処理速度との兼ね合いも見て、力の伝達っぽく判定するのはやめるかもなぁ。JavaScriptの出せる力をまだ見極められていない感があるので、その辺は都度調整して対応していきたいですね。
ちなみにキャラクターは1アカウント1つ持つことができ、画像などは変更できるようになっています。(いろいろなパラメータを用意していじれるようにしたいな)
グリッドに沿って壁などを配置できるようになった
グリッド(画面上の点々)に沿って壁などを配置できるようになりました。これでアクションゲームっぽい画面を比較的簡単に作れるようになったかな。。。
いわゆる「マップエディタ」とは異なり、マップチップ(タイル)を並べてマップを作るというよりは、壁や天井などの大きめの四角いオブジェクトをならべて作るインタフェースになっています。 自由な位置にオブジェクトを配置できるようになっていますが、グリッドに沿って配置できるようにすることで、マップエディタでつくれるようなステージも作れるようになりました。
ぴこぴよにosushiのリンクを貼ってみました
ぴこぴよにosushiのリンクを貼ってみました。お寿司を送っていただいてもこれといったお返しができるわけではないのですが、くれると私がよろこびます。 「ぴこぴよ」(picopiyo):ドット絵ツイート支援ツール
まとめ
というわけで、スローペースになってしまっていますが、ちょっとずつ手を動かしたりしています。「みんなでつくるダンジョン」のフロントエンド側はVue.jsを使っているのですが、Angularを触らなければいけない状況になったりしている関係もあり、どこかでAngularをつかった小さいプログラムを作りたいなぁと思ったりしています。
ではでは。今後もしばらくはスローペースになったりちょっと開発をお休みしたりすることもありそうですが、ちょいちょい更新情報を報告できるようにがんばります。
作品ページをつくりました・続
しばらく更新をさぼってしまっておりました。最近進捗報告ができておらず、なかなかもんもんとしておりますが、ちまちまと作業しておりますのでもう少々おまちください。 (「みんなでつくるダンジョン」については、画像募集しておきながら、ぜんぜん活用できていなくて申し訳ないなと思っています)
そういえば、先日に「作品ページを作りました」という報告をしましたが、細かい点で(技術的に)苦労したので、その辺の話をまとめました。 (少々技術的なお話をば。)
作ったサイトはこれ。 garakuta-toolbox.com
デザイン
私は最近「Vue.js」にはまっておりまして、これを使って「みんなでつくるダンジョン」も開発しています。 その過程で「ウインドウっぽいものがつくれるコンポーネント」を作ったので、せっかくだからそれを活用しよう、ということで Windows風デザインのウェブサイトを作りました。
また、こちらのX68000データベース をみて、「かっこいい!」と思ったことも理由の一つです。
ここで面倒なのが、ウインドウの前後関係を管理する部分です。 こんなかんじに、ウインドウをクリックすると最前面に表示されるのですが、このときクリックされたウインドウより手前に表示されているウインドウの 前後関係をいい感じに設定してあげなければいけません。
このへんは、「Vuex」をつかってウインドウを管理することで解決しました。ウインドウを最前面に表示したり、前後関係を設定するmutationを定義して、 よしなに処理しています。
(このへんのソースコードは、まだちょいと整理できていないので今回は掲載を見送り。。。)
ルーティング
1ページで全ての情報を表現するので、何も考えずに作るとURLが一つになります。 これでは特定の記事について紹介するためのURLが存在しないことになり、とても不便です。
そこで、今回はJavaScriptでルーティングを行うようにしました。 ルーティングライブラリを用いてもよいのですが、私自身のお勉強もかねて、簡易なプログラムを組んでみました。
まずは、こんなクラスを定義します。
export default class router { constructor(baseURI, routeInfo) { this.baseURI = baseURI; this.routeInfo = routeInfo; } route() { let parameter = location.href.replace(this.baseURI, ''); if( !this.routeInfo[parameter] ) { return false; } this.routeInfo[parameter].callback(); return true; } }
この router
クラスは以下のように使います。コンストラクタに起点となるURL(たとえば https://garakuta-toolbox.com
)とルーティング情報を渡しておきます。
ルーティング情報は、URLの情報をキーとしたオブジェクトで、コールバック関数を持ちます。
route()
を呼び出すと、location.href
を見て現在のURLを取り出し、一致するルーティング情報のコールバック関数を呼びます。
routes = new router('https://garakuta-toolbox.com', { 'contents/introduction/memorian': {callback: ()=>{showMemorian()}}, '/': {callback: ()=>{resetDialogVisible()}}, }); this.route();
あとは、サーバ側で(画像やjsファイルを除く)ファイルにアクセスしようとしたときは、常に index.html
を返すようにしておけば
URLに応じた処理を行うことができるようになります。(Apacheなら .htaccess
を設定するなど)
これで「URLに応じた処理」ができるようになったので、たとえば https://garakuta-toolbox.com/contents/memorian
にアクセスがあったら「めもりあん用のウインドウを表示させよう」みたいなことが
できるようになります。
URLの取り扱い
今回作ったページでは、「最前面のウインドウを指すURL」をアドレスバーに入れるようにしています。(うまく言語化できない。。。)
じぶんで文章を書いていてもなかなかしっくりこないので、以下の動画をご覧ください。
これは、 History API を活用することで実装しています。 (参考:https://developer.mozilla.org/ja/docs/Web/Guide/DOM/Manipulating_the_browser_history)
history.pushState(state, "", url);
上記のようにすると、指定した url
をブラウザの履歴に追加でき、かつアドレスバーに url
を設定できます。
これを「ウインドウが選択されたタイミング」(=ウインドウが最前面に表示されるタイミング)で実行しています。
また、ブラウザの「戻る」ボタンが押されたとき、先ほどのrouterの route()
を呼び出すことで対応するウインドウが最前面に表示されるように実装しています。
さいごに
今回作ったサイト、閑古鳥がないておりますが、ちょいちょい更新していければなーと思っているので、思い出したころにでもちょいちょい覗いていただければと思います。 ではでは!
作品まとめ用のウェブサイトを公開しました
あけましておめでとうございます。 今作っている作品をなんとか形にできたらいいな、というのがとりあえずの今年の目標です。
新年初めの公開情報をば。そろそろじぶんの作品をまとめたサイトが欲しいなぁと思っていたので、じぶんの作品紹介ウェブサイトをつくりました。
※スマートフォン・タブレットでは正常に閲覧できません。そのうち対応しますので、それまでお待ちください。
古いWindowsのような見た目のウェブサイトにしよう、と思って作り始めたのですが、なんだかいろいろと実装が増えて、結構な 作業量になってしまいました。(ウインドウの管理部分とか、ブラウザの履歴管理まわりとか。ちょっと変わったUIにしようと思ったら、 なんだか大変なことになってしまった。。。)
実装まわりのもろもろは、そのうちブログ記事にできたらなーと思っています。
そんなこんなで作ったサイトですが、肝心のコンテンツがまだいろいろ足りないな、という感じなので、 随時更新していければと思っています。
ではではー。今年もよろしくお願いします。
2017年の週末開発ふりかえり
(これは2017/12/31に書いています。ちょいと時間がないので乱文になっているかも。。)
そろそろ年があけるので、今年の週末開発について振り返ってみようかなーと思います。 だいたい以下のようなことをしました。
概ね時系列順になっているかな?と思います。ひとつずつふりかえってみます。
あいこんくらぶの「おへや機能」のリリース
あいこんくらぶでは、作品を公開する手段として「マイページ」機能を提供していましたが、 原寸大のドット絵をかわいく表示するにはちょいと不満がありました。(原寸大のドット絵をマイページで表示すると、余白ばかりでスカスカになってしまうので。。。)
そこで、もういっそ自由にドット絵をならべて、自由なサイズで公開できるようにすればいいのでは?と思い立ってつくったのが「おへや機能」です。 簡易な図形の描画や背景機能、文字列挿入機能、バックアップ機能など、作っていくうちにいろいろ盛り込んだなぁという感じになりましたが、 個人的にはそこそこ満足のいくものができました。
おへや機能でつくったわたしのページはこちら
コードスニペットメモツール「めもりあん」のリリース
あいこんくらぶの開発も概ね落ち着いてきたので、そろそろ次の何かを作りたいなぁと思っていたときに、 「Vue.jsをさわってみたいなぁ」という気持ちになったので作ったツールです。 「この技術がつかいたいな」という気持ちで開発を始めたのは初めてかもしれません。
また、ちょうどこのとき「Ruby on Railsチュートリアル」というものをやっておりまして、これは Ruby on Railsの開発技術を学ぶのにもってこいな教材なのですが、途中で「あれ?これどうやって書けばいいんだっけ?」となったときに 長大なページの中から該当場所を探すのに大変な思いをしていました。
そんなこんなでつくったので、みなさんもつかってみてください!
ステージデザイナーの開発停止
ステージデザイナーは2013年以前から(!)ちまちまと開発していたのですが、利用者数が伸びないことや、最近放置気味だったこと、またソフトウェアとしてもいろいろと課題を抱えていたので、 思い切って開発停止とすることにしました。(期待いただいていた方々には本当に申し訳ありません、という気持ちです。。。)
長いことつくっていたソフトだけに思い入れも大きかったのですが、ここに書くと長くなってしまうのできょうはここまで。
いろいろと機能を盛り込みすぎて、操作が複雑になってしまったことなどが失敗点かなぁと思っています。 しかし、ステージデザイナーで得られた開発技術や知見も多いので、これからの開発に生かしていきたいです。
ぴこぴよのアドレス変更
「ぴこぴよ」は「あいこんくらぶ」の派生サービスとして提供していたのですが、いまや「ぴこぴよ」のほうがアクセス数で上回り、 そのへんが影響して旧来のアドレスだともろもろ問題がありそうだと感じたので、アドレスを変更することにしました。
もともとはあいこんくらぶの機能を切り出して提供していたこともあり、あいこんくらぶのシステムと密結合になっていたので、 なかなか面倒な作業でしたが、なんとか作業を完了できたな、という感じです。
このへんについてくわしくはこちら
「みんなでつくるダンジョン(仮称)」の開発開始
みんなが思いのままにつくったマップを自由に移動しながら探検出来たら面白いだろうなぁと思って作りはじめました。 また、Twitterなどで素敵なゲーム素材(っぽい画像など)を描いている方が「ゲーム作りたいなぁ」とつぶやいているのを見ていて、 ゲームまではいかなくても、マップをかんたんに作れて公開出来たら楽しいだろうなぁと思ったのも、開発を始めた動機のひとつです。
いまのところ、なんとか飽きずに作り続けています。
じぶんの力量不足的な問題で、技術的にもなかなか大変なこともあり、苦労していますがなんとか完成できるといいなぁ(とは言っておりますが、完成はまだ保証できない程度の進捗です)。
こちらについては、これからもちまちまと情報を載せていければなと思っています。 (スクショ用素材の募集も引き続き行っておりますので、よろしくおねがいします!)
まとめ
今年もそれなりにいろいろつくったなぁという感じです。Vue.jsやRails、ちょっとだけWebGLやWebAudioも触ったりと、技術的にも それなりにいろいろ触れることができました。
一方で、つくったものが思うように使っていただけなくて、落ちこむことが多い年でもあったなと思います。 趣味開発なので、好きなように作ればいいのかもですが、やっぱりたくさんの方々に使っていただいたほうがやる気も出るので、 来年以降もこのあたりを意識して開発していければよいですね。
また、ドット絵Advent Calendarに参加しましたね。ふだんはこういうイベントに参加することに対して及び腰なのですが、 もうちょっと積極的にイベントごとなどに参加していきたいな、と思いました。
ではでは!