mieki256's diary



2018/03/01(木) [n年前の日記]

#1 [dxruby] 先日書いたDXOpalのアレコレを別PC上で動かして確認したり

先日書いた DXOpal用のアレコレを、メインPC以外でも動かしてみて、処理落ちするかどうかを確認してみたのだけど。なかなか厳しい結果に。

手持ちの WindowsタブレットPC DELL Latitude 10 (CPU: Atom Z2760(1.5 - 1.8GHz)) + Windows 8.1 32bit + Firefox で動かしてみたら、8FPSとか16FPSとかそんな感じで。まあ、CPU が Atom だから…。これは仕方ないだろう…。

足元で埃を被ってるサブPCで ―― CPU: AMD Athlon II X2 250 (3.0GHz, 2コア), M/B : ASRock M3A785GMH/128M (AMD785G + AMD SB710, ATI Radeon HD 4200) + Ubuntu 16.04 LTS + Google Chrome で動かしたら、54 - 60FPS の間をフラフラ。昔の CPUとは言え、3.0GHz、2コアのCPUで動かしても、安定して60FPSは出ないのか…。

どうもブラウザ上で動かすと、違う処理がちょこちょこと割り込んでしまって、フレームレートが安定しないのではないか、という気もする。特に、拡張の類を入れていると、そういうことが起きたりするのではないかという疑念も。

フレームレートが安定しないなら、前フレームからの経過時間で計算して動かすぐらいしか手が思いつかないなと。

#2 [nitijyou] 日記をアップロード

2018/02/20を最後に、日記をアップロードしてなかったので、アップロード。

2018/03/02(金) [n年前の日記]

#1 [cg_tools] ドットを打ってる

EDGE2を使って、プレイヤーキャラっぽいドットを打ってるところ。

テスト用のプログラムを書くにしても、それっぽい画像が無いと、アタリ範囲の座標設定がちゃんとできないので、これはちょっと作らないといかんかなと。

昔に作った、 _ワイデスモドキな画像 で実験できなくもないけれど…。彼は見た目が大きいので少々問題が。 なので、「おそらく本番ではこのくらいのサイズになるはず」てな基準画像を作ってから各作業に挑むのが適切、だろうなと。

このあたり、2Dゲームに限らず、3Dゲームも同様で。「とりあえず実験を始められるから…」的に、只のボックスを表示して実験していると、後になって人体モデルと差し替えた際、「アレレ?」「こんなはずではなかったに」という感覚になる。ローポリでも構わないから、まずはとにかく人体に見えるもの、かつ、頭身等が本番とそこそこ一致するシルエットのモデルを仮表示しておいたほうがいいのだろうなと。

EDGE2でアニメは作りづらい気がする。 :

とりあえず EDGE2 で作業しているけれど。どうもアニメが作りづらいなと…。静止画相当のドット絵を打ってる分には、これといった不満はないのだけど。 *1

作業の流れとしては、以下のような感じでやっているけれど。
  1. 大きいサイズの画像を用意して。
  2. 80x80ドットや96x96ドットでグリッドを表示して。
  3. 各グリッド内で1コマずつ描いて。
  4. キャプチャフレームウインドウを表示して、アニメにしたいコマをキャプチャして(範囲を登録して)。
  5. アニメーションプレイやウインドウでアニメとして再生して。
  6. 動きがおかしいなと感じたら元のドット部分を再修正。
再生ウインドウで「むっ」と思ったら、その場でその場所を修正、というわけにはいかないあたりがなんだかアレだなと。敷き詰めることが前提のタイル画像を作成する際もそうなのだけど、プレビューと、ドット編集作業が、分離してるあたりが…。

もっとも、本来なら、「ページ」を活用して作業すべきなのかも。「ページ」を使えば、オニオンスキンも利用できるし。ただ、「ページ」を使ってしまうと、大きい画像内に色んなパターンを敷き詰めた、最終画像のイメージが想像できなくなるところもあって。

作業を始める前に、今回はアニメを描くのか、それとも各パターンをまとめるのか、どちらの作業が優先されるのかを意識してから、作業の流れ・利用する機能を決めるべきだったのかもしれず…。

*1: いやまあ、静止画相当の際は、シンメトリーモード(左右対称、上下対称、上下左右対称で描画できるモード)や、タイルモード(タイルを敷き詰めて、どこにドットを打っても元のタイル画像が修正されるモード)が欲しい気もしてるけど。もっとも、描画機能が充実してるツールなので、今からそれらモードを追加実装するなんて、かなり難しいだろうと予想してるわけだけど。自由曲線ツールや直線ツールとは別に、シンメトリーペンツール等の専用ツールを別途実装するか、それとも各描画ツールに少しずつ各モードへの対応処理を追加していくか…。後者は絶対バグが混入する予感。他に、左領域に何か描いたら即座に右領域へと左右反転転送、右領域に書いたら即座に左領域へと左右反転転送、といった実装もありそうだけど、レスポンスが悪くなりそうな予感も。

2018/03/03() [n年前の日記]

#1 [cg_tools] ドットをまだ打ってる

EDGE2を使ってまだドットを打ってたり。

スライディングは…どうしよう…。入れといたほうがいいかな…。アレのソレって元々はストライダー飛竜から来てるからスライディングも入ってるのだろうけど、緊急回避の操作として考えると、エイリアンソルジャーのゼロ移動のほうが面白くなりそうな気もするわけで。

#2 [windows][cg_tools] WACOMドライバは最新版を入れれば良いと言うものでもないらしい

弟から譲ってもらった、WACOMデジタイザ(アクティブスタイラス)搭載のWindowsタブレット機、DELL Latitude 10 を触っていたのだけど。ペンを使うと何かの拍子に、マウスカーソルの下に「Alt」だの「Ctrl」だのが表示されて、デスクトップ操作のアレコレができなくなって困ってしまったり。

調べてみたら、どうやら _Wacom Feel Driver の現行版、ISD_DualTouch_7.3.4-47.exe をインストーしていたのがマズかったらしい…。ISD_DualTouch_720-10.exe (7.2.0-10)をインストールしてみたら、件の症状が出なくなった。

以下、参考ページ。

_ASUS vivotab note 8 メモ - カニ食べたい
_Wacomペン関連 - Latitude 10 まとめ @ ウィキ - アットウィキ

それはさておき。しばらく作業をしてみたものの…。自分の手が邪魔。この手はせめて半透明にならないのですか。無理か。

2018/03/04() [n年前の日記]

#1 [cg_tools][ruby][dxruby] ドットをまだ打ってるけどそろそろなんとかなりそう

EDGE2を使ってドットを打ってるけど、そろそろある程度、仮画像が出来上がってきた。とは言っても、斜め床への対応や、しゃがみ攻撃のパターンその他は描いてないけど…。

キャプチャフレームウインドウを表示して、アニメに使いたい領域を指定して、アニメパターンを列挙してみたけど。アニメーションデータをxmlでエクスポートした後で悩んだり。この xml を、DXRuby/DXOpal で、そのまま使うのはちょっと難しいよな…。JSONに変換するツールスクリプトを書くか…。

ところで。自分、EDGE2でxml出力できるのは、キャプチャグループフレームアニメだけと _思い込んでいた けど。随分前から、キャプチャフレームアニメもxmlエクスポートができる状態だったらしい…。以下の更新履歴を見ると他にも色々な改良がされているようで、少しずつ眺めて把握しようとしているところ。

_EDGE2 更新履歴 | TAKABO SOFT

EDGE1の動作が少し気になる。 :

ふとなんとなく、EDGE2 ではなく EDGE1 でキャプチャフレームアニメ機能(アニメーションフレーム)が使えるか試してみたところ、画像をクリックして領域を選択した瞬間に EDGE1 が不正終了してしまった…。環境は Windows10 x64 バージョン 1709 Fall Creators Update。

ただ、2〜3回動作確認していたら、不正終了しなくなった。何故。もしかして、弄ってるうちに、落ちなくなる儀式を行ってしまったのだろうか。 *1

まあ、普段は EDGE2 を使って作業してるからアレなのだけど。なんだかちょっと気になる動作だなと…思ったので一応メモ。

*1: グリッドサイズを設定し直すとか、パターンを新規作成するとか…。本来必要な初期化処理が正しく行われる操作が存在するのかもしれず。

#2 [ruby] Rubyでxmlのパースについて少しメモ

Ruby の場合、以下のライブラリが標準添付されているので…。 これらを使えば、xml を読んで JSON にして出力することも難しくはないはず。

ちなみに、REXML は、動作がめちゃくちゃ遅いそうで、一般的には Nokogiri その他を使うことが多いらしい。

_GemのいろいろXML/HTMLparserをまとめたい(Oga特集) - Qiita
_XMLパースはPython速い。Ruby糞遅い。でもRubyにも希望はある。それはOx! - new_pill’s blog

今回は、それほど大きいxmlをパースするわけではないので、REXML で済むのではないかと予想しているところ。とりあえず、以下を眺めながら、irb を起動して、使い方を調べているところ。

_XML処理 REXMLの使い方 - プログラムメモ
_たのしいXML: RubyでXMLデータを扱う

2018/03/05(月) [n年前の日記]

#1 [dxruby] EDGE2からエクスポートしたアニメデータをDXOpalで描画

EDGE2からエクスポートしたキャプチャフレームアニメデータのxmlを、JSONに変換して DXRuby/DXOpal で読み込んで描画するサンプルを書いてみたり。

_DXOpal animxml2json

カーソルキーの上下でパターン切り替え。左右で水平反転の切り替え。

素材画像について。 :

今回作成したドット絵画像は以下。License : CC0 / Public Domain ってことで。自由に使ってください。1パターン 96x96ドット。10x12個並べてある状態。

scifistk01_pose.png

各パターンを作成するため使ったパーツ画像は以下。これも 96x96ドット単位で並べてある。何か抜けてるところがありそうだけど…。

scifistk01_parts_only.png

EDGE2のキャプチャフレームアニメxmlファイルと、変換後の JSON は以下。

_scifistk01_anime.xml
_animedata.json

攻撃方向は減らしたほうが良かったかも。 :

画像を作っていて思ったけれど、プレイヤーキャラの攻撃方向は、横のみにしたほうが良かったのかもしれないなと。上下や斜めも攻撃できるようにすると、御覧の通り、膨大なパターン数になってしまう…。

これでもまだ、斜め床には非対応なわけで…。仮に、斜め床も対応させようとすると、上記画像の立ってるパターン数 x 4倍のパターン数を増やさないといけない。 *1 更に、しゃがみ攻撃まで加えた場合は、2倍のパターン数になる。

考えてみたら、例えばストライダー飛竜、悪魔城ドラキュラシリーズ、SHINOBIシリーズなどは、基本的に横方向にしか攻撃できないけれど、それでもプレイしていてちゃんと面白いわけで。攻撃方向に制限があったほうが、攻略方法を工夫することに繋がって、むしろ遊びになる、ような気もしてきた。

とは言え、上下や斜めに攻撃できると、敵が空中で派手に動いても狙い撃てるから、敵の動きの制約が少なくなって、ゲーム画面の見た目を派手にできるところもあるわけで。うーん。

せめて、上半身と下半身を、分けて管理するとか…。それもそれでパズルになりそうだけど。

*1: x:y = 2:1(22.5度)、1:1(45度)の角度の床に対して、右向きと左向きの足の角度をそれぞれ別途用意しないといけないから、4種類(4倍)を追加することになる。

#2 [ruby][dxruby] RubyのOpalで少しハマったかもしれず

DXRuby で動いていたスクリプトを DXOpal で動かしたら謎のエラーが出て悩んでしまった。

どうも、ハッシュのキーを配列で返してくれる、Hash#keys が、Opal では動かない気配がする…。いや、もしかすると、自前で(?)JSON からハッシュに変換した際に妙なことになったのかもしれないけど。

更に加えて、以下の記述もエラーになった。

_Hashのキーを文字列からシンボルに変換する - Qiita
Hash[ h.map{|k,v| [k.to_sym, v] } ]

どうも Opal のハッシュ関係は、未実装な部分があるか、あるいは動作が元々の Ruby と何か違っている状態なのかもしれない…。いや、もしかすると、自前で(?)JSON からハッシュに変換した際に妙なことに以下略。ちょっと自信無し。

何にせよ、素直な書き方をしてる分にはOpal上でも動くけど、どこかRubyらしい変態チックな書き方をし始めると、Opal上では動かなくなる可能性があったりするのかもしれないなと思えてきたりもして。

文字列のキーをシンボルのキーに変換したいのだけど。 :

JSON を読み込んでハッシュにすると、キーが全部、文字列になってしまう。シンボルのキーにしたいのだけど…。

Ruby の _JSONライブラリ を使えるなら、オプションの :symbolize_names に true を指定してやれば変換してくれるのだけど。DXOpal の場合、そういうことはできない予感。おそらく JSONライブラリ自体が使えない状態であろう気もする。

となると、自前で変換しないといけないわけだけど。おそらく今後も何度かそういう処理をすることになるだろうから、文字列やシンボル名を決め打ちにして処理せずに、汎用性がある関数にできれば…。

いや、以下の記事によると、あまり気にしなくてもいいのかな。シンボルのほうが速くなるのだろうと思ったけど、昔ならともかく最近はそうでもないようだし。

_HashキーのStringアクセスとSymbolアクセスのパフォーマンス比較 - Hack Your Design!

少し話はずれるけど。Ruby 2.5 は、ハッシュのキーを文字列からシンボルに変換する機能を標準で持っているらしい。

_Ruby の Hash のキーを Symbol に変更する - Secret Garden(Instrumental)

調べているうちに、ふと思った。一般的なプログラミング言語では、ハッシュのキーを文字列にしてあるのが普通で、シンボルにして扱うなんて特殊だよなと。処理速度的に大きなメリットがあるならともかく、たいして変わらないのであれば、キーは文字列のままでいいんじゃないか…。

ということで、一旦はキーをシンボルに変換する処理を書いていたけど、やっぱり文字列のまま扱うことにしてしまったり。

2018/03/06(火) [n年前の日記]

#1 [ruby][emacs] Rubyソースの整形ツール rufoをインストールしてみた

Rubyソースを整形してくれる、rufoというツールがあるらしい。

_Rubyの高速フォーマッタ−"Rufo"を使ってみる - Qiita
_ruby-formatter/rufo: The Ruby Formatter - created by @asterite

インストールしてみた。環境は Windows10 x64。
gem install rufo

rufo hoge.rb で整形できる…のかな。たぶん。

Emacsからrufoを呼び出す。 :

自分は普段、Rubyソースを Emacs (NTEmacs) で書いてるけれど、Emacs から rufo を呼び出すために、rufo.el をインストールしてみた。

_aleandros/emacs-rufo: Emacs integration with the Rufo ruby code formatter

gitを使ってローカルにクローン。
gti clone https://github.com/aleandros/emacs-rufo.git

rufo.el を、~/.emacs.d/elisp/ 以下にコピー。

~/.emacs ( ~/.emacs.d/ntemacs.el ) に以下を記述。
;; rofu - Ruby source formatter
;; C-z f  rufo-format-buffer
(require 'rufo)
;; (setq rufo-enable-format-on-save t)
(setq rufo-enable-format-on-save t) を有効にすれば、.rb ファイルを保存するたびに rufo が呼び出されるのではないだろうか。試してないけど。

rufo.el の中で、C-c f を rufo-format-buffer に割り当ててあったが、自分の環境では既に利用していたショートカットキーだったので、rufo.el を直接弄って C-z f に変更しておいた。とメモ。

#2 [xyzzy] xyzzyのlispを少し勉強

この日記ページを書く際には、xyzzy というEmacs系のエディタを使っているのだけど。時々、同じような編集作業をする時があるので、多少自動化できないかと xyzzy の lisp についてググって勉強してみたり。

リンクの記述を変更する関数。 :

以下のような行があったとして。
正規表現をテストして遊ぶ (xyzzy[しょぼしょぼすくりぷと])
http://edutainment-fun.com/script/xyzzy/tips/regular.html

上記の記述を、以下のように変更したい。
 LINK http://edutainment-fun.com/script/xyzzy/tips/regular.html 正規表現をテストして遊ぶ (xyzzy[しょぼしょぼすくりぷと])

そういう処理をする関数を書いてみたり。
(defun transpose-hnf-link ()
  (interactive)
  (progn
    (goto-bol)
    (forward-line)
    (transpose-lines)
    (backward-line 2)
    (goto-eol)
    (insert " ")
    (delete-char)
    (goto-bol)
    (insert "LINK ")
    (goto-bol)
    (forward-line)))

(define-key *hnf-mode-map* '(#\C-c #\k) 'transpose-hnf-link)

lisp の達人が見たらゲロを吐きそうなソレだろうけど…目的が果たせそうだから、これでいいや…。

少し説明すると…。
  • 関数を作る時は、(defun hoge () 〜 ) と書く。
  • (interactive) と書いておくと、「この関数はコマンドだよ」「M-x 関数名で呼び出せるよ」という意味になる。
  • (progn 〜 ) と書いておくと、上から順々に処理をしてくれる。
  • (goto-bol) で行頭に、(goto-eol) で行末に、カーソルが移動する。
  • (forward-line) で、1行下に、(backward-line)で、1行上に、カーソルが移動する。
  • (forward-line n) (backward-line n) で、n行下、n行上に、カーソルが移動する。
  • (transpose-lines) で、現在行と一行上を入れ替える。カーソルは、現在行の1つ下に移動する。
  • (insert "hoge") で、現在のカーソル位置に hoge という文字列を挿入できる。
  • (delete-char) で、現在のカーソル位置で、1文字削除できる。Deleteキーを押した時と同じ動作、だろうか。
  • (define-key *hoge-mode-map* '(#\C-c #\k) 'fuga-func) で、ショートカットキーが設定できる。この場合は、「hoge-mode 時に、C-c k のキー入力で fuga-func を呼び出せ」という設定になる。

リンクURLを変更したいけどやり方が分からず。 :

以下のような記述があったとして。
 LINK http://hogefuga/~piyo/diary/201312203.html#201312203 piyo's diary - 記事名

以下のように変更したい。
 LINK #{2013,12,20,3} piyo's diary - 記事名

しかし、やり方が分からない。

正規表現を使えば、該当文字列にマッチさせることはできそう。
 M-x query-replace-regexp
 Query repla regexp: ^LINK http:///hogefuga/.+#
 With: LINK #

ただ、xyzzy の lisp から、それを呼び出す方法が分からない…。

余分な部分を削除するだけなら、以下のような感じだろうか…。
(defun change-hnf-link-uri ()
  (interactive)
  (if (looking-at "^LINK http://hogefuga/.+#")
      (progn
        (delete-region (match-beginning 0) (match-end 0))
        (goto-bol)
        (insert "LINK #"))))
  • (if a b) で、a が t なら、b を実行。
  • (looking-at "正規表現") で、正規表現とマッチするか場所があるかを調べられる。マッチしたら t、しなかったら nil が返る。
  • (delete-region A B) で、A から B までの範囲を削除。
  • (match-beginning 0) で、正規表現に一致した場所の先頭を、(match-end 0) で、正規表現に一致した場所の末尾を取得。

待てよ? 余分な部分を削除できたら、後は「{」「,」「}」を挿入していくだけなのでは…。(forward-char n) で、カーソルをn文字右に移動して、(insert ",") で挿入していけばなんとかなるかも。

#3 [pc] 無線LANルータが正しいIPアドレスを渡してくれない

手持ちのタブレットPC、DELL Latitude 10 がインターネットに接続できなくて悩んだり。調べてみたら、無線LAN(Wi-Fi)が、正常なIPアドレスを取得できてなくて。ウチの場合は、192.168.n.xxx になるはずが、192.168.27.3 になっていて…。なんでや。

使ってるルータは、NEC Aterm WR8300N。

ルータを再起動したり、タブレットPCの Windows8.1 x86 を再起動したり、管理者権限でコマンドプロンプトを開いて ipconfig /release や ipconfig /renew を打ってみたりしたけど変化無し。

よく分からないことに、Aterm WR8300N が提供する、2種類の無線LANのうち、暗号化が甘いほう(WEP)に繋ぐと、正しく 192.168.n.xxx が得られる。しかし、WPA/WPA2-PSK(AES)のほうに繋ごうとすると、妙なIPアドレスが返ってくる。

結局、ルータ側のDHCP固定割当設定を使って、IPアドレスを固定する方向で対処。タブレットPC側も、DHCPを使わず、IPアドレスを決め打ちで設定してみたり。

しかし、どうしてこんな状況になるのだろう…。

2018/03/07(水) [n年前の日記]

#1 [xyzzy] xyzzy のlispについてまだ勉強中

リンクのURLを変換する処理について、まだ試行錯誤中。

例としては…。以下のような記述があったとして。
 LINK http://hogefuga/~piyo/diary/201312203.html#201312203 piyo's diary - 記事名

以下のように変更したい。
 LINK #{2013,12,20,3} piyo's diary - 記事名

一応、こんな感じかなと。
(defun change-hnf-link-uri ()
  (interactive)
  (if (looking-at "^LINK http://keroro/.+#")
      (progn
        (delete-region (match-beginning 0) (match-end 0))
        (goto-bol)
        (insert "LINK #{")
        (forward-char 4) (insert ",")
        (forward-char 2) (insert ",")
        (forward-char 2) (insert ",")
        (forward-char 1) (insert "}"))))

(define-key *hnf-mode-map* '(#\C-c #\C-k) 'change-hnf-link-uri)

別のやり方も試してみたり。looking-at で探す際にグルーピングをしておいて、後で特定のフォーマットに並び替えて挿入。
;; 別のやり方
(defun change-hnf-link-uri-b ()
  (interactive)
  (if (looking-at "^LINK http://keroro/.+#")
      (progn
        (delete-region (match-beginning 0) (match-end 0))
        (goto-bol)
        (if (looking-at "^\\([0-9]\\{4\\}\\)\\([0-9]\\{2\\}\\)\\([0-9]\\{2\\}\\)\\([0-9]+\\)S\\([0-9]+\\)")
            (let ((yyyy (match-string 1)) (mm (match-string 2))
                  (dd (match-string 3)) (xx (match-string 4)) (yy (match-string 5)))
              (delete-region (match-beginning 0) (match-end 0))
              (goto-bol)
              (insert (format nil "LINK #{~A,~A,~A,~A,~A}" yyyy mm dd xx yy)))
          (if (looking-at "^\\([0-9]\\{4\\}\\)\\([0-9]\\{2\\}\\)\\([0-9]\\{2\\}\\)\\([0-9]+\\)")
              (let ((y (match-string 1)) (m (match-string 2))
                    (d (match-string 3)) (s (match-string 4)))
                (delete-region (match-beginning 0) (match-end 0))
                (goto-bol)
                (insert (format nil "LINK #{~A,~A,~A,~A}" y m d s)))
            )))))

正規表現のグルーピングを使うところでちょっとハマった。例えば、M-x replace-regexp などを使うときは、
\([0-9]\{4\}\)
みたいな書き方でいいのだけど。lispスクリプト(?)内に正規表現を書く際は、
\\([0-9]\\{4\\}\\)
といった感じに書かないといかんらしい。

つまり、
\(   \)   \{   \}
は、
\\(  \\)  \\{  \\}
と書くことになるようで。最初、そのことが分からなくて、「変だなー。マッチしないなー」と悩んでしまった…。

参考ページ。 :

#2 [pc] 正体不明のDHCPサーバがどこかに居る

LAN内で、DHCPが正常に働かない時があるので、少し調べていたのだけど。どうも、NEC製ルータ Aterm WR8300N 以外に、謎のDHCPサーバが居るような気がしてきた。

以下の、dhcploc.exe というツールを使うと、DHCPサーバが居るかどうかを調べることができるようで。

_TechNet DHCPLOC Utility
_不正なDHCPサーバを見付ける − @IT
_不正DHCPサーバを探す - 負け組小道を行く
_DHCPサーバーが複数できちゃったとき、原因となる機器を探すには・・・ | GalaxyRing

使い方は、以下。
dhcploc 自分が使ってるPCのIPアドレス
実行後、何も表示されないのが正常状態。dキーを叩くとDHCPサーバにダミーの要求を送って結果を表示するので、どんなDHCPサーバが居るのかが分かる。終了は qキー。終了までちょっと待たされる。

試してみたら、192.168.n.1 以外に、192.168.27.1 てのが居るっぽい…。
> dhcploc 192.168.n.7
22:02:48    OFFER (IP)192.168.27.4    (S)192.168.27.1    ***
22:02:48    OFFER (IP)192.168.n.6     (S)192.168.n.1     ***
お前、一体誰なんだ。

しかし、必ず居るとは限らないようで…。出てくる時もあれば、出てこない時もある…。ということは、常時電源を入れてる機器ではなく、時間帯によって電源を入れたり切ったりしてる機器、ということになるのだろうか。

当初、東芝製HDDレコーダ RD-BZ710 を疑ったけど、電源を入れたり切ったりしても変化はなく。コイツではないな…。

#3 [zatta][neta] 「ケータイ」と呼ぶのか「スマホ」と呼ぶのか

「からかい上手の高木さん」というアニメを見てたら、スマホのことを「ケータイ」「ケータイ」と呼んでいて、なんだか気になり始めてしまったり。

いやまあ、スマホも携帯電話の一種なので、ケータイと呼んでも間違いではないのだけれど。しかし、個人的には、しっくりこない…。目の前に「スマホ」があったら、「スマホ」と呼んじゃうよな…。「ケータイ」と言われると、どうしても「ガラケー」が脳裏に浮かぶわけで…。

小中学生の間ではスマホもケータイと呼ばれていて、それを漫画やアニメにも反映させているなら、それはそれで、とも思うのだけど。実際には、どちらで呼ばれている場面が多いのだろう。

_「ケータイ」って呼んだらオバサン扱い?使われなくなった「携帯電話用語」5選 - モデルプレス
_「スマホ」って呼び方に違和感あるやつwwww : スペア速報@まとめ
_スマートフォンを「携帯」と呼ぶのはおかしいでしょうか?前に友達... - Yahoo!知恵袋
_ケータイやスマホの呼び方について - 私は30歳なのですが、携帯電話の事... - Yahoo!知恵袋
_スマホを携帯と呼ぶのはナンセンスでしょうか? - スマートフォン... - Yahoo!知恵袋

うむ。分からん。どっちなんだ。

ただ、「スマホもケータイの一種だからケータイと呼んでも何らおかしくないです」と、やや攻撃的に主張を繰り返しているように見えなくもない人が存在するようではあるなと…。わざわざそのような主張を繰り返すということは…。たぶんその人は、常日頃周囲から「ケータイ」と呼ぶことについて何かしら言われていて、必死に反抗してる可能性があるかもなと。つまり、「スマホ」を「スマホ」と呼ぶ人が、実際には多数派なのではないか…。てのはちょっと邪推し過ぎだろうか。

これって例えば、(ファミコン|PCエンジン|メガドライブ|スーファミ|プレステ)を「ゲーム機」「ゲーム機」と呼んでるような状態なのだろうか。いや、それはちょっと違うか…。その場合、(iPhone|Android)を「スマホ」「スマホ」と呼んでる状態に近い気がする…。別におかしくはないよな…。

「ガラケー」を使っていた時期がある世代は、「ガラケー」と「スマホ」を区別する必要があったから、「スマホ」は「スマホ」と呼んだのだろうけど。今の子供さんが物心ついたときには、「ガラケー」は絶滅状態だから、「えっ? 『スマホ』以外の『ケータイ』なんてあるの?」という感覚なのかもしれない。となると、「スマホ」は「ケータイ」と呼ばれている可能性が高い…? つまり、「スマホ」を「スマホ」と呼ぶのは「オジン」「オバン」で、「スマホ」を「ケータイ」と呼ぶのがナウいヤング、だったりする…?

まあ、意味が伝わればどっちでもいいので、実にどうでもいい話だったりするわけですが。

余談。 :

それにしても、あの作品、時代設定が分からん…。「ママレードボーイ」っぽいアニメが流行ってるらしいので昔の設定なのかと思いきや、その劇中アニメは深夜アニメとして放送されてるし、フツーにスマホも出てくるし。しかし現代なのかと思いきや、主人公とヒロインは後に、という作品も存在するらしいので、するとやっぱりアレは昔の話なのかと…。

もっとも、そのへん言い出したら、例えばCCさくらの新作アニメ版も見れなくなってしまう。前作は小学生時代、今作は中学生時代だけど、今作はスマホもドローンも出てくる…。中学生になるまでに、一体何年経過してるのか…。いや待て。そんなこと言ってたら、名探偵コナンなんて一体どうなっちゃうのか。

まあ、漫画やアニメ作品の時代設定について考えるのは野暮ですな。面白くなるなら何でもアリだよなあ…。むしろ、漫画なんだから、スマホで連絡を取り合う助さん格さん黄門様や、ドローンを活用する風車の弥七、ハーレーダビッドソンを乗り回す暴れん坊将軍が出てきちゃってもいいぐらい、だよなと。

2018/03/08(木) [n年前の日記]

#1 [pc] LAN内のDHCPが正常に働かない原因が分かった

ここ最近、稀に、家の中のPC、スマホ、タブレットが、インターネットに接続できなくなる不具合に遭遇してたのだけど。ようやく原因が分かった。

犯人は、茶の間に設置してある、東芝製液晶TV、REGZA Z9000 (37Z9000) だった。コイツが、「俺もDHCPサーバだよ! お前のIPアドレス、俺が決めちゃうよ!」と、NEC製ルータ Aterm WR8300N を遮って、妙なIPアドレスをPC群に渡してた…。

LAN内にDHCPサーバが2台あるのだから、そりゃおかしなことになりますわな。そして、時間帯によって居たり居なかったりもするわけで。茶の間のTVをつけている時だけ、2台目のDHCPサーバがLAN上に出現していたのだな…。なんだかちょっぴりシュタインズ・ゲートっぽい。プチシュタゲ。

正確には、東芝やREGZAが悪いわけではなくて…。REGZA背面の、LAN接続HDD専用LAN端子に、イーサネットコンバータ(として使ってる) PLANEX MZK-MF150B を誰かが繋いじゃったのが悪いわけですが。 *1

REGZA Z9000 背面のLAN端子について。 :

もう少し解説しておくと…。REGZA Z9000 の背面には3つのLAN端子があって。(REGZA Z9000 取扱説明書・準備編 19ページ目、64ページ目に図がある。)
  LAN-HDD専用端子    汎用LAN端子     ひかりTV専用
    ┌────┐    ┌────┐    ┌────┐
    │        │    │        │    │        │
    │┌──┐│    │┌──┐│    │┌──┐│
    └┴──┴┘    └┴──┴┘    └┴──┴┘
  • 一番左の、LAN接続HDD専用端子にLANケーブルを差すと、REGZA内部のDHCPサーバが動き始める。LAN接続HDDに対してIPアドレスを割り当てて、REGZAから使えるようにするために、そういう仕様になっているのだろう。
  • イーサネットコンバータの類を接続するなら、真ん中の端子に差さないといけない。
今回は、一番左と、真ん中の端子から、イーサネットコンバータ側の2つのLANポートに、わざわざケーブルを2本使って接続してあった…。真ん中の一本だけ繋いどけばいいのに…。

ちなみに、ググってみたら、今時のREGZAなら無線LAN機能を内蔵してる製品もあるらしい。最初から無線LANを内蔵してあったら、こんなトラブルには遭遇しないのだろうな…。

漫画にできそう。 :

どんな状態になっていたのかを漫画にできそうだなと思えてきたので、試しに漫画にしてみたり。

dhcpserver_01_001.png

dhcpserver_02_001.png

許さない。2台目のDHCPサーバ…お前の存在を絶対に許さない。

それにしても、自分のような絵心の無い人間でも漫画を作れるのだから、 _コミPo! って便利だなと…。

参考ページ。 :


*1: まあ、おそらくやったのは親父さんかお袋さんだろうけど…。「アレ? このケーブル、どこに差すんだ? ここが空いてるな。きっとここだろう」と、掃除でもした時に差しちゃったのだろう…。「HDD専用」と書いてあるのだけど、親父さんも、お袋さんも、もはや小さな文字は読めないし。そもそも、イーサネットコンバータが何なのか分かってないみたいだし。そういえば、たしか以前、イーサネットコンバータを指差しながら、「コレがHDDじゃないのか?」と親父さんが言っていた、そんな朧げな記憶も…。たぶんコレ、繋いだのは親父さんっぽいな…。

#2 [ruby][neta] Rubyに見捨てられる前に見捨てたほうがいいのだろうか

Ruby の MJIT云々の話や、Rubyコミュニティ内では「OSはUNIXに収束した」という認識だったりするあたりの話や、元々Rubyの神様は「Windowsは無視する」と決めた上でRubyを開発してきた、という過去の記事も読んだりしているうちに、今後のRubyは*NIXサーバ専用言語になっていくのだろうか、これはいよいよ Windows上で Ruby を使うのは諦めたほうがいいのだろうか、などとなんとなく思えてきてしまったりもして。そのあたりの思考過程をGRPでメモした、とメモ。

「Rubyでゲームが作れないかと試してきたけど。俺達(?)、(Ruby|Matz|Rubyコミュニティ)に嫌われているんじゃないか……」みたいな。いやまあ、嫌われる以前に存在を認識されてない気配も。

#3 [ruby][mruby] mrubyについてググってたり

サクッと起動してサッと処理してスッと終わる系のアレコレは mruby とやらを使ってどうにかできんのかなと思ったのだけど、そもそも mruby って、名前はよく聞くけど何ができそうなのか全然分からないのでググっているところ。

require が使えないからライブラリが使えない、という話が気になる。代わりに mrbgem てのがあるらしいのだけど、どういうものなのか分からない…。

luaで2Dゲームが作れる _love2d というゲーム制作環境があったりするのだけど。それの Ruby版を作れたりしないかな、例えば mruby + SDL2 で、などと夢想したりもするわけで。ググってみたら、mruby + SDL2 が実現できないか試してた方もいらっしゃるようだし…。「Rubyでゲームを」という需要には、そういった別の何かで対応できたりはせんのかなと。

_mruby-sdl2作ってます - crimsonwoodsのブログ

もっとも、mruby って何なのかよく分かってないので、とにかくそこから把握していかないと…。

2018/03/09(金) [n年前の日記]

#1 [ruby][mruby] Windows上でmrubyのビルドを試したり

以下の記事を読みながら、Windows10 x64 + Visual Studio 2015 Community + bison + Ruby 2.2.6 p396 mingw32版で、mruby がビルドできるのか実験。

_Windows上でmrubyをビルドし動かしてみる - Qiita
_mruby概論(2):“組み込みRuby”こと「mruby」をセットアップしてみよう (1/3) - MONOist(モノイスト)
_mruby/mruby: Lightweight Ruby

おお。スゴイ。あっという間にビルドが終わった。bin/ディレクトリ内に、*.exe ができてる。

mruby hoge.rb を実行したら動いてくれた。なんだか感動。

以下の記事によると、MinGW + MSYS を使ってもビルドできるらしい。MinGW + MSYS もインストールしてある環境なので、試してみたり。

_mrubyをWindows 7(MinGW, msys)でビルドしてみた - 平凡なエンジニアの独り言 はてなブログ出張所

ビルドできてしまった…。

でも、Visual Studio 2015 でビルドした時は、各exeが数百KBという小ささになったのに、MinGW版は、各exeが6〜7MBぐらいになってしまった。かつ、MinGW版は、実行して結果が返ってくるまで待たされる。puts "Hello world" しか書いてないスクリプトも、1秒ぐらい経ってから出力される。何故なんだろうな。

MSYS2 を使ってもビルドできるのかなと試してみたら、コレは途中でエラーになった。

mrbgemについて勉強。 :

以下のページを眺めながら勉強。

_mrbgemの話それから標準ライブラリの話 - けいぞうのメモ帳
_mrubyのビルド方法 - Qiita

mrubyをビルドするためのファイル一式の中に、 _build_config.rb というファイルがあって、コレを修正してから mruby をビルドすることで、欲しい機能・ライブラリが追加された状態の mruby が出来上がるらしい。で、そういう仕組みを mrbgem と呼んでいる、のかな。たぶんそうなんだろう…。

つまり、一般的なRuby(CRuby?)はガンダムみたいなもんで…。コアファイターの上にガンキャノンの上半身をつけたり、下にガンタンクの下半身をつけたりして、コアファイターを一々作り直すことなく、MS(モビルスーツ)のスペックを変えることができる。

mrubyは、ザク、グフ、ドムみたいなもんで…。電撃が使いたかったら、ザクを改良してグフを開発しないといけないし、ホバー機能が欲しかったら、ドムを作らないといけない。ザクに何かを合体させたら電撃が使えたりホバー機能が使えるようになるわけじゃない。MSそのものを最初から作り替えないといけない。

ますます分かりづらい喩えになってないかコレ。

2018/03/10() [n年前の日記]

#1 [windows] FLTKをVisual Studio 2015でビルド

FLTKなるGUIライブラリがあるらしい。

_Fast Light Toolkit - Fast Light Toolkit (FLTK)
_Download - Fast Light Toolkit (FLTK)

mrubyでGUI表示をする際に使われていたりするようで。

_RyanScottLewis/mruby-fltk: FLTK 1.3.2 GUI binding, built for MRuby 1.0.0.
_Big Sky :: mruby で GUI!もう組み込み用途とは言わせない!mruby-fltk3 書いた。
_mattn/mruby-fltk3

興味が湧いたので、Windows10 x64 + Visual Studio 2015 Community でビルドできるか実験。以下のページを参考にしながら作業してみた。

_How to install and use fltk-1.3.4 in Visual Studio 2017 2.0 [complete guide] - preventing cross-contamination - bumpy road to code
_How to install and use fltk-1.3.4 in Visual Studio 2017 [complete guide] - bumpy road to code

ビルドできるか試す。 :

以前は FLTK3 なるバージョンがあったらしいけど。公式サイトでは「FLTK3 は開発停止じゃよ」と書いてあった。ひとまず FLTK 1.3.4-2 をビルドできるか試してみる。

_Download - Fast Light Toolkit (FLTK)

fltk-1.3.4-2-source.tar.gz をDL。解凍。今回は D:\Dev\fltk\ に、fltk-1.3.4-2 フォルダを置いてみた。

fltk-1.3.4-2\ide\VisualC2010\fltk.sln を、VSS2015 で開く。「これは VS2010用だからVS2015用に更新するよ」的ダイアログが表示された。OKをクリック。

右上の「ソリューションエクスプローラー」の中の、demo を右クリックして、スタートアッププロジェクトに設定、を選択。

ビルド → ソリューションのビルド、を選択。ビルドが始まる。

ビルドに成功すると、「ビルド: 79 正常終了」とメッセージ欄に表示される。

上のほうで「ローカルWindowsデバッガー」が表示されてる状態で、F5キーを叩いて実行してみる。

DOS窓が一つと、ウインドウが表示された。ウインドウ上のボタンを押すと、FLTKのウィジェットが色々見られる。Exitボタンを押して一旦終了。どうやらビルドはできたらしい。

上のほうの「Debug」を「Release」に変更。ビルド → ソリューションのリビルド。F5キーで実行。

今度はリリース版としてビルドしたので、DOS窓は無しでウインドウだけ表示された。

ライブラリの追加方法。 :

ビルドができることは分かったけど、他のアレコレで、FLTK を使う方法がよく分からない。Visual Studio のインストールフォルダ内に、FL、libフォルダ等をコピーしちゃう手もあるらしいけど…。

とりあえず、Vsiaul Studio 上でプロジェクトを作成して作業する分には、プロパティで追加ライブラリを指定することができるっぽい。

例えば、ファイル → 新規作成 → プロジェクト → テンプレートの中の、Visual C++ → Win32 → Win32コンソールアプリケーション、を選んで、空のプロジェクト、にチェックを入れてプロジェクトを作成。

ソリューションエクスプローラー → ソースファイルを右クリック → 追加 → 新しい項目 → C++ファイル(.cpp) を選んで、fltktest.cpp を作成。以下を記述。
#include <FL/Fl.h>
#include <FL/Fl_Box.h>
#include <FL/Fl_Window.h>
int main()
{
       Fl_Window window(200, 200, "Window title");
       Fl_Box box(0, 0, 200, 200, "Hey, I mean, Hello, World!");
       window.show();
       return Fl::run();
}

プロジェクト → 一番下の、〜のプロパティを選択。

構成を「Debug」に。リンカー → 入力 → 追加の依存ファイル → 右側の下向き三角ボタンを押して「編集」 → 以下を追加。
fltkd.lib
wsock32.lib
comctl32.lib
fltkjpegd.lib
fltkimagesd.lib

構成を「すべての構成」に。VC++ディレクトリ → ライブラリディレクトリ → D:\Dev\fltk\fltk-1.3.4-2\lib を追加。

C/C++ → 全般 → 追加のインクルードディレクトリ → D:\Dev\fltk\fltk-1.3.4-2 を追加。

この状態でビルドすれば、ウインドウとメッセージが表示される。

リリース版でビルドしたい時は、プロジェクト → 〜のプロパティ。構成を「Release」に。リンカー → 入力 → 追加の依存ファイル。以下(Debugと違って、最後に「d」がついてないファイル名)を追加。
fltk.lib
wsock32.lib
comctl32.lib
fltkjpeg.lib
fltkimages.lib

リンカー → システム → サブシステム → Windows (/SUBSYSTEM:WINDOWS) に変更。

これで、上のほうの「Debug」を「Release」に変更してF5キーを押せば、ビルドし直してリリース版が動く。

つまり、追加ライブラリの場所を適切に指定できればビルドはできるようになるはず。

だけど。必ずしも Visual Studio を起動してビルドするとは限らないわけで。

以下を参考にして、Visual Studio 2015 のインストールフォルダ内にコピーするしかないのだろうか。

_Installing FLTK with Visual Studio
  • D:\Dev\fltk\fltk-1.3.4-2\FL フォルダを、C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include 内にコピー。
  • D:\Dev\fltk\fltk-1.3.4-2\lib\*.lib等を、C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\lib 内にコピー。
  • D:\Dev\fltk\fltk-1.3.4-2\fluid\*.exe を、C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin 内にコピー。
コレで合ってるのかな…。

FLTK3の入手方法が分からない。 :

さておき、mruby-fltk3 とやらを使ってみたくて FLTK3 を入手しようと思ったのだけど、入手方法が分からない。公式サイトのリンクをクリックすると、ユーザ名とパスワードを要求される…。

一応 MSYS2 上で Subversion をインストールして、
svn co http://seriss.com/public/fltk/fltk/branches/branch-3.0/ fltk-3.0
と打ってみたけど、こちらもユーザ名やパスワードを要求されるし、何かがDLできたものの、中に必要なファイルが入ってるようには見えない。

やはり FLTK3 は開発中止になったと捉えるべきなのだろうか。

#2 [ruby][mruby] mrubyのmrbgemを試す

mruby に機能を追加していく時は、mrbgem なるものを使うらしい。build_config.rb を編集して、追加したいアレコレを記述してビルドし直して、追加機能入りの mruby を作る…のだとか。

実際試してみないと感じが掴めないなと。試してみたり。

mruby-jsonを追加。 :

JSONのパースができるライブラリがあるらしいので追加してみた。

_mattn/mruby-json

"mrubyのファイル一式を置いてある場所"\build_config.rb を編集。

  # Use mrbgems
と書かれたあたりのところに、以下の行を追加。
  conf.gem :github => 'mattn/mruby-json'

mruby をビルドし直し。自分の環境は、Windows10 x64 + Visual Studio 2015 Community なので、スタートメニューから、Visual Studio 2015 → 開発者コマンドプロンプト for 2015 を起動。cd hoge で目的のディレクトリに移動してから、以下。
ruby ./minirake

出来上がった .exe は、少しファイルサイズが増えた。

mirb を起動して動作確認。
> mirb
mirb - Embeddable Interactive Ruby Shell
> jsontext = '{"x":100, "y":200, "names":["hoge", "fuga", "piyo"]}'
=> "{\"x\":100, \"y\":200, \"names\":[\"hoge\", \"fuga\", \"piyo\"]}"
> hash = JSON::parse(jsontext)
=> {"x"=>100, "y"=>200, "names"=>["hoge", "fuga", "piyo"]}
> hash["x"]
=> 100
> hash["y"]
=> 200
> hash["names"].each {|s| puts s}
hoge
fuga
piyo
=> ["hoge", "fuga", "piyo"]
> exit

機能として追加されたっぽい。なるほど、こういう感じで使うのか…な。

mruby-randomは追加できなかった。 :

疑似乱数が得られる、Random というクラスもあるらしいので追加しようとしたけれど…。エラーが出る…。

_matsumotory/mruby-random: mruby-random

build_config.rb を編集。以下を追加。
conf.gem :git => 'https://github.com/matsumoto-r/mruby-random.git'

ビルド。
ruby ./minirake

エラーが出る…。
rake aborted!
Don't know how to rake D:/Ruby/mruby/mruby/build/host/mrbgems/mruby-random/src/mrb_random.obj

どういう意味のエラーメッセージだろう…。

mruby-tinymtを追加。 :

疑似乱数に関しては、mruby-TinyMT という版もあるらしい。Ruby で使われてる Random、というか _Mersenne twister に、何か制限を加えて軽くした版、とかなんとか。

_matsumotory/mruby-tinymt: rand() and srand() method with TinyMT
_Tiny Mersenne Twister (TinyMT)

build_config.rb を編集。以下を追加。
  conf.gem :git => 'https://github.com/matsumoto-r/mruby-tinymt.git'

ruby ./minirake

こちらはビルドが通った。

> mirb
mirb - Embeddable Interactive Ruby Shell
> tmt = TinyMT.new(0xf50a1d49, 0xffa8ffeb, 0x0bf2bfff)
=> #<TinyMT:0xd28ad0 tinymt32_ctx=#<Object:0xd28ab0>>
> tmt.srand(5)
=> nil
> tmt.rand()
=> 0.061755396425724
> tmt.rand()
=> 0.47946119308472
> tmt.rand(6)
=> 5
> tmt.rand(6)
=> 5
> tmt.rand(6)
=> 3
> tmt.rand(6)
=> 1
> tmt.rand(6)
=> 5
> exit

動いてるっぽい。

その他のライブラリ。 :

以下でその他のライブラリが紹介されてるのでメモ。

_mruby - libraries

2018/03/11() [n年前の日記]

#1 [windows][mruby] Visual Studio 2015上でSDL2を使った何かをビルド

Windows10 x64 上で、mruby + SDL2 を動かしてみたいのだけど。その前に、Visual Studio 上で SDL2 を使った何かしらをビルドできる状態にしておかないといかんのだろうと想像するわけで。

ということで、Windows10 x64 + Visual Studio 2015 Community で、SDL2 を使った何かをビルドできそうかどうか実験。

SDL2関係のファイルを入手 :

Visual Studio で SDL2 を利用するなら、以下のファイルが必要らしい。
  • SDL2-devel-2.0.8-VC.zip (Visual C++ 32/64-bit)
  • SDL2_image-devel-2.0.3-VC.zip (Visual C++ 32/64-bit)
  • SDL2_mixer-devel-2.0.2-VC.zip (Visual C++ 32/64-bit)
  • SDL2_ttf-devel-2.0.14-VC.zip (Visual C++ 32/64-bit)
  • SDL2_net-devel-2.0.1-VC.zip (Visual C++ 32/64-bit)

以下から入手する。

_Simple DirectMedia Layer - SDL version 2.0.8 (stable)
_SDL_image 2.0
_SDL_mixer 2.0
_SDL_ttf 2.0
_SDL_net 2.0

一々ページを開いてDLするのが面倒なら、以下のリストを使って…。

_urls.txt
https://www.libsdl.org/release/SDL2-devel-2.0.8-VC.zip
https://www.libsdl.org/projects/SDL_image/release/SDL2_image-devel-2.0.3-VC.zip
https://www.libsdl.org/projects/SDL_mixer/release/SDL2_mixer-devel-2.0.2-VC.zip
https://www.libsdl.org/projects/SDL_ttf/release/SDL2_ttf-devel-2.0.14-VC.zip
https://www.libsdl.org/projects/SDL_net/release/SDL2_net-devel-2.0.1-VC.zip

wget にURLリストファイルを渡して、一気にDLする、とか。
wget --no-check-certificate -i urls.txt
wget を使ってhttpsサーバにアクセスさせる時は、wget --no-check-certificate をつけるといいらしい。

_wgetでこういう時はこうする!! - Qiita

zip群をDLできたら、解凍する。今回は D:\sdl2\dev\vc\ 以下にコピーした。includeフォルダ内に *.h を、libフォルダ内に *.lib と *.dll をまとめておく。lib は、x86 と x64 (32bit版と64bit版)があるので、今回は x86 版を使って作業した。

VS2015でプロジェクトを作成。 :

ファイル → 新規作成 → プロジェクト → Visual C++ → Win32 → Win32コンソールアプリケーション。

Win32アプリケーションウイザードが開くので、空のプロジェクト、にのみチェックを入れて、プロジェクトを新規作成。

ソリューションエクスプローラーで、ソースファイルを右クリック → 追加 → 新しい項目 → main.cpp を追加。

main.cpp の内容は以下にする。ウインドウを開いて2秒経ったら閉じる、という処理らしい。

_開発環境 Linux | ゲーム作ろう
#include <SDL.h>
 
int main(int argc, char *argv[])
{
    SDL_Window* win = NULL;
 
    if( SDL_Init( SDL_INIT_EVERYTHING ) < 0 )
    {
        return 1;
    }
 
    win = SDL_CreateWindow("hello",
            SDL_WINDOWPOS_UNDEFINED,
            SDL_WINDOWPOS_UNDEFINED,
            640, 480,
            SDL_WINDOW_RESIZABLE);
 
    if( ! win )
    {
        return 1;
    }
 
    SDL_Delay(2000);
 
    SDL_DestroyWindow( win );
    SDL_Quit();
 
    return 0;
}

プロジェクトのプロパティを設定。 :

プロジェクト → プロパティ。構成を「すべての構成」に。
  • VC++ディレクトリ → インクルードディレクトリに、SDL2 の includeフォルダを追加。
  • VC++ディレクトリ → ライブラリディレクトリに、SDL2 の lib でディレクトリを追加。

リンカー → 入力 → 追加の依存ファイル → 以下を追加。
SDL2main.lib
SDL2.lib

リンカー → システム → サブシステム → Windows(/SUBSYTEM:WINDOWS) に変更。

C/C++ → コード生成 → ランタイムライブラリ → /MT に変更。これで静的リンクがされるらしい。が、このへんよく分かってない。メモリリークがどうのこうのという話もあるらしいけど…。

ビルドしてみる。 :

ビルド → ソリューションのビルド。正常終了と表示されたらいいな。

F5キーを押して実行。

「SDL2.dll が見つからないため、コードの実行を続行できません。」とエラーメッセージが表示された。

DL・解凍した、SDL2 の libディレクトリ内に、*.dll がたくさん入っているので…。プロジェクトの保存ディレクトリ内の、DebugディレクトリやReleaseディレクトリの中に、*.dll をごっそりコピーする。

再度 F5キーを押して実行。今度はウインドウが表示された。

ということで、Visual Studio 上でビルドはできる、ようではあるなと…。

画像を表示したい。 :

せっかくだから画像を表示してみたい。main.cpp を以下の内容にして、(Debug|Release)ディレクトリに sample.bmp や sample.png を置いて実験。
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
// #include <stdio.h>
// #include <string>
#include <iostream>
// #include <fstream>


int main(int argc, char *argv[])
{
    SDL_Window* win = NULL;
    SDL_Renderer *renderer;
    SDL_Surface *image;
    SDL_Texture *tex;
    SDL_Event ev;


    if (SDL_Init(SDL_INIT_VIDEO) < 0)
    {
        return 1;
    }

    win = SDL_CreateWindow("hello",
        SDL_WINDOWPOS_UNDEFINED,
        SDL_WINDOWPOS_UNDEFINED,
        640, 480,
        SDL_WINDOW_RESIZABLE);

    if (!win)
    {
        return 1;
    }

    renderer = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED);

    IMG_Init(IMG_INIT_PNG);

    image = IMG_Load("sample.png");
    // image = SDL_LoadBMP("sample.bmp");
    if (image == NULL)
    {
        return 1;
    }

    tex = SDL_CreateTextureFromSurface(renderer, image);
    SDL_FreeSurface(image);

    while (true) {

        SDL_SetRenderDrawColor(renderer, 32, 160, 64, 255);
        SDL_RenderClear(renderer);

        if (SDL_PollEvent(&ev)) {
            if (ev.type == SDL_QUIT) {
                break;
            }
        }

        SDL_RenderCopy(renderer, tex, NULL, NULL);
        SDL_RenderPresent(renderer);
        SDL_Delay(10);
    }

    IMG_Quit();
    SDL_DestroyTexture(tex);
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(win);
    SDL_Quit();

    return 0;
}

Visual Studio 上で F5キーを叩いてみたけど、画像が表示されない…。(Debug|Release)ディレクトリ内に出来上がった .exe を実行すると、画像が表示されるのだけど…。

Visual Studio の作業ディレクトリ設定を変更しないといけないらしい。デフォルトでは、プロジェクトディレクトリが作業ディレクトリになっているので、プロジェクト → 〜のプロパティ → デバッグ → 作業ディレクトリ → 「参照」を選んで、Releaseディレクトリ、もしくは、Debugディレクトリを選択してやることで、任意の作業ディレクトリを設定することができる。

これで、Visual Studio 上で F5キーを叩いた時も、画像が表示されるようになった。

vs2015_sdl2_ss01.png

文字列の出力ができない。 :

処理が失敗した時に何かメッセージを出力するようにしてみたかったのだけど、やり方が分からない…。

#include <iostream> をして、std::cout << "hoge" << std::endl; で出力できたりしないのかな…。それとも、#include <stdio.h> を書いて、printf("hoge"); とか。でも、どこにも文字列が出力されてないような。

参考ページ。 :


2018/03/12(月) [n年前の日記]

#1 [windows][mruby] Visual Studio上でデバッグウインドウに何かメッセージを出す

昨日、Visual Studio 2015 Community上で、C++ で書いたプログラム内から何かメッセージをどこかしらに出力したいけど出力されなくて悩んでたのだけど。

その後ググってたら、#include <Windows.h> をして、OutputDebugString() を使えば、デバッグウインドウにメッセージを出せるらしい、と分かった。

_その3 デバッグウィンドウを知らないと大変です
_Win32アプリケーションのデバッグ方法 [VC++の使い方]

ただ、tchar.h もインクルードして、出力したい文字列は _T("hoge") と囲まないといかんようだなと…。
#include <Windows.h>
#include <tchar.h>

...

        OutputDebugString(_T("# MSG: Load Image\n"));

...

もっとも、コレ、Windows + Visual Studio でしか使えない気がするわけで。MinGW用や、*NIX上でも使えるソースを書きたい場合は、何かもうちょっと工夫が必要になるのだろうなと。

まあ、動作確認が終わったら、該当行をコメントアウトしちゃうだけでもいいのかもしれんけど。

#2 [ruby][mruby] MinGWでSDL2関係のビルドができるか実験

Windows10 x64 上で、mruby-sdl2 をビルドしたい。が、どうも sdl2-config を呼び出してるように見える。

_crimsonwoods/mruby-sdl2: mrbgem to use SDL2.0
_mruby-sdl2/mrbgem.rake at master - crimsonwoods/mruby-sdl2

sdl2-config の中身はシェルスクリプトなので、bash だの sh だのが用意されてる環境が前提のような気がする。となると、Visual Studio (Visual C++) を使ったビルドはできない予感。

しかし、もしかしたら MinGW + MSYS ならビルドできるのだろうか…? 実験してみないと分からんな…。実験しよう…。

SDL2関係のインストール。 :

以下の記事を参考にして、MinGW + MSYS で、SDL2関係が使えるように環境を整える。

_MinGW 用の SDL2 インストール手順 メモ
_MinGW (32bit) 開発環境 インストール手順 メモ

自分の環境には MinGW + MSYS がインストールしてあるので、足りてなかった mingw32-libz dev (v1.2.8-1) だけ、MinGW Installer を使って、追加インストールした。

環境変数PATHの最初のほうに、以下を追加した状態で…。つまり、MinGW の bin/* と、MSYS の bin/* が呼び出せるようにしておいてから…。
C:\mingw\MinGW\bin;C:\mingw\MinGW\msys\1.0\bin

C:\mingw\MinGW\msys\1.0\msys.bat を実行。bash が起動する。

MinGW 用の SDL2関係ファイルを入手。

_Simple DirectMedia Layer - SDL version 2.0.8 (stable)
_https://www.libsdl.org/release/SDL2-devel-2.0.8-mingw.tar.gz

SDL2-devel-2.0.8-mingw.tar.gz をDL・解凍して、出てきたディレクトリをカレントディレクトリにする。今回は、D:\sdl2\dev\mingw\ というフォルダを作成して、その中に入れておいた。

以下を実行。
make install-package arch=i686-w64-mingw32 prefix=/mingw

これで、MinGWインストールフォルダ内の bin/ , include/ , lib/ ディレクトリ等の中に、SDL2関係のファイル(*.dll , *.h , *.a 等)がコピーされた。ちなみに、sdl2-config も bin/ にコピーされて、実行権限もついている。

この make install-package、今まで知らなかった…。これでサクッと下準備ができたのか…。

ビルドしてみる。 :

以下を参考にして、サンプルがビルドできるかどうか確認。

_MSYS2 + MinGW 環境に SDL2 をインストール - takaya030の備忘録

適当なフォルダを作成して、sdl2_sample.cpp を作成。sdl2_sample.cpp の内容は、上記ページのソレを使わせてもらったり。ちなみに、return (TRUE); でエラーが出たので、return (true); に変更。

Makefile を作成。上記ページのソレを参考にして、内容は以下にした。SDL_PREFIX を /mingw にしてるところが違い、だろうか。
TARGETS = sdl2_sample

all: $(TARGETS)

SDL_PREFIX  = /mingw
SDL_CONFIG  = $(SDL_PREFIX)/bin/sdl2-config
CG_LIBS     =

CROSS_COMPILE   = /mingw/bin/
CC = $(CROSS_COMPILE)gcc
CXX = $(CROSS_COMPILE)g++

CFLAGS = -g -Wall `/bin/sh $(SDL_CONFIG) --cflags`
CXXFLAGS = -g -Wall `/bin/sh $(SDL_CONFIG) --cflags`
LDFLAGS = `/bin/sh $(SDL_CONFIG) --libs`    -Wl,-rpath,$(SDL_PREFIX)/lib
LIBS = -lopengl32 -lglu32 -lm

clean:
    rm -f *.o *.a *~ $(TARGETS)

sdl2_sample: sdl2_sample.o
    $(CXX) -o $@ $^ $(LDFLAGS) $(LIBS)
clean: だの sdl2_sample: だのの次の行の先頭のスペースは、タブ文字を入れておかないといかんらしい。空白スペース4つにしたら、「区切り文字がおかしいぞ」と怒られた。

make を実行。sdl2_sample.o と sdl2_sample.exe ができた。

sdl2_sample.exe を実行。ウインドウが開いて何か描画された。

とりあえずここまでの作業で、MinGW + MSYS を利用すれば SDL2 を使った何かしらをビルドすることはできる、と分かった。

mruby-sdl2 をビルドしようとするが失敗。 :

以下の mrbgem をビルドできるのか実験。

_crimsonwoods/mruby-sdl2: mrbgem to use SDL2.0

mruby のファイル一式が入ってるディレクトリをカレントディレクトリにして、build_config.rb を編集。以下を最初のほうに追加。
conf.gem :github => 'crimsonwoods/mruby-sdl2', :branch => 'master'

make を実行。エラーが出た。
$ make
ruby ./minirake
(in d:/Ruby/mruby/mruby)
CC build/mrbgems/mruby-sdl2/src/misc.c -> build/host/mrbgems/mruby-sdl2/src/misc.o
gcc: error: `sdl2-config: No such file or directory
gcc: error: unrecognized command line option '--cflags`'
gcc: error: `sdl2-config: No such file or directory
gcc: error: unrecognized command line option '--cflags`'
rake aborted!
Command Failed: [gcc -g -std=gnu99 -O3 -Wall -Werror-implicit-function-declaration -Wdeclaration-after-statement -Wwrite-strings -g3 -O0 `sdl2-config --cflags` -DMRB_DEBUG -DMRBGEM_MRUBY_SDL2_VERSION=0.0.0 -I"d:/Ruby/mruby/mruby/include" -MMD -o "d:/Ruby/mruby/mruby/build/host/mrbgems/mruby-sdl2/src/misc.o" -c "d:/Ruby/mruby/mruby/build/mrbgems/mruby-sdl2/src/misc.c"]
make: *** [all] Error 1

sdl2-config が無いと言われてるような気がする…。でも、変だな。sdl2-config は、PATHが通った場所に、ちゃんとあるように見えるけど。
$ which sdl2-config
/mingw/bin/sdl2-config
あるよなあ。おかしいな。

Windowsの場合はshebangが使えないのではないかという疑惑。 :

*NIXの世界では、shebang というものがあって。

_シバン (Unix) - Wikipedia

テキストファイルの一行目に、
#!/bin/sh
とか
#!/usr/bin/ebv ruby
と書いておくと、

「このテキストファイルは /bin/sh で動かすファイルだよ」
「このテキストファイルは /usr/bin/env ruby で見つかったファイルで動かすファイルだよ」

という指定になって、それぞれを動かすことができる ―― てな仕組みを shebang と呼ぶらしい。

sdl2-config も、一番最初の行に、
#!/bin/sh
と書いてある。だから、bash上で、いきなり sdl2-config と打っても、実行することができる。

しかし、Windows上で動く Ruby は、shebang は見てないような気がするわけで。
mieki256@hogefuga: MINGW32: ~$ ruby -v
ruby 2.2.6p396 (2016-11-15 revision 56800) [i386-mingw32]

mieki256@hogefuga: MINGW32: ~$ irb

irb(main):001:0> `echo "hoge"`
=> "\"hoge\"\n"

irb(main):002:0> `which sdl2-config`
=> "\"C:\\mingw\\MinGW\\bin\\sdl2-config\"\n"

irb(main):003:0> `sdl2-config`
Errno::ENOENT: No such file or directory - sdl2-config
        from (irb):3:in ``'
        from (irb):3
        from c:/Ruby/Ruby22/bin/irb:11:in `<main>'

irb(main):004:0> `sh sdl2-config`
Usage: sdl2-config [--prefix[=DIR]] [--exec-prefix[=DIR]] [--version] [--cflags] [--libs] [--static-libs]
=> ""

irb(main):005:0> exit

MinGW + MSYS 上で、Ruby mingw版 の irb を実行すると…。
  • `which sdl2-config` で、sdl2-config が置いてある場所を把握できていることは分かる。
  • しかし、`sdl2-config` をしても、実行できない。
  • `sh sdl2-config` なら、実行できる。
ということで、どうも shebang は見てないのではないか、そのファイルを何を使って動かすか、そこまで指定しないといかんのではないかなあ、という気がしてきたわけで。

ならば、mruby-sdl2 の、mrbgem.rake を修正して、sdl2-config の前に sh をつければ動くのだろうか。以下のように修正してみた。
MRuby::Gem::Specification.new('mruby-sdl2') do |spec|
  spec.license = 'MIT'
  spec.authors = 'crimsonwoods'

  spec.cc.flags << '`sh sdl2-config --cflags`'
  spec.linker.flags_before_libraries << '`sh sdl2-config --libs`'
end

mieki256@dorobune: MINGW32: /d/Ruby/mruby/mruby$ make
ruby ./minirake
(in d:/Ruby/mruby/mruby)
CC build/mrbgems/mruby-sdl2/src/misc.c -> build/host/mrbgems/mruby-sdl2/src/misc.o
gcc: error: `sh: No such file or directory
gcc: error: sdl2-config: No such file or directory
gcc: error: unrecognized command line option '--cflags`'
gcc: error: `sh: No such file or directory
gcc: error: sdl2-config: No such file or directory
gcc: error: unrecognized command line option '--cflags`'
rake aborted!
Command Failed: [gcc -g -std=gnu99 -O3 -Wall -Werror-implicit-function-declaration -Wdeclaration-after-statement -Wwrite-strings -g3 -O0 `sh sdl2-config --cflags` -DMRB_DEBUG -DMRBGEM_MRUBY_SDL2_VERSION=0.0.0 -I"d:/Ruby/mruby/mruby/include" -MMD -o "d:/Ruby/mruby/mruby/build/host/mrbgems/mruby-sdl2/src/misc.o" -c "d:/Ruby/mruby/mruby/build/mrbgems/mruby-sdl2/src/misc.c"]

make: *** [all] Error 1

sdl2-config のみならず、sh すら見つからないと言ってきた。うーん。

もしかして、rake だか minirake だか分からんけど、どうもソレが動いてるときは、MinGW の bin/ や MSYS の bin/ を検索できないPATH状態になっているのかな…。

直接書いてみる。 :

このあたり、要するに、sdl2-config が出力した文字列を、コンパイラだかリンカだかのオプションとして指定してる、ということだよなと。

だったら、sdl2-config を介さずに、sdl2-config が出力した文字列を、mrbgem.rake に直接書いちゃえば、ひとまずビルドが通ったりしないかと思えてきたわけで。
$ sdl2-config --cflags
-I/mingw/include/SDL2 -Dmain=SDL_main

$ sdl2-config --libs
-L/mingw/lib -lmingw32 -lSDL2main -lSDL2 -mwindows

上の出力結果を参考にして、mrbgem.rake を以下のように修正。
MRuby::Gem::Specification.new('mruby-sdl2') do |spec|
  spec.license = 'MIT'
  spec.authors = 'crimsonwoods'

  # spec.cc.flags << '`sh sdl2-config --cflags`'
  # spec.linker.flags_before_libraries << '`sh sdl2-config --libs`'
  spec.cc.flags << '-I"d:/mingw/MinGW/include/SDL2" -Dmain=SDL_main'
  spec.linker.flags_before_libraries << '-L"d:/mingw/MinGW/lib" -lmingw32 -lSDL2main -lSDL2 -mwindows'
end

これで make したら…。
mieki256@dorobune: MINGW32: /d/Ruby/mruby/mruby$ make
ruby ./minirake
(in d:/Ruby/mruby/mruby)
CC build/mrbgems/mruby-sdl2/src/misc.c -> build/host/mrbgems/mruby-sdl2/src/misc.o
d:/Ruby/mruby/mruby/build/mrbgems/mruby-sdl2/src/misc.c: In function 'mrb_sdl2_misc_buffer_initialize':
d:/Ruby/mruby/mruby/build/mrbgems/mruby-sdl2/src/misc.c:37:3: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement]
   mrb_sdl2_misc_buffer_data_t *data =
   ^~~~~~~~~~~~~~~~~~~~~~~~~~
d:/Ruby/mruby/mruby/build/mrbgems/mruby-sdl2/src/misc.c:49:3: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement] enum mrb_vtype const arg_type = mrb_type(arg); ^~~
d:/Ruby/mruby/mruby/build/mrbgems/mruby-sdl2/src/misc.c:62:25: error: implicit declaration of function 'mrb_ary_len' [-Werror=implicit-function-declaration] mrb_int const n = mrb_ary_len(mrb, arg); ^~~~~~~~~~
... d:/Ruby/mruby/mruby/build/mrbgems/mruby-sdl2/src/misc.c:446:3: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement] mrb_sdl2_misc_buffer_data_t *data = ^~~~~~~~~~~~~~~~~~~~~~~~~~
cc1.exe: some warnings being treated as errors rake aborted! Command Failed: [gcc -g -std=gnu99 -O3 -Wall -Werror-implicit-function-declaration -Wdeclaration-after-statement -Wwrite-strings -g3 -O0 -I"d:/mingw/MinGW/include/SDL2" -Dmain=SDL_main -DMRB_DEBUG -DMRBGEM_MRUBY_SDL2_VERSION=0.0.0 -I"d:/Ruby/mruby/mruby/include" -MMD -o "d:/Ruby/mruby/mruby/build/host/mrbgems/mruby-sdl2/src/misc.o" -c "d:/Ruby/mruby/mruby/build/mrbgems/mruby-sdl2/src/misc.c"] make: *** [all] Error 1
今までと違って、sdl2-config が見つからない等の文句は出なくなった。しかし、それでもエラーが。「mrb_ary_len なんて知らんわい」と怒られてる。

ググってみたら、mrb_ary_len は、 _mruby 1.3.0 まではあった けど、 _mruby 1.4.0 では無くなった ように見える。

ということは、mrb_ary_len() を別の何かで代替すればビルドできるようになるのかな。と思ってググってみたけど、「代わりにコレを使えや」という話は見つからず。そもそもどうして無くなったんだろう…。神様の気分かな。

ならば、mruby 1.3.0 のファイル一式を使えばビルドできるんじゃないか。 _Releases - mruby/mruby から 1.3.0 のzip をDL・解凍して、それらのファイル群を使って試してみた。

今度は「strlen なんて知らねえよ」とエラーが出た。

おかしいな…。mruby のソースの中でも strlen() って結構使われてるのに…。

mruby-sdl2 の sdl2.h に #include <string.h> を追加してみた。一応ビルドは通ったように見えた。

ビルドは通ったけど、実行してもうんともすんとも言わない mruby.exe や mirb.exe が出来上がってしまった…。なんだこりゃ…。

mruby-sdl2 を追加すると、文字の出力ができない mruby, mirb が出来上がるっぽいな…。外してビルドすると各種メッセージがちゃんと表示される…。何故。

余談。 :

mruby関係の記事をググって眺めていた際、「mruby のライブラリ作者は mruby 本体のアップデートに追従していくのが大変」という話を見かけたけれど。なるほど、こんな感じで、今までビルドできていたものがビルドできなくなっていくのかと、たかだか一例ではあるけれど、素人なりになんとなく分かったつもりになったりもして。

また、Ruby関係は、「タダ乗りさせないために積極的に改変していく」「タダ乗り連中は置いてけぼりにする」というポリシーで開発をしていると神様自ら発言しているわけで…。

_今日現在のmrubyについて雑想 - もなもなもなかのページ
_参加しないと見せないよ.を作った罪 - もなもなもなかのページ

「コレどうしてビルドできないんだ」と仮に問うてみても、「俺達についてこないライブラリ作者が悪い」と返されるのがRubyの文化、なのだろうと。

mruby + SDL2 で、love2d みたいな形でアプリを作っておけば、CRuby のバージョンが上がるたびにライブラリ側も更新する苦労を味合わなくて済むのだろうか、などと素人考えで夢想していたのだけど。mruby も mruby で、コレを使うのはなんだか大変そうだなという印象になってきたりもして。だったら、まだ、古い CRuby + ライブラリで作業してたほうがいいのかもしれないよな…。

いやまあ、love2d みたいなのが欲しければ love2d 使えばいいじゃん、lua も比較的習得しやすい言語だし、という話にもなりそうだけど。

2018/03/13(火) [n年前の日記]

#1 [ruby][mruby] mrubyにRandomは用意されてた

mrubyを何度かビルドしているうちに、ふと、mruby-random という文字列が目に入って。

調べてみたら、mruby 1.4.0 は、Randomが含まれていたのですな…。mrbgem で別途導入しなくても良かったのか…。知らなかった…。とメモ。

#2 [windows][mruby] MSYS2でSDL2関係をビルドしたりmrubyをビルドしたり

先日、Windows10 x64 + MSYS2 で mruby をビルドした際は、エラーが出てしまってビルドできなかったのだけど。

ふと、github から最新版の mruby を clone して試していたのがマズかったのではないかと思えてきたわけで。

試しに _mruby 1.4.0 の zip をDLしてビルドしてみたところ、最後までビルドが通った。とメモ。

せっかくだから、SDL2関係も MSYS2 上でビルドできるか実験。

SDL2関係をビルドするために必要なファイルをインストール。 :

以下のページを参考にして作業。

_MSYS2/MinGW-w64 (64bit/32bit) インストール手順 メモ

  • スタートメニューから、MSYS2 MinGW 32bit (32bit)、を起動。
  • pacman -Syuu で、インストール済みのパッケージを最新版に更新。
  • pacman -S base-devel で、おそらくは開発に必要になりそうなツール群をインストール。
  • pacman -S mingw-w64-i686-toolchain で、コンパイラその他をインストール。ada や fortran や objc はインストールしなくていいと思うので、「1 2 3 7 9 10 11 12 13 14 15 16 17」みたいな感じで番号を打ち込んでインストールすることになるかと。
  • pacman -Ss SDL2 i686 で、SDL2関係のパッケージ一覧を表示。
  • pacman -S パッケージ名、で、SDL2関係のパッケージをインストール。

ところで、どうもよく分からんのだけど…。スタートメニュー内にある、以下のショートカット…。
  • 「MSYS2 MinGW 32bit (32bit)」
  • 「MSYS2 MinGW 64bit (32bit)」
  • 「MSYS2 MinGW 32bit (64bit)」
  • 「MSYS2 MinGW 64bit (64bit)」
それぞれ、どういう意味なんだろう。32bit用のバイナリを作りたいときは、どれを選べばいいの?

それはそれとして。SDL2関係のパッケージをインストールできたら、sdl2-config でバージョンを確認することができるはず。
$ sdl2-config --version
2.0.8

コンパイラやリンカに渡すオプションも確認できる。
$ sdl2-config --cflags
-I/mingw32/include/SDL2 -Dmain=SDL_main

$ sdl2-config --libs
-L/mingw32/lib -lmingw32 -lSDL2main -lSDL2 -mwindows

SDL2を使ったCソースをビルドしてみる。 :

以下を参考にして、test.c を作成。今回は、~/prg/sdl2/ 以下に、 test.c を作成した。

_Installing SDL for MinGW
#include "SDL2/SDL.h" 
#include <stdio.h>

int main( int argc, char* args[] ) 
{ 
  SDL_Window     *window;

  SDL_Init(SDL_INIT_VIDEO);

  window = SDL_CreateWindow("SDL2 Window", 100, 100, 640, 480, 0); 
  
  if(window==NULL)
  {   
    printf("Could not create window: %s\n", SDL_GetError());
    return 1;
  }
  
  SDL_Delay(3000);
  
  SDL_DestroyWindow(window); 
   
  SDL_Quit(); 

  return 0;   
}

コンパイルする。
g++ -o test.exe test.c -lmingw32 -lSDL2main -lSDL2
test.exe ができた。

MSYS2 を使う際に立ち上がる mintty 上から test.exe を実行しても何も出てこないけど、DOS窓を開いて、そこから test.exe を実行したら、ウインドウが開いて、3秒後にウインドウが閉じられた。どうやらビルドできたっぽい。

更に、以下も参考にして、ビルドできるかどうかテスト。

_MSYS2 + MinGW 環境に SDL2 をインストール - takaya030の備忘録

/mingw64 を /mingw32 に変更した Makefile を作成してから make と打ってみたけれど。「/bin/sh が無いよ」と怒られる…。何故…。which sh をしたら、/usr/bin/sh が出てきた。/bin/sh じゃないんか…。

とりあえず、MSYS2 上ならいきなり sdl2-config と打っても動作するので、Makefile 内の 「/bin/sh sdl2-config」の記述は「sdl2-config」にしてみた。この状態ならビルドも通ったし、DOS窓上で実行したらウインドウも表示された。

しかし、mintty 上から実行しようとすると、何も表示されないのは何故なんだろう…。

#3 [ruby][mruby] 他のmruby-sdl2をビルドしようと試していたり

github で「mruby sdl2」で検索したら、色んな人が mruby + sdl2 を試しているようで。他の mruby-sdl2 ならビルドできるのかなと試したり。

_mruby-sdl2/mruby-sdl2

上記の mrgbgem を追加して、mruby をビルドしてみたり。

MSYS2上ですんなりビルドできたけど、出来上がった mruby , mirb は、メッセージが出力されなかった…。そして、この mruby-sdl2 を外してビルドすると、やはり、メッセージがちゃんと出力される版になる…。何故なんだ。

もしかして、mruby で SDL2 を使えるようにすると、メッセージ出力が必ずできなくなってしまう、そんな仕様だったりするのだろうか。分からんなあ…。

Ubuntu Linux 16.04上で試してみた。 :

VMware + Ubuntu 16.04 LTS 上で、SDL2関係をインストールした上で、mruby + mruby-sdl2 をビルドできるか試してみたり。

サンプルスクリプト群がすんなり動いてしまった…。ウインドウが表示されて、何か画面に出てる…。更に、mruby も mirb も、メッセージ出力ができている…。

つまり、Windows + mruby + SDL2 だと、妙な状態になる模様。何故。

#4 [ruby][mruby] love2dのRuby版を作ろうとしてる方はいるらしい

以下のプロジェクトが気になった。

_jfcalvo/yoko: Yoko is a small framework to make games with ruby (mruby).

「love2dのRuby版を志向してる」と書いてあるように見える。同じことを既に考えて、しかも夢想で終わらせずに行動を起こした方が居たのだな…。素晴らしい。

ただ、導入方法に関しては、Mac と *NIX にしか触れてないようで。たぶんコレ、Windowsでは動かないな…。Rubyコミュニティの「OSは*NIXに収束した」という認識が、こんなところにまで…ということかしら。

一応、MSYS2上で、
git clone https://github.com/jfcalvo/yoko.git
cd yoko
make
をしてみたけれど、予想通りエラーが出て最後までビルドできなかった。やはり Windows は非対応らしい。 *1

他に、以下のようなプロジェクトもあるようで。

_elct9620/hiro: The game framework based on mruby.

これも、「Windows (Coming soon)」となってる…。

ちなみに、love2d は、Windows、Mac、Linux、Andorid、iOS でも動くので…。その点にのみ着目しても、

「Ruby (mruby) は Lua より劣っている」
「なぜなら、Lua はOSを問わずに動くけれど、Ruby (mruby) は *NIX上でしかまともに使えないから」

と言い切ってしまってもいいのではないかと思えてきちゃったりなんかしちゃったりもして(広川太一郎風に)。 *2
*1: VMware + Ubuntu 16.04 LTS上で試したら、ビルドできたし、実行もできた…。
*2: もっとも、Ruby (mruby) 本体だけならどこでも動くのだけど…。しかし、何か機能を追加してという話になると、途端に *NIXという制約が出現する ―― てな印象。

#5 [nitijyou] 某所に行ってきた

Excelのトラブル相談を受けて某所まで。詳細はGRPでメモ。

2018/03/14(水) [n年前の日記]

#1 [pc][neta] *NIXはコマンド入力方式のアドベンチャーゲーム

*NIXはどれもこれもコマンド入力方式のアドベンチャーゲーム。思いついた単語を手当たり次第に打ってみて、通ったら喜ぶ、そんなタイトルばかり。入り口では門前払い。ダフ屋さんには遭遇しない。潜り込んだらこのゲーム特有の attach が分からない。一体何を見つければこの迷宮から脱出できるのか。

とでも思いながら触らないと、耐えられない…。

#2 [windows][ruby][mruby] SDL2を使うとコンソール出力がされなくなる問題

Windows10 x64 + MSYS2 で、SDL2 を使ったソースをビルドして動作確認していたのだけど。ソース内で printf() を書いてもDOS窓に何も出力されなくて悩んだり。一般的にはコンソール出力という呼び方でいいのだろうか。アレができない。

ググってみたら、どうもコンパイラだかリンカに渡すオプションが関係していたようで。

_c++ - How do I print to the console while an SDL 2 program is running? - Stack Overflow
_c++ - No stdout.txt with SDL - Stack Overflow
_windows - C printf() on win32 with mingw - Stack Overflow

「-mwindows」というオプションをつけると、コンソールアプリではなくGUIアプリとして生成されて、コンソール出力ができなくなるっぽい。外してみたら、printf() が働いて、DOS窓にメッセージが出力されるようになった。

-mconsole を指定する方法もあるらしいが、そちらは試してない。

_How to output to the console in C++/Windows - Stack Overflow

また、昔の SDL は、stdout.txt や stderr.txt というファイルが作られて、出力結果がそれらファイルに書き込まれる仕様になっていた、と知った。

_FAQ_Windows_Where_stdout_/_stderr - SDL Documentation Wiki
_SDLスレ ver.2.0

ただ、今現在の SDL2 は、そういう仕様にはなってない、ような気がする。.exe と同じ場所に (stdout|stderr).txt は作られてないし。

ちなみに、freopen() を使えば、そういったファイルを作成して出力することも可能なようで。一応、以下のような記述で、stdout.txt が作成され、出力結果が保存されることは確認できた。
  window = SDL_CreateWindow("SDL2 Window",
                            100, 100,
                            640, 480, 0);
  if (window == NULL)
  {
    FILE *fp;
    fp = freopen("stdout.txt", "w", stdout);
    printf("Could not create window: %s\n", SDL_GetError());
    fclose(fp);
    SDL_Quit();
  }
  else
  {
    FILE *fp;
    fp = freopen("stdout.txt", "w", stdout);
    printf("create window\n");
    fclose(fp);
  }

とりあえず、*.c をビルドするだけの場面なら、上記について気を付ければどうにかなりそう。

しかし、Windows10 x64 + MSYS2 上で mruby-sdl2 をビルドすると、コンソール出力できなくなる理由は相変わらず分からないまま。-mwindows なんてオプションは指定してないと思うのだけどな…。*NIX上でビルドすると、コンソール出力されるし…。

2018/03/15追記。 :

_2018/03/15の日記 に、この件に関する補足を書いた。とメモ。

2018/03/15(木) [n年前の日記]

#1 [windows][ruby][mruby] SDL2を使うとコンソール出力がされなくなる問題について追記

Windows上で、SDL2 を使って、-mwindows を指定してビルドしたプログラムは、printf() が使えなくなる ―― コンソール出力ができなくなるけれど。SDL_Log("hoge") を使えば、-mwindows をつけてビルドしても、コンソール出力っぽいことができるようだと分かった。とメモ。

ただ、DOS窓上で実行した際は、SDL_Log("hoge") でメッセージを出力した後、何かプロセス?が残る…ような気がする。Ctrl + C を押してからじゃないと、DOS窓が exit で閉じてくれない状態になる模様。

それと、sdl2-config --libs の出力結果内に、-mwindows の指定があることに今頃気づいた。

数日前に mruby-sdl2 をビルドしようとした際は、sdl2-config --libs の出力結果をそのままコピペして使っていたから、-mwindows も指定してしまっていたわけで。だから、mruby や mirb がコンソールアプリではなくGUIアプリになってしまって、実行しても何一つメッセージを出力できない状態になっていたのではないか。と想像してみたけれど、さてどうなんだろう。

#2 [windows][ruby][mruby] MSYS2 と SDL2 についてメモ

MSYS2 と SDL2 について分かったことをもう少しメモ。

MSYS2上から出来上がった .exe を実行できた。 :

以前、MSYS2上(mintty上)から、ビルドして出来上がった .exe を実行できないとメモしたけれど。

ふと、うっかり、*NIXを使ってる感覚になってしまって、hoge.exe と打ち込まず、./hoge.exe と打ち込んだら、実行できてしまった。とメモ。

なんで? そういうものなの?

dllの在り処。 :

MSYS2 の場合、/mingw32/bin/ 以下に SDL2 関係のdllが入ってる模様。pacman -S で、SDL2関係のアレコレをインストールした場合の話だけど。
$ ll /mingw32/bin/SDL2*
-rwxr-xr-x 1 mieki256 None 1113744 3月   5 14:46 /mingw32/bin/SDL2.dll
-rwxr-xr-x 1 mieki256 None  136476 3月   5 14:54 /mingw32/bin/SDL2_image.dll
-rwxr-xr-x 1 mieki256 None  142633 11月  9 14:24 /mingw32/bin/SDL2_mixer.dll
-rwxr-xr-x 1 mieki256 None   29622 1月  10  2016 /mingw32/bin/SDL2_net.dll
-rwxr-xr-x 1 mieki256 None   38303 4月   6  2016 /mingw32/bin/SDL2_ttf.dll

実際は、これだけでは動作に足りないはず…。おそらく、以下の .dll が必要になりそう。SDL2_image を利用してpng画像を使ったり、oggを再生したりするなら、だけど。
libFLAC-8.dll
libfreetype-6.dll
libjpeg-9.dll
libmodplug-1.dll
libmpg123-0.dll
libogg-0.dll
libpng16-16.dll
libtiff-5.dll
libvorbis-0.dll
libvorbisfile-3.dll
libwebp-4.dll
libwebp-7.dll
SDL2.dll
SDL2_gfx.dll
SDL2_image.dll
SDL2_mixer.dll
SDL2_net.dll
SDL2_ttf.dll
smpeg2.dll
zlib1.dll
ビルドして出来上がった .exe が置いてある場所に、上記のdllもコピーしてしまえば配布できるようになるのだろうか。

libgcc_s_dw2-1.dllが必要らしい。 :

出来た .exe を他のPC(Windows8.1機)に持っていって実行してみたら、「libgcc_s_dw2-1.dllがねえよ」と怒られてしまった。そんなファイルも必要になるのか…。

g++ のオプションに、-static-libgcc -static-libstdc++ を指定すると静的リンク(スタティックリンク)になる、という話も見かけたけれど、試してみても効果が無い。exe のファイルサイズは以前と変わらず。なんでだろ。

_MinGWでlibgomp-1.dllがstatic linkできない問題(gcc, OpenMP) - Qiita
_Windows-アプリケーション/MinGW-MSYS/MinGWでのビルド - yanor.net/wiki

他にも、-static -static-libgcc -static-libstdc++ をつけると良い、という話も見かけたけれど、試してみたら SDL2 関係で大量にエラーが出た。うーん。

仕方ないので、/mingw32/bin/ 以下から、libgcc_s_dw2-1.dll をコピーしてきたけれど。その状態で実行したら、今度は「libwinpthread-1.dll が無いぞ」と怒られた。ソレも必要なのか…。コレも、/mingw32/bin/ 以下から、libwinpthread-1.dll をコピーしてみるか…。

各dllをコピーしてきた状態なら、他のPC上でも一応動いた。

しかし、一々dllをコピーするのは面倒だな…。スタティックリンクとやらをしてみたい…。

#3 [ruby][windows][mruby] MSYS2 + SDL2 でビルドする際のスタティックリンクができた

Windows10 x64 + MSYS2 + SDL2 でビルドして作った exeファイルを他のPCに持っていく際、一々 dll までコピーするのは面倒臭い。そのあたり、exe にスタティックリンクされた状態にしてみたい。

少し試してみたけれど、コンパイラだかリンカだかにオプションを渡す際、-static というオプションをつけると、使うライブラリを全部スタティックリンクしてくれるらしい。ただ、必要になるライブラリを、全部 -l〜 で列挙しないといけないようで。

今回は、以下のような Makefile にしてみたところ、exe のみを他のPCに持っていっても、ちゃんと動いてくれた。

_Makefile
TARGETS = sdl2imagetest

all: $(TARGETS)

SDL_PREFIX  = /mingw32
# SDL_PREFIX  = /mingw

# SDL_CONFIG  = $(SDL_PREFIX)/bin/sdl2-config
SDL_CONFIG  = sdl2-config
CG_LIBS     = 

CROSS_COMPILE = $(SDL_PREFIX)/bin/
CC = $(CROSS_COMPILE)gcc
CXX = $(CROSS_COMPILE)g++

# CFLAGS      = -g -Wall `$(SDL_CONFIG) --cflags`
# CXXFLAGS    = -g -Wall `$(SDL_CONFIG) --cflags`
CFLAGS = -g -Wall -I$(SDL_PREFIX)/include/SDL2 -Dmain=SDL_main
CXXFLAGS = -g -Wall -I$(SDL_PREFIX)/include/SDL2 -Dmain=SDL_main

# LDFLAGS     = `$(SDL_CONFIG) --libs` -Wl,-rpath,$(SDL_PREFIX)/lib
LDFLAGS = -L$(SDL_PREFIX)/lib -lmingw32 -lSDL2main -lSDL2 -mwindows -Wl,-rpath,$(SDL_PREFIX)/lib

# LIBS = -lopengl32 -lglu32 -lm -lSDL2_image
LIBS = -lSDL2_image -lpng -lz -ljpeg -ltiff -lwebp -llzma -lm -ldinput8 -ldxguid -ldxerr8 -luser32 -lgdi32 -lwinmm -limm32 -lole32 -loleaut32 -lshell32 -lversion -luuid -lopengl32 -lglu32 -lpthread -static -static-libgcc -static-libstdc++

clean:
	rm -f *.o *.a *~ $(TARGETS)

sdl2imagetest: sdl2imagetest.o
	$(CXX) -o $@ $^ $(LDFLAGS) $(LIBS)

Cソースと使用画像は以下。

_sdl2imagetest.c
_sample.png

ちなみに、上記ソースの実行結果は以下。



結構滑らかに動いてる。

Makefileの内容についてメモ。 :

Makefile 内では、おそらく以下の指定がしてあるのだろう…。自分、Makefileの書き方はほとんど把握できてないので怪しいけど。
  • TARGETS が、最終的に欲しい何かの名前。
  • MSYS2 32bit で使うときは、SDL_PREFIX を /mingw32 に、MinGW + MSYS で使うときは、/mingw に変更。
  • CFLAGS , CXXFLAGS に列挙してるのは、sdl2-config --cfalgs の出力結果。
  • LDFLAGS に列挙してるのは、sdl2-config --libs の出力結果。
  • LIBS に、必要になるらしいライブラリを -l〜 の形で列挙。かつ、最後のほうに -static -static-libgcc -static-libstdc++ を記述。
  • libpng を使うときは、-lpng。zlibを使うときは -lz。libjpeg を使うときは -ljpeg。なのかな。たぶん。
  • MSYS2 でビルドした何かは libwinpthread-1.dll を必要とするけれど。それもスタティックリンクしたいときは、-lpthread を追加して、-static も追加。なのだろうか。
  • gcc だか g++ だかは、dllファイル名を直接指定するオプションも存在してるっぽいのだけど、まだそこまで調べてない。(2018/03/18追記。スタティックリンクするためには lib〜.aが必要らしい。dllファイルだけがあってもスタティックリンクはできない。となると、自分がどこかで見かけたdllの指定、アレは何だったのか…。)

本来、リンクしたいアレコレは LIBS に指定して、フラグ関係は LDFLAGS に指定するのではないか、という気もしてるのだけど…。ビルドできたから、いいか。

それと、ライセンスの問題が気になる。中には、スタティックリンクを許していないライセンスになっている何かもあったりするのではないか…。GPL とか LGPL とかありそうな。そのあたり、以下のページで解説されてる。のかな。

_Debian/Ubuntuでmingw-w64を用いてWindows向けのプログラムをコンパイルする - kakurasan

参考ページ。 :

動作に必要になるらしいライブラリの一覧は、以下を参考にした。

_Eclipse+MinGWでSDL2を静的リンクさせる覚書 - Qiita
_c - How to install libpng correcly? - Stack Overflow

Makefile は、以下を参考にした。

_MSYS2 + MinGW 環境に SDL2 をインストール - takaya030の備忘録

#4 [nitijyou] 某所に行ってきた

インターネットに接続できないというトラブル相談。10:30-15:00まで作業。詳細はGRPでメモ。

2018/03/16(金) [n年前の日記]

#1 [ruby][mruby] Cで書いたプログラムからmrubyを呼び出せるか実験

SDLを使ったCのプログラムに、mrubyを組み込んで使う事例を、DXRuby作者様が昔公開してくれていたので、それのSDL2版を書いて試そうとしていたのだけど。

_SDL_imageとmrubyを使ってみた - mirichiの日記

そもそも、ビルドの仕方が分からない…。ので、まずはシンプルな形でビルドの仕方を確認しようと。以下の記事を参考にしつつ作業。

_手探りでおぼえるmruby その1:クラスを定義する、メソッドを定義する - エンジニアのソフトウェア的愛情
_mrubyで書いたコードをC言語内で読み出す方法 - Bye Bye Moore
_Hello World - mruby/mruby Wiki

環境は、Windows10 x64 + MSYS2。

ディレクトリ構成。 :

以下のような構成にしてみたり。
~/prg
|
+---- mruby
      |
      +---- callmruby
      |
      +---- mruby

~/prg/mruby/mruby/ の中に、 _mruby 1.4.0 のファイル一式を置いた。

MSYS2 のシェルを起動。スタートメニュー内の、MSYS2 MinGW 32-bit (32bit) を実行。

カレントディレクトリを変更して、makeを実行してビルド。
cd ~/prg/mruby/mruby/
make

ビルドが成功すると、以下のような状態になる。
  • ~/prg/mruby/mruby/include/ 内に *.h ファイルが入ってる。(mrubyをDL・解凍した時点で既に入ってる)
  • ~/prg/mruby/mruby/build/host/lib/ 内に、libmruby.a ファイルが出来上がる。この .a ファイルを、Cで書いたプログラムのビルド時にリンクする。

mruby はビルドできたので、callmruby/ の中で、CソースやMakefileを用意して、mruby を組み込めそうか実験していく。

mrubyを呼び出すだけのCプログラムを書いてみる。 :

callmruby/ の中に、callmruby.c というファイル名でCソースを用意。

_callmruby.c
#include "mruby.h"
#include "mruby/compile.h"
#include "mruby/proc.h"
#include <stdio.h>

int main(int argc, char *argv[])
{
  // open mruby state
  mrb_state *mrb = mrb_open();
  if (mrb == 0)
  {
    printf("cannot open mruby state.\n");
    return -2;
  }

  // file open
  FILE *fp = fopen("main.rb", "r");

  // run mruby script
  mrb_load_file(mrb, fp);

  // file close
  fclose(fp);

  // close mruby state
  mrb_close(mrb);
  return 0;
}

上記ソースは、main.rb を読み込んで実行するので、main.rb も用意する。

_main.rb
puts "Hello, I am mruby."
puts "Ok. mruby, your number is 7. instrument recorder on."
puts "Permission to sortie."
puts "Permission granted. GOOD LUCK, mruby."

Makefile も作る。Makefile てのは、make を実行した際にどんな処理をするのか、ルールを記述するファイル。

_Makefile
TARGETS = callmruby

all: $(TARGETS)

SDL_PREFIX  = /mingw32
# SDL_PREFIX  = /mingw

MRB_HEAD    = ../mruby/include
MRB_LIBS    = ../mruby/build/host/lib

# CG_LIBS     = 

CROSS_COMPILE = $(SDL_PREFIX)/bin/
CC = $(CROSS_COMPILE)gcc
CXX = $(CROSS_COMPILE)g++

CFLAGS = -g -Wall -I$(MRB_HEAD)
CXXFLAGS = -g -Wall -I$(MRB_HEAD)

LIBS = -L$(MRB_LIBS) -lmruby -lpthread -lm
LDFLAGS = -Wl,-rpath -static -static-libgcc -static-libstdc++

clean:
	rm -f *.o *.a *~ $(TARGETS)

$(TARGETS): $(TARGETS).o
	$(CXX) -o $@ $^ $(LIBS) $(LDFLAGS)

  • mruby の includeフォルダ、libフォルダは、相対パスで指定してる。
  • LIBS に、-L$(MRB_LIBS) -lmruby を記述して、mruby をリンクするように指定してる。
  • MSYS2 でビルドしたプログラムは libwinpthread-1.dll を要求するので、-lpthread と -static を記述して、スタティックリンクをするように指定してる。

ビルドする。
$ cd ~/prg/mruby/callmruby/
$ make
/mingw32/bin/gcc -g -Wall -I../mruby/include   -c -o callmruby.o callmruby.c
/mingw32/bin/g++ -o callmruby callmruby.o -L../mruby/build/host/lib -lmruby -lpthread -Wl,-rpath -static -static-libgcc -static-libstdc++

もし、上手く行かなかったら、以下を実行することで、作業ファイル・出力ファイルを全部消すことができる。
make clean

出来上がった .exe を実行してみる。
$ ./callmruby.exe
Hello, I am mruby.
Ok. mruby, your number is 7. instrument recorder on.
Permission to sortie.
Permission granted. GOOD LUCK, mruby.
Cで書いたプログラムを実行したはずなのに、main.rb に書かれた処理が実行されて、メッセージが出力された。

これで、mruby をCプログラムの中に組み込んでビルドすることはできた。ここまでは、なんとかなった…。

少し説明。 :

Cプログラムから mruby を使うときは、
#include "mruby.h"
#include "mruby/compile.h"
#include "mruby/proc.h"
を書いて…。

  mrb_state *mrb = mrb_open();
で、mrubyの何かを開く、のかな。mrb_state ってなんだか分からんけど、コレを使って mruby のスクリプトを動かすのだろう…。

_mrb_state 解説(必ずしも徹底ではない) - Qiita

mrubyスクリプトが書かれたファイルを読み込んで実行するだけなら、以下を使うのだろう。
  FILE *fp = fopen("main.rb", "r");
  mrb_load_file(mrb, fp);
  fclose(fp);
fopen()、fclose() はCのソレで、ファイルを開いたり閉じたりする。mrb_load_file() で、開いたファイルを mruby に渡して、実行。なのかな。

Cにおいて、開いた何かしらは、えてして閉じないといけない。mruby も開いたのだから、閉じる。
  mrb_close(mrb);

#2 [nitijyou] 某所から連絡

朝方、某所から連絡。昨日のトラブルは、NTT側で、基板が故障していたらしい…。そんなこともあるのか…。何にせよ問題が解決したようで一安心。詳細はGRPでメモ。

2018/03/17() [n年前の日記]

#1 [ruby][mruby] Cで書いたプログラムからmrubyを呼び出せるか実験その2

Windows10 x64 + MSYS2 上で、Cで書いたプログラムに mruby 1.4.0 を組み込んで動かせるか実験。

昨日は、ただ単に組み込んでビルドできるか試したけれど、今回はCで書いたクラスを mrubyスクリプトから呼び出せるか試してみた。

以下の記事を参考にして作業。

_mruby で C 言語の構造体をラップしたオブジェクトを作る正しい方法 - Qiita
_手探りでおぼえるmruby その1:クラスを定義する、メソッドを定義する - エンジニアのソフトウェア的愛情

ディレクトリ構成。 :

以下のような構成で作業。
~/prg
|
+---- mruby
      |
      +---- classmruby
      |
      +---- mruby

名前が変わっている部分があるらしい。 :

mruby 1.4.0 では、タイプや名前が変わってるものがいくつかある模様。
  • RClass → struct RClass
  • ARGS_NONE() → MRB_ARGS_NONE()
  • ARGS_REQ(1) → MRB_ARGS_REQ(1)

実験に使ったソース。 :

以下のような .c、.rb、Makefile になった。前述の解説ページの写経状態だけど…。

_classmruby.c
#include <stdio.h>
#include <errno.h>
#include <mruby.h>
#include <mruby/compile.h>
#include <mruby/proc.h>
#include <mruby/class.h>
#include <mruby/data.h>
#include <mruby/variable.h>
#include <mruby/string.h>

struct my_class
{
  int num;
  FILE *fp;
};

static void mrb_my_class_free(mrb_state *mrb, void *ptr);

// const static struct mrb_data_type mrb_my_class_type = {"MyClass", mrb_free};
const static struct mrb_data_type mrb_my_class_type = {"MyClass", mrb_my_class_free};

// class method
mrb_value mrb_my_class_initialize(mrb_state *mrb, mrb_value self)
{
  FILE *fp;
  struct my_class *h;
  mrb_value path;
  char *cpath;

  h = (struct my_class *)mrb_malloc(mrb, sizeof(struct my_class));
  h->fp = NULL;
  DATA_TYPE(self) = &mrb_my_class_type;
  DATA_PTR(self) = h;

  mrb_get_args(mrb, "S", &path);
  cpath = mrb_str_to_cstr(mrb, path);
  fp = fopen(cpath, "r");
  if (fp == NULL)
  {
    if (errno == EMFILE || errno == ENFILE)
    {
      mrb_full_gc(mrb);
      fp = fopen(cpath, "r");
    }
    if (fp == NULL)
    {
      mrb_raisef(mrb, E_ARGUMENT_ERROR, "Cannot open file: %s", path);
    }
  }

  h->num = 1234;
  h->fp = fp;
  return self;
}

mrb_value mrb_my_class_get(mrb_state *mrb, mrb_value self)
{
  struct my_class *h = DATA_PTR(self);
  return mrb_fixnum_value(h->num);
}

mrb_value mrb_my_class_put(mrb_state *mrb, mrb_value self)
{
  struct my_class *h = DATA_PTR(self);
  mrb_int num;
  mrb_get_args(mrb, "i", &num);
  h->num = num;
  return mrb_fixnum_value(num);
}

mrb_value mrb_my_class_read(mrb_state *mrb, mrb_value self)
{
  struct my_class *h;
  size_t n;
  char buf[1024];

  h = DATA_PTR(self);
  n = fread(buf, 1, sizeof(buf), h->fp);
  if (n == 0)
  {
    mrb_raise(mrb, E_ARGUMENT_ERROR, "fread(3) returns 0");
  }
  return mrb_str_new(mrb, buf, n);
}

static void mrb_my_class_free(mrb_state *mrb, void *ptr)
{
  struct my_class *h = ptr;
  if (h->fp != NULL)
  {
    fclose(h->fp);
    h->fp = NULL;
  }
  mrb_free(mrb, h);
}

int main(int argc, char *argv[])
{
  // open mruby state
  mrb_state *mrb = mrb_open();
  if (mrb == 0)
  {
    printf("cannot open mruby state.\n");
    return -2;
  }

  // define mruby class
  struct RClass *my_class;
  my_class = mrb_define_class(mrb, "MyClass", mrb->object_class);
  MRB_SET_INSTANCE_TT(my_class, MRB_TT_DATA);

  // define method
  mrb_define_method(mrb, my_class, "initialize",
                    mrb_my_class_initialize, MRB_ARGS_NONE());

  mrb_define_method(mrb, my_class, "get",
                    mrb_my_class_get, MRB_ARGS_NONE());

  mrb_define_method(mrb, my_class, "put",
                    mrb_my_class_put, MRB_ARGS_REQ(1));

  mrb_define_method(mrb, my_class, "read",
                    mrb_my_class_read, MRB_ARGS_NONE());

  // file open
  FILE *fp = fopen("main.rb", "r");

  // run mruby script
  mrb_load_file(mrb, fp);

  // file close
  fclose(fp);

  // close mruby state
  mrb_close(mrb);
  return 0;
}
関係がありそうな関数をメモすると…。
  • mrb_define_class() でクラスを定義。struct RClass * が返ってくる。
  • mrb_define_method() でクラスメソッドを定義。
  • MRB_ARGS_NONE() は引数が無いことを指定。
  • MRB_ARGS_REQ(n) で引数の個数を指定。
  • const static struct mrb_data_type mrb_my_class_type = {"MyClass", mrb_my_class_free}; で、クラスのインスタンスを解放する時に呼ばれる関数を指定。

_main.rb
a = MyClass.new("main.rb")
p a.get
a.put(3)
p a.get
puts
p a.object_id
p a.nil?
puts
p a.read
やってることは…。
  • C側で書いたクラスを、パラメータを渡しながら生成。
  • クラスが持ってる変数の値を読む。
  • クラスが持ってる変数に値を設定。
  • クラスのオブジェクトIDを取得。
  • クラスが nil かどうか調べる。
  • ファイルを読んで返すメソッドを呼ぶ。

_Makefile
TARGETS = classmruby

all: $(TARGETS)

SDL_PREFIX  = /mingw32
# SDL_PREFIX  = /mingw

MRB_HEAD    = ../mruby/include
MRB_LIBS    = ../mruby/build/host/lib

# CG_LIBS     = 

CROSS_COMPILE = $(SDL_PREFIX)/bin/
CC = $(CROSS_COMPILE)gcc
CXX = $(CROSS_COMPILE)g++

CFLAGS = -g -Wall -I$(MRB_HEAD)
CXXFLAGS = -g -Wall -I$(MRB_HEAD)

LIBS = -L$(MRB_LIBS) -lmruby -lpthread -lm
LDFLAGS = -Wl,-rpath -static -static-libgcc -static-libstdc++

clean:
	rm -f *.o *.a *~ $(TARGETS)

$(TARGETS): $(TARGETS).o
	$(CXX) -o $@ $^ $(LIBS) $(LDFLAGS)

  • -static をつけて、スタティックリンクをしてる。

make でビルド。./classmruby.exe で実行。
$ make
/mingw32/bin/gcc -g -Wall -I../mruby/include   -c -o classmruby.o classmruby.c
/mingw32/bin/g++ -o classmruby classmruby.o -L../mruby/build/host/lib -lmruby -lpthread -lm -Wl,-rpath -static -static-libgcc -static-libstdc++

$ ./classmruby.exe
1234
3

48457229
false

"a = MyClass.new(\"main.rb\")\np a.get\na.put(3)\np a.get\nputs\np a.object_id\np a.nil?\nputs\np a.read\n"

mrubyスクリプト側でクラスを生成して、値を読んだり、値を設定したり等ができることが確認できた。

Makefileについて。 :

Makefile内で使われている特殊変数についてよく分からなかったのでググったり。

_Makefile の特殊変数の一覧
_Makefile の書き方 (C 言語) ・ WTOPIA v1.0 documentation

  • $@ ... ターゲット名
  • $^ ... 依存ファイルのリスト

2018/03/18() [n年前の日記]

#1 [ruby][mruby] MSYS2上でCのプログラムにmrubyを組み込んでSDL2を使う

Windows10 x64 + MSYS2 上で、SDL2を使うCプログラムに、mrruby 1.4.0 を組み込んで、スプライト相当を描画できそうか実験。

DXRuby作者様が、mruby + SDL をビルドする記事を以前公開されていたので、参考にして作業。ありがたや。

_SDL_imageとmrubyを使ってみた - mirichiの日記

MSYS2上にSDL2関係をインストール。 :

MSYS2上でSDL2関係のアレコレをインストールする手順については、 _2018/03/13の日記 にメモしてあるけど…。MSYS2は pacman というパッケージ管理ツールが入ってるので…。
  • pacman -Ss SDL2 で関連パッケージをリストアップ。
  • pacman -S 〜 でパッケージをインストール。
これだけでインストールできる。ありがたや。

mruby 1.4.0のファイル一式を入手。 :

_Releases - mruby/mruby から、mruby 1.4.0 の zip をダウンロード。

フォルダ構成。 :

今回は以下のフォルダ構成にした。
~/prg
|
+---- mruby
      |
      +---- glmrubysdl2
      |
      +---- mruby
  • ~/prg/mruby/mruby/ 以下に、mruby 1.4.0 のファイル一式を入れる。
  • ~/prg/mruby/glmrubysdl2/ 以下に、今回書いたプログラム群を入れる。

mruby 1.4.0 をビルド。 :

cd ~/prg/mruby/mruby
make

今回試したソース。 :

glmrubysdl2/ 以下に、
  • glmrubysdl2.c ... Cで書いた、SDL2を使うプログラムのソース
  • main.rb ... mruby に渡す、mrubyスクリプト
  • Makefile ... ビルドするための Makefile
  • sample.png ... 使用画像
を入れた。

_glmrubysdl2.c
#include <stdio.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <mruby.h>
#include <mruby/class.h>
#include <mruby/data.h>
#include <mruby/compile.h>
#include <mruby/variable.h>

SDL_Window *mwindow;
SDL_Renderer *renderer;

struct RClass *cSprite;

// class work
struct glmrb_sprite
{
  SDL_Surface *surface;
  SDL_Texture *texture;
  int width;
  int height;
};

static void glmrb_sprite_free(mrb_state *mrb, void *ptr);

static struct mrb_data_type mrb_sprite_type = {"Sprite", glmrb_sprite_free};

struct Timer
{
  Sint64 now, interval;
  // Uint32 now, wit, lev;
} timer;

/* Sprite#initialize */
static mrb_value
glmrb_sprite_initialize(mrb_state *mrb, mrb_value self)
{
  struct glmrb_sprite *sprite;
  mrb_value vx, vy;
  char *s;

  sprite = (struct glmrb_sprite *)mrb_malloc(mrb, sizeof(struct glmrb_sprite));
  if (sprite == NULL)
  {
    SDL_Log("Out of memory.\n");
    mrb_raise(mrb, E_RUNTIME_ERROR, "out of memory.");
  }

  DATA_TYPE(self) = &mrb_sprite_type;
  DATA_PTR(self) = sprite;
  sprite->width = 0;
  sprite->height = 0;
  sprite->surface = NULL;
  sprite->texture = NULL;

  // get paramater, o:Object [mrb_value], z:String [mrb_value]
  mrb_get_args(mrb, "ooz", &vx, &vy, &s);

  mrb_iv_set(mrb, self, mrb_intern(mrb, "@x", 2), vx);
  mrb_iv_set(mrb, self, mrb_intern(mrb, "@y", 2), vy);

  // load image file
  sprite->surface = IMG_Load(s);
  if (sprite->surface == NULL)
  {
    SDL_Log("Cannot create SDL_Surface.\n");
    mrb_raise(mrb, E_RUNTIME_ERROR, "Cannot create SDL_Surface.");
  }
  else
  {
    // get image width and height
    sprite->width = sprite->surface->w;
    sprite->height = sprite->surface->h;
  }

  // create texture
  sprite->texture = SDL_CreateTextureFromSurface(renderer, sprite->surface);
  if (sprite->texture == NULL)
  {
    SDL_Log("Cannot create SDL_Texture.\n");
    mrb_raise(mrb, E_RUNTIME_ERROR, "Cannot create SDL_Texture.");
  }

  return self;
}

/* Sprite#draw */
static mrb_value glmrb_sprite_draw(mrb_state *mrb, mrb_value self)
{
  struct glmrb_sprite *sprite = DATA_PTR(self);
  SDL_Rect src, dst;

  src.x = 0;
  src.y = 0;
  src.w = sprite->width;
  src.h = sprite->height;

  dst.x = mrb_fixnum(mrb_iv_get(mrb, self, mrb_intern(mrb, "@x", 2)));
  dst.y = mrb_fixnum(mrb_iv_get(mrb, self, mrb_intern(mrb, "@y", 2)));
  dst.w = src.w;
  dst.h = src.h;

  // SDL_BlitSurface(sprite->surface, &src, mwindow, &dst);
  SDL_RenderCopy(renderer, sprite->texture, &src, &dst);
  return self;
}

/* Sprite#width */
static mrb_value glmrb_sprite_width(mrb_state *mrb, mrb_value self)
{
  struct glmrb_sprite *sprite = DATA_PTR(self);
  return mrb_fixnum_value(sprite->width);
}

/* Sprite#height */
static mrb_value glmrb_sprite_height(mrb_state *mrb, mrb_value self)
{
  struct glmrb_sprite *sprite = DATA_PTR(self);
  return mrb_fixnum_value(sprite->height);
}

static void glmrb_sprite_free(mrb_state *mrb, void *ptr)
{
  struct glmrb_sprite *sprite = ptr;

  if (sprite->texture != NULL)
    SDL_DestroyTexture(sprite->texture);

  if (sprite->surface != NULL)
    SDL_FreeSurface(sprite->surface);

  mrb_free(mrb, sprite);
}

// quit check
int quits(void)
{
  SDL_Event events;
  if (SDL_PollEvent(&events))
  {
    switch (events.type)
    {
    case SDL_QUIT:
      return 0;
      break;
    case SDL_KEYDOWN:
      if (events.key.keysym.sym == SDLK_ESCAPE ||
          events.key.keysym.sym == SDLK_q)
        return 0;
      break;
    default:
      break;
    }
  }
  return 1;
}

int main(int argc, char *argv[])
{
  FILE *fp;
  mrb_value mrb_obj;

  // mruby state open
  mrb_state *mrb = mrb_open();
  if (mrb == 0)
  {
    SDL_Log("Cannot open mruby state.\n");
    return -2;
  }

  // define class
  cSprite = mrb_define_class(mrb, "Sprite", mrb->object_class);
  MRB_SET_INSTANCE_TT(cSprite, MRB_TT_DATA);

  // define class method
  mrb_define_method(mrb, cSprite, "initialize",
                    glmrb_sprite_initialize, MRB_ARGS_REQ(3));

  mrb_define_method(mrb, cSprite, "draw",
                    glmrb_sprite_draw, MRB_ARGS_NONE());

  mrb_define_method(mrb, cSprite, "width",
                    glmrb_sprite_width, MRB_ARGS_NONE());

  mrb_define_method(mrb, cSprite, "height",
                    glmrb_sprite_height, MRB_ARGS_NONE());

  // SDL2 init
  if (SDL_Init(SDL_INIT_EVERYTHING) < 0)
  {
    SDL_Log("Failure SDL_INIT()\n");
    mrb_close(mrb);
    return -1;
  }

  // mwindow = SDL_SetVideoMode(640, 480, 0, 0);
  // SDL_WM_SetCaption("glmruby application", NULL);
  mwindow = SDL_CreateWindow("glmrubysdl2", 100, 100, 640, 480, 0);
  if (mwindow == NULL)
  {
    SDL_Log("Cannot create window.\n");
    SDL_Quit();
    mrb_raise(mrb, E_RUNTIME_ERROR, "Cannot create window.");
    exit(-1);
  }

  // create renderer
  renderer = SDL_CreateRenderer(mwindow, -1, SDL_RENDERER_ACCELERATED);
  if (renderer == NULL)
  {
    SDL_Log("Cannot create renderer.\n");
    SDL_DestroyWindow(mwindow);
    SDL_Quit();
    mrb_raise(mrb, E_RUNTIME_ERROR, "cannot create renderer.");
    exit(-1);
  }

  // load and run mruby script. execute after create renderer
  fp = fopen("main.rb", "r");
  if (fp == NULL)
  {
    SDL_Log("Cannot load main.rb.\n");
    mrb_raise(mrb, E_RUNTIME_ERROR, "Cannot load main.rb");
    exit(-2);
  }
  mrb_obj = mrb_load_file(mrb, fp);
  fclose(fp);

  timer.interval = (Sint64)SDL_GetPerformanceFrequency() / 60;
  timer.now = 0;

  int framecounter = 0;

  // main loop
  while (quits() != 0)
  {

    mrb_funcall(mrb, mrb_obj, "update", 0);

    // clear with background color
    SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
    SDL_RenderClear(renderer);
    // SDL_FillRect(mwindow, NULL, SDL_MapRGB(mwindow->format, 0, 0, 0));

    mrb_funcall(mrb, mrb_obj, "draw", 0);
    SDL_RenderPresent(renderer);

    // timer wait
    while (SDL_TRUE)
    {
      if (((Sint64)SDL_GetPerformanceCounter() - timer.now) >= timer.interval)
        break;
      SDL_Delay(0);
    }
    timer.now = SDL_GetPerformanceCounter();

    // timer.now = SDL_GetTicks();
    // timer.wit = timer.now - timer.lev;
    // if (timer.wit < 16)
    //   SDL_Delay(16 - timer.wit);
    // timer.lev = SDL_GetTicks();

    // SDL_UpdateRect(mwindow, 0, 0, 0, 0);

    framecounter++;
    // if (framecounter % 60 == 0)
    //   printf("%d\n", framecounter);
  }

  mrb_close(mrb);

  SDL_DestroyRenderer(renderer);
  SDL_DestroyWindow(mwindow);
  SDL_Quit();

  return 0;
}

_main.rb
#!ruby

class TestSprite < Sprite
  def initialize(x, y, imagefile, dx, dy)
    super(x, y, imagefile)
    @bx = x
    @by = y
    @dx = dx
    @dy = dy
  end

  def update
    wh = width / 2
    hh = height / 2
    @bx += @dx
    @by += @dy
    @dx *= -1 if (@bx <= wh or @bx >= 640 - wh)
    @dy *= -1 if (@by <= hh or @by >= 480 - hh)
    @x = (@bx - wh).to_i
    @y = (@by - hh).to_i
  end
end

class Scene
  def initialize
    @sprs = []
    num = 128
    ang = 0
    ang_d = 360.0 / num
    num.times do
      rad = ang * Math::PI / 180.0
      r = rand * 4.0 + 1.0
      dx = r * Math.cos(rad)
      dy = r * Math.sin(rad)
      s = TestSprite.new(320, 240, "sample.png", dx, dy)
      @sprs.push(s)
      ang += ang_d
    end
  end

  def update
    @sprs.each { |s| s.update }
  end

  def draw
    @sprs.each { |s| s.draw }
  end
end

Scene.new

_Makefile
TARGETS = glmrubysdl2

all: $(TARGETS)

SDL_PREFIX  = /mingw32
# SDL_PREFIX  = /mingw

MRB_HEAD    = ../mruby/include
MRB_LIBS    = ../mruby/build/host/lib

# SDL_CONFIG  = $(SDL_PREFIX)/bin/sdl2-config
SDL_CONFIG  = sdl2-config
CG_LIBS     = 

CROSS_COMPILE = $(SDL_PREFIX)/bin/
CC = $(CROSS_COMPILE)gcc
CXX = $(CROSS_COMPILE)g++

# SDLCFLAGS   = `$(SDL_CONFIG) --cflags`
SDLCFLAGS = -I$(SDL_PREFIX)/include/SDL2 -Dmain=SDL_main
CFLAGS = -g -Wall $(SDLCFLAGS) -I$(MRB_HEAD)
CXXFLAGS = -g -Wall $(SDLCFLAGS) -I$(MRB_HEAD)

# SDLLIBS     = `$(SDL_CONFIG) --libs`
# SDLLIBS     = -L$(SDL_PREFIX)/lib -lmingw32 -lSDL2main -lSDL2 -mwindows
SDLLIBS = -L$(SDL_PREFIX)/lib -lmingw32 -lSDL2main -lSDL2

# LDFLAGS     = -Wl,-rpath,$(SDL_PREFIX)/lib  -static -static-libgcc -static-libstdc++ -mwindows
LDFLAGS = -Wl,-rpath,$(SDL_PREFIX)/lib -static -static-libgcc -static-libstdc++

# LIBS = -L$(MRB_LIBS) -lmruby -lm $(SDLLIBS) -lopengl32 -lglu32 -lm -lSDL2_image
LIBS = -L$(MRB_LIBS) -lmruby -lm $(SDLLIBS) \
  -lSDL2_image -lpng -lz -ljpeg -ltiff -lwebp -llzma \
  -ldinput8 -ldxguid -ldxerr8 -luser32 -lgdi32 -lwinmm \
  -limm32 -lole32 -loleaut32 -lshell32 -lversion -luuid \
  -lopengl32 -lglu32 -lpthread

clean:
	rm -f *.o *.a *~ $(TARGETS)

$(TARGETS): $(TARGETS).o
	$(CXX) -o $@ $^ $(LIBS) $(LDFLAGS)


使用画像。

_sample.png

ビルドしてみる。 :

$ cd ~/prg/mruby/glmrubysdl2/

$ make

/mingw32/bin/gcc -g -Wall -I/mingw32/include/SDL2 -Dmain=SDL_main -I../mruby/include   -c -o glmrubysdl2.o glmrubysdl2.c

/mingw32/bin/g++ -o glmrubysdl2 glmrubysdl2.o -L../mruby/build/host/lib -lmruby -lm -L/mingw32/lib -lmingw32 -lSDL2main -lSDL2 -lSDL2_image -lpng -lz -ljpeg -ltiff -lwebp -llzma -ldinput8 -ldxguid -ldxerr8 -luser32 -lgdi32 -lwinmm -limm32 -lole32 -loleaut32 -lshell32 -lversion -luuid -lopengl32 -lglu32 -lpthread -Wl,-rpath,/mingw32/lib -static -static-libgcc -static-libstdc++

ビルドできたら実行してみる。
$ ./glmrubysdl2.exe

実行結果。



結構滑らかに動いてるような気がする。

スタティックリンクをしたので、exe と使用画像のみを他のPC(Windows8.1機。Intel Atom CPU搭載)に持っていっただけで動いてくれた。dllファイルをごっそりコピーして持っていかなくても済むあたりはイイ感じ。もっとも、glmrubysdl2.exe のファイルサイズが 10MBを超えるサイズになってるけど…。

一応、exeも含めたファイル一式を zip にして置いておきます。

_glmrubysdl2_20180318.zip

とりあえず、
  • SDL2を使うプログラムをCで書く際のアレコレ。
  • Cで書いたプログラムに mruby を組み込む方法。
  • MSYS2上でビルドする方法。
この3つは、少し分かってきた気がする。

課題。 :

せっかくだから、DXRuby の Image っぽい感じで画像を読み込んで Sprite に渡すように…と思ったけれど、DXRuby の Image のようなものをどうやって作ればいいのか分からず。DXRuby の Image は、Image.new(w, h, color) で生成できる上に、Image.load("画像ファイル名") でも生成できる…。.new() 以外でも生成できる何か、ってどうやって作るのかしら。

また、mrubyスクリプト内で何かエラーが発生した場合に、エラーが出ていることを表示する方法も分かってなくて。当初、実行しても何も画面に表示されなくて、Cのソースとにらめっこしたのだけど、結局 mrubyスクリプト側で記述が間違っていた、てな場面があって。mrb_load_file() で mrubyスクリプトを読み込んで実行した際、エラーが出てるかどうかを調べる何かが用意されているのだろうな、とは思うのだけど…。

参考ページ。 :


2018/03/19(月) [n年前の日記]

#1 [ruby][mruby] mrubyはスクリプトソースのファイル分割ができるのだろうか

ここ数日、mruby について色々試してたけど。ふと、気づいてしまった。mruby は require が無いけれど、それはつまり、スクリプトソースのファイル分割すらできない、ということだったりするのでは…。

例えばゲームのプログラムを作る時…。 てな感じでファイルを分けたりするけれど。まさかこういうことすらできなくて、全部 main.rb に、ずらずらと書かなきゃいけない、みたいな状態になるのだろうかと。昔のベーマガで掲載されてた、1ページに収まるゲームプログラムを書け、的な縛りプレイを思い出す…。21世紀にもなって、趣味で自発的にやるならともかく、強制されちゃうのはちょっと。

例えばコレが love2d (Lua) だったら、main.lua とは別に、フォルダを作ってソースを入れておいて、それをライブラリとして扱って、
local sti = require "sti"
てな感じで使えるようになるのだけど…。

Ruby は Lua 未満なの?

mruby-requireというmrbgemがあるらしい。 :

ググってみたら、mruby-require という mrbgem があるらしい。

_iij/mruby-require: "require" and "load" for mruby
_mattn/mruby-require

コレを使えばファイル分割もできるようになるのではないか。

しかし、Windows10 x64 + mruby 1.4.0 では、ビルドが通ったり通らなかったりでハマった…。

Visual Studio 2015 Community の場合。 :

まずは、Visual Studio 2015 Community を使ってビルドを試した。

_iij/mruby-require の場合。

build_config.rb に、以下を追加。
MRuby::Build.new do |conf|
  ...
  conf.gem :github => 'iij/mruby-require'
end

「開発者コマンドプロンプト for VS2015」を開いて、ビルドすると、エラーが出てきた。
> ruby ./minirake

(in D:/Ruby/mruby/mruby-1.4.0)

CC build/mrbgems/mruby-require/src/require.c -> build/host/mrbgems/mruby-require/src/require.obj
require.c
D:\Ruby\mruby\mruby-1.4.0\build\mrbgems\mruby-require\src\require.c(6): fatal error C1083: include ファイルを開けません。'unistd.h':No such file or directory
require.c
D:\Ruby\mruby\mruby-1.4.0\build\mrbgems\mruby-require\src\require.c(6): fatal error C1083: include ファイルを開けません。'unistd.h':No such file or directory

rake aborted!

Command Failed: [cl.exe /c /nologo /W3 /we4013 /Zi /MD /O2 /D_CRT_SECURE_NO_WARNINGS /DMRB_STACK_EXTEND_DOUBLING /DMRB_DEBUG /DMRBGEM_MRUBY_REQUIRE_VERSION=0.0.0 /I"D:\Ruby\mruby\mruby-1.4.0\include" /I"D:\Ruby\mruby\mruby-1.4.0\src" /I"D:\Ruby\mruby\mruby-1.4.0\mrbgems\mruby-io\include" /Fo"D:\Ruby\mruby\mruby-1.4.0\build\host\mrbgems\mruby-require\src\require.obj" "D:\Ruby\mruby\mruby-1.4.0\build\mrbgems\mruby-require\src\require.c"]
調べてみたら、Visual C (C++?) に unistd.h なんてものは無いらしい。

ならばと、 _mattn/mruby-require を試してみたけど。

build_config.rb に、以下を追加。mattn/mruby-require は一番最後に記述しないといかんらしい。
MRuby::Build.new do |conf|
  ...
  conf.gem :core => 'mruby-bin-mrbc'
  conf.gem :github => 'mattn/mruby-require'
end

ビルド。
> ruby ./minirake

...

Build summary:

================================================
      Config Name: host
 Output Directory: build/host
         Binaries: mrbc
    Included Gems:
             mruby-sprintf - standard Kernel#sprintf method
             mruby-print - standard print/puts/p
             mruby-math - standard Math module
...
             mruby-kernel-ext - Kernel module extension
             mruby-class-ext - class/module extension
             mruby-json
             mruby-sleep - 0.0.1
             mruby-bin-mrbc - mruby compiler executable
             mruby-require
================================================
...
一見通ったように見えるけど。

_iij/mruby-require: "require" and "load" for mruby で紹介されてるサンプルを動かそうとすると…。

a.rb
require "b"

b = Bclass.new
p b.method

b.rb
class Bclass
  def method
    "BBB"
  end
end

> mruby a.rb
trace (most recent call last):
        [0] a.rb:1
a.rb:1: cannot load such file -- b (LoadError)
エラーになる。

require "b" を require "./b" や "./b.rb" にしてみてもエラーになる。
> mruby a.rb
LocalJumpError: unexpected return
> mruby a.rb
LocalJumpError: unexpected return

load "./b.rb" にしてみたら、mruby が不正終了。

このままでは、1つの .rbファイルに全ての処理をずらずらと書くしかない…。

MinGW+MSYSならビルドできた。 :

Visual Studio 2015 Community では、 _iij/mruby-require をビルドできなかったけど。MinGW系を使ったらビルドできたりしないか、と思って MinGW + MSYS で試してみたら、そちらならビルドできた。

MSYS2ではダメだった。 :

MSYS2ではビルド時にエラーが出てしまった。なんで? MinGW + MSYS なら通るのに、どうして MSYS2 は通らないの?
mieki256@dorobune: MINGW32: ~/prg/mruby/mruby$ make
ruby ./minirake
(in /d/home/mieki256/prg/mruby/mruby)
LD build/host/bin/mirb.exe
D:/home/mieki256/prg/mruby/mruby/build/host/lib/libmruby.a(io.o): In function `fptr_finalize':
D:/home/mieki256/prg/mruby/mruby/mrbgems/mruby-io/src/io.c:645: undefined reference to `_imp__closesocket@4'
D:/home/mieki256/prg/mruby/mruby/mrbgems/mruby-io/src/io.c:646: undefined reference to `_imp__WSAGetLastError@0'
D:/home/mieki256/prg/mruby/mruby/build/host/lib/libmruby.a(io.o): In function `mrb_io_s_select':
D:/home/mieki256/prg/mruby/mruby/mrbgems/mruby-io/src/io.c:1138: undefined reference to `_imp__select@20'
D:/home/mieki256/prg/mruby/mruby/mrbgems/mruby-io/src/io.c:1160: undefined reference to `__WSAFDIsSet@8'
...
D:/home/mieki256/prg/mruby/mruby/build/host/lib/libmruby.a(io.o):D:/home/mieki256/prg/mruby/mruby/mrbgems/mruby-io/src/io.c:1185: more undefined references to `__WSAFDIsSet@8' follow
collect2.exe: error: ld returned 1 exit status
D:/home/mieki256/prg/mruby/mruby/build/host/lib/libmruby.a(io.o): In function `fptr_finalize':
D:/home/mieki256/prg/mruby/mruby/mrbgems/mruby-io/src/io.c:645: undefined reference to `_imp__closesocket@4'
D:/home/mieki256/prg/mruby/mruby/mrbgems/mruby-io/src/io.c:646: undefined reference to `_imp__WSAGetLastError@0'
D:/home/mieki256/prg/mruby/mruby/build/host/lib/libmruby.a(io.o): In function `mrb_io_s_select':
D:/home/mieki256/prg/mruby/mruby/mrbgems/mruby-io/src/io.c:1138: undefined reference to `_imp__select@20'
D:/home/mieki256/prg/mruby/mruby/mrbgems/mruby-io/src/io.c:1160: undefined reference to `__WSAFDIsSet@8'
...
D:/home/mieki256/prg/mruby/mruby/mrbgems/mruby-io/src/io.c:1183: undefined reference to `__WSAFDIsSet@8'
D:/home/mieki256/prg/mruby/mruby/build/host/lib/libmruby.a(io.o):D:/home/mieki256/prg/mruby/mruby/mrbgems/mruby-io/src/io.c:1185: more undefined references to `__WSAFDIsSet@8' follow
collect2.exe: error: ld returned 1 exit status
rake aborted!
Command Failed: [gcc  -o "/d/home/mieki256/prg/mruby/mruby/build/host/bin/mirb.exe" "/d/home/mieki256/prg/mruby/mruby/build/host/mrbgems/mruby-bin-mirb/tools/mirb/mirb.o" "/d/home/mieki256/prg/mruby/mruby/build/host/lib/libmruby.a"  -lm ]
rakefile:74:in `block (4 levels) in <top (required)>'
make: *** [Makefile:8: all] エラー 1

ググってみたら、以下の記事に遭遇。

_Windows ネイティブなmruby.exeをmsys2で作る - Qiita
_Cross-compilation for Windows using MinGW fails - Issue #3046 ・ mruby/mruby

build_config.rb に以下を追加、とあるが…。
  conf.cc.command = ENV['CC'] || 'i686-w64-mingw32-gcc'
  conf.linker.command = ENV['LD'] || 'i686-w64-mingw32-gcc'

試してみても、やはりエラーが。

github から mruby の最新版を git clone で入手して試してみたけど、やはりエラーが出る。

mruby-require を外すと、MSYS2 上でもビルドができる。どうやらその場合、mruby-io が組み込まれない状態になって、エラーも出なくなる模様。mruby-io が足を引っ張ってる。

_WIN32 ってなんだろう。 :

mruby/mrbgems/mruby-io/src/io.c でエラーが出てるみたいなので眺めてみたら、_WIN32 が定義されてる場合とそれ以外で処理が分けてあった。_WIN32 のほうは、closesocket() という関数を使っているけど…。MinGW + MSYS と、MSYS2 で、その関数があったりなかったりするのだろうか?

そもそも _WIN32 って、どの環境なら定義されてるのだろう。確認してみたり。

definecheck.c
#include <stdio.h>

int main(int argc, char *argv[])
{

#ifdef _WIN32
  printf("_WIN32\n");
#else
  printf("not _WIN32\n");
#endif
  
#ifdef _WIN64
  printf("_WIN64\n");
#else
  printf("not _WIN64\n");
#endif

  return 0;
}

Makefile
TARGETS = definecheck

all: $(TARGETS)

# SDL_PREFIX  = /mingw64
# SDL_PREFIX  = /mingw32
SDL_PREFIX  = /mingw

MRB_HEAD    = ../mruby/include
MRB_LIBS    = ../mruby/build/host/lib

# CG_LIBS     = 

CROSS_COMPILE = $(SDL_PREFIX)/bin/
CC = $(CROSS_COMPILE)gcc
CXX = $(CROSS_COMPILE)g++

CFLAGS = -g -Wall
CXXFLAGS = -g -Wall

LIBS = -lpthread -lm
# LIBS        = -lm
LDFLAGS = -Wl,-rpath -static -static-libgcc -static-libstdc++

clean:
	rm -f *.o *.a *.exe *~ $(TARGETS)

$(TARGETS): $(TARGETS).o
	$(CXX) -o $@ $^ $(LIBS) $(LDFLAGS)

MinGW + MSYS で make した場合。
$ ./definecheck.exe
_WIN32
not _WIN64

MSYS2 MinGW 32-bit (32bit) で make した場合。
$ ./definecheck.exe
_WIN32
not _WIN64

MSYS2 MinGW 64-bit (64bit) で make した場合。
$ ./definecheck.exe
_WIN32
_WIN64

_WIN32 と _WIN64 の両方が定義される環境があるのは予想外だった…。排他じゃないのか…。

何にせよ、MinGW系ならどれも _WIN32 が定義された状態でコンパイルされるのだろう。

ということは、io.c の件の場所は、_WIN32 のほうの処理がコンパイルされるはずで…。

closesocket()の定義場所を探す。 :

MinGW の場合、MinGW/include/winsock.h で closescoket() が定義されてるように見えた。

MSYS2 MinGW 32-bit (32bit) の場合、mingw32/i686-w64-mingw32/include/winsock.h で定義されてる。/mingw32/include/ の中では無いのだな…。

MSYS2 MinGW 64-bit (64bit) の場合、mingw64/x86_64-w64-mingw32/include/winsock.h で定義されてる。これも、/mingw64/include の中では無い、と。

このあたりは関係があるのかないのか…。分からんなあ…。

mrbgem.rake が関係してるかも。 :

mruby/mrbgems/ に入ってる、mruby-io の mrbgem.rake を眺めてるうちに、以下の行が気になった。
  case RUBY_PLATFORM
  when /mingw|mswin/
何のCRubyを使っているかで、処理というか、定義を分けているような気がする。ここでは mingw か mswin だった場合を想定しているようだけど…。

MinGW + MSYS 上で調べてみたら、以下の結果になった。この場合は、mingw という文字列が入ってる。
$ which ruby
/c/Ruby/Ruby22/bin/ruby.exe

$ ruby --version
ruby 2.2.6p396 (2016-11-15 revision 56800) [i386-mingw32]

$ ruby -e "puts RUBY_PLATFORM"
i386-mingw32

MSYS2 MinGW 32-bit (32bit) で調べてみると、以下。
$ which ruby
/usr/bin/ruby

$ ruby --version
ruby 2.4.0p0 (2016-12-24 revision 57164) [i386-msys]

$ ruby -e "puts RUBY_PLATFORM"
i386-msys

MSYS2 MinGW 64-bit (64bit) で調べてみると、以下。
$ which ruby
/usr/bin/ruby

$ ruby --version
ruby 2.4.0p0 (2016-12-24 revision 57164) [x86_64-msys]

$ ruby -e "puts RUBY_PLATFORM"
x86_64-msys

つまり、MSYS2上で、MSYS2用の Ruby を動かした場合は、RUBY_PLATFORM に、mingw も mswin も含まれていない場面があるようで。

であれば、mruby-io の mrbgem.rake を修正してみたらどうなるだろう。
  case RUBY_PLATFORM
  when /mingw|mswin/
  case RUBY_PLATFORM
  when /mingw|mswin|msys/

ビルドしてみた。mruby-require を含めても、mruby-io のコンパイルでエラーが出なくなった。ビルドが最後まで通った。

ココかー。ココだったのか。この記述のせいで、MinGW + MSYS と、MSYS2 で、ビルドが通ったり通らなかったりしていたのだな。

Cプログラムにmrubyを組み込めなくなった。 :

MSYS2上でも mruby-require を組み込んだ形でビルドできるようになったはずなので、昨日書いた、SDL2を使うCプログラム + mruby を、mruby-require を使うこと前提の形に書き換えられるはず。

と思ったが、ビルドが通らなくなってしまった。
$ make
/mingw32/bin/gcc -g -Wall -I/mingw32/include/SDL2 -Dmain=SDL_main -I../mruby/include   -c -o glmrubysdl2.o glmrubysdl2.c
/mingw32/bin/g++ -o glmrubysdl2 glmrubysdl2.o -L../mruby/build/host/lib -lmruby -lm -L/mingw32/lib -lmingw32 -lSDL2main -lSDL2 -lSDL2_image -lpng -lz -ljpeg -ltiff -lwebp -llzma -ldinput8 -ldxguid -ldxerr8 -luser32 -lgdi32 -lwinmm -limm32 -lole32 -loleaut32 -lshell32 -lversion -luuid -lopengl32 -lglu32 -lpthread -Wl,-rpath,/mingw32/lib -static -static-libgcc -static-libstdc++
../mruby/build/host/lib\libmruby.a(io.o): In function `fptr_finalize':
D:/home/mieki256/prg/mruby/mruby/mrbgems/mruby-io/src/io.c:653: undefined reference to `_imp__closesocket@4'
D:/home/mieki256/prg/mruby/mruby/mrbgems/mruby-io/src/io.c:654: undefined reference to `_imp__WSAGetLastError@0'
../mruby/build/host/lib\libmruby.a(io.o): In function `mrb_io_s_select':
D:/home/mieki256/prg/mruby/mruby/mrbgems/mruby-io/src/io.c:1146: undefined reference to `_imp__select@20'
D:/home/mieki256/prg/mruby/mruby/mrbgems/mruby-io/src/io.c:1168: undefined reference to `__WSAFDIsSet@8'
D:/home/mieki256/prg/mruby/mruby/mrbgems/mruby-io/src/io.c:1169: undefined reference to `__WSAFDIsSet@8'
D:/home/mieki256/prg/mruby/mruby/mrbgems/mruby-io/src/io.c:1179: undefined reference to `__WSAFDIsSet@8'
D:/home/mieki256/prg/mruby/mruby/mrbgems/mruby-io/src/io.c:1181: undefined reference to `__WSAFDIsSet@8'
D:/home/mieki256/prg/mruby/mruby/mrbgems/mruby-io/src/io.c:1191: undefined reference to `__WSAFDIsSet@8'
../mruby/build/host/lib\libmruby.a(io.o):D:/home/mieki256/prg/mruby/mruby/mrbgems/mruby-io/src/io.c:1193: more undefined references to `__WSAFDIsSet@8' follow
collect2.exe: error: ld returned 1 exit status
make: *** [Makefile:42: glmrubysdl2] エラー 1
なんだかまた似たようなエラーが。closesocket なんて知らねえよと言われてる…。

ググったら以下の記事に遭遇。

_MinGWにてSocket通信を行うには - ハードリカーエンジニア
Winsockを使うためには、 #include にてインクルードしてあげれば良いのです…が、他にもコンパイル時に ws2_32.lib もリンカに設定してあげないといけません。設定するにはコンパイル時に下記のようなコマンドを入力します。

gcc -lwsock32 main.c -lws2_32

MinGWにてSocket通信を行うには - ハードリカーエンジニア より


そういうものなのか…。Makefile を修正。

Makefile
TARGETS = glmrubysdl2

all: $(TARGETS)

SDL_PREFIX  = /mingw32
# SDL_PREFIX  = /mingw

MRB_HEAD    = ../mruby/include
MRB_LIBS    = ../mruby/build/host/lib

# SDL_CONFIG  = $(SDL_PREFIX)/bin/sdl2-config
SDL_CONFIG  = sdl2-config
CG_LIBS     = 

CROSS_COMPILE = $(SDL_PREFIX)/bin/
CC = $(CROSS_COMPILE)gcc
CXX = $(CROSS_COMPILE)g++

# SDLCFLAGS   = `$(SDL_CONFIG) --cflags`
SDLCFLAGS = -I$(SDL_PREFIX)/include/SDL2 -Dmain=SDL_main
CFLAGS = -g -Wall $(SDLCFLAGS) -I$(MRB_HEAD)
CXXFLAGS = -g -Wall $(SDLCFLAGS) -I$(MRB_HEAD)

# SDLLIBS     = `$(SDL_CONFIG) --libs`
# SDLLIBS     = -L$(SDL_PREFIX)/lib -lmingw32 -lSDL2main -lSDL2 -mwindows
SDLLIBS = -L$(SDL_PREFIX)/lib -lmingw32 -lSDL2main -lSDL2

# LDFLAGS     = -Wl,-rpath,$(SDL_PREFIX)/lib  -static -static-libgcc -static-libstdc++ -mwindows
LDFLAGS = -Wl,-rpath,$(SDL_PREFIX)/lib -static -static-libgcc -static-libstdc++

# LIBS = -L$(MRB_LIBS) -lmruby -lm $(SDLLIBS) -lopengl32 -lglu32 -lm -lSDL2_image
LIBS = -L$(MRB_LIBS) -lmruby -lm $(SDLLIBS) \
  -lSDL2_image -lpng -lz -ljpeg -ltiff -lwebp -llzma \
  -ldinput8 -ldxguid -ldxerr8 -luser32 -lgdi32 -lwinmm \
  -limm32 -lole32 -loleaut32 -lshell32 -lversion -luuid \
  -lopengl32 -lglu32 -lpthread \
  -lwsock32 -lws2_32

clean:
	rm -f *.o *.a *~ $(TARGETS)

$(TARGETS): $(TARGETS).o
	$(CXX) -o $@ $^ $(LIBS) $(LDFLAGS)
LIBS に、-lwsock32 -lws2_32 を追加してみた。

ビルドが通った。

いよいよ、mrubyスクリプトの、main.rb を修正。main.rb から、testsprite.rb というファイルを require で読み込むようにしてみる。

main.rb
#!ruby

require "testsprite"

class Scene
  def initialize
    @sprs = []
    num = 128
    ang = 0
    ang_d = 360.0 / num
    num.times do
      rad = ang * Math::PI / 180.0
      r = rand * 4.0 + 1.0
      dx = r * Math.cos(rad)
      dy = r * Math.sin(rad)
      s = TestSprite.new(320, 240, "sample.png", dx, dy)
      @sprs.push(s)
      ang += ang_d
    end
  end

  def update
    @sprs.each { |s| s.update }
  end

  def draw
    @sprs.each { |s| s.draw }
  end
end

Scene.new

testsprite.rb
#!ruby

class TestSprite < Sprite
  def initialize(x, y, imagefile, dx, dy)
    super(x, y, imagefile)
    @bx = x
    @by = y
    @dx = dx
    @dy = dy
  end

  def update
    wh = width / 2
    hh = height / 2
    @bx += @dx
    @by += @dy
    @dx *= -1 if (@bx <= wh or @bx >= 640 - wh)
    @dy *= -1 if (@by <= hh or @by >= 480 - hh)
    @x = (@bx - wh).to_i
    @y = (@by - hh).to_i
  end
end

出来上がった .exe を実行してみた。画像が表示された。

つまり、mruby-require を使えば、mrubyスクリプトソースをファイル分割して扱うことも可能、と分かった。まあ、MSYS2上で作業するなら、ビルド設定の記述を修正しないといけないあたりがアレではあるけど。何にせよ、良かった。Ruby は Lua 未満、という状態にならずに済みそう。

しかし…。最初、「testsprite」を「testprite」と間違って打ってしまって、真っ黒なウインドウが表示されるだけの状態になって悩んでしまった。やはり、mruby 側でどんなエラーが発生しているのか、エラー情報を取得して出力する何かが必要になりそうだなと…。そういう機能は絶対ありそうだけど、何をどう調べたらいいのやら。

2018/03/20(火) [n年前の日記]

#1 [ruby][mruby] Cプログラムに組み込んだmruby側のエラー処理

Cで書いたプログラムに組み込んだ mruby 側で、エラーが出ていることを判別したり、どんなエラー内容なのかを取得したり、ということをしたいわけで。

ググったら、やっぱりちゃんと機能として用意されてた。

_Cでmrubyコード実行時に発生したエラーの内容とバックトレースを取得 - Qiita
_Cに組み込んだmrubyのコードのエラーハンドリングについて - Kentaro Kuribayashi's blog

手元のソースでは、以下のような感じにしてみた。mruby 側でエラーが出た時だけ、エラー内容を printf() で出力して、return -2 で戻る処理。

// display mruby state error
void mrb_state_error_disp(mrb_state *mrb)
{
  // error
  mrb_value exc = mrb_obj_value(mrb->exc);

  // error information
  mrb_value backtrace = mrb_get_backtrace(mrb, exc);
  mrb_value inspect_bt = mrb_inspect(mrb, backtrace);
  printf("%s\n", mrb_str_to_cstr(mrb, inspect_bt));

  // backtrace
  enum mrb_vtype type = mrb_type(exc);
  mrb_value inspect = mrb_inspect(mrb, exc);
  printf("%d : %s\n", type, mrb_str_to_cstr(mrb, inspect));
}

...

  mrb_state *mrb = mrb_open();

  fp = fopen("main.rb", "r");
  mrb_obj = mrb_load_file(mrb, fp);
  fclose(fp);

  if (mrb->exc != 0 && (mrb_nil_p(mrb_obj) || mrb_undef_p(mrb_obj)))
  {
    // error
    mrb_state_error_disp(mrb);
    mrb->exc = 0;

    mrb_close(mrb);
    return -2;
  }

mrb_load_file(mrb_state *mrb, FILE *fp) で、mrubyスクリプトファイルを読み込んで実行することができるけど、その時の戻り値を取っておいて…。

mrubyのコードを評価した結果が上記のようなエラーとなった場合、以下の値が帰ってきます。

* コンパイル時のエラー: nil(mrb_nil_value()の返す値)
* 実行時のエラー: undef(mrb_undef_value()の返す値)

また、mrb->excにエラーの内容が代入されます。

Cに組み込んだmrubyのコードのエラーハンドリングについて - Kentaro Kuribayashi's blog より

ということらしいから、以下でエラーが出たかどうかを判別できる。
  if (mrb->exc != 0 && (mrb_nil_p(mrb_obj) || mrb_undef_p(mrb_obj)))
  {
    // error
  }

ちなみに、mruby関係の記事を色々眺めていて、なんだか分かってきたけど、mruby の場合、〜_p とついてる関数だかマクロだかは、「〜な状態か?」を 真/偽 (1/0、TRUE/FALSE) で返すことになっているらしい。

#2 [ruby][mruby] mrubyのタグをつけた

ここ最近 mruby 関係を弄ってたけど、日記にメモする際に「ruby」のタグをつけてたわけで。しかし、なんだかちょっとメモの量が多くなってきたような気がするので、ここに来て「mruby」のタグを各メモに対してつけ直しておいた。とメモ。

しかし、数ヶ月後には、このタグをつけてたことを忘れそう。どんなタグを用意したのか、すぐ忘れちゃうんだよな…。

2018/03/21(水) [n年前の日記]

#1 [ruby][mruby] Rubyにおいてnew以外でクラスを生成する書き方

DXRuby の Image のように、Image.new でもクラス(のインスタンス)を生成できるけど Image.load("画像ファイル名") でも生成できる、そんなクラスを作りたかったのだけど、その方法がずっと分からなかったわけで。

しかし、 _dxruby_sdl_dxsdl2r の image.rb を眺めて、「あっ…そうやればいいのか」と分かった、とメモ。

_dxruby_sdl/image.rb at master - takaokouji/dxruby_sdl
_dxsdl2r/image.rb at master - mirichi/dxsdl2r

つまり、クラスの中で、def self.load 〜 end でクラスメソッドを作って、その中で自身のクラス、のインスタンスを .new で生成して、その生成したインスタンスを返してやればいいのだなと。

であれば、それを mruby を組み込んだCのプログラムの中でやればいい…。

mruby でクラスメソッドを定義するのは、 _mrb_define_class_method() 。ちなみに、インスタンスメソッドを定義するのは、 _mrb_define_method 。なので、以下のような感じの記述になるはず。
  // define class
  cImage = mrb_define_class(mrb, "ImageSurface", mrb->object_class);
  MRB_SET_INSTANCE_TT(cImage, MRB_TT_DATA);

  // define class method
  mrb_define_class_method(mrb, cImage, "load",
                          glmrb_image_load, MRB_ARGS_REQ(1));

  // define instance method
  mrb_define_method(mrb, cImage, "initialize",
                    glmrb_image_initialize, MRB_ARGS_REQ(3));

メソッドに対応する関数の中で、インスタンスを生成するのは、 _mrb_obj_new()
  mrb_value param[3];
  param[0] = mrb_nil_value();
  param[1] = mrb_nil_value();
  param[2] = mrb_ary_new(mrb);

  mrb_value obj = mrb_obj_new(mrb, cImage, 3, param);

  ...

  return obj;

そんな感じで、以下のようなソースになった。…ちょっと長くなりすぎてしまったので、github に置いておきました。

_mieki256/glmrubysdl2-c
_glmrubysdl2-c/glmrubysdl2.c

2018/03/22(木) [n年前の日記]

#1 [nitijyou] 漫画を消化中

弟が帰省した際に置いていってくれた漫画単行本を消化中。「球場ラヴァーズ」シリーズ(石田敦子著)や、「ハチワンダイバー」(柴田ヨクサル著)を読んでいたり。

「球場ラヴァーズ」は、野球漫画でもなく、応援団漫画でもなく、野球応援漫画、というなんだかちょっと妙なジャンルで、その視点に感心してしまった。特撮漫画ではなく、特撮オタク漫画というジャンルの「トクサツガガガ」(丹羽庭著)との共通点を感じたりもして。野球について全然知らない読者も想定して、専門用語(?)の解説が散りばめられていることにも感心。野球鑑賞の入門漫画としての価値も高いのではないかと。

それにしても、元アニメーターさんの漫画は、どうしてこうも読みづらいのだろうなと…。石田敦子先生の作品に限らず、安彦良和先生の漫画もそうだったりするわけで…。アニメーターさんとしての経歴より、漫画家さんとしての経歴のほうが、下手すると長いのではないかと思えるのだけど、しかし、どうにも読みづらい。何故なのだろう。ネームの作り方に関する根本の部分で、漫画家として育った方々と、何か大きな違いがあるのだろうけど、具体的に何が違うのか、そこが全然分からない。アニメーター時代にフレーム単位でレイアウトすることに慣れ過ぎてしまって、ページ単位でレイアウトする能力が…というわけでもなさそうだし。コマを跨いだレイアウトも多用してたりするから、未だにフレームに縛られてるわけでもないよなと…。分からんなあ。何が違うんだろう。

「ハチワンダイバー」は、異様なテンションにとにかく圧倒されてしまった。何なんだろう、このテンション…。

最初の頃のペンタッチと、中盤あたりのペンタッチが変わってるあたりがなんだか気になったり。最初のあたりは…もしや筆で輪郭を描いてたのだろうか。途中からGペンや丸ペンになってる、とか。それとも初期からGペン使いで、グイグイとタッチをつけてたけど、次第に線の傾向が変わってきただけだろうか。

2018/03/23(金) [n年前の日記]

#1 [nitijyou] 漫画を消化できた

「ハチワンダイバー」の最終巻までなんとか読んだ。面白かった。なんともスゴイ迫力だった。それにしても、この作品、将棋漫画というより格闘漫画だよな…。

ググってみたら、作者さんは小学生時代にプロを目指しそうになるぐらい将棋にハマってたそうで。なるほど、それで将棋部分も比較的しっかり描いてあるのか…。いや、監修者が何人もついてるあたりも、成果物に反映されてるのだろうけど。

#2 [anime] 「ゆるキャン」最終回を鑑賞

イイ感じのアニメだったなと…。キャンプ云々について勉強にもなったし、背景美術が良かったのか、各地の雰囲気もなんとなく伝わってきたし。とにかく雰囲気がいいアニメだなと…。若干、アニメ版「けいおん」を思い出したりもして。ちゃんと作れば、その分ちゃんと良くなってくれる作品ってあるんだなと。

少しネタバレになるけど…。1話の冒頭を再現しつつ、かつ、ちょっと違いがある、てな見せ方をしてたあたりが上手いなと。こういうソレはたしかキュウレンジャーのラスト近辺でも見たような記憶があるけど…。ポプテピピックの、1回目の放送と2回目の放送では視聴者の中でのネタの性質が変わる、みたいな話と通ずる何かがありそうな。繰り返すことで、未知のシチュエーションから既知のシチュエーションに変化しつつ、そこには明確な違いも盛り込まれていることで、視聴者の中で、懐かしさと新鮮さを同時に味わうことができる、とでもいうか…。何にせよ、こういうソレはなんだか上手いなと感心してしまったり。

#3 [anime] 「トイストーリー3」を視聴

TV放送されてたので見てみたり。視聴済みかどうかの記憶が無かったのだけど、ピンクの熊が出てきたカットで、「あ。これ見たことあるぞ」とようやく思い出せた。

何度も見ても、やっぱり上手いなと…。まるでピタゴラスイッチのように、コレをこうしたらアレがこうなって、するとコレがこうなるからココがこうなって、てな展開に唸ってしまう。こんな脚本を書ける人は…日本には居るのだろうか…。いや、ピクサーのことだから、会議をしながらこういう脚本にまとめていったのかなと想像したりもするけれど。おそらく一人で書いてるわけではないのだろう。

ラストのあたりが…いいんだよなあ…。次代に継承されていくこと、受け継がれていくことの喜びと、かすかな寂しさがそこにある、とでもいうか…。観客の心に、じわじわとゆっくりゆっくり染み込んでくる脚本。そういう脚本は、やはり強いなと。

おそらく、子供より大人のほうが泣いてしまう映画ではあるのだろうなと。お子さんと一緒に見ていた親がうっかり涙ぐんでいるのを見て、お子さんは、「え? なんでコレで泣くの?」と若干ドン引きするかもしれないけれど。そのお子さんが大人になって、子供ができて、子供にコレを見せつつ自分もチラチラと見てみたら、「あっ…。なるほど、こりゃ泣くわ」と涙ぐんで、その光景を見たお子さんが「え? なんで?」とまたドン引き…てなことが繰り返される、そういう種類の映画ではあるまいかと。間違いなく名作。ではないのかな。たぶん。

細かいことだけど、カウボーイの玩具が他のキャラに対して酷い発言をした際に、豚の玩具が「お前ってホントいいヤツ」と皮肉たっぷりに言うあたりで、何故か感心してしまったり。フツーだったら「お前酷いヤツだな」とそのまんまの面白みのない台詞を書いちゃいそうだけど、そういうところでもちょっと捻る、てのがなんだかいいなと。と言っても海外の映画ではよく見かけるやり取りではあるけれど…。考えてみたら日本の作品でもたまにそういう台詞回しを見かける、ような気もしてきた。

2018/03/24() [n年前の日記]

#1 [nitijyou] 日記をアップロード

2018/03/05にアップロードしたままだったので、2018/03/21の日記までアップロードした、とメモ。

#2 [nitijyou] 雷が鳴ってる

夜、雷が鳴り始めた。もう、そういう時期か…。福島県は落雷が多いので、困る…。

#3 [anime][neta] キャラクターソフトウェアデザイン

思考メモ。

寝ていたら夢の中で、「キャラクターソフトウェアデザイン」という役職名が出てきて。目が覚めてから、「なんだその役職…」と妄想を始めてしまったり。

集団制作のアニメにおいて、各キャラの外見については、キャラクターデザインと呼ばれる役職の方がデザインをして、監督やP(プロデューサー)、原作の編集部、原作者がOKを出すのだろうけど。

各キャラが、各場面でどういう物言いをするのか、どんな行動をとるタイプなのか、つまり見た目以外の部分については…。事前に規定して、ブレがないかチェックする役職が、用意されてない場合が多いのだろうなと想像したりもして。

もし、将来、更に分業が進んでいくと、キャラの見た目のデザインだけではなく、内面部分の設定についてもまとめあげる役職が発生したりするのかもしれないなと。おそらくそれが、「キャラクターソフトウェアデザイン」みたいなものなんだろうと…。いやまあ、現状では、監督さんやシリーズ構成さんがその役を兼任、というか担当してどうにかしてるのだろうけど。最終的には監督さんが脚本やコンテをチェックして、「これは違うのでやり直し」と指示を出して解決してるのだろうな、と…。

キャラのブレ。 :

例えば、先日までBS11で放送されてた「名探偵ホームズ」などは、そのあたりの統一がされてなくて。分かりやすいのが、警部のキャラ。

片渕脚本+宮崎駿演出回では、警部はホームズを「ホームズさん」と呼んでいて。「警察が解決できない難事件を見事に解決してくれる、とても頼りになる方だから、失礼があってはならないぞ」的な捉え方をしてるのであろうことが全体を通じて感じ取れる。

対して、荒木芳久脚本回では、警部はホームズを「ホームズ」と呼び捨てにしていて。シーンによっては、「ホームズめ。またアイツか」「ホームズのヤツ」等の台詞もポンポン出てくる。警察の捜査に首を突っ込んで邪魔をしたあげく、手柄を掠め取っていく実に邪魔な奴、という認識っぽいなと感じさせるあたり、片渕脚本が提示していた警部の姿とは真逆なキャラとして脚本が書かれていたりする。

また、ホームズというキャラの捉え方も違っていて。例えばモリアーティ教授が何か酷い目に合っている時、荒木脚本のホームズは平気で「ざまあみろ」に近い物言いをする。これが片渕脚本だと、「あらまあ。彼もなかなか大変なことになってるようですな」的な、どことなくとぼけた、あるいは紳士らしさを感じさせる言い方を選んでいたりする。

てな感じで…。各キャラの見た目については、キャラクターデザインという役職の方がキャラデザ表という形でまとめてあるので、各スタッフがキャラを違う見た目で描いてしまうことはほとんどないのだけど。脚本や演出の段階においては、性格設定等を統一させる役が不在で、回によってはキャラが全くの別人になってしまう、みたいなことが集団制作ではたまにあるわけで。 *1

そういったことを考えると…。そのあたりを統一させる役職というのが、作品によっては必要になったりするんだろうなと。スタッフ全員がキャラの性格設定について統一した認識を持てるように、キャラデザ表ならぬキャラ内面表・キャラ性格表みたいなものをまとめあげる役職、あるいは、各人の成果物をチェックしてキャラの性格が統一されるように修正を加えていく役職、みたいな。作画監督・総作画監督に相当する役が、脚本や演出の部分でも用意されたりするのかもなと。

並列処理と統一感。 :

もっともこのあたり、作り方によるわけで。例えば全話の脚本、あるいはコンテを一人で書けば、そういったキャラのブレはほぼ無くなるはず。その代わり、並列処理で脚本・コンテを用意することが難しくなって、一定の制作期間が必ず必要になるだろうけど…。

極めて短いスケジュールでとにかく早く作らねばならない、なんて時には、作業を始める前に「このキャラはこういうキャラ」とすぐ分かる何かしらをひたすら提示する専門の役が必要になるのかも、と。

もっとも、特定の一人が、全体を規定する何かを提示したり、全体をチェックして修正してしまう仕組みにすると、そこで並列処理ができなくなって、「最低限でもこの段階でこれだけの作業時間は必要」という話になるから、スケジュールが厳しくなるはずで…。

作品内の何かしらを統一しようとすると並列処理ができなくなってスケジュールが必要になるし、スケジュールを優先すると並列処理になって作品内のアレコレが統一できなくなるし。とにかく分業を進めればいいのだ…というものでもないのだろうなと。

てな感じのことを起きたばかりのぼんやりした頭でもやもやとつい考えてしまったのでなんとなくメモ。思考メモ。

*1: まあ、「名探偵ホームズ」の場合、制作期間が分断されている上に、制作スタジオすら途中で変わってしまっているので、仕方ないのだろうけど…。

2018/03/25() [n年前の日記]

#1 [cg_tools] Krita 4.0.0 を試用

オープンソースのペイントソフト、Krita 4.0.0 が公開されたらしいので試用してみたり。なんでも、ベクターツールがSVGを使う形になって強化されているらしい。

少し触ってみたけれど、想像してた以上に、ベクターツールがベクターツールらしくなっていた。

使い方は…。
  1. ベクターレイヤーを新規作成
  2. その上で直線、曲線、四角等を描いて図形作成
  3. ベクター図形ツールで、属性(線幅、線の太さ、線の色、線のスタイル、面の色、面の塗り種類)を変更
  4. ベクター図形編集ツールで、制御点の位置やハンドルを変更
てな感じ。たぶん。

ベクターライブラリというドックを表示したところ、吹き出しの類が大量に入ってた。上手く使えば漫画っぽい画像を作れたりもするのだろうか。

以下の動画を眺めれば、雰囲気が分かるかなと…。

_Krita 4 | New features - YouTube
_Krita 4.0 Pre-Alpha: New Features - YouTube
_Vector Graphics in Krita 4.0 - YouTube

2018/03/26(月) [n年前の日記]

#1 [cg_tools] Inkscape 0.92.3 x64を試用

Inkscape 0.92.3 が公開されたので試用してみたり。環境は Windows10 x64。

_Download Inkscape 0.92.3 | Inkscape を眺めると、「fontconfigの新しい版を使ったから Windows上での起動が速くなったぜ!」と書いてあった。たしかに、なんだか速くなっている気がする。

ちなみに、fontconfig のキャッシュは、
C:\Users\USERNAME\AppData\Local\fontconfig\
にあるので、調子が悪い時は該当フォルダを削除してから Inkscape を実行してみると改善する可能性もありそうな。初回起動時はキャッシュを作るはずだから時間がかかるけど、2回目からはキャッシュを読んで起動が速くなる…のではないかと。たぶん。

フィルタがなんだか妙な感じ。 :

フィルタ → 光と影 → 影を落とす、を実行してみたら、オフセット値と見た目がなんだか一致してないような感じがしたり。影が領域外に出ちゃって切り取られてしまっている…。

Inkscape 0.91 Portable x86 を動かして確認してみたら、0.92.3 は、やはり以前と結果が違っているような。

_Inkscape 0.92.2 Portable x86 をDL・インストールして確認してみたら、0.92.3 と同様の妙な結果になった。最近の版はバグってるみたいだな…。

_Bug #1690324 “Drop Shadow Blurs Edge of Rectangle” : Bugs : Inkscape

2017/05頃に報告されてるけど誰も気づいてないっぽい。

_Bug #1323047 “Filter effect is clipped because the filter boundi...” : Bugs : Inkscape

フィルタエディタを開いて範囲を変更すれば、一応はクリッピングされずに済む状態にできるようではあるなと…。

2018/03/27追記。 :

その後もしつこく弄ってたら、ドキュメントのプロパティを変更することで、0.91 の状態に近づけられそうと分かった。ファイル → ドキュメントのプロパティ → ページ、で、単位を px にしつつ、拡大縮小の値を1.0にすればいい、のかな。たぶん。ちなみに、各単位は、デフォルトでは mm になってる模様。

おそらく、バグというわけではなくて…。0.91 と 0.92 で、起動直後に新規作成されてるドキュメントのプロパティ値が変更されたことで、フィルタの効果の見え方が変わったのではないか、と。

#2 [anime][neta] 「三ツ星カラーズ」最終回を視聴

思考メモ。

BS11で放送されてた「三ツ星カラーズ」の最終回を視聴。

このアニメ、個人的には、見ていてなんだか考え込んでしまう作品だったなと…。

基本設定としては、東京上野を舞台に3人の女子小学生が小さな騒動を巻き起こす日常系、みたいな感じだと思うのだけど。しかし、女子小学生と称しながら、中身というかやってることは完全に男子小学生のソレで、かつ、「それはアウトだろう」と思える悪質な行為に対しても、周囲の大人達が全く叱ってくれないと言う…。 *1 ぶっちゃけ、とても気持ち悪い作品になっていて。(感想には個人差があります)

なんとなく、ゲーム業界を舞台にした「NEW GAME」を思い出したりもして。アレも、登場人物が全員美少女で…。ネット上では、「ブラックな職場で精神を病んでしまったおじさん達が自分も周囲も全部美少女に見えている様子を描いている」てな設定を誰かが言い出しちゃってたけど、そういう設定と思って眺めないとちょっと耐えられない感じの、妙な不自然さが…。

ということで、1話から最終話まで、「何故、この子達を、男子小学生として描けないのだろう…」てなあたりでずっと悩みながら眺めてたという。

商品訴求力。 :

やってることが男子小学生なのだから、見た目も男子小学生のほうが良いのではないか、などとうっかり思ったりするものの。しかし、それを実現したら、おそらく「団地ともお」や、未見だけど「ズッコケ三人組」シリーズになるのではという予感もあって。

「カラーズ」を喜んで見てる層が、「団地ともお」その他を視聴してるかと言えば、おそらくその手の作品は完全無視だろう、それでは商売にならない・商品にならないだろうと想像もするわけで。

つまり、やってることは同じでも、見た目が変わるだけで既存作や他作品との差別化ができて、別の層に受容される展開はいくらでもあるわけで。

例えばの話、 _UNITY-CHAN が「ユニティおじさん」だったらここまで使ってもらえたか、知名度を得られただろうかと考えると、それは難しいだろうなと想像するし。同様に、
  • 「ガルパン」が女子高生集団ではなくて男子高校生集団だったらどうか。
  • 「ラブライブ」が女子高生アイドルグループではなく男子高校生アイドルグループだったらどうか。
  • 「宇宙よりも遠い場所」が女子高生4人組ではなく男子高校生4人組だったらどうか。
  • 「りゅうおうのおしごと」が、お兄さんと幼女ではなく、おじさんと少年だったらどうか。
メインキャラが男になった時、それら作品をアニメファンは見てくれるのだろうか。…見てくれないような気がする。商売にならないのではないか。たぶん。

などと考えると、中身は男でも見た目を美少女にするのは戦法としてアリで。故に、「カラーズ」は正しい。アレはアレで仕方ない。ある意味賢い。とも思えてくるわけだけど。

とは言え…。
  • 「GANGSTA.」のおじさん2人が美少女だったらどうなのか。
  • 「カウボーイビバップ」のおじさん2人が美少女だったらどうなのか。
  • 「ルパン三世」のルパン、次元、ゴエモンが美少女だったらどうなのか。
その場合、なんだか色々と台無しだよなと…。

作品によって、見た目を変えてもアリなものと、見た目を変えたら台無しなものがありそうな気もしたり。ただ、「カラーズ」はどうなのか、そこはちょっと判断できなくて。…いや、ウケていたのだから、アレはアリな事例、なんだろうか。なのだろうな。たぶん。

見た目を変える際の飛躍。 :

キャラの見た目を変えて売り込んだ作品と言っても、各作品の飛躍振りには差があって。

例えば、日本刀をイケメン男子にしてしまった「刀剣乱舞」などは、ホームラン級の飛距離・飛躍なので、逆に感心したりもするわけで。他にも、歴史上の偉人達がどれもこれも異なるイメージで描かれてしまう「Fate」シリーズとか。文豪の実像とは完全に乖離してる「文豪ストレイドッグス」とか。そこまで行けば文句のつけようがないというか、視点や発想に脱帽する以外にないわけだけど。

その点、「カラーズ」はどうかと考えると、これは飛躍が少ない。だから、言い方としては悪いけど、個人的には「誤解を生みやすい悪質さ」もしくは「安直さ」を感じ取ってしまうところもあったというか。とは言え、見た目を美少女にして売り込むというのは、他作品・他ジャンルでもよくやってることなのだから、「カラーズ」だけ責めたりしたら、それはおかしい話で…。

外見と内面のギャップ、という視点もあるのかな…。
  • 宇宙人の外見なのに、中身はガンプラオタクの「ケロロ軍曹」
  • 女子高生(女子中学生?)の見た目なのに、中身はおじさんの「ポプテピピック」
  • 外見は小太りおっさんなのに、少年キャラという設定の「パタリロ」
等々。考えてみたら、そのあたりはギャグ漫画なのか…。ギャグ漫画の場合は、飛躍・ギャップがあったほうが面白くなる…?

見た目は幼女なのに中身はおっさんの「幼女戦記」もあったか…。アレは、個人的にしっくりきたんだけど…。飛躍してるからかな…。

企画が通るか通らないか。 :

大体にして、「男子小学生が騒動を起こす」という企画だったら、今、この御時勢、漫画の連載企画としてGOサインが出るのですかという問題が。「ソレ『団地ともお』じゃん」「なんでウチでアレをわざわざやらなくちゃいけないの」「別な企画考えてこいよ」と言われて没になりそうだよなと。どの層に売り込めそうか、そこも見えてこないし…。

しかし、「女子小学生が騒動を起こす」という企画で、しかもそこで提示された絵が可愛いキャラだったら、「これ、もしかしてイケるかな?」という気になってくるよなと。しかも、原作者の絵はめっちゃ上手いし、実に可愛らしいキャラを描くし。あの魅力的な絵柄を活かさないなんて、あまりにも勿体無いし。

企画が通らないことには、ヒットもアニメ化もへったくれもないわけで。故に、やはり「カラーズ」は正しい。どう考えてもアレはアリだろう、と思えるのだけど。

でも、見ていて、「コレじゃ男子小学生だよなあ…。うーん」という複雑な気分になってしまうわけで。理屈ではアリだ、これが正解だと分かってるつもりでも、感覚的になんだかギクシャクするというか。

そのあたり、1クール眺めながら、ずっともやもやしていたのでした。しかも、喜んで見ている人が多いらしいあたりが、更にもやもや…。この気持ち悪さを感じているのは自分だけなのか。「NEW GAME」の時は気持ち悪さを感じてる人がチラホラ居てちょっと安心したけど、「カラーズ」には居ないのか。居ないとしたら、それは何故なのか。「NEW GAME」とは何が違うのか。一体どこで差が出てくるのか。みたいな。

てな感じで、漫画やアニメの類において、キャラの見た目を変えて提示することについて、自分の中では、なんだかちょっと考え込んでしまうアニメでした。とメモ。

いやまあ、現実にはあり得ないファンタジーを描けるのが漫画やアニメだし、面白くなるならどんな設定もアリで、何でもリアルにすればいいってもんでもないでしょ、と常々思ってるのでアリかナシかで言えば当然アリなのですが。

アリのはずなのですが…。自分の中で、「コレはアリだろう。正しいだろう」と言ってる自分と、「いや…ちょっと待って…。でもなんか違うんだよ…何だろう…」とごね続けてる自分が居るわけで。これだけダラダラ書いても違和感の正体を言語化できない。何だろうなあ…。うーん。分からん。

まあ、思考メモです。

*1: 若い男性警察官だけが主人公達の行為について怒るのだけど、そのキャラも中身が小学生なので、叱ってるというより単に怒ってるだけで…。

2018/03/27(火) [n年前の日記]

#1 [cg_tools] ドットを打ってる

HDDを漁ってたら昔書いたソースが見つかったのだけど、先日作成した仮画像で置き換えつつ動作させようと思ったらパターンが足りてないことに気づいたり。やはりしゃがみパターンはあったほうがいいかな、と思えてきたので、EDGE2 を起動してドット打ちを始めたり。

どうも手足の長さのバランスがおかしいような気もする。Spriter や Moho を使って、パーツを回転させて大き目の画像を作ってから、縮小・加工したほうが良かっただろうか…。

2018/03/28(水) [n年前の日記]

#1 [cg_tools] まだドットを打ってる

まだドット打ち作業中。

以前作ったソレは銃を撃ってるアニメパターンしか用意してなかったけど、プレイヤー仕様によっては撃たないパターンも必要かなと思い直してパターンを追加していたら、数がどんどん増えてきた。パーツを組み合わせてアニメを作ったほうが良かっただろうか…。でも、それだと仮画像としては扱いづらくなるし…。

#2 [cg_tools] GIMP 2.10.0 RC1を試用

GIMP 2.10.0 RC1 が公開されたらしい。RC1とついてるので、「まだ開発版だけど基本的にはコレを元にしつつ正式版まで持っていきたいなあ」てな版ではあるけれど、気になったのでインストールして試用してみたり。環境は Windows10 x64。

ダウンロードは以下から。

_GIMP - Development

インストールして起動してみたら、起動直後のフォントの検索で、いきなり落ちた。おそらく、Inkscape が作った fontconfig のキャッシュを読み込もうとして、フォーマットが合わなくてエラーが出たのではあるまいか。とりあえず、
C:\Users\USERNAME\AppData\Local\fontconfig
を削除して再度実行。今度は起動してくれた。

コレ、下手すると Windows上で、Inkscape と GIMP 2.10 の共存ができない可能性もありそうな。…と思ったけれど、その後試してみたら、Inkscape も GIMP 2.10.0 RC1 も起動する。何だったんだ…?

デフォルトのテーマは黒系になったらしい。アイコンもモノトーン。メニュー内のグレーアウトされた文字列が見づらい…。たぶんこれ、テーマに合わせたグレーアウト色で描画せずに、決め打ちのグレーアウト色で描画してるんじゃないかな…。

一応、編集 → 設定 → テーマ、で、System にすれば今まで通りの見た目になる。アイコンも、Icon Theme を変更すれば、今まで通りの見た目になる。

MyPaint のブラシが組み込まれているらしい。鉛筆やブラシではなく、専用ツールに切り替えると利用できるようになる。

左右対称描画、上下対象描画もサポートされているらしい。ただ、左右と上下の両方にチェックを入れると、対角線上の領域に描画されないようで…。バグなのか仕様なのか分からんけど、片方だけ使うしかないのかな…。

タイリング描画もついている。どうやら描画関係の各仕様は、Krita を追随してるように思える…。

設定その他は、C:\Users\USERNAME\AppData\Roaming\GIMP\2.10\ 以下に保存されている模様。環境変数 HOME は見ないで、決め打ちになったのかな…。

2018/03/29(木) [n年前の日記]

#1 [anime][neta] SE付きのOPについて思うこと

「ダメプリ」の最終回を眺めてたらOPにSEがついてて、なんだか考え込んでしまったり。いやまあ、「ダメプリ」は狙ってやった事例じゃないかと想像するので問題無いと思うのですが。

SE付きOPと言えば、「ポプテピピック」だよなと。あの作品のSE付き版OPは、アニメを作ってる人なら絶対に見なきゃダメだろうなと。アレはスゴイ。皮肉たっぷり。曲にしっかり合わせて作った映像に、頓珍漢なタイミングでSEをつけていく行為の無意味さを教えてくれる。結局、SEをつけるとギャグにしかならないんだよな…。もちろん、ギャグやパロディのつもりで狙ってつけてるならアリだとは思うけど。

そもそも、一体誰が、どのタイトルで、何を目的として、SEをつけ始めたのだろう…。まあ、昭和アニメのどれか、だろうけど。

2018/03/30(金) [n年前の日記]

#1 [ruby] Rubyのスクリプトソースを眺めてる

昔書いた、DXRubyを使ったスクリプトを眺めてるところ。どういう処理をしてたのかすっかり忘れてるので、クラス毎に別ファイルにしたり、コメントを yardoc 形式に修正したりつつ、動作を把握しようとしていたり。

2018/03/31() [n年前の日記]

#1 [nitijyou] まだRubyのスクリプトソースを眺めてる

昔書いたスクリプトは、Tiled の保存ファイルをそのまま読んでテキスト形式に変換して、その変換したテキスト形式のファイルを読んで画面に表示、みたいなことをしてたけど。今の Tiled は JSON でエクスポートできるので、JSON を読んで表示できるようにしたいなと。以前書いたスクリプトの、どのあたりを修正すれば変更できそうか眺めてるところ。

以上、31 日分です。

過去ログ表示

Prev - 2018/03 - Next
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31

カテゴリで表示

検索機能は Namazu for hns で提供されています。(詳細指定/ヘルプ


注意: 現在使用の日記自動生成システムは Version 2.19.6 です。
公開されている日記自動生成システムは Version 2.19.5 です。

Powered by hns-2.19.6, HyperNikkiSystem Project