さわらブログ

さわら(@xhiroga)の技術ブログ

RPG(プログラミング言語)はどうして自分には読みづらいのか

現場のRPGのプログラムがどうして自分には読みづらかったのか、考えたことの棚卸し。

抽象度が低いコードも書かなくてはいけない(環境の問題)ことと、JavaPythonなら普通にある文法がない(言語自体の問題)ことの二つが原因だと考えています。

環境の問題

JavaPythonならライブラリを導入するところを、開発者が手動で実装している印象があります。
実行環境がベンダー製のOSに限られること、開発当時にインターネットがそれほど普及していなかったことから、ライブラリという考え方そのものが広まっていなかったのではないでしょうか。

具体的になかったものは、

  • 標準ライブラリがない
    カレンダー型とかtimestamp型とかそういう便利なものを見た覚えがありません(そもそもimportがないと思います)

  • 外部ライブラリがない
    例えば、データを帳票に印刷するためのスプールファイルを作るための外部ライブラリが現場になく、その部分のコードを各実装者が手動で書いていた状況を知っています。
    そのせいで、印刷に関すること(どこで改行する、何列目に印字する、etc...)と、ロジックに関すること(値がゼロなら項目を印刷しない、見出しは内容がある時だけ印字する、etc...)が混ざっていて、読み解くのに苦労しました。

ただし、共通のサブルーチン(メソッドのようなもの)はあり、処理の共通化はそこで行われていました。

言語自体の問題

文法で一番びっくりしたのは、ソースコード1行あたりの文字数が決まっていたことでした。
f:id:hiroga_cc:20170908070928p:plain

(wikipediaより)
調べたら、「自由形式」というソースの記述方法を使っていないらしいです。

他にも、こんな文法がありませんでした。

  • ループ処理の種類が少ない
    doループしか見た覚えがない。for、while、mapは見当たりませんでした。

  • 例外処理がない
    try - catch- finallyがなく、実行時エラーが起きた場合は呼び出し元にステータスコードを返却していました。

  • インデントが自由に使えない
    IF文とかFOR文の中身にインデントがかかってないのを想像してほしいのですが、かなり読みづらいです。

  • クラスがない(最新の言語仕様にはある)
    全部がJavaでいうところのプリミティブ型。timestampを呼び出して年月を取得するみたいなことはできません。 ただし、構造体はあります。dateクラスにあたるオブジェクトを構造体で表現しているのをよく見かけました。

  • SQLがない(最新の言語仕様にはある)
    データベースのデータをテーブルとして抽象化して扱わずに、その中のファイルを直接読み書きすることができます。
    高速な一方で、SQLと1対1で理解しようとすると難しかったです。

まとめ

普段使っているJavaなどと比べると、RPGのプログラムは様々な経緯から読みづらく感じることが多くありました。
ただ、そのおかげでプログラミング言語の進歩を感じることができ、個人的には読む経験ができてよかったと感じています。

(2018年7月28日 Update)

ショッカソン2017ひとり反省会(アップデート版)

8月26日(土), 27日(日)の2日間、ショッカソン(触覚デバイスを使ったハッカソン)に参加した。 ハッカソンを通しての自身の反省と、運営について感じたことをいくつか。

ちなみにハッカソン自体はチームメンバーにも恵まれ、先生方から勉強になるフィードバックをいただき、初のショッカソンの雰囲気も体験できてすごいよかった。

ひとり反省会

チーム「のんあーる」として参加したけど、なんだか小さくまとまってしまったと思った。

※来場者の皆さんに楽しんでもらえたと思うし、チームメンバーは素晴らしく専門性を発揮していたけど!

自身の担当パート(VRメガネ)は改良の余地があったし、チーム全体に働きかけてもっと面白いアイデアを出したかった。 それができてなくてちょっとショック。

ハッカソンに悪い意味でこなれてきているせいで、「コミュニケーションをサボってる」ことが原因だと思う。

自分のパートで

VRメガネでも、「自分が傾くと画面がもっと傾く」とか「ピントが勝手にずれる」とかやりたいことが他にもあった。 ところが、Unity上で画面を赤くするだけで2日目の朝までかかってしまった!(徹夜ではない)

実装力がないのは仕方ないけど、優先度のつけ方と相談が減っていることが問題だと思う。 どうしてそう思ったかというと、1日目にめちゃくちゃ悩んだ「なぜかGoogle CardBoardでも視野が複眼にならない」問題について 自分がドツボにはまっている時に、チームメンバーの@TJ16thさんがググってパッと解決してしまったから。 TJ16thさんは(多分)Unityの専門家じゃないんだけど、困っていることはちゃんと共有しなきゃと思った。

もっと言えば、実装の順番も違ったと思う。 佐藤先生から「画面が傾いたらどう?」ってアドバイスをもらった時、「あ〜赤くするのにこだわってないでそっちやれば…」と思った。 こういう優先度付けをちゃんとチームの人と話し合っていれば…悔しい…

チーム全体で

チーム内で「これって本当に酔ってる感覚?」とか「気持ちよい酔いってなんだろう?」とかもっと話すよう働きかけたかった。 お客さんからたくさん指摘をもらって、そういう議論が足りなかったことがわかった。

例えば、気持ち良い酔いを目指していたはずなのに、「気持ち悪い〜」という反応がたくさん出てしまったこと。 逆に気持ち悪い酔いを目指しました!でも全然ありなんだから、そういう方向で考え直すべきだった。 そうすれば、もっと触覚をオーバーにするようなアイデアが出たかもしれない。

他には、画面がなんで赤いのか全然伝わってなかった&自分自身も説明に困った。 実は初めは黒く染まるように設計していて、「めまいを再現しました!」っていうつもりだった。ただ、黒くしているはずが灰色になってうまく伝わらなさそうだったので、じゃあ赤だ、みたいな感じで実装してしまった… なんでチームメンバーに相談しなかったんだろう。

運営について感じたこと

自分も近いうちにハッカソンに運営側で参加してみたいなって思うので、その観点から気が付いたことを。

1日目~2日目通して審査員さんを呼んだり、各チームに行き渡るだけの協賛を取ってきたり、etc…ショッカソン運営の方々には本当に感謝してます! 一方で、初めて参加する人にもっと親切にできたかも?って思いました。 特にアイデアソンとデモ以降の流れについて。

イデアソンでは、特に発表〜チーム決めの時間を倍くらい取った方が、やりたいことが決まっていない人に親切だと思います。 今回は投票上位のアイデアをプレゼン→参加者はやりたいアイデアのところに並ぶ、という流れでしたが、 1. 情熱枠(投票では上位に入っていないけど、やりたいことがある人枠)をやりたい人がいないか聞いてみた方がよかったかも 2. 各アイデアの発表者に参加者がインタビューしに行く時間があってもよかったかも と思います。

  1. については、上位アイデアの中に一人で複数アイデアを出している人がいたり、発案者が「他のやりたいです」って言っているものがあったので、 その分だけは情熱枠を募ってもよかったんじゃないか?と思いました。
  2. については、単に焦らずにチームを決めたかったというのがあります。笑 混雑していてあんまり話を聞く時間も取れなかったので…

限られた時間である程度の人数のいるチームを作成する(完成度を保証する必要があると思うので)ってとても大変だと思うので、もし自分が運営で↑をやれって言われたら準備できるかちょっと不安ですが…。

デモ以降の流れについては、「他チームのデモを体験する時間がどこか分からなかった(来場者向けデモとは別にあると思った)」という意見をチームメンバーから聞きました。 プレゼン以降は作品に触る時間ありません、っていうのがわかっていたら…と思います。 そうすればチーム内でシフトを組んで他のチームのデモの体験とかもできたと思うので、残念でした。

【備忘録】DB2における「表の参照が必要なんだけど内容はどうでもいい」の書き方

SQLのMERGE句で、対象のテーブルと比較するデータソースをプログラムの変数として渡す場合って、
USING句の中身が不要になると思います。

例:任意の従業員の給料を30万円にする。その従業員が見つからない場合、新たにレコードを追加する。


MERGE EMPLOYEE
USING (不要)
ON EMP_ID = ?
WHEN MATCHED THEN UPDATE SET EMP_SALARY = '300000'
WHEN NOT MATCHED THEN INSERT (EMP_ID, EMP_SALARY) VALUES (?, '300000')

こうした場合の書き方を先輩から習ったので備忘録に。

MERGE EMPLOYEE
USING SYSIBM.SYSDUMMY1
ON EMP_ID = ?
WHEN MATCHED THEN UPDATE SET EMP_SALARY = '300000'
WHEN NOT MATCHED THEN INSERT (EMP_ID, EMP_SALARY) VALUES (?, '300000')

SYSIBM.SYSDUMMY1は必ず1行のレコードが入ったテーブルで、こうした参照が必要な場合に使われているようです。

福島GameJam'17 観測範囲のノウハウまとめ

アセット編

3Dモデルの投稿サイト。 www.sketchup.com

3Dドット絵の可愛いキャラクターの詰め合わせパック。 https://www.assetstore.unity3d.com/jp/#!/content/28926

株式会社ビサイドさま作成の車椅子に乗った女性キャラクター。 ゲームジャムにおいては無償で使用可能。 github.com

探し方のコツ * “Police"より"Policeman”,“COP"の方がヒットするかもしれない。

その他編

地形をUnityに取り込む qiita.com

焼印付き段ボールの生成 Online Photo Editor | Pixlr Editor

Pixlrを使って、レイヤーの重ね方をoverlayにする f:id:hiroga_cc:20170821074720p:plain

音源の生成

rbenvで初めてのRuby on Rails

ローカル環境で作業すると色々苦労が多そう。なので備忘録を作っておきます。

 

本当はMastodonのローカルサーバーを建てる時が初めてのRailsだったのだけど、Railsの勉強という意味では初めて。今回はQiitaで紹介されてたチュートリアルを進めてる。

 

ローカル環境構築で参考にしたのはコレ

どっちもググって頭の方に出てきたもの。ありがたいなあ。 

 

やったこと

まずはvendor/bundleという即席フォルダにrailsをinstall。

Gemfileのひな形作成→railsを対象に含めるよう書き換え→bundle installの順。

Gemfileにはもともとrailsコメントアウトされているので、viで編集して外します。

$ rbenv version
$ rbenv exec bundle init
$ vi Gemfile
$ rbenv exec bundle install --path vendor/bundle

 

次はアプリケーションの作成と即席フォルダ等の削除。

ここまで環境を汚さないことに拘るのか。初心者なので素直にやる。

$ rbenv exec rails new hello_app
$ rm -f Gemfile
$ rm -r Gemfile.lock
$ rm -r .bundle
$ rm -r vendor

 

できたらサーバーの起動。

$ rbenv exec rails server

http://localhost:3000/

 

やったね!

f:id:hiroga_cc:20170816155513p:plain

 

やってみて 

チュートリアルのいう通りCloud9でやったほうが絶対楽だ。Cloud9からHerokuに直接デプロイもできるらしい。すげえな。

でもMastodon建てた時の知識を整理しておきたかったので良い機会にはなった。 

Githubでコミットのたびにツイートする(ときの名前の出どころが知りたかった)

先人の知恵をお借りするのが一番。

pogin.hatenablog.com

 

設定するとこんな感じになる。

 どうしても分からなかったのが、この名前部分をどこから持ってきているのか。

(コミット時の署名から持ってきているのだけど、当時は知らなかったので)GithubとかTwitterのアカウント設定を隅々まで見ても、どこにも本名は入れてないので不思議でした。

 

ここに入ってる名前はホームディレクトリの.gitconfigファイルで確認できます。

$ cd ~

$ vi .gitconfig

みたいなね。

 

仕事でGit使ってる人なら常識なんだろうけど、業務系システムだとGit使ってるとこはまだ少数派なんじゃないかな?分からんけども。

Unityでウォーグレイモンを走らせてジャンプさせてみた

f:id:hiroga_cc:20170815083858j:plain

 

Unityで自分の好きなキャラ動かせるとめっちゃ気持ちいんですよ。

 キャラクターのインポートからキーボードでグリグリ動かすまで、備忘録を作りました。

 

参考にしたページ

第8回目:3Dキャラクターをノンプログラミングで動かす(後編)|Tech Book Zone Manatee

Unityちゃんを動かしてみる | Think IT(シンクイット)

Unity - 入力されたキーの情報を取得する - Qiita

 

手順

1. 準備
1-1. プロジェクトの作成
1-2. オブジェクトの配置

2. ウォーグレイモンの作成
2-1. アバター定義の追加
2-2. ウォーグレイモン召喚
2-3. Character Controllerの追加

3. ダッシュ編
3-1. 走るアニメーションの追加

4. ジャンプ編
4-1. カメラに追わせる
4-2. ジャンプの追加

* もしUnity未経験なら初めに公式のチュートリアルやってからの方が絶対いいです

 

 1. 準備

まず、必要なアセットをインポートします。

・キャラクター

今回はこちらのウォーグレイモンのモデルを拝借しました。

free3d.com

・動き

https://www.assetstore.unity3d.com/jp/#!/content/7673

https://www.assetstore.unity3d.com/jp/#!/content/5330

 

完了したらプロジェクトを作成し、上記のアセットをインポート。

これからウォーグレイモンが立つ場所を作っておきます。

Create > 3D Object > Plane

* PlaneのScaleをx,y,zそれぞれ5づつくらいにしておくと、走らせた時に落ちなくて良いです。

 

2. ウォーグレイモンの作成 

モデルをHierarchyに追加する前に、アバター定義(グリグリ動かすための骨組みと肌との間のマッピングのことらしい)を作成します。

ProjectビューのWarGraymon.fbxを選択し、InspectorのRigタブで

Animetion Type > Humanoid を選択し、Applyを選択。

* 画像はデュークモンですが手順は一緒です。

f:id:hiroga_cc:20170815001502p:plain

ちなみにここで失敗すると

Invalid Avatar Rig COnfiguration. Missing or invaild trasform:

        Required human bone 'Hip' not found

って表示がよく出てきます。

文字通りお尻に当たる部分のパーツが見つからないか、もしくは単にアバターがパーツごとの区別を保って作成されていないかどどちらか。(単にHipを解析するのが最初だからHipでエラーになるだけで、細分化されてない時はだいたいこのエラーになる)

 

エラーがなければウォーグレイモンのPrefabをHierarchyにドラッグ&ドロップし、ウォーグレイモンを召喚します。

ここで再生するとこんな感じ。

f:id:hiroga_cc:20170815001148p:plain

さらに、重力とか回転とかをUnityの物理エンジンに再現させるためのComponentをウォーグレイモンに追加します。

Add ComponentでRigidbodyを追加し、Use Gravityをチェック。

f:id:hiroga_cc:20170815001151p:plain

この時点で再生するとこんな感じになります。落下する。

これは地面とウォーグレイモンに当たり判定をするためのComponentが追加されていないため。それぞれ追加します。

PlaneにBox Colliderを追加

ウォーグレイモンにはCharacter Contorollerを追加。*1

多分ウォーグレイモンの体のサイズと合ってないので、Sceneビューを見ながら数値をいじって調整します。特に、地面に埋まらないように足元の調整に気を使う。*2

f:id:hiroga_cc:20170815001158p:plain

私の場合はこんな結果になりました。

f:id:hiroga_cc:20170815001204p:plain

* ウォーグレイモンにCapsule Colliderを追加してもいいのですが、Character Controllerだと変にウォーグレイモンが転がってしまうことがないのでこっちのが便利。

* 私の環境のウォーグレイモンは足元を調整しても地面に埋まったんですけど、ポージングに問題があったっぽい。Motionで適当なアニメーションを設定したら埋まらなくなりました。

 

ここまでで役者は揃いました。あとはアニメーション。

 

3. ダッシュ編 

初めにインポートしたMecanim Locomotion Starter Kitをウォーグレイモンに追加していく作業です。

 ウォーグレイモンのAnimator > Controllerの右側の◉をクリックし、Locomotionを選択。合わせて、Apply Root Motionをチェック(これやらないと方向キーに反応してくれないっぽい)

f:id:hiroga_cc:20170815001201p:plain

さらにAdd Component > ScriptでLocomotion Controllerを選択します。

ここまでで再生すると方向キーに合わせてウォーグレイモンが動くはず!

 

4. ジャンプ編

せっかくなのでカメラにウォーグレイモンを追わせます。

一番手軽なのはMain CameraをHierarchyでウォーグレイモンの子要素にしてしまうことなのですが、もっとスムーズにカメラが付いてくるやり方があるのでそっちにしましょう。

Main CameraにAdd ComponentでSmooth Followを追加します。次に、TargetにWarGraymonを追加します。これでいい感じにカメラが追尾してくれます!

 

ジャンプを追加します。ジャンプのモーションをもつ状態を作成し、それへの遷移を追加する感じです。

Asset > Locomotion Setup > Locomotion > Locomotionをダブルクリックし、Animatorビューへ移動。下の画面になると思います。

f:id:hiroga_cc:20170815001206p:plain

 

まずStateを新規作成します。空白部分で右クリック  > Create State > Emptyし、名前を任意に変更(Jumpとか)

MotionにRunJumpを追加します。(何種類かあるので適当に選んで、あとで気に入ったのにすると良いと思います。)

 

次に遷移を追加します。新規作成したStateの上で右クリックしMake Transitionを選択。矢印をWalkRunへと結びます。できたら逆に、WalkRunの上で右クリックして新規作成したStateへのTransitionを追加します。

 

最後に、Transitionに遷移のための条件を追加します。

Animatorビュー左上のParametersで+を押下し、Triggerを選択。名前は"Jump"としておきましょう。

できたら先ほど追加したTransitionのうち、WalkRunからJumpに伸びるほうをクリック。Inspectorビューで変更を加えます。Conditionsで+を押下し、先ほど作成したParametersのJumpを選択してください。

ここまでできたらAnimatorビューでの作業は終わりです。

 

ParametorsのJumpをオンオフするスクリプトを追加します。HierarchyビューでWarGraymonを選択し、Add Component > New Scriptで"WGController"を作成します。

* 別に名前はなんでもいいのですが、C#のクラス名とは合わせる必要があります。

 

できたらvoid Update( ){ }の中を以下の通り書き換えてしまってください。

 

void Update () { 
  Animator anim = GetComponent ();
  AnimatorStateInfo state = anim.GetCurrentAnimatorStateInfo (0);
if (Input.GetKeyDown (KeyCode.Space)) { anim.SetTrigger ("Jump"); }
}

 

以上で作業は全て終了です。あとは再生ボタンを押せばウォーグレイモンが動くはず!

 

やってみて

好きなキャラクターがグリグリ動くのって予想以上に楽しい。Unityってとっつきにくそうなイメージがあったけど全然そんなことはなかった(Adobe触った経験があったからかもしれない。 UIが似てる)

個人で楽しむ分には色んなモデルがインターネット上にあるし、こういうので楽しみながら練習してハッカソンとかで役に立てたいなと思う所存です。