Quantcast
Channel: 気ままなタンス*プログラミングなどのノートブック
Viewing all 242 articles
Browse latest View live

【ツクールMV】メニューから回想モードの呼び出しを行えるようにする補助プラグインを作った

$
0
0

RecollectionMode.js(回想プラグイン)の補助として、メニューから回想モードを呼び出すための 補助プラグインを作りました。

現状の回想プラグインだけだと、タイトル画面からの移動しかできませんが、 本プラグインを追加することで、下記利用イメージのように、メニューに回想モードに移動するためのコマンドが表示されるようになります

利用イメージ

f:id:rinne_grid2_1:20180331213104p:plain

f:id:rinne_grid2_1:20180331213124p:plain

使い方

RecollectionMode.jsの導入

まず、RecollectionMode.jsがすでに適用済みである必要があります。
適用方法については、以下のリンク先をご確認ください。

https://github.com/rinne-grid/tkoolmv_plugin_RecollectionMode

補助プラグインのダウンロード

下記のURLより、補助プラグイン(RecollectionMode_back_to_menu_and_title_patch.js)をダウンロードし、 ツクールプロジェクト/js/plugins/に配置します。

https://raw.githubusercontent.com/rinne-grid/tkoolmv_plugin_RecollectionMode/master/RecollectionMode/js/plugins/RecollectionMode_back_to_menu_and_title_patch.js

プラグインの適用

プラグイン管理から、補助プラグインの状態をONにします f:id:rinne_grid2_1:20180331213157p:plain

プラグインパラメータの設定(任意)

各パラメータの設定を行います。

パラメータ説明デフォルト
コマンド追加位置1~8の数字を指定します。
1: アイテムの下に追加
2: スキルの下に追加
3: 装備の下に追加
4: ステータスの下に追加
5: 並び替えの下に追加
6: オプションの下に追加
5: 並び替えの下に追加
「回想」コマンドの名称」回想モードに移動するためのコマンド名称として表示される文字です。回想モード
「戻る」コマンドの名称回想モードからメニューに戻るためのコマンド名称として表示される文字です。メニューに戻る
回想コマンドを表示する条件スイッチID回想コマンドが表示される条件スイッチIDを指定します。
このスイッチがONになった場合に回想コマンドをメニューに追加します。
IDに0を指定した場合は常に回想コマンドが表示されます
0

問題点・注意事項

1点、よろしくない問題があります。

【問題の概要】

メニューから移動した回想モードで、回想を観てから、メニューに戻ってきた時、 背景(マップキャラクター等)が消えてしまう。

回想モードに移動する前f:id:rinne_grid2_1:20180331213212p:plain

回想モードに移動し、回想を観てから、メニューに戻ってきた時f:id:rinne_grid2_1:20180331213223p:plain

一度メニューを閉じてしまえば、元に戻るのですが、 メニュー経由での回想を観るたびに、背景表示が消えるという問題が残っている状況です。

このような問題がある状態で恐縮ですが、 もし使ってみたいという方がいらっしゃいましたら、ご利用をご検討いただけると幸いです。


【雑記】一つのことに集中できるのが理想だがそうもいかないため、タスク・時間管理を頑張る話

$
0
0

至極真っ当な結論になったけど、自分の悩みの中で、なんとなく腑に落ちたことがあったので書く。

僕は会社では主にJavaを書いている。最近はSQLチューニングの知識が求められている。 また社内システムではあるが、要件定義や基本設計などのスキルも求められ、 他部門との調整・交渉力も必要になってきている。

一方、家では趣味でフロントエンドの勉強をしていたり、ゲームを作ったりと、 最近の流行り(?)に置いていかれないように勉強するようにしている。

  • 仕事の学習
  • 仕事のプログラミング
  • 趣味の学習
  • 趣味のプログラミング
  • 趣味の制作

主に趣味の学習系において、思うように自分の力になっていない気がして、もどかしい。

なぜだろう?

ポイントは、自身の情報受信時の衝動性と、タスクへの強制力。

趣味のプログラミングでは、Webアプリを主として学習を行っている。
しかし、周囲の情報に流されやすく、一つの技術を突き詰める前に、別の技術に目移りする傾向にある。 (仕事に関していえば、目移りしたとしても、取り組むべき業務が終わないという結末がわかりきっており、強制的に完了させるため問題にはならない。  さらに完成させた事実があるので、少しは自分の力になっている)

例えば、2017年11月頃は、GoLangに夢中だった。 書籍をある程度読み終えたところで、APIの実装を模索しようとしているとき・・・ 何も成し得ることなく、Angularの学習を始めた。

理由としては、以下のとおりだと考えている

  • 自分自身のGoLang学習のゴール地点や成果物が定まっていなかった
  • 別部署の業務で「Angular」(フロントエンド)の話が湧いて出てきた

少なからず、趣味と仕事で同じ技術、言語を突き詰めて書きたいという想いを持っており、 今思うと非常に浅はかな考えではあるものの、こう考えたのだ。

「Angularの勉強を始めれば、技術要員としてアサインされて、家でも仕事でも同じ技術が使えるかもしれない」と。

結果として、「非公認オブザーバー」のような形で、Angularに関する意見交換を行うことはできたものの、 自部門の業務が手一杯であるのと、部門間の見えない壁により、浅はかな理想像は砕け散った。

さて、その後はどうなったのだろうか?

2018年1月、ゲームフェスの存在と、その締め切りが数日後に迫っていることを知ると・・・ なんと、急に(衝動的に)ゲームが作りたくなったのだ!

間に合わないことは目に見えてはいるものの、ゲームの全体的な流れは確定でき、OPまで実装した。 (その間のAngularの勉強状況は、ご想像におまかせする)

この状態について、よくわからない造語をすると、情報過敏というものになるのだろうか。 様々なことに手を出してしまい、一つのことを突き詰めてこなすことができていないということを認識した。

では、僕は今後どうすべきなのだろうか?

情報の受信をトリガーとして、衝動的な欲求(学習欲、創作欲)が発生し、別のことが中断されてしまう弱点はあるものの その事象自体がモチベーションにつながることは間違いない。 (衝動的な欲求が発生した時の集中力は凄まじいものがある気がする)

したがって、それを弱点ではなくチャンスに変換し、価値あるものとすることが、自分自身の行うべき課題であると言える。

やはり、一番適切なのはこれしかないだろう。 基本中の基本である、正確な時間管理、タスク管理が必要だ。

  • 時間を決めてタスクをこなす(何時間もぶっ続けでやらないし、毎日最低限の時間を作る)
  • 定期的に復習する

そう、そもそも趣味でやることについては、期限がない。 そうすると当然のことながら、時間を意識するはずもない。

インプットもアウトプットも期限を決めて、計画的に実行していく必要がある。

【RPGツクールMV】スマホブラウザでInvalidStateErrorが発生した場合の備忘録

$
0
0

概要

RPGツクールMVで、ウェブブラウザ向けにデプロイメントを実施し、 iPhoneやiPad等のiOS系端末でゲームをプレイしていると下記のようなエラーが発生した。

Error
InvalidStateError (DOM Exception 11): The object is in an invalid state.

原因

ゲームイベントで指定されている BGMやSEのm4a形式ファイルが存在しないため。

対策

m4a形式ファイルをインポートする。

個人的に気を付けること

PC版のブラウザだと、開発者コンソールに「ファイルが見つからない」エラー出力があり、ゲームの継続が可能。 しかしスマホ・タブレットの場合はゲーム自体が停止する。

個人的な話だが、外部サイト様の音楽素材を利用する際、 oggファイルだけをインポートし、m4aファイルの方が漏れてしまうことがたまにあるので、 それぞれのファイルをセットでインポートすることを意識しておく。

m4aファイルを配置しても、上記エラーが発生した

  • 下記の端末で、現象を確認
    • iPod touch(MKH02J/A iOS 10.1.1)のSafari、Chrome
    • iPad mini2(ME280J/A iOS 10.0.2)のSafari、Chrome

推測と対策

  • m4aファイルのサイズが大きすぎる可能性がある。
    • 2種類のm4aファイル(1.9MB、2.4MB)がそれぞれ再生されなかった
    • ビットレート変更ツール等を利用し、音質を下げ、1.1MB程度に圧縮したところ、問題なく再生できた
    • ※ブラウザキャッシュを削除しないと、キャッシュからBGMを読んでしまい、いつまでたっても反映されない

公開バージョンで、ファイル系エラーを起こさないために

本事象に出くわしたことで、公開時に留意しておくべき点がいくつかわかった

  • ゲーム停止は絶対に避ける(ゲーム進行できないより、音楽がならない方がマシ)
  • m4aファイルサイズを意識する

ゲーム停止を避けるために

とても素敵なプラグインがありました。

【RecoGene】使い方について(ツクールMV回想モードプラグイン用ツール)

$
0
0

RPGツクールMVの回想モード導入プラグイン用のツール「RecoGene」を作りました。

α版:RecoGene - RecollectionMode.jsジェネレータ

f:id:rinne_grid2_1:20160511211307j:plain

RecoGeneとは?

RPGツクールMVの回想モード導入プラグインRecollectionMode.js」の設定生成ツールです。 Web画面上でCG設定に関する情報を入力し、設定済みのプラグインをダウンロードできます。 さらに、既存のRecollectionMode.js(バージョン1.1.2以降)ファイルから、設定を読み込み、編集することも可能です

主な機能

注意事項

α版ということもあり、不具合が含まれている可能性があります。 必ずプラグインのバックアップを実施いただきますようお願いします。

使い方

1.「回想用のCG設定」タブを開き、CG設定を入力します。

f:id:rinne_grid2_1:20160511204209j:plain

2.(必要に応じて)「回想モードのウィンドウ設定」タブを開き、回想モードのウィンドウ関係の設定を行います

f:id:rinne_grid2_1:20160511205019j:plain

3.(必要に応じて)「回想モードのBGM設定」タブを開き、BGMに関する設定を行います。

f:id:rinne_grid2_1:20160511205212j:plain

4.(必要に応じて)「その他設定」タブを開き、セーブ共有や一時マップの設定を行います。

f:id:rinne_grid2_1:20160511205347j:plain

5.下記画像の赤枠「プラグイン保存」ボタンを押下します

f:id:rinne_grid2_1:20160511205347j:plain

6.以下のようなダイアログが出てくるので、赤枠「クリップボードに保存」ボタンを押下します

f:id:rinne_grid2_1:20160511205555j:plain

7.任意のファイルを作成し、クリップボードの内容を貼り付けます。

8.ツクールMVにプラグインを登録します。

9.ツクールMVを起動し、プラグイン内容が反映されていることを確認します

f:id:rinne_grid2_1:20160511210702j:plain

設定のアップロード

  • RecollectionMode.jsのバージョン1.1.2以降を利用している場合、設定を読み込むことができます

1.「設定をアップロード」ボタンを押下し、プラグインファイルを選択します

f:id:rinne_grid2_1:20160511210932j:plain

2.プラグイン内容が読み込まれたことを確認します

f:id:rinne_grid2_1:20160511211307j:plain

作成について

普段JavaScriptjsonを記述しない方にとっては、 直接プラグイン設定を変更することに対して少々抵抗感があるのではないかと考え、GUIツールを作成しました。

少しでもお役に立てれば幸いです。

不具合等ありましたら、こちらの記事のコメント欄に投稿をお願いします。

【読書メモ】パーフェクトJavaScript(サーバーサイド)

$
0
0

part6を読んだのでメモ。

パーフェクトJavaScript (PERFECT SERIES 4)

パーフェクトJavaScript (PERFECT SERIES 4)

Node.js

イベントループ

Node.jsでHTTPサーバー処理を行う Node.jsはイベント待ちのコードを書くとスクリプトが暗黙にループに入る。 イベント待ちのコードがなければ、スクリプトの最後まで実行すると、スクリプトが終了する

以下のコード例:

  • listen(8080)で接続待ちのイベントソース(イベントを発生させるオブジェクト)が生成され、 コードの最後で暗黙のイベントループに入る。 ポート番号8080番にHTTPの接続があると、イベントループからコールバック関数が呼ばれる。 コールバック関数の中でHTTPのレスポンス処理をする。 コールバック関数を抜けると、再び暗黙のイベントループに入る。
var http = require('http');

http.createServer(function(request, response) {
  response.writeHead(200, {'Content-Type': 'text/plain'});
  response.write('Hello');
  response.end('World\n');
}).listen(8080);
  • 上記処理を明示的に記載

    • httpdオブジェクトにon関数でコールバックを設定
    • on関数はNode.jsプログラミングで最重要な関数で、イベントに対するコールバック関数をセットする関数
      • このようなコールバック関数をイベントハンドラという。
    • on関数は、内部的にはaddListener関数の別名。
  • 1. httpdオブジェクトの'request'イベントにイベントハンドラをセットする

  • 2. httpdオブジェクトの'request'イベントはHTTPリクエストを受けたときに起きるイベント 通常Node.jsではこのようにイベント名でイベントを識別し、イベントハンドラを関連付ける。
  • 3. 前述のコールバック関数も内部的には'request'イベントのイベントハンドラである
var http = require('http');

var httpd = http.createServer();
httpd.listen(8080);

httpd.on('request', function(request, response) {
  response.writeHead(200, {'Content-Type': 'text/plain'});
  response.write('Hello');
  response.end('World\n');
});

【vim】各種操作-part1(オペレータ、モーション等)

$
0
0

オペレータ

あとにモーションを続けて入力することで モーションによってカーソルが移動する範囲に対して操作を行うことができる

dw

  • dは削除を行うオペレータ
  • wは次の単語の先頭まで移動するモーション
  • dを押し、wを押すと単語が削除

d$

  • dは削除を行うオペレータ
  • $は行末まで移動するモーション
  • dを押し、$を押すと、行末まで削除

gU

  • gUはアルファベットを大文字にするオペレータ
  • wは次の単語の先頭まで移動するモーション
  • gUを押し、wを押すと、単語を大文字にする

ビジュアルモードでオペレータを使う

  • ビジュアルモードにvで入る
  • 大文字に変更する→gU

テキストオブジェクト

  • 操作対象を論理的に意味のある単位で指定できる
  • モーションwはカーソルが先頭位置になくても、次の単語の先頭に移動する

  • 単語内のどこかにカーソルがあっても「現在の単語」を対象として操作できると便利

  • それを可能にするのがテキストオブジェクト

テキストオブジェクトの使い方

  • aもしくはiから始まる
  • aは境界を含む、iは境界を含まないという方針で定義されていると考えておく
  • dawを使うと単語を削除
  • cを使って単語を別のものに書き換えたい場合はciwが使える
    • ciweasyのようにする

ドットコマンド

  • ドットキーを押すことで、最後に行った変更を繰り返す機能
  • dawを使うことで、単語を削除するコマンドが実行された
  • これを繰り返し行うには、ドットコマンドを実行する

www.rinsymbol.net

【vim】各種操作-part2(数値の増減、マクロ等)

$
0
0

ソフトウェアデザイン 2016年 05 月号 [雑誌]

ソフトウェアデザイン 2016年 05 月号 [雑誌]

Vim実践投入(コード編集の高速化からGithub連携まで)を読んでおり、メモを残す

gnコマンド

  • 検索の次のマッチへ移動するnの亜種
  • ノーマルモードで使うと、次のマッチへ移動し、対象をビジュアルモードで選択する
  • オペレータに続けて使うと、テキストオブジェクトのように動作する
  • /varで検索
    • cgnvarでciwletとして、.を押すと変換する

マクロ

  • .では直前の動作を繰り返すことができた。
  • もっと長い操作を繰り返したい場合には、一般的にマクロと呼ばれる機能を利用できる
  • qに続けて、任意のアルファベットを入力すると記録モードに入る。
  • その状態で操作を行い、最後に再びqを押すことでアルファベットに対して操作を記録できる
  • 記録した操作を実行したい場合は、@に続けて記録したアルファベットを入力する

数値の増減

  • <C-a>と<C-x>を使うとカーソル下もしくはカーソル以降にある数値の値を増減できる。
  • 事前に数値を入力してから使うことで、例えば5<C-a>のように入力すれば数値を「5」増やすといったこともできる

Vimと正規表現

  • vimの検索は、Vimの検索コマンドである/や?を入力しなければならない
  • プログラミング言語によって方言がある
# 検索対象 Vim, Visual Studio Code, Emacs, Eclipse

# 基本正規表現
# (Vim, grep)
¥(V¥(im¥|isual Studio Code¥)¥|E¥(macs¥|clipse¥)¥)

# 拡張正規表現
# (Perl, grep -E)
(V(im|isual Studio Code)|E(macs|eclipse))
  • ¥vをつけることでvimでも拡張正規表現が利用できる

www.rinsymbol.net

【vim】各種操作-part3(タブ、正規表現)

$
0
0

読み進めているので、メモ。

タブ

タブでオープン

:tabnew ~/.vimrc

タブ切り替え

Shift + Command + {

正規表現

行頭・行末^, $

  • 先頭に#がついた行 ^#

  • 行末に;がついた行 $;

量指定子

  • パターンの繰り返しには「*」または「+」を使う
  • *は0個異常の繰り返し、+は1個異常の繰り返しを表す
  • ¥vをつけない場合は、または¥と書く
# 検索対象:String str
# パターン(¥vあり)
¥vStrings+str

# パターン(¥vなし)
String¥s¥+str
  • ¥sや+のような特殊な文字を「メタ文字」と呼ぶ
  • *や+のようなマッチする個数を指定するメタ文字を「量指定子」と呼ぶ
  • ¥sは空白文字を表す
    • ¥sはVimでは半角スペースとタブ文字にマッチする
    • ¥s+と書くことで、「半角スペースかタブ文字1文字以上の繰り返し」という意味になる

量指定子:0個または1個?、=

?または=は0個または1個の量指定子

# 検索対象:「function foo(」または「function(」

¥vfunction(¥s+¥w+)¥(

量指定子:回数指定{n}, {n, m}

  • 回数指定の繰り返しには、{n}や{n,m}を使う
# 検索対象:2016/01/31
¥v¥d{4}¥/¥d{2}¥/¥d{2}
  • 正規表現エンジンによっては使えない場合もあるため そういう場合は、文字クラスを使い、[0-9]を書く
  • /を検索するためにバックスラッシュでエスケープしている

  • 2016/1/31にはマッチしない。月の部分が2文字の数値ではないため

# 上記を考慮

¥v¥d{4}¥/¥d{1,2}¥/¥d{1,2}

  • ¥d{1,2}とすることで1文字から2文字までの数字(¥d)にマッチする

    • 1が最小の繰り返し回数、2が最大の繰り返し回数
  • はそれぞれ{0,} {1,}のように書くこともできる

¥のエスケープ

  • 文字の/を検索したい場合は、¥/のようにエスケープする必要がある
  • これは正規表現というよりも、Vimの/コマンドと?コマンドの仕様によるもの

固定文字列を検索 ¥V

  • 正規表現のメタ文字を無視して固定文字列で検索する
  • ¥Vをパターンの先頭につけることで固定文字列検索が可能

【雑記】なにがやりたいか聞かれて即答できなかった話

$
0
0

なにがやりたいか

懇親会で上司や先輩と飲んでいた時、質問された。

「よく家でコーディングやってるみたいだけど、やりたいことは何?」

その質問を受けて、少々困惑した。 なぜならば、自分自身では何がやりたいのか、明確にできているつもりだったが、 客観的に見ると、明確に意識できていないことに気づかされたからだ。

根底にある考え

基本的にはプラグインの開発やフリーゲームの作成を行い、 「人の役に立つことをしたい、人を楽しんでもらいたい」という想いの元に動いている。

仕事でも他の人から「これ作って」「これやって」と言われたら、 その人のことを優先的に考えて行動している。*1

(どうやったら使いやすいか常に考えたり、はやく使わせてあげたいと考える)

しかし、人の役に立つことをしたいというのは、 先輩からしたら、曖昧な考えであったようで、今振り返ると確かにその指摘も妥当だと感じる。

指摘を受けて振り返る

なんとなくではあったが、 自分から主体的にモノを考え、何かに取り組むことができておらず、悩み続けていた。

何かを作ろうとしても、 「既存のサービスがあるから作っても無駄」「1から作るにも、数式が入ってくると、膨大な時間がかかりそう」 こんな理由で反射的・無意識的に断念していることがわかった。

新しいプログラミング言語を学ぶにしても、そこからどんなものを生み出すか見当がつかない状況。 (仕事で新言語での開発等に携わっていれば、ノウハウ蓄積の観点で違ったものになったのかもしれない)

本当に先輩が聞きたかったことは何か

会話にズレがあったようにも感じる。

先輩としては、BtoBか、BtoCかという、金銭の絡む話の中で「やりたいこと」が聞きたかった様子。

しかし、現在の自分としては報酬等、かかわりのない部分で動いている(が、やりたいことは明確に言えない)*2

今後なにをしていくべきか

未完成の状態にあるものを挙げてみる(何度も書いている気がする)

  • ツクールMVゲーム
  • ツクールVX aceゲーム
  • プラグイン(RecollectionMode)の機能追加

最近はツクールMVも影響で、JavaScriptを学ぶことが多い。 (ツクールMVJavaScript、Node.jsやES2015)

クライアント側で完結するものだけではなくWebアプリも作りたい(主にDjango。だけどネタがない)

少し整理すると、「むしろやりたいけど、詰まってる」ことが多い? やりたいことが多すぎて、結局取り組めていない状況にも見える。

軌道に乗ればほぼほぼ解決しそう。

*1:もちろん自分の仕事が忙しいときは少々ずれることはある

*2:というよりも、今は言えないだけで作りたいものがでてきたら当然それが最優先になるので、一時的なものだとも思う

【JavaScript】Grunt + babelの環境メモ

$
0
0

最近はES2015(以下ES6)について学んでいる。

babelを利用し、ES6のコードをコンパイルを行い、ES5に変換して利用するとのこと。 (目的:ブラウザでまだ実装されていない、JavaScriptの新機能を使えるようにする)

コンパイルに必要なライブラリ

ライブラリインストールコマンド備考
babel-clinpm install -g babel-cliグローバルインストール
babel-preset-es2015npm install --save-dev babel-preset-es2015
babel-polyfillnpm install --save-dev babel-polyfillpolyfillの意味:古いブラウザであってもモダンブラウザと同様の機能を提供する方法

タスクランナー(Grunt)のライブラリ

ライブラリインストールコマンド備考
grunt-clinpm install -g grunt-cliグローバルインストール
gruntnpm install --save-dev grunt
grunt-babel npm install --save-dev grunt-babel
grunt-contrib-watchnpm install --save-dev grunt-contrib-watchファイル変更の監視。grunt watch
load-grunt-tasksnpm install --save-dev load-grunt-tasks

Gruntfile.jsの作成

  • ひとまず、src/basic.es6.jsをコンパイルし、lib/basic.jsとしてアウトプット
// Gruntfile.js - 1ファイル
module.exports = function(grunt) {
    require('load-grunt-tasks')(grunt);
    grunt.initConfig({
        babel: {
            options: {
                sourceMap: true,
                presets: ['es2015']},
            dist: {
                files: {'lib/basic.js': 'src/basic.es6.js'}}}});
    grunt.registerTask('default', ['babel']);
}
  • パターンを指定し、src配下のソースを対象とすることも可能
// Gruntfile.js - 複数ファイル
module.exports = function(grunt) {
    require('load-grunt-tasks')(grunt);
    grunt.initConfig({
        babel: {
            options: {
                sourceMap: true,
                presets: ['es2015']},
            dist: {
                files: [{
                    expand: true,
                    cwd: 'src',
                    src: ['**/*.js'],
                    dest: 'lib/',
                    ext: '.js'}]},
            watch: {
                js: {
                    files: ['src/**/*.js'],
                    tasks: ['babel']}}}});
    grunt.registerTask('default', ['babel']);
};


実行コマンド一覧

# 各ライブラリのインストール
$ npm install -g grunt-cli
$ npm install -g babel-cli
$ npm install --save-dev babel-preset-es2015
$ npm install --save-dev babel-polyfill
$ npm install --save-dev grunt
$ npm install --save-dev grunt-babel
$ npm install --save-dev grunt-contrib-watch
$ npm install --save-dev load-grunt-tasks

# Gruntfile.jsの記述
$ touch Gruntfile.js


# ファイル変更監視の開始
$ grunt watch

参考にした本や記事

  • 速習ECMAScript6: 次世代の標準JavaScriptを今すぐマスター!

  • HTML5 Experts.jp

html5experts.jp

  • mae's blog

mae.chab.in

【JavaScript】webpack + babelの環境メモ

$
0
0

webpackとbabelでES6の自動コンパイル環境を準備したのでメモを残す。

コンパイルに必要なライブラリ

ライブラリインストールコマンド備考
babel-clinpm install -g babel-cliグローバルインストール
babel-preset-es2015npm install --save-dev babel-preset-es2015
babel-polyfillnpm install --save-dev babel-polyfillpolyfillの意味:古いブラウザであってもモダンブラウザと同様の機能を提供する方法

webpackのライブラリ

ライブラリインストールコマンド備考
webpacknpm install -g webpackグローバルインストール
style-loadernpm install --save-dev style-loader
css-loader npm install --save-dev css-loader
babel-loadernpm install --save-dev babel-loader

ついでにjQueryをインストール

ライブラリインストールコマンド備考
jquerynpm install jquery

webpack.config.jsの作成

  • エントリーは/src/entry.jsとする
  • コンパイル後の出力先ディレクトリは/dist/bundle.jsとする
  • コンパイル前のjsファイルを確認(devtool)
  • babel-loader、style-loader、css-loaderを指定する
module.exports = {
    entry: "/src/entry.js",
    output: {
        path: __dirname + "/dist,
        filename: "bundle.js"},
    devtool: "inline-source-map",
    module: {
        loaders: [{"test": /\.js$/, exclude: /node_modules/, loader: "babel-loader"},
            {"test": /\.css$/, loader: "style-loader!css-loader"}]}}

style.cssを作成

body{background: blue;
}

src/entry.jsを作成

// entry.js
require("./style.css");
let $ = require('jquery');
// import $ from 'jquery' // これは動かなかった。。let v = [1, 2, 3];
v.forEach(x => console.log(x));

htmlより、dist/bundle.jsを読み込み

<!DOCTYPE html><htmllang="ja"><head><metacharset="UTF-8"><title>Title</title></head><body><scriptsrc="dist/bundle.js"></script></body></html>

自動コンパイルをするため、--watchオプションをつける。

$ webpack --watch

通常のビルドはこちら

$ webpack

実行コマンド一覧

$ npm init -y# ライブラリインストール
$ npm install-g babel-cli
$ npm install--save-dev babel-preset-es2015
$ npm install--save-dev babel-polyfill
$ npm install-g webpack
$ npm install--save-dev style-loader
$ npm install--save-dev css-loader
$ npm install--save-dev babel-loader

# webpack.config.jsを作成(上記、「webpack.config.jsの作成」の内容を記述し保存
$ touch ./webpack.config.js


# ファイルの監視(自動コンパイル)を実行
$ webpack --watch

参考にさせていただいた記事

qiita.com

library and externals

mae.chab.in

d.hatena.ne.jp

所感

個人的にWebフレームワークDjango(https://www.djangoproject.com/)を使っており、 DJangoテンプレートからbundle.jsを読み込み、動かすところまでできた。

あとは、ES6を使って、実際にアプリを書いてみる。

npmについては、ほぼほぼ初心者といって良い状態。 Gruntとwebpackを使ってみて、個人的にはwebpackの方がシンプルで使いやすいように思った。

【Django】Formの使い方について復習(2016/06/11)

$
0
0

数か月ぶりにDjango(バージョンは1.9)を書いていたけど、色々と忘れてしまっていた。 復習のためメモしておく。

Formの定義

from django import forms

classAnyForm(forms.ModelForm):
    
    classMeta:
        model = AnyModel
        fields = ('any_id', 'any_name')

Formの利用

  • モデルのPK(any_id)がビューに渡された場合は、既存データの更新処理として動く
  • それ以外は新規作成を行う
#-----------------------------------------------------# views.py#-----------------------------------------------------from django.shortcuts import get_object_or_404, render
from django.core.urlresolvers import reverse_lazy

from .forms import AnyForm
defdo_any_action(request, any_id):
    # 更新・登録if request.method == "POST":
        any_form = AnyForm(request.POST)
        if any_form.is_valid():
            if any_id:
                any_obj = get_object_or_404(AnyModel, pk=any_id)
                any_obj.any_name = any_form.cleaned_data["any_name"]

            else:
                # ModelFormはモデルインスタンスを返す(commit=Falseの場合、DBには保存しない)
                any_obj = any_form.save(commit=False)


            # any_objに作成・更新で共通の処理# 保存
            any_obj.save()
            return redirect(reverse_lazy('pj:result'))
        else:
            return render(request, 'pj/any.html', dict(any_id=any_id, form=any_form)

    # 更新・登録画面への遷移        else: 
        any_form = AnyForm()
        return render(request, 'pj/any.html', dict(any_id=any_id, form=any_form))


#-----------------------------------------------------# urls.py#-----------------------------------------------------from django.conf.urls import url
from django.views.generic import TemplateView
from . import views

name = "pj"
urlpatterns = [
   url(r'^mod_any_action/(P<any_id>\d+)/$', views.do_any_action, name="mod_any_action"),
   url(r'^cre_any_action/$', views.do_any_action, name="cre_any_action"),
   url(r'^result$', TemplateView.as_view(template_name="result.html")),
]           

テンプレート

<!-- any.html -->

<!doctype html>
<html>
<head>
  <title>any</title>
</head>
<body>
  {% if any_id %}<form action="{% url'pj:mod_any_action' any_id %}" method="post">
  {% else %}<form action="{% url'pj:cre_any_action' %} method="post">
  {% endif %}{{ form.any_name }}{% csrf_token%}</form>
</body>
</html>

雑感

あまりに久々すぎて、しょぼいミスが目立ってしまった。 ModelFormではない普通のFormを定義していて、そのフィールドにカンマをつけるというミスをしていることに気づかずに 「意図した動作をしない」と悩んでしまった。

定期的にコードを書く機会を作るべきだと感じた。

【読書メモ】“内向型”のための雑談術 自分にムリせずラクに話せる51のルール

$
0
0

昔からずっと、雑談がうまくできない。 友人同士や職場の同僚同士なら、まだそれでも良かった。

しかし、最近はよくお客さん先に訪問するようになったため、 この「雑談できない事象」が自分自身の「問題」に変わった。

タイトルやレビューや確認していたのだが、 「内向型」のための雑談というあまり読んだことがない(個人的に)ようなタイトルであり、 自分の求めるものに合致していると感じて、購入を決めた。

“内向型”のための雑談術―自分にムリせずラクに話せる51のルール

ラインを引いたところ、印象に残った部分をメモする

読書メモ

雑談の悩み

  • 初対面の人と何をしゃべっていいのかわからないために、なかなか打ち解けられない
  • だれかと一緒にいると、沈黙をやぶる言葉が出てこなくて、いつも重苦しい空気になる
  • 大勢の人が集まるパーティや飲み会の席などでたいてい孤立してしまう

雑談は大切

  • 意味のないふざけた会話や人を笑わせるバカな話が、人と接する場面では大切な役割を果たす
  • 最初の雑談ができなければ、本当にいいたいことが伝えられない
  • 近づきすぎても、遠すぎても人付き合いはうまくいかない。その役割を果たしているのが「雑談」
  • 「小さな雑談」さえうまく使えれば、不思議と会話全体がうまくまわる

雑談の役割

楽しい話をすることでも、笑いをとることでもない
雑談のネタは、何も笑えるものでなく、身近なところに取り上げるだけで十分

雑談の目的

常に、雑談の目的を意識すべき。

  • 苦痛な状態からの回避
  • 場の空気を温める(相手の心を開きたい)
  • 好印象を残す(信頼を得ることで「次」につなげたい)

雑談の勘違い

  • 笑い話で盛り上げなければならない
  • たくさんしゃべらなければならない
    • 自分では喋らずに相手に喋ってもらう方が、雑談としての効果が高い
    • 「聞く雑談」に徹することでうまく切る抜けることができる
  • 豊富な話題をもっていなければならない
  • 普通の会話テクニックは内向型人間には使えない(そのとおり)
    • 感情を素直に表現する、明るい表情でからだ全体を使っておおげさにうなづく、自分から率先して会話に入る・・・等々、無理がある。

内向型人間の強み

  • 喋りが苦手である
    • 聞き役に徹することができる
  • 相手の気持ちに敏感である
    • 相手に迷惑がかかりそうになると、すぐにやめてしまう
  • しゃべる言葉を厳選している

感想等

「雑談の悩み」で記載した内容は、そのまま自分の悩みと言える。 こうったタイプの人間がどのように雑談に関する力を身につけていけば良いのか、そもそも身につけることができるのか、 様々な疑問が浮かんできており、本の内容がどう進むのか楽しみである。

【読書メモ】あなたの話はなぜ「通じない」のか-part1

$
0
0

あなたの話はなぜ「通じない」のか (ちくま文庫)

あなたの話はなぜ「通じない」のか (ちくま文庫)

心に残った言葉、ラインを引いた部分についてメモを残す。

誰が言うか(メディアにより印象が変わる)

同じことでも、あなたが言うのと別の人が言うのでは、 与える印象がまるで違う。人間もメッセージを伝えるメディア(=媒介)だとすれば あなたは相手からどんな風に見られているだろうか

話が通じるためには

日ごろから人との関わり合いの中で、 自分というメディアの信頼性を高めていく必要がある。

話が通じるためにおさえておきたい基礎

  • 自分のメディア力を上げる

あなたという人間への信頼、共感を高めながら 相手に言いたいことを伝えるか、その技術をつかむ。 話が通じるとは"勝ち負けでなく、あなたと相手の間に橋を架けるようなものだ"

  • 相手にとっての意味を考える

相手とはどんな人か?
例えばあなたが「恋人と映画に行った」ことを話すとする。
もし相手が映画好きで感性が合う人なら、映画の情報として「役立つ知らせ」という意味がでてくる。
また相手が沈んでいて、あなたの話が笑えるものだったら「気が晴れる楽しい話」という意味がでてくる。
相手へのメリットが何もなかったとしたら、あなたの話は「単なる自慢」とうつるかもしれない。

人は自分に関係ない、意味のない話はなかなか聞こうとしないものだ。
まずこの厳しい現実をしっかり押さえよう

  • 自分が一番言いたいことをはっきりさせる

自分が一番言いたいことを、極力はっきりさせておき、 それを頭か結論にもってくるだけで、ずいぶん話は通じやすくなる。 「言いたいことはあるんだけど、自分でもはっきりしない」という状態で切り出すと 相手までモヤモヤさせてしまう

  • 意見の理由を説明する

自分に都合のいい理由ばかりでたたみかけてもだめだ。 あなたと、相手の真ん中に「理由」がある。理由を、自分側、相手側、あるいはもっと普遍的な 角度からと、多角的に引いてくる方法や、論理的な説得の筋道を組み立てていく技術もつかもう

  • 自分の根っこの想いにうそをつかない

その人の根っこにある想い・発言の動機、これを「根本思想」という。 「言葉はちょうど氷山の見えるところのようなもので、水面下には、その何倍もの大きな その人の生き方や価値観が横たわっている」
本書は「自分に想いにうそをつかない」ということを一歩も譲らず考えた。

感想

現在、序盤を読み進めている状態である。 上記に記載した5つの「基礎」はプロローグのみの内容である。

それぞれ言葉ではわかっていて、 気を付けているつもりだが、実際の会話ではできていないということが多いのではないだろうか。 僕自身は、おそらくできていないように思う。

仕事での「報告」では、事実を手短に話すことを意識してはいるものの、 自分が一番言いたいこと(キーセンテンスやキラーメッセージ)を常に意識できてはいない。

また、話をする際に、「前提は知っているだろう」ということで、理由を省くこともある。

これらの基礎を元に、 今まで「話が通じなかった」と感じた時の経験を思い出し 「自分はダメだ」で終わるのではなく、原因と対処方法を考えるべきだと強く感じた。

結局のところ、「通じない」痛みによって当時の「思い出」がマイナスイメージとなっていることから、 傷つくのが嫌で、どうにも重い腰が動かせないのではないだろうか。

失敗から学べることは多い。それを改めて実感するきっかけとなったように思う。

www.rinsymbol.net

【読書メモ】あなたの話はなぜ「通じない」のか-part2

$
0
0

あなたの話はなぜ「通じない」のか (ちくま文庫)

あなたの話はなぜ「通じない」のか (ちくま文庫)

ラインを引いたところや印象に残った部分をメモする

コミュニケーション技術を磨いてどうなりたいのか

ある人は「交渉で常に自分が勝てるようになりたい」と言うかもしれない。
またある人は「人間関係で傷つかないようになりたい」と言うかもしれない。
あなたの目指すコミュニケーションのゴールは何だろう?

【Memo】
じぶんのゴール

交渉やお客様との打ち合わせで、
相手の話に真剣に耳を傾け、相手の抱える問題を解決して、信頼し合う関係を作りたい

自分の想いで人と通じ合う、それが(山田ズーニーさんの)コミュニケーションのゴール

伝えなければ、伝わらない

わかってもらえないと思うとき、落ち込んだり、相手をうらんだりする前に
二つ自問してみよう。

  • わかってもらうために自分はどんなことをしてきたか?
  • 自分は人のことをわかろうとしているのか?
【Memo】
言わなきゃ、結局何もわからない。
自分の言葉で、伝えるように心がけている。

「黙っていい仕事をしていればわかってもらえる」と私は思っていた。
でも多くの人が忙しく、さまざまな仕事をしている会社では、
人の仕事をいちいち見てはいられない。
仕事の成果を見ても、どうやってつくったかプロセスまでわからない。
ましてや隣りの席に居る一の頭の中の、まだ形にしていないものを、
一体どうやってわかれというのだろう

感想等

「わかってもらうために自分はどんなことをしてきたか?」

「自分は人のことをわかろうとしているのか?」

この問いは、自分にとって非常に厳しいものである。 二つの問いを突き付けられ、何か、心に刺さるような感覚があった。

わかってもらうために、何をしてきたか?

何冊か、本を読んだ。しかし、実際に人とのコミュニケーションで、実践しただろうか?

自分は人のことをわかろうとしているのか?

「自分は、自分は」で、人の意見をきちんと聞けているだろうか? 「興味がない話は理解できない」とそもそも聴く気を失っていないだろうか?

https://twitter.com/rinne_grid/status/710441674271363072

ポイントを絞って話をすること、相手の話を要約すること、 相手の言ったことを理解すること、自分の伝えたいことを明確にしておくこと

これらがうまくできず、怖くて逃げている節があるように思う。

もっと相手を決めつけず、相手のことを考えたいと感じた。


【体験レポート】メイン機をWindows10にアップグレードした

$
0
0

メイン機をようやくWindows10にアップグレードしたので、メモを残しておく。

基本的には、何事もなく無事にアップグレードできた。

個人的には、特に違和感なく使えている。

(サブ端末としてSurface Pro3を利用しており、 そちらはすでにWin10にアップグレード済みであるため)

目次

Windows10にして本当に大丈夫なのか

正直なところ、メインで使っているPCをWindows10にアップグレードするのは不安だった。

以下の記事で今年夏のWindows10向けアップデートで bash対応されるということがわかり、不安に思う中、アップグレードを決意した。

japanese.engadget.com

PC構成

  • 2010年4月にドスパラで購入したタワー型に、いくつかパーツ交換を実施
    • Prime Monarch ZF
    • OS: Windows8.1
    • マザーボード: ASRock X58 Extreme
    • CPU: Core i7-960
    • メモリ: 12GB(PC3-10600(2GB) × 6)
    • ストレージ: CT512MX100SSD1(C: 150, D:残)
    • グラフィックボード:Geforce GTX650 2GB
    • オーディオキャプチャ: UA-4FX(Roland)
    • TVチューナ: BUFFALO DT-H10 PCI

念のため最初にやったこと

  • システムイメージの作成
  • 回復ディスクの作成

アップグレード実施

右下に常駐しているWindowsマークから、「アップグレードを予約」する。

なお、僕の環境ではマークをクリックした後、 アップグレード予約のウィンドウが「応答なし」となってしまっていた。

しかし、5分~10分放置しておくと、「応答なし」が解除され、きちんとウィンドウ内容が表示されるので、 気長に待てばOKだと思われる。

予約時間になると「準備完了」というウィンドウが表示されるので、 表示内容に従って、作業を進めていく。

アップグレード結果

基本的に問題なし

ただし、地デジチューナー(DT-H10)が動作しなくなったため、一度アンインストールし、改めてインストールを実施

起動確認したソフトウェア(一通り問題なし)

  • RPGツクール2000、
  • RPGツクールXP
  • RPGツクールVX ace
  • RPGツクールMV
  • SONAR X1 Studio
  • Music Studio Producer
  • PyCharm4.5.4
  • VOCALOID3
  • GIMP2
  • GTA4(Grand Theft Auto Ⅳ)

なお、驚いたのはUA-4FXのドライバがWindows10経由で直接インストールされたことだ。 特に意識してドライバダウンロードし、インストールせずともデバイスを認識してくれた。

一部問題あり

  • PCast TV for 地デジ Lite (上記にも記載どおり、一度アンインストールし、再度インストール対応を実施)

初回はドライバ系が不安定になる

再起動もしくは一度電源を落として、改めて起動するとほぼ解決している。

【雑記】嫉妬について

$
0
0

最近、なんとなく、とある方をすごく尊敬しつつ、 嫉妬の感情を抱いていることに気づいた。

その人のツイートを見ると「すごい」と思いつつ、非常にモヤモヤする。

いい機会なので、嫉妬について調べていたところ良い記事を見つけた。

www.huffingtonpost.jp

結果だけ見るのはNG

ネットには"すごい人"がたくさんいる。 ごく平凡だと思っていた人が、ある日とつぜん頭角を現すことも少なくない。 自分と対等のように見える相手が、自由に空を飛び回っている。 その姿を目したときこそ、"見えない部分"に想いを馳せたい。

他人の努力は見えない

努力は誇るものではない。 努力はいつだって見えない場所に隠される。 彼らを対等な相手だと考えるのは、言うまでもなく私の勘違いだ。

自分を振り返る

彼らの積み重ねてきたモノに想像をめぐらせたあと、自分の手のひらをじっと見つめてみる。 自分が経験してきたことを、積み重ねてきたモノを考えてみる。 そこには、たぶん彼らの無視してきたものがある。 すると、嫉妬心はウソのように消えていく。

自分は?
・DjangoでWebアプリが書ける
・CakePHPが使える
・RGSSが書ける
・ツクールゲームを完成させて、人を楽しませたことがある
・楽曲が作れる
・物事の継続ができる
 ・ブログを毎日書いている(400日以上続いている)
・その他

以下、感想。

その人の努力が見えないからこそ、 完璧超人に見えるということが理解できた。

振り返ると、色々と実践できており、全くダメというわけではない。 (そもそも対比できるものじゃないし、比較すべきではない)

【Windows10】スタートメニューを使いやすくするための工夫

$
0
0

Windows10スタートメニューの不満点

Windows10を利用していて、使いづらいと思うことがあります。

それは、スタートメニューに、「マイコンピュータ」(各ドライブのルート)への移動方法がないことです。

僕はいつもスタートメニューから、「マイコンピュータ」を経由して、 各フォルダに移動していたので、そのルートが断ち切られてしまい少々不便に感じていました。

ちょっとした工夫

そこで一つ工夫をすることにしました。

単純ではありますが、 スタートメニューの上部に「マイコンピュータ」に対応する「PC」タイルを配置するというものです。

  • スタートメニューを開いたら、すぐに「PC」がある

こうすることで、従来までの「スタートメニュー」と同じような操作で各ドライブのルートに移動することができます。

f:id:rinne_grid2_1:20160418093353p:plain

やりかた

1. 左下の検索(WebとWindowsを検索)より、「PC」を検索

f:id:rinne_grid2_1:20160418093819p:plain

2. 「PC」が見つかったら右クリックをして「スタート画面にピン留めする」を選択

f:id:rinne_grid2_1:20160418093912p:plain

3. 一旦スタートメニューを閉じて、再度開き、「タイル」がある部分を下にスクロールし「PC」を見つける

f:id:rinne_grid2_1:20160418094024p:plain

4. 「PC」を上部にドラッグドロップし、グループに名前をつける

f:id:rinne_grid2_1:20160418094057p:plain

5. これで完成

f:id:rinne_grid2_1:20160418094116p:plain

僕のPCはこんな感じにしています。

PC、マイドキュメント、コントロールパネルを追加

f:id:rinne_grid2_1:20160418094920p:plain

その他

なお、「スタートメニューからじゃなくて、エクスプローラ開くときにクイックアクセスじゃなくてPCに移動したい」という場合は、 以下の記事の迷った点と備忘録を参照すると、やり方が書いてあります。

rinnegrid.hatenablog.com

検索バーで入力すればすぐに出てくるのですが、 毎回入力するのはわりと手間ですし、やはり慣れている操作方法でできるのがベストだと思います。

【Django】1.9チュートリアル実施メモ

$
0
0

Django1.9のチュートリアルの日本語訳版が公開されていたので、 改めて実施することにした。

今まで実施したチュートリアル(1.4)との違いや復習としてのメモを記載する。

今回はチュートリアル1-3までの内容に関するメモ。

さぁ始めましょう。 | Django documentation | Django

apps.pyについて

AppConfigクラスを継承したクラスを記載する

from django.apps import AppConfig
classPollsConfig(AppConfig):
    name = 'polls'

INSTALLED_APPSには、上記Configを指定する

INSTALLED_APPS = [
    'polls.apps.PollsConfig',
]
  • ここは、1.7より前まではアプリ名を指定していた。

マイグレーション

マイグレーションファイルの作成

python manage.py makemigrations polls

マイグレーションのSQL確認

python manage.py sqlmigrate polls 0001

マイグレーションの確認

python manage.py check

マイグレーションの適用

python manage.py migrate

manage.pyについて

  • manage.pyでは、DJANGO_SETTINGS_MODULEの環境変数を設定している
  • DJANGO_SETTINGS_MODULE環境変数はDjangoに対して、設定ファイルへのimportパスを渡す際に利用される
  • django-admin.py startprojectで作成した時点で、'projectname.settings'が指定されている

timezoneについて

  • よく使う
    • django.utils.timezone
    • datetime
  • 個人的に忘れがち
from django.utils import timezone
import datetime

time = timezone.now()

# 7日前
delta = datetime.timedelta(days=-7)

before_week = time + delta

モデルの属性について

属性 + __yearで年指定

from django.utils import timezone
current_year = timezone.now().year
Question.objects.get(pub_date__year=current_year)

外部キーを張った属性のセット

q = Question.objects.get(pk=1)
# Choiceには、Questionへの外部キーが張られている
q.choice_set.all()

# 外部キー側のオブジェクトを作成
q.choice_set.create(choice_text='hoge', votes=0)

adminサイト

  • フォームは、モデルから自動的に生成される
  • モデルのフィールド型によって、適切なHTML入力ウィジェットが対応している
  • 各フィールドには、Django管理サイトでデータを表示する方法が定義されている

DjangoのURLについて

  • URLパターンは、URLをシンプルに一般化したものである
  • Djangoでは、URLとビューをひもづけるため、URLconfを利用する

urlpatterns

  • プロジェクトフォルダ内のurls.py
from django.conf.urls import url, include

urlpatterns = [
    url(r'polls/', include('polls.urls')),
]

  • アプリケーションのurls.py
from django.conf.urls import url
from . import views

urlpatterns = [
    urls(r'^(?P<object_id>[0-9]+)/resources/$', views.resource, name='resource' ),
]

ビューについて

  • ビューには二つの役割がある
    • リクエストされたコンテンツを含むHttpResponseオブジェクトを返す
    • Http404のような例外の送出

Djangoテンプレートについて

  • アプリケーションフォルダ内に、templatesフォルダを作成する *【Memo:】 (今までDjangoで作ったアプリは、プロジェクトの直下に作成していた気がする
  • DjangoTemplatesの設定ファイルについて、APP_DIRSオプションがTrueに設定されていることにより、INSTALLED_APPSのそれぞれのサブディレクトリにおけるtemplatesフォルダを検索する。
  • アプリケーションが複数ある場合は、URLconfに名前空間を追加する
from django.conf.urls import url
from . import views

name = 'polls'
urlpatterns = [
    urls(r'^(?P<object_id>[0-9]+)/resources/$', views.resource, name='resource' ),
]

チュートリアルのドキュメント

はじめての Django アプリ作成、その 1 | Django documentation | Django

はじめての Django アプリ作成、その2 | Django documentation | Django

はじめての Django アプリ作成、その 3 | Django documentation | Django

【RPGツクールMV】セーブ・ロード系のメソッドメモ

$
0
0

セーブ・ロード時に利用するメソッドやゲーム変数の変化等、 必要になり調査したのでメモ。

loadFromLocalFile(ローカル実行時のセーブファイル読み込み)

// rpg_managers.js 610行目
StorageManager.loadFromLocalFile = function(savefileId) {var data = null;
    var fs = require('fs');
    var filePath = this.localFilePath(savefileId);
    if (fs.existsSync(filePath)) {
        data = fs.readFileSync(filePath, { encoding: 'utf8'});
    }return LZString.decompressFromBase64(data);
};
  • this.localFilePathは、以下のような条件でパスを返す
    • savefileIdが0より小さい場合:"config.rpgsave"を返す
    • savefileIdが0と同じ場合:"global.rpgsave"を返す
    • savefileIdが1以上の場合:"file%1.rpgsave".format(savefileId)を返す

loadFromWebStorage(ブラウザ実行時のセーブファイル読み込み)

// rpg_managers.js 639行目
StorageManager.loadFromWebStorage = function(savefileId) {var key = this.webStorageKey(savefileId);
    var data = localStorage.getItem(key);
    return LZString.decompressFromBase64(data);
};
  • this.webStorageKeyは以下のような条件でキー名を返す
    • savefileIdが0より小さい場合:"RPG Config"
    • savefileIdが0と同じ場合:"RPG Global"
    • savefileIdが1以上の場合:"RPG File%1".format(savefileId);

saveToLocalFile(ローカル実行時のセーブファイル書き込み)

// rpg_managers.js 599行目
StorageManager.saveToLocalFile = function(savefileId, json) {var data = LZString.compressToBase64(json);
    var fs = require('fs');
    var dirPath = this.localFileDirectoryPath();
    var filePath = this.localFilePath(savefileId);
    if (!fs.existsSync(dirPath)) {
        fs.mkdirSync(dirPath);
    }
    fs.writeFileSync(filePath, data);
};
  • 引数で受け取ったjsonをBase64にエンコード

saveToWebStorage(ブラウザ実行時のセーブファイル書き込み)

// rpg_managers.js 633行目
StorageManager.saveToWebStorage = function(savefileId, json) {var key = this.webStorageKey(savefileId);
    var data = LZString.compressToBase64(json);
    localStorage.setItem(key, data);
};

ローカルか、ブラウザ実行かの判定

// rpg_managers.js 595行目
StorageManager.isLocalMode = function() {return Utils.isNwjs();
};

セーブ(ローカル、ブラウザ)の判定

// rpg_managers.js 563行目
StorageManager.save = function(savefileId, json) {if (this.isLocalMode()) {this.saveToLocalFile(savefileId, json);
    }else{this.saveToWebStorage(savefileId, json);
    }};

セーブの呼び出し

// rpg_managers.js 362行目
DataManager.saveGameWithoutRescue = function(savefileId) {var json = JsonEx.stringify(this.makeSaveContents());
    if (json.length >= 200000) {
        console.warn('Save data too big!');
    }
    StorageManager.save(savefileId, json);
    this._lastAccessedId = savefileId;
    var globalInfo = this.loadGlobalInfo() || [];
    globalInfo[savefileId] = this.makeSavefileInfo();
    this.saveGlobalInfo(globalInfo);
    returntrue;
};
  • this.makeSaveContentsで、ゲーム変数($gameSystem等)をオブジェクトに格納
// rpg_managers.js 422行目
DataManager.makeSaveContents = function() {// A save data does not contain $gameTemp, $gameMessage, and $gameTroop.var contents = {};
    contents.system       = $gameSystem;
    contents.screen       = $gameScreen;
    contents.timer        = $gameTimer;
    contents.switches     = $gameSwitches;
    contents.variables    = $gameVariables;
    contents.selfSwitches = $gameSelfSwitches;
    contents.actors       = $gameActors;
    contents.party        = $gameParty;
    contents.map          = $gameMap;
    contents.player       = $gamePlayer;
    return contents;
};
  • ゲーム変数を格納したオブジェクトをjsonに変換し、563行目のsaveメソッドに渡す
  • makeSavefileInfoメソッドで、セーブ画面に表示するキャラクターやプレイ時間等の情報をオブジェクトにセットする
// game_managers.js 411行目
DataManager.makeSavefileInfo = function() {var info = {};
    info.globalId   = this._globalId;
    info.title      = $dataSystem.gameTitle;
    info.characters = $gameParty.charactersForSavefile();
    info.faces      = $gameParty.facesForSavefile();
    info.playtime   = $gameSystem.playtimeText();
    info.timestamp  = Date.now();
    return info;
};

ロード(ローカル、ブラウザ)の判定

StorageManager.load = function(savefileId) {if (this.isLocalMode()) {returnthis.loadFromLocalFile(savefileId);
    }else{returnthis.loadFromWebStorage(savefileId);
    }};

ロードの呼び出し

DataManager.loadGameWithoutRescue = function(savefileId) {var globalInfo = this.loadGlobalInfo();
    if (this.isThisGameFile(savefileId)) {var json = StorageManager.load(savefileId);
        this.createGameObjects();
        this.extractSaveContents(JsonEx.parse(json));
        this._lastAccessedId = savefileId;
        returntrue;
    }else{returnfalse;
    }};
  • StorageManager.loadで、セーブファイルから文字列(Base64からデコード済み)を取得
  • this.createGameObjectsで、Game_XXXXオブジェクトを生成
// game_managers.js 194行目
DataManager.createGameObjects = function() {
    $gameTemp          = new Game_Temp();
    $gameSystem        = new Game_System();
    $gameScreen        = new Game_Screen();
    $gameTimer         = new Game_Timer();
    $gameMessage       = new Game_Message();
    $gameSwitches      = new Game_Switches();
    $gameVariables     = new Game_Variables();
    $gameSelfSwitches  = new Game_SelfSwitches();
    $gameActors        = new Game_Actors();
    $gameParty         = new Game_Party();
    $gameTroop         = new Game_Troop();
    $gameMap           = new Game_Map();
    $gamePlayer        = new Game_Player();
};
  • セーブファイルの文字列を、jsonパースし、ゲーム変数($gameSystem等)に格納
// game_managers.js 438行目
DataManager.extractSaveContents = function(contents) {
    $gameSystem        = contents.system;
    $gameScreen        = contents.screen;
    $gameTimer         = contents.timer;
    $gameSwitches      = contents.switches;
    $gameVariables     = contents.variables;
    $gameSelfSwitches  = contents.selfSwitches;
    $gameActors        = contents.actors;
    $gameParty         = contents.party;
    $gameMap           = contents.map;
    $gamePlayer        = contents.player;
};
Viewing all 242 articles
Browse latest View live