mieki256's diary



2016/12/01(木) [n年前の日記]

#1 [python] ドットエディタモドキをgithubにアップロードしておいた

Python + PySide + Pillow(PIL) を使って、ドットエディタモドキを作ってるところ、なのだけど。少しずつそれっぽくなってきたので、github にアップロードしてみたり。

_mieki256/stampixelart: Pixel art creation tool.

とりあえず、Python + PySide を使えば、こういうアプリを作れるようですよ、と実証するサンプルぐらいにはなっているかなと。

現状。 :

ここまで作ってはみたけれど。悲しいかな、今のところ、売りが無いなと。ドットエディタとしての基本機能すら満足に実装されてない状態なので、まだこれでは使い道が…。

RGBAブラシ画像の色を変えながら描画できたら新しい何かが見えてきたりしないか、とか、既に出来てるパーツ画像を気軽にペタペタやれたら何か見えてこないか、などと思って作ってみたものの。うーん。どうなんだ。

「ブラシの色を変える? そんなのフォトショでもできるじゃん」とか言い出す人だって出てくる予感。まあ、そのあたりは、 _2016/10/05の日記 を眺めてもらえば話が分かるだろうけど。

#2 [zatta] 流行語ってどこで流行してるのだろう

たまたまNHKをつけてたら流行語大賞なるものを紹介していて。選ばれた言葉が…。自分、「神ってる」なんて知らなかったんだけど…。ソレ、一体どこで流行してたの…。

ああ…野球関係から出てきた言葉なのか…。自分、野球は嫌いなもんで、その手のニュースの類は見てないから、完全に知らなかったですわ…。へえ。そうなんだ。流行ってたんだ。へえ。

ていうかNHKの番組の中でも、スタッフが街に出て独自に行ったアンケート結果と、大賞の結果が大きくずれていて、「どうしてこの言葉が選ばれたんでしょう?」と専門家と称する人に質問していて。つまり、TV番組の中でも疑問を呈されてしまうほどに、大賞なるものを審査してる人達の感覚や印象と、世間のソレが、もはや大きくずれている、ということなのかもしれないなと。

まあ、ジャンルの細分化が進んで、特定分野では流行してるけどその分野に興味が無い人は全くソレを知らない、てな場面が増えたのだろうと思わないでもないけど。例えばアニメのタイトルなんて、アニメに興味がない人達なら、まず知らないだろうし。もちろん、逆もしかりで。その言葉を知ってた人は「ええー、アレ流行ってただろー」と言うだろうけど、知らない人は「あ、そうなの?」みたいな。ますます更に温度差が、てな状況があったりするのだろうか。分からんですが。

それはともかく。気になったので選考委員を調べてみたら、やくみつる氏が居て、なるほどそれじゃこうなるわなと納得。

2016/12/02(金) [n年前の日記]

#1 [python] PySideのQRubberBandを試していたり

PySideには、選択範囲を表示するための QRubberBand なるウィジェットがあるらしいので、以下を参考にしてスクリプトを書いて動作確認中。

_python - How to use QRubberBand with QRect Class in PyQt? - Stack Overflow
_PyQt/Selecting a region of a widget - Python Wiki

#2 [nitijyou] 自転車で買い物に

夜食その他を買いに近所のスーパーまで。

途中で、自転車をたくさん並べてるお店に寄った。随分と綺麗な見た目の店なので、てっきり自転車を売るだけで修理はしないのかなと予想してたけど、自転車のパンク修理やブレーキ修理もやってるようで、なんだか一安心。ではあるけれど、自分以外にお客さんが居なくて…。その手の店が無くなると困るのだけど…。

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

1ヶ月ほど日記をアップロードしてなかったのでアップロード。

内容を読み返して問題が無さそうかチェックするのが面倒で、ついついサボってしまうわけで…。2016/10/28からアップしてなかったらしい、とメモ。

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

#1 [python] PySideのQRubberBandの動作確認

PySideのQRubberBandの動作確認中。

_rubberband_test.py
u"""
QRubberBandの動作確認.

動作確認環境 : Windows10 x64 + Python 2.7.12 + PySide 1.2.4
"""
import sys
from PySide.QtCore import *  # NOQA
from PySide.QtGui import *   # NOQA


class GView(QGraphicsView):

    """Graphics View."""

    def __init__(self, *argv, **keywords):
        """init."""
        super(GView, self).__init__(*argv, **keywords)
        scene = QGraphicsScene(self)
        self.setScene(scene)

        pm = QPixmap("./tmp_bg.png")
        pm_item = QGraphicsPixmapItem(pm)
        scene.addItem(pm_item)

        # ラバーバンドを生成
        self.rband = QRubberBand(QRubberBand.Rectangle, self)
        self.start_pos = QPoint()

    def mousePressEvent(self, event):
        u"""マウスボタンが押された."""
        if event.button() == Qt.LeftButton:
            # 左ボタンが押された
            self.start_pos = event.pos()  # クリックした座標を記憶
            rect = QRect(self.start_pos, QSize())
            self.rband.setGeometry(rect)  # ラバーバンドの範囲を設定
            self.rband.show()  # ラバーバンドを表示

            p0 = self.mapToScene(self.start_pos)
            x0 = p0.x()
            y0 = p0.y()
            self.set_status("(%d, %d)" % (x0, y0))
        elif event.button() == Qt.RightButton:
            # 右ボタンが押された
            self.rband.hide()  # ラバーバンドを非表示に

    def mouseMoveEvent(self, event):
        u"""マウスカーソルが動いた."""
        if not self.start_pos.isNull():
            # マウスクリック後の状態
            rect = QRect(self.start_pos, QPoint(event.pos())).normalized()
            self.rband.setGeometry(rect)  # ラバーバンドの範囲を再設定

            # ステータスバー相当に座標を表示
            p0 = self.mapToScene(self.start_pos)
            x0 = p0.x()
            y0 = p0.y()
            p1 = self.mapToScene(event.pos())
            x1 = p1.x()
            y1 = p1.y()
            dx = abs(x1 - x0)
            dy = abs(y1 - y0)
            self.set_status("(%d, %d) - (%d, %d) : (%d x %d)" %
                            (x0, y0, x1, y1, dx, dy))

    def mouseReleaseEvent(self, event):
        u"""マウスボタンが離された."""
        if event.button() == Qt.LeftButton:
            self.start_pos = QPoint()

    def set_status(self, str):
        u"""ステータスバー相当のテキストを設定."""
        self.parent().set_status(str)


class MyWidget(QWidget):

    u"""メインウインドウ相当."""

    def __init__(self, *argv, **keywords):
        """init."""
        super(MyWidget, self).__init__(*argv, **keywords)
        self.gview = GView(self)
        self.lbl = QLabel("Ready", self)

        l = QVBoxLayout()
        l.addWidget(self.gview)
        l.addWidget(self.lbl)
        self.setLayout(l)

    def set_status(self, str):
        u"""ステータスバー相当にテキストを設定."""
        self.lbl.setText(str)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    w = MyWidget()
    w.show()
    sys.exit(app.exec_())

テスト画像。 _tmp_bg.png

こんな感じになった。
rubberband_test_ss01.gif

動かしてみて分かったけれど、これはグラフィックツール等で使うタイプの選択範囲のソレじゃないなと。おそらく用途としては、エクスプローラ等でファイル選択する時に使う系のラバーバンド、ではないかと。グラフィックツール用のソレが欲しい場合は、自分で実装しないとダメっぽい。

グラフィックツール用の選択範囲に求められる仕様。 :

グラフィックツール用の選択範囲に求められる仕様としては…。
  • 矩形の境界線だけ描いてあればいい。中は塗り潰しをしなくても構わない。
  • 境界線は、蟻の行進(Marching ants)か、XOR表示が望ましい。
  • 境界線の上にマウスカーソルを合わせてドラッグすると、境界線の位置を変更できたりするとありがたい。
そんな感じだろうか。

蟻の行進(Marching ants)てのは、以下が参考になるかと。2D画像編集ツールを使ってる人なら「あー、ハイハイ。アレか」と分かるはず。

_Marching ants - Wikipedia
_Fun with marching ants - Banu Blog

実は意外と実装が面倒…のような気がする。

#2 [cg_tools] 各種CGツールの選択範囲の境界線について

ふと気になったので確認してみて知ったのだけど。Windows10 のペイントの選択範囲って、只の点線なのですな。蟻の行進とかしていない。フツーはこれでも十分、だったりするのだろうか。

下地の色に応じて点線の色が変わってるのかと一瞬思ったけど、拡大表示して確認したら、点線は白と青の色で固定してある模様。下地が一色でベタ塗りされているなら、白か青のどちらかで、そこに境界線があると分かるだろう…と考えて、この仕様にしたのかもしれず。

ちなみに、Paint.NET の選択範囲を確認したら、こちらはきっちりと蟻の行進をしているようで。どういう処理をしているんだろう…。パターンで一部を塗り潰し、ではなくて、線として描いているのかな…。

ついでに、Photoshop Elements 8.0 と GIMP 2.8.18 の選択範囲の境界線を確認してみたら、こちらはパターンで塗り潰してるタイプに見えた。斜めの境界線ではちょっと見づらくなるソレというか。

実際に動いてるところを見たほうが分かりやすいのだろうか。試しにキャプチャしてみたり。

以下は、Paint.NET。


以下は、Photoshop Elements 8.0。


以下は、GIMP 2.8.18。


まあ、とりあえず、色々な見た目があるようで。

2016/12/04() [n年前の日記]

#1 [python] PySideでCGツールっぽい選択範囲を作れるかテスト

PySideを使って、CGツールでよく見かける蟻の行進(Marching ants)っぽい選択範囲だかラバーバンドだかを表示できるかテスト。

_graphicsrubberband.py
u"""
CGツール用RubberBandを実装.

蟻の行進(Marching ant)が表示できるのか実験。

動作確認環境 : Windows10 x64 + Python 2.7.12 + PySide 1.2.4
"""
import sys
from PySide.QtCore import *  # NOQA
from PySide.QtGui import *   # NOQA


class CGRuberBand(QGraphicsPolygonItem, QObject):

    u"""CGツール用のラバーバンド. 2つのクラスを継承してる."""

    def __init__(self, rect, parent=None, scene=None):
        """init."""
        QGraphicsPolygonItem.__init__(self, parent)
        QObject.__init__(self, parent)  # タイマーを使うために多重継承
        self.start_pos = QPoint()
        self.end_pos = QPoint()

        # 背景用のQGraphics*Itemを用意する
        # 白黒の点線を描画するため、背景は白、自分自身は黒で線を描画する
        self.bg = QGraphicsPolygonItem(self)

        # 背景用のpen設定。白一色の線。
        bg_pen = QPen(QBrush(Qt.white), 1, s=Qt.SolidLine, c=Qt.SquareCap,
                      j=Qt.MiterJoin)
        self.bg.setPen(bg_pen)
        self.bg_pen = bg_pen
        scene.addItem(self.bg)

        # 点線用のpen設定。黒の点線。
        pen = QPen(QBrush(Qt.black), 1, s=Qt.DashLine, c=Qt.SquareCap,
                   j=Qt.MiterJoin)
        pen.setDashPattern([3, 3])  # Dash line のパターンを設定
        self.setPen(pen)
        self.pen = pen

        # 内部を半透明で塗り潰すなら以下のコメントアウトを外す
        # self.brush = QBrush(QColor(48, 160, 255, 64))
        # self.setBrush(self.brush)

        self.startTimer(25)  # 一定時間毎に処理を呼んで点線をアニメさせる
        self.hide()  # 発生時は非表示にしておく
        scene.addItem(self)  # 自身をsceneに追加登録

    def timerEvent(self, event):
        u"""一定時間毎に呼ばれる処理."""
        if self.isVisible():
            # 点線の描画開始位置を変化させて蟻の行進に見せる
            do = (self.pen.dashOffset() + 1) % 6
            self.pen.setDashOffset(do)
            self.setPen(self.pen)

    def set_geometry(self, p0, p1):
        u"""範囲を設定."""
        self.start_pos = QPoint(p0)
        self.end_pos = QPoint(p1)

        # ドット単位で正確に表示するためにwidthとheightを調整
        rect = QRect(p0, p1)
        w = p1.x() - p0.x()
        h = p1.y() - p0.y()
        rect.setWidth(w)
        rect.setHeight(h)
        self.poly = QPolygonF(rect)
        self.bg.setPolygon(self.poly)
        self.setPolygon(self.poly)

    def show(self):
        u"""表示."""
        self.bg.show()
        super(CGRuberBand, self).show()

    def hide(self):
        u"""非表示."""
        self.bg.hide()
        super(CGRuberBand, self).hide()


class GView(QGraphicsView):

    """Graphics View."""

    def __init__(self, *argv, **keywords):
        """init."""
        super(GView, self).__init__(*argv, **keywords)
        scene = QGraphicsScene(self)
        self.setScene(scene)

        # 背景画像
        pm = QPixmap("./tmp_bg.png")
        pm_item = QGraphicsPixmapItem(pm)
        scene.addItem(pm_item)

        # ラバーバンドを生成
        # sceneへの追加登録は、sceneを渡してラバーバンド側で行う
        self.rband = CGRuberBand(QRect(), parent=None, scene=self.scene())

        self.start_pos = QPoint()
        self.end_pos = QPoint()
        self.selecting = False

    def mousePressEvent(self, event):
        u"""マウスボタンが押された."""
        if event.button() == Qt.LeftButton:
            # 左ボタンが押された
            if not self.selecting:
                self.start_pos = event.pos()  # クリックした座標を記憶
                self.end_pos = self.start_pos
                self.set_rubberband_geometry(self.start_pos, self.end_pos)
                self.rband.show()
                self.selecting = True
        elif event.button() == Qt.RightButton:
            # 右ボタンが押された
            self.clear_rubberband_area()

    def mouseMoveEvent(self, event):
        u"""マウスカーソルが動いた."""
        if self.selecting:
            self.end_pos = event.pos()
            self.set_rubberband_geometry(self.start_pos, self.end_pos)

    def mouseReleaseEvent(self, event):
        u"""マウスボタンが離された."""
        if event.button() == Qt.LeftButton:
            self.selecting = False

    def set_rubberband_geometry(self, p0, p1):
        u"""ラバーバンドの範囲を設定."""
        if p0.isNull():
            return

        if p0 == p1:
            p0 = self.mapToScene(p0).toPoint()
            p1 = p0
            self.rband.set_geometry(p0, p1)
            self.set_status("(%d, %d)" % (p0.x(), p0.y()))
            return

        # scene上の座標値に変換
        p0 = self.mapToScene(p0).toPoint()
        p1 = self.mapToScene(p1).toPoint()
        self.rband.set_geometry(p0, p1)

        x0, y0 = p0.x(), p0.y()
        x1, y1 = p1.x(), p1.y()
        dx, dy = x1 - x0, y1 - y0
        if dx >= 0:
            dx += 1
        elif dx < 0:
            dx = -dx + 1
        if dy >= 0:
            dy += 1
        if dy < 0:
            dy = -dy + 1
        s = "(%d, %d) - (%d, %d) : (%d x %d)" % (x0, y0, x1, y1, dx, dy)
        self.set_status(s)

    def clear_rubberband_area(self):
        u"""ラバーバンドの範囲をクリア."""
        self.rband.hide()
        self.start_pos = QPoint()
        self.end_pos = QPoint()

    def set_status(self, str):
        u"""ステータスバー相当のテキストを設定."""
        self.parent().set_status(str)


class MyWidget(QWidget):

    u"""メインウインドウ相当."""

    def __init__(self, *argv, **keywords):
        """init."""
        super(MyWidget, self).__init__(*argv, **keywords)
        self.gview = GView(self)
        self.lbl = QLabel("Ready", self)

        l = QVBoxLayout()
        l.addWidget(self.gview)
        l.addWidget(self.lbl)
        self.setLayout(l)

    def set_status(self, str):
        u"""ステータスバー相当にテキストを設定."""
        self.lbl.setText(str)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    w = MyWidget()
    w.show()
    sys.exit(app.exec_())

テスト用画像。 _tmp_bg.png



見た目はそれっぽくなった気がする。なんとかなりそう。

実装についてメモ。 :

PySide には、線の設定時に使う _QPen てのがあるのだけど、その QPen の style に _Qt.DashLine を指定すれば点線が引けるし、dashOffset() を使うと点線の描画開始位置をずらせるので、それらを使えば蟻の行進ができそうだなと。

ただ、実際に黒い点線を描いてみたところ、背景が黒かった場合にほとんど点線が見えなくて。まあ、黒い背景に黒い点線を描いてるから見えなくて当然だけど。

改めて GIMP の選択範囲の境界線を確認してみたところ、必ず白と黒の点線を描いていた。そうすることで、どんな背景でも境界線がちゃんと分かる上に、境界線の色を背景に応じて変更、等の処理をしなくて済む。

ということは、PySide上でも白と黒の点線を描けばいい…のだけど、どうやら QPen は背景色と前景色の2つを指定できない模様。なので、QGraphicsPolygonItem の中でもう一つ QGraphicsPolygonItem を確保して、白一色の線の上に、黒い点線を乗せることで白黒の点線に見せかけてみたり。

点線の描画開始位置を一定時間毎にずらすあたりは、QObject も継承(多重継承?)して _QObject.startTimer() を使った。コレを使うと、指定したミリ秒毎に、timerEvent(self, event) という関数が呼ばれるようになる。その中で dashOffset() を変化させてやれば、見た目、蟻の行進っぽくなる。

ちょっとハマったのは、境界線の描画位置。ドットエディタ用として使いたいからドット単位でキッチリと表示したかったのだけど、何故か範囲の大きさが1ドット大きくなって。

矩形情報を持てる _QRect のドキュメントを眺めて理由が分かった。右、および下については、内部で持ってる座標値の1ドット外側に境界線を描く仕様になっているのだな…。ということで、そのあたりはちょっと調整。もっとも、今回はドットエディタ用を意識しつつ書いてるからそういう調整処理が必要になるわけで、一般的なCGツールのように選択範囲境界線の内側に対して処理が行われるのだ、という取り決めにしておくなら問題にはならないような気もする。

課題。 :

後は境界線をドラッグして範囲をリサイズできれば、なのだけど、この先は結構面倒臭そうで。以下のような仕様になるだろうけど…。
  • 境界線の上にマウスカーソルが乗ったらマウスカーソルが変化する。
  • 境界線の左上、右下、で「\」のマウスカーソルになる。
  • 境界線の右上、左下、で「/」のマウスカーソルになる。
  • 境界線の上、下、で「|」のマウスカーソルになる。
  • 境界線の左、右、で「―」のマウスカーソルになる。
  • マウスカーソルが変わっている時にドラッグすると下にある境界線の位置を変更できる。通常のマウスカーソルの時は新規に選択範囲を指定する。
マウスカーソルが境界線の上に乗ってるかどうかを判断するためには、境界線の、左上、右上、左下、右下、上、下、左、右、の8つの領域を持って、それらの領域の中にマウスカーソルが入ってるか判別しないといけない。

また、マウスカーソルを移動しただけでも常時それらの判別処理をしないといけないので、PySideの場合はマウストラッキング(常時マウスカーソル座標を取得できる状態)が必要になる。

これだけ面倒臭い処理をするのだから、何かのクラス、例えば QGraphics*Item を継承したクラスの中に関連処理をまとめてしまってあちこちで流用したいところだけど…。QGraphicsView側でマウス座標の取得等をやってる関係で、そのあたりの整理が悩ましいというか。

巷のグラフィックツールは、よくまああれだけ上手に作ってあるものだなあ、などと再認識。

2016/12/05(月) [n年前の日記]

#1 [ruby] Gosuを触っていたり

_Ruby Game Developing Advent Calendar 2016 - Adventar_よくわかる Ruby ゲーム開発のいま - あおたくノート で、Gosuというゲーム制作用ライブラリの存在を知って、興味が湧いたので触ってみているところ。

SDL2を使っているらしいので速度的に大丈夫なのかなと不安だったけど、GeForce GTX 750 Ti を積んでるメインPC上ではそれらしい速度で動いてくれた。が、DXRuby と比べるとなんだか動きが若干ガクガクしてるような…。気のせいかな…。オンボードGPUを積んでるPC上で動かすとどうなるのか、ちょっと気になる。

以前、SDLを使っている PyGame 等を試した時は、描画に結構時間がかかってる感じだったので、それ以来SDLとやらは速度面で期待できないのかなと偏見を持ってたりするのだけど。ただ、SDL2はハードウェアアクセラレーション対応、という話もあるし、そもそもGosu関係のアレコレを眺めたら描画にOpenGLを使ってる気配がありそうで。 *1 であれば描画速度についてはそれほど不安視しなくてもいいのかなと。でも、以前 OpenGL を使った2Dゲーム用ライブラリを触った際も、DXRuby より描画が重かった記憶もあって。

何にせよ、もうちょっと色々試してみないと。
*1: Linux上でGosuを使う際はOpenGLが有効になってないと描画速度が出ないよ、という話を見かけたので、すると描画はOpenGLを使うのかなと。

#2 [pc] デスクトップを動画でキャプチャ

Windows10 x64 + VMware Player + Ubuntu 16.04 LTS上で、デスクトップを動画でキャプチャしたいなと。

ググってみたら、SimpleScreenRecorder なるキャプチャソフトの評判が高いらしい。

_Ubuntuの画面録画が簡単にできるSimpleScreenRecorderのインストール方法と使い方 - Ry0 Note
_第316回 SimpleScreenRecorderで簡単スクリーンレコード:Ubuntu Weekly Recipe|gihyo.jp … 技術評論社
_Main page - SimpleScreenRecorder - Maarten Baert's website

試しにインストールして使ってみたら、デスクトップがあっさり録画できた。素晴らしい。

他にも、 _Ubuntu画面録画にオススメのソフト5選 で、Kazam なるキャプチャソフトもあると知り、そちらもインストール。これも操作が簡単だった。

_おもいたったがきちじつ - ubuntu - TrustyTahr(14.04) - Kazamでスクリーンキャプチャ

更に、Ubuntu ではほぼ標準扱いらしい RecordMyDesktop なるキャプチャソフトもインストールしてみたけど…。これはなんだかしっくりこなかった。

ちなみに、Ubuntu上で静止画キャプチャをしたいならキーボードの PrintScreen を叩くだけでいいらしい。「どこに画像を保存する?」と尋ねてきた。Ubuntu に、こんな機能があったのか…。

Windows10上でデスクトップをキャプチャ。 :

Windows10上でもその手のキャプチャソフトを試したり。メインPCは GeForce GTX 750 Ti を積んでいるので、NVEnc(ハードウェアエンコーダ)が使えるとありがたい。

ここ最近は、その手の動画キャプチャをする時に _oCam を使わせてもらっているけど。本来は有料ソフトなので、無料利用時は終了時に広告が表示される。もっとも利用頻度はそんなに高くないので、この程度なら、まあ、という気もするけれど。

_Bandicam も NVEnc に対応していてイイ感じだけど、無料利用時は録画した動画にロゴが入る。購入すればその手の制限は無くなるけど、韓国企業が作ったソフトらしいから、購入時に個人情報を渡すあたりがちと不安だったりもして。万が一、社内に過激な反日の人が居たら何をされるか…。もっともそんなこと言ってたらLINEなんか使えないだろうけど。

ググってたら、 _Open Broadcaster Software (以下OBSと略)なる実況配信ソフトもローカル録画ができて、かつ、NVEnc に対応してるという話を見かけた。巷の情報では現行版ではなく OBS Classic なる版の利用事例・説明ページが多いようで。

試しに OSB Classic をインストールして動作確認してみたけど、ちょっと設定が面倒というか、分かりづらいなと。いや、元々配信ソフトだから仕方ないのだろうけど。それにしても複数の映像ソースを一つにまとめてリアルタイムに動画にできるあたり、なんだかスゴイ。

一応ローカル録画はできたけど、録画した動画の周辺や下のほうに、何故か黒い領域が入る…。 _VIPで初心者がゲーム実況するには@ Wiki - OBSローカル録画 を参考にして、ソースを右クリックして「位置/大きさ」→「画面に合わせる」を選んだはずなのだけど。

#3 [nitijyou] 自転車で買い物に

夜食等を買いに、近所のコンビニとサンドラッグまで。

親父さんが自転車の前ブレーキのゴムパッド?を交換してくれたのだけど、ブレーキレバーを握る量が少なくなったもののキーキー音が鳴るようになってしまって。コレって何が原因で鳴るんだっけ…。

ググってみたら、アレはゴムパッドじゃなくてブレーキシューと呼ぶのだな…。

2016/12/06(火) [n年前の日記]

#1 [python] PySideでラバーバンドの実装を試していたり

蟻の行進の表示はできたので、境界線をドラッグして選択範囲をリサイズする処理の実装にチャレンジしてるところ。

境界線を9分割してアタリ判定?をして処理を分けてるけど。なんというか、処理が泥臭い。もうちょっと綺麗に書けないものか…。

#2 [ubuntu] サブPCのUbuntu を 14.04 LTS から 16.04 LTS にアップグレード

足元で埃を被ってるサブPCに Ubuntu 14.04 LTS を入れていたのだけど、動作確認のために起動したついでに、16.04 LTS にアップグレード。

数時間かかかったけど、すんなりアップグレードできた。後は、以下のページを参考にして各種設定を。ありがたや。

_Ubuntu 16.04 LTSをインストールした直後に行う設定 & インストールするソフト

時刻合わせでちと問題が。 :

Ubuntu 15.10 から、時刻合わせの方法が少し変わったらしい。

_Ubuntu 16.04と15.10で時刻合わせの設定を変更する - Sickly Life Blog

systemctl -l status systemd-timesyncd
と打って時刻合わせができてるか確認したら、failed の文字が。時刻合わせに失敗してた。

14.04 LTS から 16.04 LTS にアップグレードした環境だと、ntp、ntpdate が入ってるので標準状態とは違ってしまうようで。
sudo aptitude purge ntp
sudo aptitude purge ntpdate
これでアンインストールしたら、前述のコマンドを打った際の結果が違ってきた。

2016/12/07(水) [n年前の日記]

#1 [python] PySideでCGツール用のラバーバンドを書いてみる

PySideで、CGツール用のラバーバンドを試しに書いてみたり。選択範囲を作成する時に使うアレ。境界線をドラッグするとリサイズできる仕様をどうにか盛り込んでみた。

ソースが長くなってしまったので、Gist にアップロード。

_PySideでCGツール用ラバーバンドを試しに書いてみる - Gist

こんな感じになった。



処理もクラス分けもグチャグチャになってしまったので、そっくりそのまま何かに使えるソースではないけれど。一応どうにか実装できるみたいだよ、ぐらいのことは程度は実証できた、かなと。

処理の流れについてメモ。 :

ラバーバンド(選択範囲の境界線)が、存在する(表示されている)場合、領域を9分割して、マウスカーソルがどこにあるかを判断。その領域にマウスカーソルが乗ってたら、まずはマウスカーソル形状を変更。

pyside_rubberband_01.png

更に、マウスボタンが押された時に、マウスカーソルがラバーバンド上に乗っているなら、マウス座標の反対側にある座標を開始点に設定して、終了点のほうをドラッグで指定する処理に入る、みたいな感じ。

しかし、この仕様だと、選択範囲がめちゃくちゃ狭い・小さい時にはリサイズが上手くいかないことに気づいてしまったりもして。そのあたり、例えばGIMPの場合は、選択範囲がめちゃくちゃ狭い場合は境界線の外側にドラッグ可能な領域を用意する、てな仕様になっていて。なるほどうまいこと考えたもんだなと改めて感心したり。

ところで。選択範囲を作ってる途中で、ウインドウ外にマウスカーソルが移動すると、ウインドウ内の表示領域が自動で大きくなって開始点と終了点が QGraphicsView の返す座標値とずれてしまうことに気がついてしまって。そのあたりを解決しようとしているうちに、ソースがどんどんグチャグチャになってしまったという…。なかなか難しい。

それはともかく、もっとイイ感じのやり方があるんじゃないか、という気もするのだけど…。例えばウインドウのサイズ変更時はこういう操作仕様になってるのだから、ノウハウというか、プログラムの書き方としてある程度確立してたりするんじゃないの、とも思えるわけで…。

#2 [pc] GeForceドライバをアップデートしてみたけど

自分のメインPCには Geforce GTX 750 Ti が乗っているのだけど。GeForceドライバーの新しい版、376.19 が出たらしいのでアップデート作業を。

GeForce Experience 経由でアップグレードしようとしたら、カスタムインストールを選んだはずなのに「クリーンインストール」を尋ねるウインドウが出てこなくて。しかも最後に「インストールに失敗」と言われて。さすが、NVIDIA…。

仕方ないので、NVIDIAのサイトからドライバをダウンロードしてインストールし直し。

しかしコレ、クリーンインストールすると、GeForce Experience 初回起動時にHDD内からゲームを再度検索して30分ぐらい何もできなくなる…。最適化されそうなゲームなんて一本も持ってないのに。Visual Studio や FL Studio のインストールフォルダを検索してどうするんだ…。スキップできる仕様をつけてほしい…。

低負荷でデスクトップの録画ができるという旧ShadowPlay相当の機能をそのうち使ってみたいので、仕方なく GeForce Experience をインストールしてるのだけど、ドライバを更新するたびにこうして待たされるのが…。なんだか馬鹿馬鹿しいなと…。

2016/12/08(木) [n年前の日記]

#1 [ruby][windows] Rubyのバージョンを切り替えるuruが動作しなくて悩んだり

Windows上でRubyのバージョンを切り替えることができる uru というツールがあるのだけど。気づいたら動作しなくなっていて悩んだり。環境は Windows10 x64。

症状としては、uru 23 といった具合に uru TAG を打ち込めばRubyのバージョンを切り替えられるはずなのだけど、妙なエラーメッセージが表示されて切り替わってくれない。
> uru version
uru v0.8.3 [windows/386 go1.7.3]

> uru ls
    187mingw32  : ruby 1.8.7 (2013-06-27 patchlevel 374) [i386-mingw32]
    187mswin32  : ruby 1.8.7 (2010-12-23 patchlevel 330) [i386-mswin32]
    19          : ruby 1.9.3p551 (2014-11-13) [i386-mingw32]
    200         : ruby 2.0.0p648 (2015-12-16) [i386-mingw32]
    21          : ruby 2.1.9p490 (2016-03-30 revision 54437) [i386-mingw32]
    220mswin32  : ruby 2.2.0p0 (2014-12-25 revision 49005) [i386-mswin32_100]
    23          : ruby 2.3.3p222 (2016-11-21 revision 56859) [i386-mingw32]
 => system      : ruby 2.2.6p396 (2016-11-15 revision 56800) [i386-mingw32]

> uru 23
---> now using ruby 2.3.3-p222 tagged as `23`
'autogenerated' は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。
入力行が長すぎます。

さて、なんでだろ。

ソースネクストのせいだった。 :

昨晩、ソースネクストで販売されてる本格翻訳9ダウンロード版を購入して、Windows10 x64上でインストールしたのだけど。

その本格翻訳9が、環境変数PATHに漢字交じりのパス、「D:\Program Files (x86)\SOURCENEXT\本格翻訳9\lic」を追加していて。そのパスが存在すると uru が異常動作することが分かった。

試しに mklink を使って、件の「本格翻訳9\」に「honyaku\」というシンボリックリンクを割り当てて、それでパスを置き換えてみたら、uru が動作した…。
> uru 23
---> now using ruby 2.3.3-p222 tagged as `23`

> ruby --version
ruby 2.3.3p222 (2016-11-21 revision 56859) [i386-mingw32]

想像するに、uru というツールは英語圏のことしか考えてない作りのツールで、環境変数PATHの中に2バイト文字だか多バイト文字だかが含まれていると異常動作する、ということだろうなと。

フォルダ名に日本語文字列は避けるべき。 :

てなわけで、本格翻訳9に限った話じゃないけど、ソフトをインストールする際は日本語文字列を含むインストールパスは避けるべし、というよく見かける教訓にこうして遭遇、みたいな。

というか、環境変数PATHに対して無頓着に漢字交じりのパスを追加してしまう、そんなデフォルト値でソフトを販売してるあたりがあかんのではないか、お前のせいで他のアプリが動かなくなったやんけ、一体どうしてくれるんや、という気もするのだけど、まあ、所詮はソースネクストだから…。

もっとも、日本語文字列が含まれてると異常動作するツールってのがそもそもどうなのよ、という気もするけれど。このあたり、このツールに限った話じゃないし…。英語圏の人に言ってみてもどうせキョトンとされるだけだろうし。下手すると「英語環境以外で使うな」とか平気で言い出しかねんし。ソースのコメントすら「英語で書け」と強要してくる方々だから…。

それにしても、Windows 3.1 や Windows 95 を使ってた時代ならともかく、20年経った現在においても日本語文字列を含んだパスを使うと不具合が出るというのは、なんだかな。

#2 [windows] 環境変数PATHを見直した

Windows10上で uru が動かなくなった関係で、ついでに環境変数PATHを見直すことにした。そもそもPATHがとんでもなく長い状態になっていたわけで。

解決策をググってみたところ、シンボリックリンクを利用して短く見せかける方法があるようで。

_Windowsのパスの長さ制限に引っかかったので短くしてみた - Qiita

他にも、例えば _Rapid Environment Editor を使って、8.3の短縮パスで置き換えていく方法もあるけれど。その方法を試したところ、何のパスが登録されてるのか全く分からない状態になってしまったので、今回はシンボリックリンクを使って短くしていくことに。

#3 [windows] 本格翻訳9を購入

ポイントが溜まってたのでソースネクストから本格翻訳9ダウンロード版を購入。

少し使ってみたけど…。翻訳速度が遅い…。自分のPCが非力ってことかもしれないけど。

使い勝手が悪い…。Webページを翻訳できればありがたいのだけど、IE用のプラグインしか存在しない。しかもページ単位で翻訳する感じになるようで。翻訳後のページのレイアウトはグチャグチャで、翻訳精度云々以前に、違う意味で読みづらい。

アプリ本体側の翻訳結果表示ウインドウは、表示フォント変更すらできない模様。

2016/12/09(金) [n年前の日記]

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

DELL製PCの電源がまた入らなくなったと某所から連絡があったので、電動自転車で行ってきた。AM09:00-AM11:00まで作業。メールデータとアドレス帳をバックアップしてなかったとの話なので、そのあたりどうにかできないか試行錯誤。

電源ボタンを20秒以上押しっぱなしにして内部放電とやらをすれば起動してくれないかなと淡い期待をしていたけど、今回は起動してくれなかった。電源LEDの黄色い点滅も前回とはパターンが違って。2回点滅+3回点滅を繰り返す状態。

HDDを取り出して、念のために持っていった、裸族の頭 IDE+SATA CRAISU2 で中身を吸い出そうとしたけれど。HDDがキュイーン、キュイーンと鳴るだけでアクセスできず。HDDが壊れてるのかと思ったけど、ふと思い出した。こういう状態になる時は電源不足の可能性があったよなと。もしかすると裸族の頭のACアダプタが弱まっていて立ち上がるための電流が足りてないのかもしれない。

某所にある機材だけでは策が思いつかず、HDDだけ預かって自分の部屋に転がってるPCパーツを使って吸出しできるか試してみたい、と申し込んで了承してもらった。

自室で作業。 :

帰宅後、HDDを200円PCケースのPCに接続して、KNOPPIX 7.6からアクセスできるか試したところ一応中身を読み出せた。ということは、HDDが壊れてたわけではなく、やはり裸族の頭のACアダプタの電源不足だったのかなと。そのうち買い換えないと…。

メールデータとアドレス帳データのファイル群は吸い出せたけど、このままでは復元も閲覧もできないわけで。VMware Player 上で Windows8.1評価版をインストール後、Windows Live メール 2012もインストールして、データフォルダに上書きして中身を見れるか確認してみたり。

Windows Live メール 2012 のデータフォルダは以下。
C:\Users\ユーザ名\AppData\Local\Microsoft\Windows Live Mail\
C:\Users\ユーザ名\AppData\Local\Microsoft\Windows Live\Contacts\Default\

その他詳細はGRPでメモ。

#2 [nitijyou] 自転車で買い物に

某所から帰宅後、夜食等を買いに近所のヨークベニマルまで。

#3 [linux] USBメモリにKNOPPIX 7.7.1 DVDをインストール

HDDから吸出しをするために、USBメモリに入れてた KNOPPIX 7.6 を使ったけれど。ググってみたら今現在は KNOPPIX 7.7.1 が出てるようで。せっかくだからUSBメモリにインストール。VMware Player上でISOから起動して、USBメモリを接続して KNOPPIX のメニュー経由でインストール。

USBメモリから起動することが確認できたら、?/syslinux/syslinux.cfg を修正。起動時のオプションが並んでる各行に lang=ja xkeyboard=jp も指定。これで起動時に毎回オプション指定しなくても、日本語表示有効、かつ、日本語キーボードが有効になる、はず。たぶん。

#4 [pc] HDD等のドライブを確実に動かせるACアダプタ電源って無いのかな

裸族の頭のACアダプタ電源がどうやら経年劣化でダメになってるっぽいので新しい品をググって探してみたのだけど、どれも2Aまでの出力のようで。そのスペックだと今まで使ってたソレと同じスペックなので、相変わらず駆動しないドライブが出てくるのでは、てな不安が。

考えてみたら Raspberry Pi3 の電源でも似たような問題があったような。Raspberry Pi3 は 2.5A必要なのに、そのクラスのUSBアダプタがなかなか無くて。ACアダプタの類は2Aを超えるか超えないかのあたりに何か壁でもあるんだろうか…。

2016/12/10() [n年前の日記]

#1 [windows] LibreOffice Drawが落ちる状態になっていた

某所のネットワーク構成図を更新しようとして、以前作成した LibreOffice Drawファイル(.odg)を開こうとしたら、いきなり LibreOffice Draw が落ちてしまって。他のファイルはどうだろうと試してみたけど、あらゆるファイルが開けず。

環境は Windows10 x64 バージョン 1607 ビルド 14393.479。LibreOffice 5.2.3.3 x86版(32bit版)。

色々試してみたけれど、症状は変わらず。 改善するどころか、LibreOffice Writer で何か文字を打ち込もうとした途端に落ちたり、メニューの「ツール」をクリックしただけで落ちたり、ファイル保存しようとすると落ちたりする状態に。

試しているうちに気づいたけど、LibreOfficeのランチャー?を起動して、ツール → オプション → 言語、のあたりの何かしらの項目をクリックするだけで落ちるなと。

libreoffice_5233_crash_01.png

また、拡張機能マネージャー → 英語スペル辞書〜、のオプションボタンをクリックしただけでも落ちる。

libreoffice_5233_crash_02.png

もしかすると、英語スペル辞書絡みがおかしいんじゃないか…?

試しに、LibreOfficeインストール時、カスタムインストールを選んで、「辞書」をまるっとインストールしない設定にしてみた。

libreoffice_5233_crash_03.png

む。この状態でインストールすると、全然落ちない。ツール → オプション → 言語、の全項目もちゃんと選べるし表示される。また、今まで作成した各種ファイルも問題なく開けた。ちなみに拡張機能マネージャ―上では、英語スペル辞書〜の拡張は無くなった。

libreoffice_5233_crash_04.png

てなわけで、一応使えるようにはなったけど…。何故、こんな状態に。

もしかしてWindows Updateのせいだろうか。 :

今までは LibreOffice 5.2.3.3 が使えていた印象があるので…。最近、環境周りで変わったことと言えば…。
  • 昨日だったか今日だったか忘れたけど、Windows Update で Windows10 に今月分のパッチが当たったこと。
  • しばらく前から NVIDIA GeForce driver をちょくちょく更新してるけど、最近のドライバは結構バグがあって、例えば Adobe Premiere Element 13 が起動中にクラッシュするバグが仕込まれてたり。
  • 環境変数PATHを短くするためにシンボリックリンクを多用して環境変数PATHを短くしたこと。

_【GPU】 GeForce 375.95 WHQLドライバ公開。Adobe Premiere Element 13が起動中にクラッシュする不具合付き : ニッチなPCゲーマーの環境構築

しかし…。
  • 環境変数PATHは、元に戻しても症状が変わらなかったので、それじゃなさそう。
  • GeForce Driverのせいなら、LibreOffice の表示設定で「ハードウェアアクセラレーション」「OpenGL」あたりを無効にすれば症状が変わりそうだが、変化しなかった。
となると…。Windows Updateのせいで、LibreOffice の言語関係の何かしらが異常動作するようになった・状態を取得できなくなって crash するようになった、とか…?

そういえば、今回の Windows Update 直後、Mozilla Firefox 拡張の、firelink の設定が全部消えていて首を捻ったっけ。なんだか怪しい…。

#2 [nitijyou][pc] 200円PCケースのPCを弄ってた

昨日、HDDの吸出し作業に200円PCケースのPCを使ったので、その片づけ作業をしていたのだけど結構時間がかかってしまった。

蓋を閉めて終わりかと思いきや、実際閉めたらPCが起動しなくなって、復活させるまでちょっとハマった。電源コードがCPUファンを押さえつけてたり、IDE-HDDとの接触が悪かったり等、そんな状態だったようで。

せっかく復活したので、中に入ってる Ubuntu 14.04 LTS を少し触ったり。Gosu をインストールしようとしたらそもそも libsdl2-dev がインストールできなくて悩んでしまった。Ubuntu 16.04 LTS ではすんなりインストールできたのだけど、14.04 はダメなのか…。

描画パフォーマンスをわずかでも改善できないものかとBIOS設定を弄ってみたら、また起動しなくなって。蓋を開けてボタン型電池を外してマニュアルを発掘して眺めてCMOSクリアをして。

色々設定してみたところで、どうせ普段は滅多に使わない個体なのに、自分は一体何をやっているのか…。

綺麗なまな板ケースを作れないものか。 :

そもそも、この200円PCケース、中が狭すぎるんだよな…。使うとしてもPCパーツの動作確認その他に使うのだろうから、まな板ケースのほうがいいんじゃないか…。でも、まな板ケースってそのままだと埃だらけになりそうだし。

見た目はまな板ケースなのに、普段は蓋を閉められる、みたいなケースは作れないものだろうか…。まあ、段ボール箱の中にでも入れとけばええやん、という気もしてくるけど。

2016/12/11() [n年前の日記]

#1 [ruby][gosu] WIndows上で Ruby + Gosu を試してみたり

_Ruby というプログラミング言語を使って2Dゲームが作れるようになる _Gosu というライブラリがあるそうで。クロスプラットフォーム対応ライブラリ、つまりは Windows、Mac、Linux、どのOSでも動くライブラリなのだとか。

Windows に特化した2Dゲーム制作ライブラリなら _DXRuby があるけれど。DXRubyは、Windows の DirectX という機能を呼び出しているから、裏技(?)を使わないと Mac や Linux では動かない。もし、「Mac や Linux でも動くゲームを作ってみたいな」と思った時は、Gosu が選択肢に入ってくるのかもしれないなと。

ということで、数日前に Windows上で Gosu を少し触ってたのだけど。せっかくだからメモをまとめておいたほうがいいよなと思えてきたので、こうしてメモしておくのです。

環境は、Windows 10 x64 + Ruby 2.2.6 p396 mingw32版 + gosu 0.10.8 x86-mingw32版。

Rubyのインストール。 :

まずは Ruby をインストールしないと話にならない。 _RubyInstaller for Windows という、Windows にインストールできる Ruby があるので、ソレを利用させてもらう。

_Downloads ページから、Ruby 2.2.6 (rubyinstaller-2.2.6.exe) か Ruby 2.3.3 (rubyinstaller-2.3.3.exe) をダウンロード。

ダウンロードした .exe を実行するとRubyのインストールができる。詳細は以下の解説記事を参考に。

_WindowsにRubyをインストールする(初心者向け) - Qiita
_はじめてのRuby環境構築 (Windows編その1) - Qiita
_Rubyダウンロード及びインストール | Rubyインストール

DOS窓(コマンドプロンプト)を開いて、ruby -v と打ち込むと、Rubyのバージョンが表示される。
> ruby -v

ruby 2.2.6p396 (2016-11-15 revision 56800) [i386-mingw32]
バージョンが表示されたということは、インストールができたということ。

DOS窓の開き方が分からない? いくつか開き方があるけれど…。
  • Win+Rキーを押して「cmd」と打ち込んでEnterキー。
  • スタートボタンを右クリックして「コマンドプロンプト」を選択。(Windows8.1/10の場合)
  • Cortanaに「cmd」と打ち込むと「コマンドプロンプト」が一覧に出てくるのでソレをクリック。(Windows10の場合)
好みのやり方でどうぞ。

Gosuのインストール。 :

Ruby には、gem というライブラリ管理ツールがあって、インターネット経由でライブラリをダウンロードしてインストールしたり、簡単にアンインストールできたりする。

例えばDOS窓を開いて gem list と打ち込んでみれば、今現在インストールされてるライブラリの一覧が表示される。
> gem list

*** LOCAL GEMS ***

addressable (2.5.0)
aozora (0.2.0)
ast (2.3.0)
astrolabe (1.3.1)
(以下略)

この gem というツールを使えば gosu をインストールすることができる。以下を打ち込むだけ。
gem install gosu
> gem install gosu

Fetching: gosu-0.10.8-x86-mingw32.gem (100%)
Successfully installed gosu-0.10.8-x86-mingw32
Parsing documentation for gosu-0.10.8-x86-mingw32
Installing ri documentation for gosu-0.10.8-x86-mingw32
Done installing documentation for gosu after 1 seconds
1 gem installed
インストールできた。

Hello World. :

gosuを使って、まずはウインドウを表示してみる。以下のソースを書いた。

_helloworld.rb
require 'gosu'

class MyWindow < Gosu::Window
  
  # コンストラクタ
  def initialize
    super 640, 480, false
    self.caption = 'Hello World!'
  end
  
  # 更新処理
  def update
  end
  
  # 描画処理
  def draw
  end
end

window = MyWindow.new
window.show

実行してみる。
ruby helloworld.rb

helloworld_ss.png

ウインドウが表示された。

これだけではさすがに何もできないので、せめて最低限、画像とテキストだけでも表示してみる。以下のソースを書いた。

helloworld2.rb
require 'gosu'

class MyWindow < Gosu::Window
  
  # コンストラクタ
  def initialize
    super 640, 480, false
    self.caption = 'Hello World!'
    @font = Gosu::Font.new(32)  # フォントを用意
    @bg_img = Gosu::Image.new("tmp_bg.png", :tileable => true)    # BG画像
    @spr_img = Gosu::Image.new("tmp_ufo.png", :tileable => true)  # スプライト画像
  end
  
  # 更新処理
  def update
  end
  
  # 描画処理
  def draw
    @bg_img.draw(0, 0, 100)                 # BG描画
    @spr_img.draw(320, 240, 200)            # スプライト描画
    @font.draw("Hello World", 10, 10, 300)  # テキスト描画
  end
end

window = MyWindow.new
window.show
使用した画像は以下。

_tmp_bg.png
_tmp_ufo.png

実行。
ruby helloworld2.rb

helloworld2_ss.png

画像とテキストが表示された。

各行を解説。 :

Gosuのウインドウは、Gosu::Window というクラスを使えば作れるらしい。
class MyWindow < Gosu::Window

  (中略)

end
これで、Gosu::Window を継承したクラスを作ってる。この中がメイン処理(?)になる。

ソースの最後のほうで、
window = MyWindow.new
window.show
とあるけれど。それぞれ、以下を指示している。
window = MyWindow.new  # MyWindowクラスを生成してる
window.show            # 「ウインドウを表示しろ」と命令してる

Gosu::Window は、3つのメソッドを持つ。
  • 初期化を担当する initialize()。(コンストラクタ)
  • 毎フレームの更新処理を担当する update()。
  • 毎フレームの描画処理を担当する draw()。
この3つの中に色々書いていけばゲームっぽいモノが作れるはずだ、という構成になっている。

毎フレーム、と書いてしまったけど、どのくらいの頻度で更新処理・描画処理がされるのか。Gosuは、デフォルト設定なら60FPSで処理するよ、ということになってるらしい。

ちなみに、FPSってのは、Frame Per Second の略。フレーム/秒。1秒間に何フレーム表示するか、という単位。60FPSってことは、1秒間に60回画面が書き換わるよ、ということ。

さて。画像の読み込みは、Gosu::Image.new() を使う。
@img = Gosu::Image.new("画像ファイル名", :tileable => true)
:tileable って何じゃ? …画像の端をクッキリスパッとさせるなら true、隙間が入ってもいいなら false を指定するようで。例えば、BG(背景、Background)をタイルマップで描画したい時は、画像の端がクッキリしてないと隙間が入ってしまって見苦しいので、そんな時は true を指定すべし、とのこと。

扱える画像ファイルのフォーマットは、 _ドキュメント を眺めた感じだと、png画像とbmp画像は使えるようで。
  • png画像はアルファチャンネルも反映してくれる。
  • bmp画像の場合は、マゼンタ色(0xff00ff)を透明色として扱うぜ、と書いてあるように見えた。
ちなみに、「他の画像フォーマットを使いたければ RMagick ライブラリをインストールせよ」ってドキュメントには書いてあるけど…。 _Windows上でのRMagickインストールは鬼門 で…。時期によってはインストールできなかったりするんだよなあ…。なので、Gosuを使う時は、「pngとbmpしか使わないぜ」ってことにしといたほうがトラブル回避できそうな気がしますよ。

画像の描画は、以下のように書く。
@img.draw(x, y, z)
x, y は分かるとして、z は何だろう? …描画の優先順位らしい。z値が大きければ手前に描画されて、z値が小さければ奥に描画される。のかな。たぶん。

テキスト描画は、Gosu::Font.new() と draw() を使う。
# フォントを用意
@font = Gosu::Font.new(フォントサイズ)
# テキスト描画
@font.draw("描画したい文字列", x, y, z, x拡大率, y拡大率, 色指定)
描画時の、拡大率と色指定は省略することもできるらしい。

_ドキュメント によると、フォントファイル(.ttf)を別途用意して、ソレを読み込んで使うこともできるらしい。
class MyWindow < Gosu::Window
  def initialize
    @font = Gosu::Font.new(self, "./LiberationMono-Bold.ttf", 22)
  end
end
  • フォント名の指定文字列内に「/」があったら、ttf読み込みを要求されてるものとして扱う。
  • 「/」が無かったら、OSにインストール済みのフォント名を指定しているものとして扱う。
と、ドキュメントに書いてあった。

余談。Gosuを使うということは、クロスプラットフォームを意識してライブラリを選んだということだろうから…。もし、デフォルトフォントではなく、少し変わった見た目のオシャレなフォントを使いたいなら、OSインストール済みのフォントをあてにせず、別途、ttfファイルも同梱して配布したほうがいいでしょうな…。一応、Windows、Mac、Linuxで共通して使えるフォント種類を少し調べてみたのですけど、どのOSでも共通して使えるフォントって、ほとんど無いようで…。

とりあえず、画像を表示するところまではできたから、これで色々とやれるはず。

長くなってきたので、以降は別記事で。

Gosuのサンプルスクリプトのインストールについて。 :

念のためにメモしとく。

Gosuのサンプルスクリプトが、gosu-examples にまとまってるらしい。以下を打てばインストールできる。
gem install gosu-examples

以下の場所にインストールされた。
Rubyインストールフォルダ\lib\ruby\gems\2.2.0\gems\gosu-examples-1.0.3
examplesフォルダの中にサンプルがいくつか入ってるので、例えば ruby tutorial.rb、てな感じで実行できる。

サンプルスクリプトによっては、実行時に必要になるライブラリがあるようで。とりあえず、手元の環境では以下をインストールして、サンプルスクリプトを動かすことができた。
gem install chipmunk
gem install opengl
chipmunk のインストールに関しては、Ruby の DevKit が必要になるようで。そのあたりは以下を参考にしてインストールしてくださいなと。

_WindowsにRubyをインストールする(初心者向け) - Qiita

#2 [ruby][gosu] Windows + Ruby + Gosu を使ってもうちょっと色々試す

もうちょっと色々試してみる。

タイルマップでBGを描画してみる。 :

タイルマップでBGを描画してみよう。

とりあえず、2枚描画してみる。メガドライブがBG2枚だったから、Gosuも2枚描けたら、メガドラ程度のゲーム画面は実現できる、はず。

_tilemap_bg_test.rb
require 'gosu'

# 背景描画用クラス
class Map

  # コンストラクタ
  # @param wdw_w [Integer] ウインドウ横幅
  # @param wdw_h [Integer] ウインドウ縦幅
  def initialize(wdw_w, wdw_h)
    @wdw_w = wdw_w
    @wdw_h = wdw_h

    # 画像の読み込み
    @imgs = []
    ["tmp_bg1.png", "tmp_bg2.png"].each do |fn|
      # Gosu::Image.load_tiles()を使えば画像を分割して読み込める。
      # ここでは 512x512の画像を、1チップ32x32として読み込んでるので
      # 16x16個 = 256個の画像に分割されているはず
      imgs = Gosu::Image.load_tiles(fn, 32, 32, :tileable => true)
      @imgs.push(imgs)
    end

    # タイルマップ用の配列を作成
    @bgarr = []
    c = 0
    16.times do |by|
      @bgarr[by] = []
      16.times do |bx|
        @bgarr[by][bx] = c
        c = (c + 1) % 256
      end
    end
  end

  # 背景描画処理
  # @param bx [Integer] BG座標x
  # @param by [Integer] BG座標y
  # @param n [Integer] BG番号(0 or 1)
  def draw(bx, by, n)
    cw, ch = 32, 32  # セル1つ分のサイズ
    bx = bx.to_i
    by = by.to_i

    imgs = @imgs[n]
    lenx = @bgarr[0].length
    leny = @bgarr.length
    cx = (bx / cw) % lenx
    cy = (by / ch) % leny
    sx = (bx % cw)
    sy = (by % ch)
    wcnt = @wdw_w / cw + 1
    hcnt = @wdw_h / ch + 1
    hcnt.times do |y|
      wcnt.times do |x|
        k = @bgarr[(cy + y) % leny][(cx + x) % lenx]
        imgs[k].draw(x * cw - sx, y * ch - sy, 0)
      end
    end
  end
end

class MyWindow < Gosu::Window

  # コンストラクタ
  def initialize
    super 640, 480, false
    self.caption = "Tilemap BG Test"

    @maps = Map.new(self.width, self.height)  # マップ表示用
    # self.width、self.height はウインドウの横幅、縦幅になってる

    @bgx = [0, 0]
    @bgy = [0, 0]
    @frame = 0
  end

  # 更新処理
  def update
    # BGスクロール位置を更新
    ang = Math::cos(@frame * Math::PI / 180.0)
    @bgx[0] = -64 + (64.0 * ang) + 640
    @bgx[1] = -128 + (128.0 * ang) + 640
    @bgy[0] = (@bgy[0] + 2)
    @bgy[1] = (@bgy[1] + 6)

    @frame += 1
  end

  # 描画処理
  def draw
    2.times do |i|
      @maps.draw(@bgx[i], @bgy[i], i)
    end
  end

  # キーボードチェック
  def button_down(id)
    if id == Gosu::KbEscape
      # ESCキーが押されたらウインドウを閉じて終了する
      close
    end
  end
end

window = MyWindow.new
window.show
使用画像は以下。

_tmp_bg1.png
_tmp_bg2.png

ruby tilemap_bg_test.rb と打って実行してみる。



描画できてる。メガドラ程度にはなりそう。

少し解説。

タイルマップ用の画像は、えてして、たくさんのチップ画像が一枚の画像にまとめてあったりするので、画像を分割して読み込む必要が出てくる。

Gosu も、画像を分割して読み込む機能が用意されてる。以下のように書けばOK。結果は、Gosu::Image の配列で返ってくる。
# 画像を分割して読み込む
@imgs = Gosu::Image.load_tiles("画像ファイル名", 32, 32, :tileable => true)
「32, 32」のあたりは、1チップが何x何ドットなのか、の指定。例えばこれが DXRuby だったら、「画像を何分割するか」で指定するけど、Gosuの場合は「チップの大きさ」を指定するので少し注意。

タイルマップ用の画像なので、画像の端がクッキリスパッとしていてくれないと困る。敷き詰めた時に隙間が入ったら見苦しい。故に、:tileable => true を指定してる。

描画については…。例えば DXRuby なら、タイルマップBGを描画するための機能があらかじめ用意されてるけど、どうやら Gosu には無いらしい。仕方ないので、Rubyスクリプト内でループを回して描画してる。

ESCキーを押したら終了するようにしたい。 :

前述のスクリプトは、ESCキーを押すと終了することができる。処理してるのは以下の部分。
  # キーボードチェック
  def button_down(id)
    if id == Gosu::KbEscape
      # ESCキーが押されたらウインドウを閉じて終了する
      close
    end
  end
button_down(id) というメソッドを書くと、何かキーが押された時に、このメソッドを呼んでくれるらしい。id にはキーの種類が入ってるので、Gosu::KbEscape (ESCキー)だったら、close を呼んでウインドウを閉じている。

今気づいたけど、上の部分、Ruby なら以下のように書けますな…。1行で済む…。
  def button_down(id)
    close if id == Gosu::KbEscape
  end

キー種類は、 _Module: Gosu - Documentation for gosu/gosu (master) を眺めてもらえば予想できるかなと。KbXXXXX てのがキー種類、だと思われます。

スプライト相当を描画してみる。 :

スプライト相当を描画してみる。64x64ドットの画像を、512枚描画してみよう。

_sprite_test.rb
require 'gosu'

# スプライト相当のクラス
class MySpr

  # コンストラクタ
  def initialize(x, y, vx, vy, img, scrw, scrh)
    @fpx = x
    @fpy = y
    @fpvx = vx
    @fpvy = vy
    @scrw = scrw
    @scrh = scrh
    @w = img.width
    @h = img.height
    @whf = @w / 2
    @hhf = @h / 2
    @image = img
    @x = (@fpx - @whf).to_i
    @y = (@fpy - @hhf).to_i
  end

  # 更新処理
  def update
    @fpx += @fpvx
    @fpy += @fpvy
    @x = (@fpx - @whf).to_i
    @y = (@fpy - @hhf).to_i
    @fpvx *= -1 if @x + @w >= @scrw or @x <= 0
    @fpvy *= -1 if @y + @h >= @scrh or @y <= 0
  end

  # 描画処理
  def draw
    @image.draw(@x, @y, 0)
  end
end

class MyWindow < Gosu::Window

  # コンストラクタ
  def initialize
    super 640, 480, false
    self.caption = "Sprite Test"
    scrw = self.width
    scrh = self.height

    # スプライト発生
    pmax = 512
    img = Gosu::Image.new("tmp_ufo.png", :tileable => true)
    x, y = 320, 240
    @sprgroup = []
    pmax.times do |i|
      rad = (i * 360 / pmax) * Math::PI / 180
      dx = 3.0 * Math::cos(rad)
      dy = 3.0 * Math::sin(rad)
      @sprgroup.push(MySpr.new(x, y, dx, dy, img, scrw, scrh))
    end

    @frame = 0
  end

  # 更新処理
  def update
    @sprgroup.each do |spr|
      spr.update
    end

    @frame += 1
  end

  # 描画処理
  def draw
    @sprgroup.each do |spr|
      spr.draw
    end
  end

  # キーボードチェック
  def button_down(id)
    if id == Gosu::KbEscape
      # ESCキーが押されたらウインドウを閉じて終了する
      # Gosu::Window.close() を呼ぶとウインドウが閉じる
      close
    end
  end
end

window = MyWindow.new
window.show
使用画像は以下。

_tmp_ufo.png

ruby sprite_test.rb で実行してみる。



動きました。

DXRuby には、Sprite というクラスが用意されてたりするけど、Gosu には無いみたい。なので、スプライト相当のクラスを自前で作って、描画処理等もその中で書いている。

FPS(フレームレート)を測定する。 :

ところで、自分の手元の環境で Gosu を動かすと、なんだか動きがガクガクするんだよな…。Gosuって、本当に60FPS出てるのかな?

不安になってきたので、 _フレームレートの計測 を参考にして、FPSを測定する処理を書いてみたり。

_framerate_test.rb
require 'gosu'

# フレームレートを測定するクラス
class FrameRate
  attr_reader :framerate

  def initialize
    @cnt = 0
    @framerate = 0
    @start_time = Time.now
  end

  # 毎フレーム呼ぶ
  def update
    @cnt += 1
    n = Time.now
    nd = n - @start_time
    return if nd < 1.0
    @framerate = @cnt / nd
    @start_time = n
    @cnt = 0
  end
end

# メインウインドウ
class MyWindow < Gosu::Window
  # コンストラクタ
  def initialize
    super 640, 480, false
    self.caption = 'Sprite Test'
    @font = Gosu::Font.new(20)
    @frate = FrameRate.new
  end

  # 更新処理
  # def update
  # end

  # 描画処理
  def draw
    @frate.update
    f = @frate.framerate.to_s
    @font.draw("FPS #{f}", 10, 10, 0)
  end

  # キーボードチェック
  def button_down(id)
    # ESCキーが押されたらウインドウを閉じて終了する
    # Gosu::Window.close() を呼ぶとウインドウが閉じる
    close if id == Gosu::KbEscape
  end
end

window = MyWindow.new
window.show

ruby framerate_test.rb で実行。



計測できてるみたい。しかし、どうも微妙に60FPSに足りてない感じが。なんでだろ。

合体させる。 :

今まで書いてきたソレを全部合体させてみる。ソースが長くなってきたので貼らないけど。

やってることは、スプライト相当 512枚 + タイルマップBG x 2枚の描画。その程度の描画ができれば、一般的というか、若干レトロ風なリアルタイム2Dゲームも書けるだろう…。

_gosu_fps_test.rb

使用画像。

_tmp_bg1.png
_tmp_bg2.png
_tmp_ufo.png

ruby gosu_fps_test.rb で実行。



何故か微妙に60FPSに足りてなくて、そのせいかガクガクしてる感じもするけど、このくらいの速度で動けば、まあ、ゲームになるんじゃないかな、と。

別のWindows機で動かしてみる。 :

このスクリプトを他の環境に持っていっても動くのかどうか。気になる…。

ちなみに、今まで動かしてた環境(ハードウェアスペック)は以下。
  • CPU : Intel Core i5-2500 (4コア, 3.3GHz)
  • GPU : NVIDIA GeForce GTX 750 Ti (RAM 2GB)
  • RAM : 8GB (DDR3-1333/PC-10600 SDRAM, 4GB x 2)
  • OS : Windows10 x64

前述の gosu_fps_test.rb を、他のWindows機でも動かせるように、ocra で exe化。ocra を使うと Rubyスクリプトを exe化してくれる。使い方は、DXRuby の解説記事が参考になるかと。

_ocraによるexe化

少し古い別PCに持っていって動かしてみた。
  • CPU : AMD AthlonII X4 605e (4コア, 2.3GHz, TDP 45W) …当時としては処理能力より省電力性を重視したCPU。
  • M/B : ASRock M3A785GMH/128M (MicroATX, Socket AM3, AMD 785G)
  • GPU : オンボードビデオ Radeon HD 4200 (RS800, VRAM 624MB) AMD785Gチップセットと統合されてる。
  • RAM : 8GB (DDR3-1333/PC3-10600, 4GB x 2)
  • OS : Windows7 Home x64

AMD/ATI製とは言え所詮はオンボードGPUなので、どうかなーと思ったけど。60FPS前後で動いてくれた。

一昔前の省電力性を重視したCPU + 一昔前のオンボードGPUでもこの程度動くなら、Gosuを使ってゲームを作っても動かせる環境は比較的多いのではあるまいか、と。

もっとも、Atom CPU あたりが載った環境で動かすとどうなるか、気になるところではあるけど…。もちろん初期のAtomでは話にならないはずだけど、今時のAtomならどうなのだろうと。60FPSが出ちゃうのか、ガクガクしちゃうのか、ちょっと気になるなと。

#3 [ruby][gosu][ubuntu] Ubuntu 16.04 LTS上で Ruby + Gosu を動かしてみる

Gosuはクロスプラットフォーム対応ライブラリなので、せっかくだから Ubuntu Linux 16.04 LTS上でも動かしてみる。

環境は以下。 要するに、Windows上で仮想PCを動かして、その上で Ubuntu を動かす。

Linux上での Gosu のインストール手順は、以下のページにまとまってた。ありがたや。

_Getting Started on Linux - gosu/gosu Wiki

Gosu の動作に必要なパッケージを、apt-get を使ってインストールする。端末を開いて、以下を打ち込む。
sudo apt-get install build-essential libsdl2-dev libsdl2-ttf-dev libpango1.0-dev libgl1-mesa-dev libopenal-dev libsndfile-dev
sudo apt-get install ruby-dev

準備が出来たら Gosu をインストール。
$ sudo gem install gosu

Fetching: gosu-0.10.8.gem (100%)
Building native extensions.  This could take a while...
Successfully installed gosu-0.10.8
Parsing documentation for gosu-0.10.8
Installing ri documentation for gosu-0.10.8
Done installing documentation for gosu after 7 seconds
1 gem installed
ビルドされて、インストールができた模様。

Windows上で動かしていたスクリプトを、Ubuntu上にコピーして実行してみた。



画像表示しかしてないスクリプト群ではあるけど、あっさり動いてしまった。

仮想PC上で動かすからガクガクしちゃうかなと想像していたけど、見た目それほど悪くない感じ。結構滑らかに動いてくれた。

Ubuntuを入れた実機上でも動かしてみる。 :

足元で埃を被ってる、Ubuntu 16.04 LTS を入れてある実機でも動かしてみる。スペックは以下。
  • CPU : AMD Athlon II X2 250 (2コア,3GHz, TDP 65W)
  • GPU : オンボードGPU AMD 785G (Radeon HD 4200)
  • OS : Ubuntu 16.04 LTS



フツーに60FPS前後が出た。

ていうか、メインPC(Windows10機)で動かした時より、ガクガクしてないのですけど…。となると、どうやらメインPCが、何かしらおかしい可能性が…。

Ubuntu 14.04 の実機でも動かしてみる。 :

更に、部屋の隅で埃を被ってた Lubuntu 14.04 LTS が入れてある実機でも動かしてみた。スペックは以下。
  • CPU : AMD Sempron 3100+ (シングルコア, 1.8GHz, Socket754)
  • M/B : MSI K8MM-V (VIA K8M800チップセット)
  • GPU : オンボードGPU (K8M800に統合, UniChrome Pro)
  • RAM : 1.5GB (PC3200/DDR400, SDRAM, 1GB + 512MB, シングルチャネル)
  • OS : Lubuntu 14.04 LTS (LXDEで構成された比較的軽量な Ubuntu)
ご覧の通り、かなり古いハードウェア。

動くことは動くけど、2〜3 FPSだった。60FPSには程遠い。全く話にならない。さすがにハードウェアが古過ぎた。

改善する方法は無いのかなと少しググってみたけど、チップセット VIA K8M800 に統合されてるオンボードビデオ S3 UniChrome Pro はVIAが資料を見せてくれないからLinux用のドライバ開発がなかなか進まなくてパフォーマンスが出ないのじゃよ、と嘆いてる記事が2012年頃に書かれてた。このPC上では、別途ビデオカードを追加しないとダメっぽいな…。

さておき。Ubuntu 16.04 なら Gosu の動作に必要なパッケージがすんなりインストールできるのだけど。Ubuntu(Lubuntu) 14.04 上に Gosu をインストールしようとしたらちょっとハマったので、そのあたりは別記事にしてメモ。

#4 [ruby][gosu][ubuntu] Lubuntu 14.04 LTSに Ruby 2.3 + Gosu をインストール

Lubuntu 14.04 LTS 上で、Ruby 2.3 + Gosu をインストールした際の手順をメモ。

以下の、Ubuntu 14.04版のインストール手引書を参考にして打ち込んでみたけれど…。

_Getting Started on Linux - gosu/gosu Wiki

$ sudo apt-get install build-essential libsdl2-dev libsdl2-ttf-dev libpango1.0-dev libgl1-mesa-dev libfreeimage-dev libopenal-dev libsndfile-dev

パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています
状態情報を読み取っています... 完了
注意、'libsndfile-dev' の代わりに 'libsndfile1-dev' を選択します
build-essential はすでに最新版です。
インストールすることができないパッケージがありました。おそらく、あり得
ない状況を要求したか、(不安定版ディストリビューションを使用しているの
であれば) 必要なパッケージがまだ作成されていなかったり Incoming から移
動されていないことが考えられます。
以下の情報がこの問題を解決するために役立つかもしれません:

以下のパッケージには満たせない依存関係があります:
 libsdl2-dev : 依存: libgles2-mesa-dev
E: 問題を解決することができません。壊れた変更禁止パッケージがあります。

そもそも libsdl2-dev がインストールできないという。

以下を参考にして、もう少し作業。

_Raspberry Pi 2にUbuntu 14.04を入れてみた - Qiita
_Raspberry Pi - View topic - Ubuntu 14.04 (trusty) Raspberry Pi 2 image

$ sudo apt-get download libegl1-mesa-dev
$ sudo apt-get download libgles2-mesa-dev
$ sudo dpkg -i --force-overwrite libegl1-mesa-dev_*.deb
# => エラーになる
$ sudo dpkg -i --force-overwrite libgles2-mesa-dev_*.deb
# => エラーになる
$ sudo apt-get install -f

ここまでやってから、以下を実行。
$ sudo apt-get install libsdl2-dev
インストールできた、かな。続けて以下を実行。
$ sudo apt-get install build-essential libsdl2-dev libsdl2-ttf-dev libpango1.0-dev libgl1-mesa-dev libfreeimage-dev libopenal-dev libsndfile-dev
インストールできた。が、コレでいいのかどうか…。

続けて Ruby自体をインストール。Ubuntu 14.04 LTS は、公式では Ruby 1.9 までしかパッケージが用意されてないので、リポジトリ?を追加して Ruby 2.3 をインストールすることにする。

_Ubuntu 14.04 に apt-get で Ruby 2.1 をインストールする方法 - Rails 雑感 - Ruby on Rails with OIAX
_PPAパッケージを利用してRuby 2.2をUbuntu 14.04にインストールする | hrendoh's memo

$ sudo add-apt-repository -y ppa:brightbox/ruby-ng
$ sudo apt-get update
$ sudo apt-get install ruby2.3 ruby2.3-dev

$ ruby --version
ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-linux-gnu]
インストールできた、かな。

ちなみに、Rubyのバージョンを切り替えたい時は以下を打って設定する。
$ sudo update-alternatives --list ruby
$ sudo update-alternatives --config ruby

これで必要なアレコレは入ったはずなので、Gosuをインストールしてみた。
$ gem install gosu
インストールできた。

ここまでやって、ようやく Lubuntu (Ubuntu) 14.04 LTS 上でも Gosu が動くようになった。

apt-get関係でもう少し作業。 :

libsdl2-dev をインストールする際、 _apt - Cannot install libgles2-mesa-dev - Ask Ubuntu に従って、以下も実行してみた。
sudo apt-get clean
sudo apt-get autoclean
sudo apt-get -f install
sudo dpkg --configure -a
sudo apt-get -f install
sudo apt-get -u dist-upgrade
sudo apt-get -o Debug::pkgProblemResolver=yes dist-upgrade
関係してくるのかどうかは分からないけど一応メモ。

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

#1 [ruby][gosu] Windows + Ruby + Gosu でキーボード入力を検出

Windows10 x64 + Ruby 2.2.6 p396 + Gosu 0.10.8 で、キーボード入力を検出してみる。

キーボード入力で画像を動かす。 :

UFO画像をキーボード入力で動かしてみよう。
  • カーソルキーで上下左右に移動。
  • Zキーで拡大縮小。

_input_test1.rb
require 'gosu'

class MyWindow < Gosu::Window

  # コンストラクタ
  def initialize
    super 640, 480, false
    self.caption = "Input Test"

    @img = Gosu::Image.new("tmp_ufo.png", :tileable => true, :retro => true)
    @x = 320
    @y = 240
    @scale = 1.0
  end

  # 更新処理
  def update
    spd = 6  # 座標の変化量

    # キー入力、またはゲームパッド入力に応じて座標を増減させる

    # 左キーが押された?
    if button_down?(Gosu::KbLeft) or button_down?(Gosu::GpLeft)
      @x -= spd
    end

    # 右キーが押された?
    if button_down?(Gosu::KbRight) or button_down?(Gosu::GpRight)
      @x += spd
    end

    # 上キーが押された?
    if button_down?(Gosu::KbUp) or button_down?(Gosu::GpUp)
      @y -= spd
    end

    # 下キーが押された?
    if button_down?(Gosu::KbDown) or button_down?(Gosu::GpDown)
      @y += spd
    end

    # Zキー or ボタン1 が押された?
    if button_down?(Gosu::KbZ) or button_down?(Gosu::GpButton0)
      @scale += (8.0 - @scale) * 0.1
    else
      @scale += (1.0 - @scale) * 0.3
    end
  end

  # 描画処理
  def draw
    x = @x - (@img.width / 2) * @scale
    y = @y - (@img.height / 2) * @scale
    @img.draw(x, y, 0, @scale, @scale)
  end

  # キーボードチェック
  def button_down(id)
    # ESCキーが押されたらウインドウを閉じて終了する
    # Gosu::Window.close() を呼ぶとウインドウが閉じる
    close if id == Gosu::KbEscape
  end
end

window = MyWindow.new
window.show

使用画像は以下。

_tmp_ufo.png

ruby input_test1.rb で実行。



動きました。

少し解説。

キーが押されたか判別するには、button_down?(キー種類)を使う。そのキーが押されっぱなしだと true が返ってくる。

それと、Gosu::Window を継承したクラスの中で、def button_down(id) 〜 end を書いておくと、何かキーが押された時にそのメソッドが呼ばれるようになる。

キー種類は、 _ドキュメント を眺めれば予想できるかなと。KbXXXX がキー種類。

例えば、ゲームで使いそうなキーをいくつか列挙してみると…。
KbLeftカーソルキー左
KbRightカーソルキー右
KbUpカーソルキー上
KbDownカーソルキー下
KbA 〜 KbZAキー 〜 Zキー
Kb0 〜 Kb90キー 〜 9キー
KbEscapeESCキー
こんな感じで割り当てられてる。

ゲームパッド入力について。 :

リアルタイム2Dゲームの類を作るなら、ゲームパッド(ジョイパッド)入力もサポートしてるほうが望ましい。キーボードでは難しいプレイも、ゲームパッドなら楽々プレイできたりするわけで。キーボードでしかプレイできないリアルタイム2Dゲームなんて、現代技術で新規開発された拷問器具に等しい。

というわけで、Ruby + Gosu でもゲームパッド入力ができるのか調べてみたのだけど、これが若干悩ましい部分があって。

ゲームパッド入力は、キーボード入力と同様、button_down?(ボタン種類) で判別できる。GpXXXX がボタン種類。例えば…。
GpLeft十字ボタン左
GpRight十字ボタン右
GpUp十字ボタン上
GpDown十字ボタン下
GpButton0 〜 GpButton15ボタン0 〜 15
割り当てはこんな感じ。

ところが。Windows10 x64 + Ruby + Gosu 上で、いつも使ってるUSB接続ゲームパッドを持ち出してきて動作確認してみても全く無反応で。

変だな、Windows上ではゲームパッド入力をサポートしてないのかな? と思ったけれど、ふと気が付いた。もしかして XInput にしか対応してないんじゃないか…?

Windows PC で使えるUSB接続ゲームパッドには、大別すると2種類あって。
  • DirectInput … 旧規格。若干お値段が安い。製品種類が豊富。ボタン数・配置は製品毎にバラバラ。
  • XInput … 新規格。若干お値段が高い。製品種類がほとんど無い。ボタン数・配置は Xbox 360 コントローラに準拠。
自分が動作確認に使ったのは、DirectInput対応のゲームパッドだった。

試しに XInput対応のゲームパッドを使ってみたら…。やっぱり反応した。

手持ちのゲームパッドで動作確認してみたら、以下の結果に。
ELECOM JC-U3613M (XInput)OK (ドライバのインストールが必要)
ELECOM JC-U3613M (DirectInput)NG
ELECOM JC-U2410TWH (DirectInput)NG
BUFFALO BSGP801GY (DirectInput)NG
やはり Ruby + Gosu は XInput にしか対応してないらしい。

更に加えて。

左アナログスティック・右アナログスティック・十字ボタンのどれを使っても、8方向のデジタル入力として扱われるようで。これは…わざわざボタン配置をキッチリ決めた、XInputを使ってる意味が無いのでは…。

そんなわけで、入手しやすい DirectInput対応製品が使えないのはどうなんだろう、しかも XInput をイマイチ活かせてないような、などとモヤモヤしちゃうところもあるのだけれど、でもまあ一応、Ruby + Gosu はゲームパッド入力にも対応、とは言えそうかなと。

各ゲームパッドの製品情報へのリンク。 :

動作確認に使ったゲームパッドの製品情報へのリンクを列挙しておくのです。

_Xinput対応ゲームパッド ELECOM JC-U3613MBK
_10ボタン配列USBゲームパッド ELECOM JC-U2410T
_レトロ調USBゲームパッド 8ボタンタイプ - BUFFALO BSGP801GY

Ruby + Gosu で使えたのは、JC-U3613MBK だけ、かつ、別途ドライバをインストールしないと使えなかった、とメモ。

それにしても、ELECOM製品ばかりだな…。値段が安いので、つい選んでしまう…。

ツールを使う手もありますね。 :

Ruby + Gosu に限った話じゃないけれど。キーボード入力にしか対応してないゲームアプリでも、 _JoyToKey_NanJoy_JoyAdapter 等のツールを使えばゲームパッドで操作できたりする時もありますよ、と一応言及しておくのです。 *1

Ubuntu Linux 16.04 LTS上でも試した。 :

ググってみたら、Ubuntu Linux もゲームパッドは使えるらしい。

_Ubuntuでゲームパッドを使う | レンズの向こう
_ubuntuでゲームパッドを使用する方法: suzukikenzouのブログ

だったら試してみるか…。VMware Player + Ubuntu 16.04 LTS 上で動作確認。

端末を開いて以下を打ち込んで、ドライバと動作確認ツールをインストール。
sudo apt-get install joystick jstest-gtk

今回は、DirectInputタイプのUSB接続ゲームパッド ELECOM JC-U2410TWH を接続してみた。

jstest-gtk を実行したところ、ちゃんと入力に反応している模様。スンナリ動くんだな…。素晴らしい。

前述の Gosu のスクリプトも動かしてみた。これまた反応してしまった。Windows上で動作確認した時よりもスンナリと確認できちゃった。素晴らしい。

ということで、Windows + Ruby + Gosu は XInput にしか対応してないのに、Linux + Ruby + Gosu は DirectInput に対応してるという。なんだかずるい。

Macはどうなんでしょうね。 :

Macは持ってないから確認のしようもないけれど。そもそも Mac はUSB接続ゲームパッドって使えるのでしょうかね…。

_Macでゲームパッド(Logicool F310r)を使う - Paalonのブログ
_【Macでも使えた】ゲームパッド・ゲームコントローラー・ジョイパッド

使えるみたいではありますな。Gosu で使えるかどうかは分かりませんが。

*1: ただ、ゲームアプリによっては、それらのツールを不正ツール扱いする時もあるそうで…。なので、「できたりする時もありますよ」と若干ぼやけた説明に。

#2 [zatta] アレ用の記事にすべきだったかも

思考メモ。

昨日今日書いたGosu関係の記事は、もしかすると _Ruby Game Developing Advent Calendar 2016 用の記事にすべきだった、かも…。ちょっと失敗した、かも…。

「Advent Calendar、今年も相変わらず高度過ぎて、こりゃ自分が参加できそうなレベルじゃないわ…」と思ってたけど。「○○が動いたよ」的なこういう薄い内容のソレでも、さすがにこれだけ長々と書いてあったら質より量みたいな感じで一応アリ扱いになったのでは、などと今頃になって思えてきたりもして。

もっとも、どうも Advent Calendar って自分のソレとはペースが違うんだよな、という感もどこかにあって。

例えばこれが、数ヶ月に1回ぐらいの頻度でキッチリした内容のblog記事をビシッビシッと書くような方々なら、この時期用の記事としてじわじわじっくりネタを集めてタイミングを見計らってドーン、とかできるんだろうけど。自分の場合、「この日はこんなことしてました」的に実験内容をすぐにダラダラとWeb日記にメモして終わり、てな感じで公開するのが当たり前になっていて。

なので、その日やったことをずっとこっそり隠しておいて後でまとめてドーン、期日が来たタイミングでババーン、というスタイル自体が結構なストレスになるというか…。自分、隠し事(?)が大の苦手で…。 *1

自分の中では、作業内容・実験内容の公開云々なんてもんは、もやもやとストレスを感じながらやるもんでもないだろう、仕事じゃないんだし、趣味なんだし、無料で公開してるんだし、という(甘えた)気持ちもあったりして。てなわけで、Advent Calendar の類はどうもビミョーに参加しづらい…。

それ以前に自分がやってることはどれもこれも低レベル過ぎてそもそも参加できないわけですけど(木亥火暴)

「インターネットは毎日天下一武道会が開かれてるようなもん」と誰かが言ってたけど、特にこの時期はソレが更に強化されてるような。かめはめ波だか魔貫光殺砲だかが飛びまくってる中に狼牙風風拳で飛び込めるのか、っていう…。 *2

まあ、自分が試したアレコレはこうしてWeb日記上でまるっと公開してるわけだし。隠してるならともかく誰でも見れる場所に公開してるという点では違いは無いはずで。故にその手のイベントに参加できなくても大目に見てもらいたい…てのはダメでしょうかって一体誰に許しを請うているのだか。

思考メモでした。
*1: 考えてみたら、時々日記のアップロードが滞るのはソレだな…。まとめてドーン、に近づいていくとストレスになってアップロードが億劫に…。
*2: ドラゴンボールってほとんど見てないんですけど、こういう喩えで合ってます?

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

電動自転車で某所まで。AM9:10-12:00まで作業。詳細はGRPでメモ。

帰宅途中で夜食等を購入。 :

久々にカワチに寄って夜食等を購入。そういえば、近所にヨークベニマルができてからというもの、カワチにはほとんど足を運ばなくなってしまった…。

2016/12/13(火) [n年前の日記]

#1 [ruby][gosu] Ruby + Gosu で音が鳴らせるかテストしてみる

Windows 10 x64 + Ruby + Gosu で、サウンドが鳴らせるか動作確認してみますよ。ちょっと問題があることが分かったけど、そのあたりは後で説明するということで。…ドキュメントを読み落としてるところがありそうなので、間違ったことを書いてる可能性もありますが。

動作確認環境は、Windows10 x64 + Ruby 2.2.6 p396 mingw32 + gosu 0.10.8。

ワンショットでSEを鳴らしてみる。 :

まずは、SE(Sound Effect の略、効果音)をワンショット(一発だけ)鳴らしてみましょうか。

以下のサンプルは、一定フレーム数(60フレーム=1秒)が経ったら次々にSEを鳴らす、という処理をやってます。

_sound_test.rb
require 'gosu'

class MyWindow < Gosu::Window

  def initialize
    super 320, 240, false
    self.caption = 'Sound Play Test'

    # wavファイルを読み込む
    @sounds = []
    [
      "tmp_se_01.wav",
      "tmp_se_02.wav",
      "tmp_se_03.wav",
      "tmp_se_01.ogg",
      "tmp_se_02.ogg",
      "tmp_se_03.ogg"
    ].each do |fn|
      @sounds.push(Gosu::Sample.new(fn))
    end
    @cnt = 0
  end

  def update
    if @cnt % 60 == 0
      # 一定フレーム数が過ぎたらサウンドを再生
      n = (@cnt / 60) % @sounds.length
      @sounds[n].play
    end
    @cnt += 1
  end

  def draw
  end

  def button_down(id)
    # ESCキーを押したらウインドウを閉じる
    close if id == Gosu::KbEscape
  end
end

window = MyWindow.new
window.show

使用したサウンドデータファイルは以下。自作データなので、CC0 / Public Domain にしておきます。ちと数が多いので、まとめてzipにして置いときます。

_tmp_se_all.zip

バラバラにDLしたい方は以下をどうぞ。

_tmp_se_01.wav
_tmp_se_02.wav
_tmp_se_03.wav
_tmp_se_01.ogg
_tmp_se_02.ogg
_tmp_se_03.ogg

さて。ruby sound_test.rb で実行。



鳴りましたな。

一応解説。

Ruby + Gosu でSEを鳴らすには、Sampleクラスを使います。…「Sound」クラスじゃないのですな。おそらく、波形データ(サンプリングデータ)を扱うからSample、なのでしょう。

サウンドファイルの読み込みは、以下のような感じ。
@sound = Gosu::Sample.new("サウンドファイル名")

再生する時は、play() を使うようで。
@sound.play

扱えるサウンドファイルの種類ですが、手元の環境で試したところ、wav ファイルとoggファイルが使えるようでした。ただ、自分の環境はDTMもやってる関係で何か余計なものを入れていて、故にoggが使えてる可能性もあるかもなと。他の環境でも ogg が使えるかどうかはちと分からんです。そこはそれぞれ試してもらうしか。

SEの音量を変えたり再生速度を変えたり再生停止してみたりする。 :

_Sampleクラスのドキュメント を眺めた感じでは、Sample#play() は音量指定、再生速度指定、ループ再生指定ができるようで。

また、ゲーム制作用ライブラリとしては、SE再生後に任意のタイミングで再生停止できないとゲーム用として使えなかったりするので、そのあたりも動作確認してみます。

とりあえず、各キーを押すと再生だの停止だのをするサンプルを書いてみました。キーの割り当ては以下。
  • Aキー : 通常再生
  • Bキー : 音量を小さくして再生
  • Cキー : 低速再生
  • Dキー : 高速再生
  • Eキー : ループ再生
  • Pキー : ポーズ/ポーズ解除
  • Vキー : 音量を0に
  • Zキー : 再生停止

_sound_test2.rb
require 'gosu'

class MyWindow < Gosu::Window

  def initialize
    super 320, 240, false
    self.caption = 'Sound Play Test'
    @fnt = Gosu::Font.new(20)

    # wavファイルを読み込む
    @sound = Gosu::Sample.new("tmp_voice.wav")

    @si = nil  # SampleInstance
    @play_msg = ""
    @pause_msg = ""
  end

  def update
    if @si
      if @si.playing?  # 再生中?
        @play_msg = "Playing"
      else
        @play_msg = "Stopped"
      end
      if @si.paused?  # ポーズ中?
        @pause_msg = "Paused"
      else
        @pause_msg = "Not Paused"
      end
    else  # まだ鳴らしてない
      @play_msg = "Not Play Start"
      @pause_msg = "Not Play Start"
    end
  end

  def draw
    @fnt.draw("Push A,B,C,D,E,P,V and Z", 4, 4, 0)

    # 再生状態、ポーズ状態を表示
    @fnt.draw(@play_msg, 4, 30, 0)
    @fnt.draw(@pause_msg, 4, 50, 0)
  end

  def button_down(id)
    close if id == Gosu::KbEscape
  end

  # キーが離された時に呼ばれる
  def button_up(id)
    @si = @sound.play if id == Gosu::KbA  # 通常再生
    @si = @sound.play(0.2, 1, false) if id == Gosu::KbB  # 音量小
    @si = @sound.play(1, 0.5, false) if id == Gosu::KbC  # 再生速度を遅く
    @si = @sound.play(1, 2.0, false) if id == Gosu::KbD  # 再生速度を早く
    @si = @sound.play(1, 1, true) if id == Gosu::KbE  # ループ再生

    if @si
      if id == Gosu::KbZ
        if @si.playing? # 再生中?
          @si.stop  # サウンドを停止
        end
      elsif id == Gosu::KbP
        if @si.paused?  # ポーズ中?
          @si.resume  # ポーズ解除
        elsif @si.playing? # 再生中?
          @si.pause  # ポーズ(一時停止)
        end
      elsif id == Gosu::KbV
        if @si.playing?
          @si.volume = 0 # ボリュームを0に
        end
      end
    end
  end
end

window = MyWindow.new
window.show

使用したサウンドファイルは以下。これも自作データなので CC0 / Public Domain ってことで。

_tmp_voice.wav

ruby sound_test2.rb で実行。



鳴りました。音量指定、再生速度指定、ループ再生もできているし、停止、ポーズ、ポーズ再開、音量変更、再生中かどうかの判別、ポーズ中かどうかの判別もできているようで。

少々解説。

Sample#play() は、以下の指定ができます。
@sound.play(音量, 再生速度, ループ再生)
  • 音量は、1.0が本来の音量。値を小さくすると音量が小さくなる。
  • 再生速度は、1.0が標準速度。値を大きくすると再生速度が速くなり、値を小さくすると再生速度が遅くなる。
  • ループ再生は、true / false で指定する。true ならループ再生。

停止や音量変更については…。Sample#play() を呼ぶと、SampleInstance なるクラスを返すようで、そのクラスをどこかに取っておいて、ソレを使って停止や音量変更をする、という手順になっているようです。
@si = @sound.play
...
@si.stop        # 再生停止
@si.pause       # ポーズ(一時停止)
@si.resume      # ポーズ解除
@si.volume = 0  # 音量変更
@si.playing?    # 再生中か否かを true / false で返す
@si.paused?     # ポーズ中か否かを true / false で返す

そういえば、ドキュメントには「SampleInstanceを使い終わったらすぐに破棄しろよな。じゃないと何がどうなるか知らねえぞ」と怖いことが書いてあるのですが…。Rubyでその破棄とやらはどうやったらできるのでしょうか。nil でも再代入しとけばいいのだろうか…。Rubyは全く詳しくないから、分からん…。

ところで、上記のサンプルでちょっとハマった点が。最初は、MyWindowクラスの update() の中で、
@si = @sound.play if button_down?(Gosu::KbA)
みたいな感じで書いてたのですけど、それだと停止その他が一切できなくて悩んでしまって。

何のことはない。update() の中で button_down?() を使うと、そのキーが押されてる間は何回も何回も処理されてしまうわけで。キーを押した瞬間だけ処理をするわけじゃない、てなあたりに気づくのが遅れて結構ハマりました…。

このあたり、DXRuby では、「キーが押された瞬間」「キーが押されてるかどうか」「キーを離した瞬間」、それぞれを判別できる機能があるので便利だったのだなと再認識した次第。

BGMを再生してみる。 :

SEを再生する時は Sampleクラスを使いますが、BGMを鳴らしたい時は Songクラスを使ってくれ、と _ドキュメント に書いてあったので、試してみます。

_song_test.rb
require 'gosu'

class MyWindow < Gosu::Window

  def initialize
    super 320, 240, false
    self.caption = 'Song (BGM) Play Test'
    @fnt = Gosu::Font.new(20)

    # BGMのoggファイルを読み込む
    @bgm = Gosu::Song.new("tmp_loop01.ogg")
    @play_msg = ""
    @pause_msg = ""
  end

  def update
    # 再生中?
    if @bgm.playing?
      @play_msg = "Playing"
    else
      @play_msg = "Stopped"
    end

    # ポーズ中?
    if @bgm.paused?
      @pause_msg = "Paused"
    else
      @pause_msg = "Not Paused"
    end
  end

  def draw
    # 再生中/停止中, ポーズ中/非ポーズを表示
    @fnt.draw("Push A:Play, Z:Stop, X:Pause", 4, 4, 0)
    @fnt.draw(@play_msg, 4, 30, 0)
    @fnt.draw(@pause_msg, 4, 50, 0)
  end

  def button_down(id)
    close if id == Gosu::KbEscape
  end

  # キーが離された時に呼ばれる
  def button_up(id)
    @bgm.play(true) if id == Gosu::KbA  # 通常再生(ループ有効)
    @bgm.stop if id == Gosu::KbZ  # 再生停止
    @bgm.pause if id == Gosu::KbX  # ポーズ
  end
end

window = MyWindow.new
window.show
使用したBGMファイル(.ogg)は以下。ループ再生ができるように、曲の終わりと頭がちゃんと繋がるデータになってます。なってるはずです。これも自作データなので CC0 / Public Domain ってことで。

_tmp_loop01.ogg

ruby song_test.rb で実行。



鳴ることは鳴ったけど、ここで問題発生。ループ再生が綺麗に繋がってない…。曲がブチッと切れてる…。どうも最後まで再生し終わる前に、頭に戻ってしまっているように聞こえますな。

一応解説。

BGMファイル(wavファイル、oggファイル)を読み込むのは、以下のように書きます。
@bgm = Gosu::Song.new("BGMファイル名")

再生、停止、ポーズは以下。
@bgm.play(true)  # 再生開始(ループ有効)
@bgm.stop        # 再生停止
@bgm.pause       # ポーズ
play(true)でループ再生、play(false)で非ループ再生のようです。また、ポーズ解除は play()を呼べばいいようです。

SE再生と違って、PAN変更、再生速度の変更はできないよ、とドキュメントには書いてありますな。音量変更はできるみたいだから、フェードアウト処理はできそうな予感。

それにしても、ループ再生ができないのは痛いなあ…。

このあたり、以前も遭遇したような。 _2013/04/30 頃に、StarRuby と HSP で似たような症状を見ましたよ。たしか StarRuby は SDL を使ってた気がするんですけど違いましたっけ。Gosu は SDL2 を使ってるらしいですが、どうもSDL関係はこのあたりに代々不具合でもあるのかな、という気がしてきました。

まあ、PCエンジンのCD-ROMゲームのように、1曲が結構長いデータを用意して誤魔化す手もあるのですけど。

とまあ、そんな感じで若干問題はありつつも、Ruby + Gosu で一応サウンドは鳴らせるようではありますね。

これで、画像表示、キー入力、サウンド再生ができることが分かったから…。これならリアルタイム2Dゲームの類も、一応は作れそうかなと。たぶん。何かトラップが隠れてそうな不安もありますが。

#2 [prog][ruby][gosu] SE再生についての余談

余談ですが。

たとえレトロ風の2Dゲーム制作であっても、SE再生後、「そのSEが再生中かどうかを判別する機能」や「再生中のSEを停止する機能」は、ゲーム制作ライブラリに必須だよな、と。

例えばの話。

プレイヤーキャラが必殺技を撃って、「はどーけん!」とか「しょーりゅーけん!」とか「たつまきせんぷうきゃく!」とか叫ぶとするじゃないですか。

必殺技を撃って「はどーけん!」が再生されてる途中で、敵がパンチを繰り出してプレイヤーキャラに当たったとします。プレイヤーキャラは「うわっ!」と叫びながら吹っ飛びますわな。

この時、SE関係はどういう処理になるか。「はどーけん!」が『再生中かどうかを判別』して、もし再生中なら「はどーけん」の『再生を停止』しないといけない。そこでようやく「うわっ!」の再生要求を続けて送れる状態になるわけです。

これがもし、「特定の音声が再生中かどうかを判別」する機能も無ければ、「音声を停止」する機能も無かったらどんな事態になるか。

「はどーけん!」という声と一緒に「うわっ!」という声も聞こえてしまうわけですよ。お前一体何人居るんだよ! それともいっこく堂かよ! いや待て、彼でもそんな喋り方は無理だよ! …まあ、こんな作りは許されないですよね。

昔話ですけど、メガドライブの「ベアナックル3」が、そんな感じの酷い実装で…。プレイヤーキャラがダメージ受けて吹っ飛んでるのに「いじょーとーさん!」と必殺技の音声だけが孤独に威勢良く流れ続けて。 *1 もうね。萎えまくりですよ。激萎えですよ。せっかくのベルトスクロールアクションの爽快感がゼロ。サウンド周りの実装が糞なせいで全編通して何もかもが台無し。ベアナックル2は名作扱いされてるのに、ベアナックル3は若干どこか無かったこと扱いになってるのは、あのサウンド周りの糞な実装が大きいのだろうなあ…と個人的には思うわけで。

ということで。SE再生中かどうかの判別と、SE再生の停止。この2つはいくらなんでも最低限実装されてないとマズいわけで。この2つすら実装されてないゲーム制作ライブラリは、なんちゃってゲーム制作ライブラリです。お前はゲーム制作ライブラリを名乗れねえよ、ゲーム制作を舐めてんじゃねえぞ、と。

なので、ゲーム制作ライブラリを評価する際、まずはこの2つがあるかどうかをチェックすれば、ちゃんと考えながら作られているライブラリか、それとも見た目だけそれっぽくした実用にならないインチキライブラリか、ひとまずすぐに分かるのかもなあ、てな気分になってきました。

まあ、余談でした。
*1: 自分の中ではそんな印象が残ってるのだけど、偽記憶だろうか…。さすがにダメージ受けた時は音声を停止してたかなあ…。攻撃が敵に当たっても時々無音になってたことはハッキリと覚えてるんですけど…。

#3 [pc] マウスを交換

今まで使ってたマウス、ELECOM M-XG1UBBK のホイール回転が妙な感じになってきて。1回分回しただけなのに連続でトリガーが送られる感じ。ロータリーエンコーダが寿命なんだろうなと。

予備の ELECOM M-XG1UBSV を発掘してきて交換。

今まで使ってた個体は、 _2015/12/01 に購入して使い始めたらしい。すると1年も持ったのか…。ELECOM製品なのに…。って去年も同じこと書いてるな…。

#4 [anime] 精霊の守り人アニメ版最終回を視聴

NHKで再放送されていた、精霊の守り人アニメ版最終回を視聴。

やっぱり名作だわ…。

2016/12/14(水) [n年前の日記]

#1 [ruby][gosu] Ubuntu 16.04 + Ruby + Gosu でサウンド再生を試してみたり

_昨日書いた各スクリプト を VMware Player + Ubuntu 16.04 LTS上でも動かしてサウンドが鳴るかどうか確認してみたり。

結果、基本的にはWindows上で試した時と同様に一応鳴ってはくれたけど、ちと気になる動作が。

各スクリプトを実行すると終了時に妙なメッセージが表示される。
$ ruby sound_test.rb
AL lib: (WW) FreeDevice: (0x22c9260) Deleting 6 Buffer(s)

$ ruby sound_test2.rb 
AL lib: (WW) FreeDevice: (0x1c2c160) Deleting 1 Buffer(s)

$ ruby song_test.rb 
AL lib: (WW) FreeDevice: (0x149c6b0) Deleting 2 Buffer(s)
コレは一体何だろう…。

たぶんサウンド関係のリソースを確保したまま終了しちゃって「そういう作りをしてるんじゃねえよ」と怒られてるのだろうけど。dispose 云々とやらを、どこでどうやってしておけばいいのやら。コレが DXRuby + Ayame なら、サウンドリソースに対しては dispose という専用メソッドが用意されてるのだけど…。

それとは別に。Songクラスを使ったBGM再生については、Ubuntu上もWindowsと同様に、ループ再生は終わりと頭がちゃんと繋がってくれなかった。最後まで再生する前に頭に戻ってる、ように聞こえる。Linux上ではちゃんと聞こえるけどWindows上ではダメ、てな面倒臭い状況にならなかったのは幸いだけど、それにしても…やっぱりループ再生すらできないのは、困るな…。

Gosuがサポートしてるサウンドファイルフォーマット。 :

_Supported Audio Formats - gosu/gosu Wiki に説明があった。Windows、Linux、Mac は wav と ogg が使えるけど、iPhone は MP3 か M4A じゃないとあかんよ、一応 ogg も使えるけど遅くなるよ、と書いてあるのかな。

Macに限っては、CAF, MP3, M4A, WAV, AIFF等々、なんでもござれ状態らしい。…CAFフォーマットなんて初めて聞いた。iPhone向けのフォーマットなのか。

謎メッセージが解決できないか試す。 :

Ubuntu上で表示される謎メッセージが気になる。表示されないように修正できないものか。つまりは終了前にリソースをちゃんと解放するように作れないものか。

DXRubyドキュメントの、 _4.11 リソースの解放について が参考になりそうな気がしてきた。参照を切って GC.start を呼ぶ、という方法が提示されてる。

が、しかし。Ruby上で参照を切る、ってのは具体的にはどうやればいいのでしょうかね? 自分は初心者なので、まずそこからして分からないという…。

_第14章 コンテキスト の中で気になる行が。
cnt = nil # 参照を切る。作ったProcはここでやっと不要になる
なるほど、nil を入れておけばいいのか…な…。本当にそうなのか分かんないけど。

試しに色々対策。

_sound_test3.rb
require 'gosu'

class MyWindow < Gosu::Window

  def initialize
    super 320, 240, false
    self.caption = 'Sound Play Test'

    # wavファイルを読み込む
    @sounds = []
    @sis = []
    [
      "tmp_se_01.wav",
      "tmp_se_02.wav",
      "tmp_se_03.wav",
      "tmp_se_01.ogg",
      "tmp_se_02.ogg",
      "tmp_se_03.ogg"
    ].each do |fn|
      @sounds.push(Gosu::Sample.new(fn))
      @sis.push(nil)
    end
    @cnt = 0
    @close_req = 0
    @se_all_stop = false
  end

  def update
    if @se_all_stop  # SE全停止が要求されてる
      stop_all_se
      @se_all_stop = false
    end

    if @close_req > 0  # ウインドウcloseが要求されてる
      @close_req -= 1
      if @close_req == 0  # 一定時間が経過した
        if se_playing?
          # まだ鳴ってる
          @close_req = 30
          puts "SE playing (in update)"
        else
          # 何も鳴ってない
          dispose_se_resource
          GC.start
          close  # ウインドウを閉じる
        end
      end
      return
    end

    tm = 45
    if @cnt % tm == 0
      # 一定フレーム数が過ぎたらサウンドを再生
      n = (@cnt / tm) % @sounds.length
      if @sis[n] == nil or !@sis[n].playing?
        @sis[n] = @sounds[n].play
      else
        # @sis[n].stop
      end
    end
    @cnt += 1
  end

  def draw
  end

  # キーが押された時に呼ばれる
  def button_down(id)
    if id == Gosu::KbEscape  # ESCキーが押された
      # @se_all_stop = true  # SE全停止を要求
      @close_req = 30  # xxフレーム後にウインドウを閉じるように要求
    end
  end

  # 何かのSEが鳴ってたら true を返す
  def se_playing?
    return false unless @sis
    cnt = 0
    @sis.each do |si|
      next unless si
      cnt += 1 if si.playing?
    end
    return true if cnt > 0
    return false
  end

  # SEを全て停止
  def stop_all_se
    return unless @sis
    @sis.length.times do |i|
      next unless @sis[i]
      @sis[i].stop
    end
    puts "SE stop all"
  end

  # サウンド関連リソースを全て破棄、するはずなんだけど…
  def dispose_se_resource
    if @sis
      @sis.length.times { |i| @sis[i] = nil }
      @sfs = nil
    end

    if @sounds
      @sounds.length.times { |i| @sounds[i] = nil }
      @sounds = nil
    end
  end
end

wdw = MyWindow.new
wdw.show

# SEが鳴り終わるまで待つ
while wdw.se_playing?
  puts "SE playing"
  sleep(1)
end
puts "SE not playing"

wdw.dispose_se_resource
wdw = nil
GC.start
exit

要するに、SEが鳴ってない状態になるまで待ってみて、それから各変数に nil を代入して GC.start を呼ぶ、という処理にしてみた。

ちなみに、もしかしてメインループの中で再生状態の検出・記録をしていたりして、となるとウインドウを閉じた後で再生状態を調べようとしても無駄なのではと疑問を持ったけど。実際試してみたら、メインループ外でもちゃんと再生・非再生が得られたので、メインループとは違うところでそのあたりを処理して調べている模様。

さておき。結果が少し変わってきた。
$ ruby sound_test3.rb 
SE playing (in update)
SE not playing
AL lib: (WW) FreeDevice: (0x1b503b0) Deleting 2 Buffer(s)
メッセージ内のバッファ数が、6から2まで減った。しかし、相変わらずメッセージが表示されてる。なんでや…。

ちなみに、github上のgosuのソレには、 _OpenAL warning on Ubuntu - Issue #292 - gosu/gosu として去年から報告が上がってるけど、誰もレスをつけてないという…。ひょっとして、Linux + Gosuを使う人は無音のゲームしか作らないのだろうか。それともそもそもLinux上でGosuを使う人はほとんど存在していないのだろうか。

メッセージ内の「(WW)」はエラーじゃなくて警告を表してるのだろうと思うので、少しウザいけど気にしないという選択肢もアリなのかしら。いやまあ、現状では解決策が見つからないので、その選択肢しか無いのだけど。

_Xorg - ArchWiki
ログファイルの中に (EE) で始まる行が存在しないか確認してください。(EE) はエラーです。また、(WW) は警告です。

Xorg - ArchWiki より

Sampleクラスを使うとちゃんとループする。 :

Songクラスを使わずに、Sampleクラスを使うとちゃんとループするようで。

_song_test3.rb
require 'gosu'

class MyWindow < Gosu::Window

  def initialize
    super 320, 240, false
    self.caption = 'Sample (BGM) Play Test'
    @fnt = Gosu::Font.new(20)

    # BGMのoggファイルを読み込む
    @bgm = Gosu::Sample.new("tmp_loop01.ogg")
    @bgm_si = nil
    @play_msg = ""
    @pause_msg = ""
  end

  def update
    # 再生中?
    @play_msg = (@bgm_si and @bgm_si.playing?)? "Playing" : "Stopped"

    # ポーズ中?
    @pause_msg = (@bgm_si and @bgm_si.paused?)? "Paused" : "Not Paused"
  end

  def draw
    # 再生中/停止中, ポーズ中/非ポーズを表示
    @fnt.draw("Push A:Play, Z:Stop, P:Pause", 4, 4, 0)
    @fnt.draw(@play_msg, 4, 30, 0)
    @fnt.draw(@pause_msg, 4, 50, 0)
  end

  # キーが押された時に呼ばれる
  def button_down(id)
    if id == Gosu::KbEscape
      close
    elsif id == Gosu::KbA
      if @bgm_si == nil or !@bgm_si.playing?
        @bgm_si = @bgm.play(1, 1, true)  # 通常再生(ループ有効)
      end
    elsif id == Gosu::KbZ
      if @bgm_si
        @bgm_si.stop  # 再生停止
      end
    elsif id == Gosu::KbP
      if @bgm_si
        if @bgm_si.paused?
          @bgm_si.resume # ポーズ解除
        elsif @bgm_si.playing?
          @bgm_si.pause  # ポーズ
        end
      end
    end
  end

  # キーが離された時に呼ばれる
  def button_up(id)
  end

  def stop_bgm
    return unless @bgm_si
    @bgm_si.stop
  end

  def dispose_bgm
    @bgm_si = nil
    @bgm = nil
  end

  def bgm_playing?
    return false unless @bgm_si
    return @bgm_si.playing?
  end
end

wdw = MyWindow.new
wdw.show

# BGM停止を指示
wdw.stop_bgm

# BGMが停止するまで待つ
while wdw.bgm_playing?
  puts "BGM playing"
  sleep(1)
end
puts "BGM not playing"

wdw.dispose_bgm
wdw = nil
GC.start
exit



曲の終わりと頭がちゃんと繋がってるように聞こえる。もしかするとノイズが入ってるかもしれないけど、聞いてる分にはほとんど分からない、ような。

また、Windows上でも、Ubuntu上でも、同じように聞こえた。

もっとも、Ubuntu上では終了時にやっぱり例のメッセージが表示されてしまうのだけど…。

#2 [ubuntu] gedit-gmateがインストールできず

Ubuntu には gedit というエディタが入ってるのだけど、どうやら gedit-gamte なるプラグインをインストールすると更に便利になるらしくて。

_gmate/gmate: Set of plugins and improvements to make Gedit a powerfull programmer text editor

しかし、Ubuntu 16.04 LTS上で試してみたところインストールできず。

sudo apt-add-repository ppa:ubuntu-on-rails/ppa
sudo apt-get update
「こんなリポジトリは使えねえよ!」と怒られる。

続けて以下を打ち込むも…。
sudo apt-get install gedit-gmate
「そんなパッケージはねえよ!」と怒られる。

もうメンテナンスされてないのかな。2015年版があるみたいだから、比較的最近までメンテナンスされてたように見えるんだけど。

とりあえず、そういう状態になったことをメモ。

#3 [ubuntu] Rubyが書けるようにvimを少しだけ設定

gedit で Rubyスクリプトを編集しようと思ったけど便利機能がほとんど無くてこれは厳しいなと。結局 vim を使うことに。

とりあえず、インデントがおかしなことになったので、以下を参考にしてそこだけは設定。

_Rubyプログラミングが快適になるVim環境を0から構築する - Qiita
_vimでrubyを使うときだけ2タブにしておこう - 雑想空間

~/.vimrc の中で、以下を記述。
set expandtab
set autoindent
filetype plugin indent on
タブ文字を使わず空白で置き換えるのと、自動インデントの有効化と、ファイル毎にインデントを変えるように設定してる、らしい。

~/.vim/indent/ruby.vim を作成して、以下を記述。
setlocal tabstop=2 shiftwidth=2 softtabstop=2

2016/12/15(木) [n年前の日記]

#1 [anime] バンバン撃ってきてるのに当たらないアレ

先日、「TRICKSTER」というアニメを見ていたら、ちょっと気になるカットがいくつかあって。

警備ロボットがマシンガン?をバババババと撃ってきて、まるで土砂降りの雨の中の地面のように床の上で火花がチュチュチュチュチュンとなっちゃってる中を、イケメンおじさんが颯爽と駆け抜けてく、てなカットだったのですが。一目見た瞬間に「おいちょっと待てソレどう見ても当たるだろ」とさすがにツッコミたくなる映像になっていて。コレはアレかな。コンテがアレなのかな…。

いやまあ、これがギャグアニメだったらこういう処理の仕方もアリだけど、とは思ったりもしたのです。例えばだけど、ナントカ松さんの足元でバンバン着弾の火花が飛んでいてナントカ松があわあわした直後に「うわ、あぶねー! 当たるところだったー!」とか言ったら別のナントカ松が「いや待って今のソレさすがにおかしいよね絶対当たるよね主人公補正にもほどがあるだろって視聴者からツッコまれちゃうレベルだったよね」とツッコミを、みたいなシーンだったらコレは全然アリだけどなあ、と。

でも、件のアニメはギャグアニメなのかというと…いや…実はギャグアニメだったのかな…自信が無くなってきた…。

それはともかく、そこでなんだか考え込んでしまったのです。どういう見せ方が適切なのかなと考えてみても、こういう見せ方がフツーだろう、てな構図がさっぱり浮かんでこなくて。アレレ? なんだこれ? どういうことだ、と。

敵がバンバン撃ってきてるけど何故かメインキャラ達には当たらない、なんてシーンはその手のアニメなら飽きるほど描かれてるし、いくらでも目にしているはずなのですよ。なのにどうしてその具体的な見せ方について自分は記憶に残ってないのか。

それはつまり、ちょっと考えるとおかしいけれどパッと見は自然に思えてくる上手な見せ方・処理の仕方をしてる作品が多数だから明確に記憶に残ってないのだろうと。大多数の作品は視聴者が話や展開に集中できるように上手いことやってるんだろうなと。たぶん。

おそらくだけど、そういうシーンの見せ方って、技と言うか、コツと言うか、何かテクニックがありそうだよなと。コレを入れとくと激しい銃撃戦の感じが出るんだよね、だけどコッチを入れちゃうと不自然さが際立つから避けたほうがいいんだよ、コレをやるなら○秒以上見せちゃダメだね一瞬チラッと挟むのが、みたいなノウハウが…。

ということで、今後そういうシーンを見かけたら一体どういう処理をしてるのかちょっと意識して観察してみようかなあ、と思った次第です。それだけです。

ちなみに、その件の回は、コンテが全部ダメってわけでもなくて。冒頭のスカイダイビングのシーンは「おおぅ…」と思ったし *1 、複数のディスプレイを使いながら複数キャラの表情を同時に見せる、みたいなカットには唸ったりもしたのでアレなんですけど。ただ、あの銃撃戦(?)だけは、ちょっと…。

ホント、どういう見せ方をすると自然に見えてくるのかなあ…。「いやいやちょっと待て」から「スゲー! カッケー!」に持っていくには、何をどうしたら…。

と、ここまで書いて気が付いたけど。そういやルパンやナウシカのソレも大体あんな感じだったなと…。もしかして今回のソレも何かの作品のパロディやオマージュの類でわざとやってたのだろうか…。「このおじさんはルパンみたいなもんだからこのくらいあり得ない感じで」てのも、なんだかあり得そうな…。考えてみればアレに出てくるあの少年は能力的には五ェ門みたいなもんだし…。そういうジャンルの作品と思えば、ああいう見せ方もアリなのかな。どうなんだ。

カリ城のソレ。 :

余談。ルパンシリーズも、不自然過ぎるぐらいにその手の銃撃が当たりませんな…。一番最初のOP、サーチライトで照らされて走り抜けるところからして当たらないですもんねえ…。

故に、カリ城のあのへんの展開がより印象的に感じられるというか。

あのへんのシーンの上手さは、ルパンが銃撃を避けるつもりで動いてないところだよなと。完全に油断してるから、あり得る展開に見える。回想シーンの、銛がタタッとなるところも同じで。後は飛び込むだけだ、楽勝楽勝、とでも油断してるのだろうなと見ていて想像できるカットでタタッとなるから自然な展開に見える。

そういう例外処理(?)を盛り込んであるという点でもカリ城は名作ってことで。見るたびに「上手いよなあ」とため息が。

ナウシカのソレ。 :

クシャナが走っていく足元でバンバン着弾してるソレは、パッと見はギャグですわな。そのカットだけ見たら「あり得ねえよ!」「当たるだろソレ!」と思える。その直後、たしかクワトロも身を乗り出して、着弾で「あぶねっ」的な反応して、そのことでクシャナが無茶苦茶なことをしてると強調された、ような気がしたけど違いましたっけ覚えてねえや偽記憶かも。

ただ、あのシーンは…。そんな無茶なことをしてしまうぐらいにクシャナはナウシカがどうなったのかとにかく知りたくて知りたくてたまらないのだ、と観客が瞬時に察することへと繋がっていくわけで。クシャナのような人物ですら、思わずそんな行動を取ってしまうほどに、ナウシカという人物は周囲の者を引き付けてやまない力があるのだ、てなことも伝わってくる。たとえパッと見はギャグ一歩手前の表現であっても、前後にどういうカットが入るのか、キャラの心情がどうなのか、何を伝えようとしているのかで、それらの表現も全然アリになる。どんな表現も使い方次第なんだよねと、わずか数カットのあのシーンは見事に教えてくれている、ような気が。

何にせよナウシカも名作ってことで。見るたびに「上手いよなあ」とため息が。

*1: あのシーン、若干エウレカセブンの飛翔感・落下感を思い出しました。イイ感じだったなと…。「コイツラ何故にこんなことを」とは思いましたが、カッコよかったからオッケー。

#2 [anime][neta] 変身美少女ならぬ変形美少女ってどうだろう

夢の中で見たネタなんですけど、変身美少女ならぬ変形美少女というネタはどうだろうかと。

プリキュアシリーズはえてして途中でパワーアップアイテムの玩具をゲットするのがお約束になってますが「やったー! ホニャララミラーを手に入れたわ!」と喜んでたらどこからともなく「トランスフォーム!」という声が聞こえて例のビシュシュシュシュのSEが鳴ってアイテムが美少女に変形。「ハロー! 貴方達が新しいプリキュアねミラー? 私の名前はホニャララ・ミラー。これからよろしくミラー!」って。

ソレ、アキバレンジャーであったよな…。銃が美少女に変形するヤツ…。いや、逆か。アレは美少女が銃に変形と捉えるべきだろうか…。

トイストーリーみたいなソレでもイケそうな。夜になって子供さんが寝静まった頃、家中の玩具が「トランスフォーム!」「トランスフォーム!」ビシュシュシュシュ。伸びをしながら「うーん、今日も一日働いたー!」「レンジャーカイザーキング王ロボちゃん、お疲れさまー」みたいなってソレ変形する必要あるのかな。トイストーリーも変形玩具が登場して活躍してた印象があるけど、アレがもし全員美少女に変形したら没個性も甚だしいのでは。脚本が実につまらなくなりそうな。

別に玩具にこだわらなくてもいいよな。自動車が美少女に変形したり、自販機が美少女に変形したり、電車が美少女に変形したり…。

そんな需要、どこにあるのですか。一体何が嬉しいのか。

#3 [zatta] オスプレイのアレ

思考メモ。

日本国内でオスプレイが不時着・損壊事故を起こしたというニュースが流れていて、ちょっと気になっていたりして。や、兵器関係は全く詳しくないんでアレなんですけど。

ほとんど誰も言及してくれないみたいだから一応自分だけでもつぶやいておきたいのですけど、「基地に戻るか、不時着するか」で「不時着したほうがええのでは」と判断したパイロットさんに対して、それはグッジョブ、ナイス判断、と褒めておきたいよなと。 *1 基地に戻ろうとして途中で落ちてたらもっと大変なことになってたはずで。なので、せめてそのあたりだけは一番最初にチラリと褒めておかないといかんのではないかと思ったりして。最初から終わりまで反対反対とギャーギャー騒いでるだけでは日本人という民族の知性・知能を疑われてしまいそうで…。 *2

それはさておき。前々から「妙に事故多いね、この飛行機」と懸念されていたソレなので「ああ、やっぱり起きたのか」という印象だったりするのですが。

なんとなく、数日前に読んだ、太平洋戦争中の米軍の魚雷の話を連想してしまったりして。まあ、その話、どこまで本当の話か分からないところもありますけど、なんだかありそうな話だよな、てな感じの話で…。

_太平洋戦争の米潜魚雷が不具合だらけ?(前編):日本を苦しめた米潜水艦搭載のMk14魚雷のトラブル
_太平洋戦争の米潜魚雷が不具合だらけ?(後編):接触信管まで動かない!Mk14魚雷の最後のトラブル
_Mk14 (魚雷) - Wikipedia

現場からは「この魚雷、妙だぞ」「狙ってるのにちっとも当たらねえ」「当たっても爆発しねえ。不発になるぞ」と報告が上がってたのに、上の人達が「どうせお前らの使い方がおかしいんだろ」と現場のせいにして無視を決め込んで、結果随分と長い間さっぱり戦果が上がらなくて。おそらくは粘着質でKYな人がブチキレて何度も実験して何度もレポートを出して、それでようやく上のほうも重い腰を上げて調べてみたら「アレ? なんじゃこの糞設計は」と分かり始めて、そこから少しずつ状況が…みたいな話だそうですけど。

ひょっとして、オスプレイもそういう感じだったりするのかなと。現場からは「この機体、なんか妙だよ」という報告が上がってるのに、上のほうが各報告を軽視して、みたいな状態がずっと続いてたりするんじゃないのかと。

仮に万が一そういうところがあるとしたら…。日本は太平洋戦争の頃から全然進歩がねえなあ、などと絶望的な気分になる場面が結構あったりするのですけど、もしかすると日本だけじゃないかもなと。アメリカも太平洋戦争の頃からたいして進歩がない、そんな可能性があるのかもと。特にあの国は戦争で負けてないことになってるから。反省する機会がどこにも無かったからますます怪しい。

てな感じの妄想・邪推が、オスプレイ関係のニュースを眺めているうちに脳裏に浮かんでしまったのでした。もちろん、実際どうなのかは分からんのですが。

技術的な問題・原因は、諦めずに調べ続ければいつかは分かるし対策だって打てると信じたいのですけど。そのへんハッキリしないまま、なんとなくポツポツと事故が起き続けるというのは、たぶんどこかでそもそも調べようとすらしない誰かさんが居るんじゃないかとちょっと疑いたくもなるというか。原発もそうでしたけど、設計者、技術者、現場の意見を無視する人が上のほうに居るとどうしようもなくなるので。技術で解決できた話が解決できない状態のまま放置されて重大事故に繋がっていくので、そういう状況があるとしたらちと困るよなと。いやまあ、米軍がそういう状態かどうかは分かんないですけど。

アメリカは、日本なんかよりはるかに賢いし、歴史から学んで進歩もしてると思いたいのだけど。さて、どうなのかな…。

てな感じの視点で、オスプレイ関連はちょっと気になるなと。件の魚雷は最後にはちゃんと使えるものになったそうですが、オスプレイはどうなるのだろうと。

とか書いてしまった後で以下の記事を読んだのだけど。

_沖縄県で空中給油中のオスプレイにトラブル、名護市沿岸に不時着水 | スラド
_空中給油 - Wikipedia

空中給油自体が、特にプロペラ機のソレが「えっ…」って感じの光景だったのでまずそこからしてなんとかならんのですか他に名案は無いのですかとつい思ってしまいました。「そんなのあったらとっくの昔に実用化してるわ」って詳しい人達から怒られそうだけど。

てなことを思ってしまったのでメモ。思考メモです。
*1: いやまあ、それは方便なのでは、実際は違ってて、という見方もあるようだけど。
*2: まずは最初に乗組員の安否を尋ねたり、現場の判断を褒めたり感謝の言葉を述べて、その上で「ここから本題なんだが」と話をしていくものじゃないのかと。最初から「てめえ何やっとんじゃ」的にいきなり抗議を始めちゃったら、そりゃ相手も感情的になるわなと。あっちだって部下の命がかかってた話なわけだし。とか言うと「こっちだって市民・県民の命がかかっとるんじゃ」と言い出す人が出てくるだろうけど、そういう気持ちが分かってるなら相手の気持ちだって容易に想像できて交渉の場の振る舞い方も分かりそうなものなのに。親に向かってダダこねてるだけの子供じゃないんだから、どうすれば要求を通しやすくなるのか考えを巡らせて上手に振る舞ってほしいものだけど。

2016/12/16(金) [n年前の日記]

#1 [windows] LibreOfficeが落ちる原因を調べようとしたけれど

Windows10 x64 + LibreOffice 5.2.3.3 x86 が何かの拍子に落ちる・crashする原因を調べようとアレコレ試したけれど、相変わらず原因が分からず。「辞書」をインストールしなければ安定動作することは分かっているけど、以前は「辞書」をインストールしていても動いてたわけで…。

確実に落ちてしまう操作手順としては…。ツール → オプション → 言語設定 → 言語、のあたりをクリックすると落ちる。

試した内容は以下。 さて、何が原因なのやら。

Windows10のイベントビューアを眺めてたら、気になるログが。MSVCR120.dll のせいで soffice.bin がエラーを出してるような。もうちょっと調べてみないと…。

2016/12/17() [n年前の日記]

#1 [windows] LibreOfficeが落ちる問題

ここ数日調べてたけど、現状をまとめておこうかなと…。

症状としては、LibreOffice 5.2.3.3 x86(32bit) が Windows10 Pro x64(64bit)上で落ちる。落ちまくる。クラッシュする。

ファイル保存するだけでも落ちるし、LibreOffice Draw を起動しようとしただけでも落ちるけど、ツール → オプション → 言語設定 → 言語、のあたりをクリックするだけで確実に落ちる。

落ちる際は、いきなりフッとウインドウ全体が消えて落ちる。Windows10のイベントビューア/イベントログには何も記録が残らない。

環境は以下。

一応回避策は見つけてあって…。インストール時に「辞書」をインストールしないようにすると落ちなくなる。「辞書」が入ってなければ、オプション → 言語設定 → 言語、のあたりをクリックして表示することもできるようになる。この場合、拡張機能マネージャ上では「英語スペル辞書〜」がインストールされてない状態になる。

ただ、以前は辞書をインストールしてあっても動いてたので、どうしてこんなことになったのか…。気になる…。

少し気になるイベントログ。 :

フッと落ちる際にはイベントログが残らないけど、ツール → オプションを開いて閉じてしてからLibreOfficeを終了した場合、以下のイベントログが残ることに気づいた。
ログの名前:         Application
ソース:           Application Error
日付:            2016/12/17 14:39:49
イベント ID:       1000
タスクのカテゴリ:      (100)
レベル:           エラー
キーワード:         クラシック
ユーザー:          N/A
コンピューター:       dorobune
説明:
障害が発生しているアプリケーション名: soffice.bin、バージョン: 5.2.3.3、タイム スタンプ: 0x5813db9e
障害が発生しているモジュール名: MSVCR120.dll、バージョン: 12.0.40649.5、タイム スタンプ: 0x56bc018f
例外コード: 0xc0000409
障害オフセット: 0x000a7746
障害が発生しているプロセス ID: 0x2cfc
障害が発生しているアプリケーションの開始時刻: 0x01d25827f0a84b32
障害が発生しているアプリケーション パス: C:\Program Files (x86)\LibreOffice 5\program\soffice.bin
障害が発生しているモジュール パス: C:\WINDOWS\SYSTEM32\MSVCR120.dll
レポート ID: 579b43e2-1c1d-48bc-8f4d-6390bfa12bf1
障害が発生しているパッケージの完全な名前:
障害が発生しているパッケージに関連するアプリケーション ID:
イベント XML:
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
  <System>
    <Provider Name="Application Error" />
    <EventID Qualifiers="0">1000</EventID>
    <Level>2</Level>
    <Task>100</Task>
    <Keywords>0x80000000000000</Keywords>
    <TimeCreated SystemTime="2016-12-17T05:39:49.312644000Z" />
    <EventRecordID>15041</EventRecordID>
    <Channel>Application</Channel>
    <Computer>dorobune</Computer>
    <Security />
  </System>
  <EventData>
    <Data>soffice.bin</Data>
    <Data>5.2.3.3</Data>
    <Data>5813db9e</Data>
    <Data>MSVCR120.dll</Data>
    <Data>12.0.40649.5</Data>
    <Data>56bc018f</Data>
    <Data>c0000409</Data>
    <Data>000a7746</Data>
    <Data>2cfc</Data>
    <Data>01d25827f0a84b32</Data>
    <Data>C:\Program Files (x86)\LibreOffice 5\program\soffice.bin</Data>
    <Data>C:\WINDOWS\SYSTEM32\MSVCR120.dll</Data>
    <Data>579b43e2-1c1d-48bc-8f4d-6390bfa12bf1</Data>
    <Data>
    </Data>
    <Data>
    </Data>
  </EventData>
</Event>

C:\WINDOWS\SYSTEM32\MSVCR120.dll のせいで soffice.bin が異常動作してる、という内容だろうか。

msvcr120.dll は、Microsoft Visual Studio 2013 を使ってアプリを作った際、そのアプリの動作に必要な dll、ということらしい。

ちなみに、〜\SYSTEM32\ と表示されてはいるけれど、System Explorer で確認したところ実際に使われているのは 〜\SysWOW64\ 以下の MSVCR120.dll のようで。x86(32bit)版の LibreOffice を使ってるからそうなるのだろう。
  • msvcr120.dll のタイムスタンプは 2016/02/10、バージョンは 12.00.40649.5。
  • ちなみに、似たようなファイル名の msvcr120d.dll は、2013/10/04、12.00.21005.1。
  • msvcr120_clr0400.dll は、2016/07/16、12.00.52512.0。

すると、その MSVCR120.dll のせいで LibreOffice が落ちているのだろうか。…そういうわけでもなさそうで。

何故なら、LibreOfficeの「辞書」をアンインストールして安定動作してる状態で確認してみても、オプションを開いて閉じてLibreOfficeを終了するだけで、相変わらず同じようにエラーログが残るからで。以下はその時のログ。
ログの名前:         Application
ソース:           Application Error
日付:            2016/12/17 14:43:10
イベント ID:       1000
タスクのカテゴリ:      (100)
レベル:           エラー
キーワード:         クラシック
ユーザー:          N/A
コンピューター:       dorobune
説明:
障害が発生しているアプリケーション名: soffice.bin、バージョン: 5.2.3.3、タイム スタンプ: 0x5813db9e
障害が発生しているモジュール名: MSVCR120.dll、バージョン: 12.0.40649.5、タイム スタンプ: 0x56bc018f
例外コード: 0xc0000409
障害オフセット: 0x000a7746
障害が発生しているプロセス ID: 0x3110
障害が発生しているアプリケーションの開始時刻: 0x01d2582864ea8ae4
障害が発生しているアプリケーション パス: C:\Program Files (x86)\LibreOffice 5\program\soffice.bin
障害が発生しているモジュール パス: C:\WINDOWS\SYSTEM32\MSVCR120.dll
レポート ID: 66759229-9836-45a8-8483-4eec954ec355
障害が発生しているパッケージの完全な名前:
障害が発生しているパッケージに関連するアプリケーション ID:
イベント XML:
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
  <System>
    <Provider Name="Application Error" />
    <EventID Qualifiers="0">1000</EventID>
    <Level>2</Level>
    <Task>100</Task>
    <Keywords>0x80000000000000</Keywords>
    <TimeCreated SystemTime="2016-12-17T05:43:10.578963300Z" />
    <EventRecordID>15049</EventRecordID>
    <Channel>Application</Channel>
    <Computer>dorobune</Computer>
    <Security />
  </System>
  <EventData>
    <Data>soffice.bin</Data>
    <Data>5.2.3.3</Data>
    <Data>5813db9e</Data>
    <Data>MSVCR120.dll</Data>
    <Data>12.0.40649.5</Data>
    <Data>56bc018f</Data>
    <Data>c0000409</Data>
    <Data>000a7746</Data>
    <Data>3110</Data>
    <Data>01d2582864ea8ae4</Data>
    <Data>C:\Program Files (x86)\LibreOffice 5\program\soffice.bin</Data>
    <Data>C:\WINDOWS\SYSTEM32\MSVCR120.dll</Data>
    <Data>66759229-9836-45a8-8483-4eec954ec355</Data>
    <Data>
    </Data>
    <Data>
    </Data>
  </EventData>
</Event>

つまり LibreOffice が落ちる決定的な原因として MSVCR120.dll が絡んでるわけでもないらしい。

仮想PC上で試してみた。 :

仮想PC VMware Player 上で、Windows10 x64 評価版(バージョン1607。Windows 10 Anniversary Update適用済み)をインストールして、Windows Update を済ませた状態で LibreOffice 5.2.3.3 x86 をインストールして動作確認してみた。

この環境だと、「辞書」がインストールされていても落ちない。イベントログにエラーも残らない。

つまり、配布公開されてる LibreOffice が最初からおかしいわけではなくて、自分のメインPCが LibreOffice を動作させるにあたって何かおかしな状態になってることがハッキリしてきた。

メインPCは、
  • Visual Studio 等をやたらめったらインストールしてある状態。
  • Windows7からアップグレードした状態。
  • 英語圏の色んなソフトをインストールしちゃってる。
てな状態なので、その際に余計な dll 等が入っておかしくなってる可能性もありそうだなと…。しかし、だとしても何が絡んでいるのか…。調べる方法は無いのだろうか…。

VMware上の綺麗なWindows10の C:\Windows\SysWOW64\ の中を覗いてみた。以下のファイルがあった。
  • MSVCR120.dll。12.0.21005.1。タイムスタンプ 2016/10/29 02:12。
  • msvcr120_clr0400.dll。12.0.52512.0。タイムスタンプ 2016/07/16 20:44。
メインPC上のdllとは微妙にバージョンが違う。また、msvcr120d.dll も無い。

試しに、メインPC上の SysWOW64\msvcr120.dll をリネームして、VMware上のWindows10のmsvcr120.dll をメインPC上にコピーしてから LibreOffice の動作確認をしてみた。

症状変わらず。相変わらず落ちる。また、特定の操作をすることで、今まで同様に msvcr120.dll 絡みのエラーログも残った。

ということは、LibreOffice が落ちるのは msvcr120.dll が原因ではない、ということになるのだろうか…。

2016/12/18() [n年前の日記]

#1 [pc] モバイル用マウスはどこに消えた

階下のノートPC用に使っていたモバイル用マウス、 _ELECOM M-D13URRD の電源スイッチ部分がいつのまにか壊れていたようで。電源スイッチを切れないのではあっという間に電池が無くなってしまう。ていうか実際に電池が切れていた。

さすがに新しいマウスを買わないとダメかなと今時の製品をググってみたのだけど、現状を知って若干絶句。そもそも今時はモバイル用マウスを売ってないのですな…。モバイル用マウスはどこに消えた…。階下のノートPCを使うのは親父さんやお袋さんで、タッチパッドでの操作に慣れることも難しく、マウスが無いと満足に操作できないのだよな…。困った…。

いやまあ、見た目が明らかにマウスっぽい小型マウスは存在していて、ソレを「モバイルにも最適」と称して売ってるようではあるけれど。形状からして「ああコレは薄いですね」と明らかに思えてくるタイプの製品が今はどこにも無いようで。マウスって分厚いから持ち運びでちょっと困るわけで、となるとやっぱり薄いのが欲しいなと思うのだけど、何故に無いのだ…。昔はポツポツ作ってたのに…。

たしかに、形状があまりに特殊だとマウスを使うことで得られたはずの操作性・快適性が得られないし、今時のタッチパッドは2本指や3本指で操作したりもできるから下手するとマウスよりサクサク操作できる部分もあるし、持ち運びを最優先で考えたらタッチパッドで済ませるのがベストやんという話にもなるしで、「タッチパッドでええやん」と言われる場面も多いのだろうけど。

にしても、ここまで壊滅的にジャンルそのものが無くなってるのはどういうことだろうと。たかが(?)マウスとは言え、右向け右で皆が一方向にガーッと走っていくあたりにいかにもな日本人らしさが感じられてなんだかちょっと怖いなと。と言ってもあくまで商売だから売れそうにないと思ったら作らないし売れそうなら作るし実際今までそんなに売れてなかったから作らなくなった、程度の話なのだろうと想像もするのですが。

もしかすると、モバイル用途ならスマホでいいじゃん、ちと無理したとしてもタブレットPCでいいじゃん、であれば指でタッチして操作するんだからマウス要らないよね、というノリも関係してるのだろうか。

まあ、そのうち電器店を回って小型マウスの大きさを確認してこよう…。もしかすると意外と小さくて代替できるかもしれんし…。

2016/12/19(月) [n年前の日記]

#1 [windows] Visual C++のランタイムについて調べていたのだけど

よく分からん…。

Windows10 x64 の C*\Windows\SysWOW64\ 内にある MSVCR120.dll だののバージョン番号を調べていたのだけど、そのあたりを最新版もしくは特定のバージョンで上書きする方法はあるのだろうかと気になってググり始めたり。

メインPCは 12.0.40649.5 が入ってるのだけど、先日 VMware Player 上にインストールした Windows10評価版では、12.00.21005.1 が入ってたりするわけで。もしかして後者のバージョンにしておいたほうが不具合は起きないのだろうかと。それとも新しければ新しいほうがいいのか。

一般的にはおそらく以下を入れればいいのだろうけど。

_Visual Studio 2013 の Visual C++ 再頒布可能パッケージ - 窓の杜ライブラリ
_最新版は、Visual C++ のダウンロードをサポートします。
_Download Visual Studio 2013 の Visual C++ 再頒布可能パッケージ from Official Microsoft Download Center

しかしコレ、Windows10は対象になってないのだよな…。試しにインストールしてみたけど、コントールパネル → プログラムのアンインストール、の一覧上では、12.0.30501 と表示されてる。

ググってるうちに、以下も見つけたりして。

_2013 の Visual C++ および Visual C++ の再頒布可能パッケージ用の更新プログラム (12.0.40649.5)
_2013 の Visual C++ および Visual C++ の再頒布可能パッケージ用の更新プログラム (12.0.40660.0)

すると一番バージョンが新しいのは、現時点では 12.0.40660.0 ということになるのかなと。

ということで試しに 12.0.40660.0 をインストールしてみちゃったのだけど。これで問題は起きないのだろうか…。

Visual Studio 2013 の Visual C++ ランタイムだけではなく、2012のランタイムも気になる。

_山市良のえぬなんとかわーるど: 1/13 以降、Visual C++ 2012 Update 4 の更新 KB3119142 が繰り返される問題 (解決)
_KB3119142問題に終止符を打つ: 部屋とバナナと私
_Microsoft Visual C++ 2012 Update 4 の再配布可能パッケージ用の更新プログラム
_Download Visual Studio 2012 更新プログラム 4 の Visual C++ 再頒布可能パッケージ from Official Microsoft Download Center

これも試しに 11.0.61030 をインストールして変更→修復までやってみたのだけど。どうも SysWOW64 以下が更新されてる気配が無くて。Windows10は対象外だよということで処理されてないのだろうか。

そのへん色々試したけど、相変わらず LibreOffice 5.2.3.3 が、msvcr120.dll で障害が起きてる的なイベントログを残す。どうすりゃいいんだ…。

Visual Studio の一部をアンインストールした。 :

複数の Visual Studio をインストールしてあるのがいかんのだろうかと思えてきたので、Visual Studio Community 2013 with Update 5 をアンインストール。Visual Studio Community 2015 は入ってるから、使いたくなったらそっちを使えばいいだろうと。

2016/12/20(火) [n年前の日記]

#1 [windows][python] LibreOfficeが落ちる原因が分かった

Windows10 x64 + LibreOffice 5.2.3.3 を使ってる状況で、「辞書」をインストールすると LibreOffice がやたらめったら落ちる状態になってしまう原因が分かった。たぶん。

環境変数の中に、
PYTHONPATH=C:\Python\Python27\Lib\site-packages
という定義があると LibreOffice が落ちまくるようで。

正直、「そこかよ!?」って感じ…。

何が起きていたか。 :

ここから先は想像なので、間違ってるかもしれんけど。たぶんこういうことが起きてたのだと思う。たぶん。自信無いけど。

LibreOffice は、 _UNO(Universal Network Objects) という仕組みを用意することで、拡張機能等の追加ができるように作ってある。そして、「辞書」を用いるスペルチェック機能(拡張機能)も、UNOを使って提供されている。更に、このUNOとやらは、Java だの Python だの Tcl だのを使って実際の処理をしてるっぽい。

で。自分のメインPC上では Python 2.7.12 をインストールして色々アレコレ試してた関係で、何かの拍子に PYTHONPATH という環境変数を設定してしまっていた。

そして LibreOffice は、LibreOffice内に入ってるPythonを使ってUNO関係の何かしらの処理をしようとした際、PYTHONPATH という環境変数の存在をチェックして、もし存在するようならそっちにライブラリその他が入ってるものとして処理を進めようとしたのだろうと。しかしWindowsのシステム側で持ってるPythonインストールフォルダには LibreOffice 用のアレコレなんて入ってるわけがないから、結果、異常動作に繋がった。

ということじゃないのかなと。たぶん。自信無いけど。

PYTHONPATHはどう扱えばいいのか。 :

どうもよく分からないのだけど、結局のところ PYTHONPATH は指定したほうがいいのかどうか。ググってみても、一般的には指定する必要はないと解説してる記事もあれば、指定することでライブラリの在処が分かるようになってトラブルが解決したと解説してる記事もあって。

それとは別に。この場合、LibreOffice はバグを持っていたと捉えるべきなのか、それともこういう仕様なのだと捉えるべきなのか。どっちなんだろうなと。

OSにPythonをインストールしてあって PYTHONPATH まで指定しちゃってる場合、LibreOfficeの拡張機能は一切使えませんよ、そういう仕様ですよ、という扱いでいいのか。それともその場合 LibreOffice が持ってる Python 側で PYTHONPATH を無視、もしくは既存のPYTHONPATH に新たなパスを追加して動作するように対策しておくのが正解なのか。

自分のレベルでは、何が正解なのか判断できないなと。

まとめ。 :

何にせよ現状では、OSにPythonをインストールしてあって、かつ、LibreOffice を使う場合、もしかするとLibreOffice の拡張機能の類が動かないかもしれないので注意しようね、という話になるのだろう…。

しかし変だな…。HDD内の記録を探したら、少なくとも去年の中頃には PYTHONPATH を指定してたみたいなんだけど。今までずっと LibreOffice は動いてたんだけどな…。どの時期から、こんなことに…。

でもまあ、どこが原因で落ちていたのか分かったので、これでようやくスッキリした。まさかそんなところに原因があったとは…。

2016/12/21(水) [n年前の日記]

#1 [nitijyou] 自転車で買い物に

ケーズデンキに寄って、マウスを購入。 _ELECOM M-DY10DRPN 。ワイヤレスマウス。Sサイズ。税込で1,080円ぐらい、だったような。階下のお袋さん用ノートPCで使うマウスなので可愛らしいほうがいいだろうと顔が印刷されてる製品を選択。というかお袋さんは職場でサイズ違いの同シリーズのマウスを使ってるそうなので。

店頭で色々眺めてみたけど、小さいマウスはどれも厚みが似たような感じで。やっぱり選択肢はほとんどないなと…。

その後、ダイソーやリオンドールに寄って、犬用のおやつ、自分の夜食等を購入。

マウスの動作確認。 :

親父さんに頼んで動作確認してもらったけどフツーに動いたっぽい。初期不良品を掴んでなかったようで一安心。

2016/12/22(木) [n年前の日記]

#1 [ruby][dxruby] 疑似3Dの初歩の基礎を(Ruby+DXRubyを使いつつ)書いてみる

_Ruby Game Developing Advent Calendar 2016 の12/19が空欄だったので、「何も入ってないよりは何か入ってたほうがええんじゃないか…」的に、この記事を登録してみました。「Rubyでゲーム制作」というテーマから全然ずれてる内容だよなと思わないでもないですが、DXRubyを使って実験してるし…いいよね? ダメ? Advent Calendar って後からこうしてアップ・登録してもいいのかどうかも分かりませんが…。

さておき。なんとなく、2Dゲームにおける疑似3Dの初歩というか基礎をメモしておこうかなと思い立ったりして。

いやまあ、「あらゆるゲームが3DCGで描画されてるこの御時勢にwww疑似3Dってwwwちょおまwww」と笑われそうな気もしますが。なんかその手の記事をぼんやり眺めてたら、式を求めるあたりで「三角形の相似」の一言で終わらせてる事例が結構あって。「説明がちょっと足りてないんじゃ」「図解しとけばすぐ分かるのに」と思えてきたので、せめてそこだけでもメモしておこうかなと。

疑似3Dと言っても、一般的には…。内部では x,y,z の3次元座標で管理していて、描画に使える何かしらが当時はスプライトかBGしかなかったからスプライト or BGで描画、みたいなことをやってたんだろうと思うわけですよ。もっとも中にはコレ全然3D計算してないだろうなって思えるアレなタイトルもありますが…。それっぽく見えてたタイトルは、内部では3次元座標で管理して、ということを多少はしてただろうと。

で、3次元空間に点があるとして、その点は画面上のどのへんに描かれるのか、ソレさえ分かれば疑似3Dはできるのですが。ソレを求める処理というか、図法のことを、 _透視投影 と呼ぶわけで。

まあ、近くのモノも遠くのモノも同じ大きさに見える _平行投影 てのもあるし、平行投影を使ってるゲームタイトルもありますが、ソレは奥行き情報であるz座標値を無視して描画すれば済んじゃうから横に置いとくとして。

透視投影をしたいなー、と思った時、実際どういう計算式になるかは、下の図を見てもらえば分かるかなと。ちなみに、画像をクリックすれば原寸大で見れます。

fake3d.png

分かりやすくするために、見ている人の目の位置を原点(0,0,0)として考えてます。また、この図では画面上のy座標しか求めてませんが、x座標も同じように考えて式を求めることができます。

ということで結局は、巷の解説記事でフツーに見かける…
画面上のx座標 sx = 画面までの距離 sz * 点のx座標 px / 点のz座標 pz
画面上のy座標 sy = 画面までの距離 sz * 点のy座標 py / 点のz座標 pz
この式になるわけですね。

実践その1。 :

本当にこの式でそれらしくなるのか、実際に試してみましょう。Ruby + DXRuby でサンプルを書いてみましたよ。

_fake3d_a.rb
require "dxruby"

img = Image.load("tmp_dot.png")

# 点の座標群を作成
py = 600.0
scale = 200.0
pos = []
10.times do |z|
  10.times do |x|
    pos.push([x * scale, py, z * scale])
    pos.push([x * -scale, py, z * scale])
  end
end

# 画面までの距離
sz = 75

Window.loop do
  break if Input.keyPush?(K_ESCAPE)

  # ウインドウの中心位置を取得
  cw = Window.width / 2
  ch = Window.height / 2

  # 画像横幅、縦幅を取得
  iw = img.width
  ih = img.height

  # マウス座標を点群の移動量にする
  mx = (Input.mousePosX - cw) * 5
  my = (Input.mousePosY - ch) * 5

  # 点の座標を透視投影で求めて描画
  pos.each do |px, py, pz|
    px += mx
    pz += my
    if pz > 0
      sx = sz * px / pz
      sy = sz * py / pz
      x = sx - iw / 2 + cw
      y = sy - ih / 2 + ch
      Window.draw(x, y, img, -pz.to_i)
    end
  end
end

画像は _tmp_dot.png を使ってください。

ruby fake3d_a.rb で実行したら、こういう結果になりました。



一見それらしく見えてますね。座標の変換は上手く行ってるみたい。

ただ、ちょっと問題が。

実践その2。 :

前述のスクリプトでは、各スプライト相当がどれも同じ大きさなので、なんだか不自然ですな。描画サイズも、z座標に応じて変化させてみませう。

_fake3d_b.rb
require "dxruby"

img = Image.load("tmp_dot.png")

# 点の座標群を作成
py = 600.0
scale = 200.0
pos = []
10.times do |z|
  10.times do |x|
    pos.push([x * scale, py, z * scale])
    pos.push([x * -scale, py, z * scale])
  end
end

# 画面までの距離
sz = 75

Window.loop do
  break if Input.keyPush?(K_ESCAPE)

  # ウインドウの中心位置を取得
  cw = Window.width / 2
  ch = Window.height / 2

  # 画像横幅、縦幅を取得
  iw = img.width
  ih = img.height

  # マウス座標を点群の移動量にする
  mx = (Input.mousePosX - cw) * 5
  my = (Input.mousePosY - ch) * 5

  # 点の座標を透視投影で求めて描画
  pos.each do |px, py, pz|
    px += mx
    pz += my
    if pz > 0
      ssz = sz / pz
      sx = px * ssz
      sy = py * ssz
      scale = 5.0 * ssz
      x = sx + cw - iw / 2
      y = sy + ch - ih / 2
      Window.drawEx( x, y, img,
                    :scalex => scale, :scaley => scale,
                    :center_x => iw / 2, :center_y => ih / 2,
                    :z => -pz.to_i)
    end
  end
end

ruby fake3d_b.rb で実行してみると…。



これならイイ感じじゃないですかね。

その他色々。 :

たったこれだけのことが分かってるだけでも、色々な見せ方ができます。

_mieki256's diary - DXRubyで通路の奥に進むようなソレ
passageway_ss.gif

_mieki256's diary - DXRubyで円柱っぽいBG描画をしてみたり
pipe_bg_ss_2.gif

_mieki256's diary - DXRuby+Shaderで床ラスタースクロールっぽいことができたような気がする
床ラスタースクロール

_mieki256's diary - 床ラスター処理をもうちょっと修正
壁として描画
壁として描画その2
壁として描画その3

それぞれの処理を書く際に使った知識(?)は、基本的には一番最初に乗せた図のソレだけです。ソレの応用で全部やってます。

fake3d.png

ということで、スプライトとBG描画しかできない2Dゲームライブラリでも、基礎というか初歩というかそのへん分かってるだけでも、こういうことができますよ、てな話でした。

OpenGL使ったほうが早いんじゃないかという気もする。 :

DXRubyというライブラリは2Dゲーム用のライブラリなんで、ちょっと変わった見た目にしたいなと思ったら、昔の2Dゲームで活用してたこういうソレを使うことになったりするんですけど。

これが、Ruby + gosu だったら、そのものズバリの、opengl というライブラリを追加して使えるようでして。

_gosu-examples というサンプル群の中に、 _opengl_integration.rb というサンプルがあるんですよ。以下に動作画面のキャプチャを貼ってみますが。



ちょっと分かりづらいけど、背景が3Dで描画されてますよね。

なので、「手前のオブジェクト群は分かりやすい2Dゲームのノリで」「でも背景だけは今風っぽく3Dで」てな希望がある時は、Ruby + gosu + opengl で作ってみるのも手かもしれないな、とも思ったりしました。

まあ、最初から3D描画をガシガシ使いたいならUnityあたりを選ぶのが妥当かも、とも思うんですけど。

2016/12/23(金) [n年前の日記]

#1 [anime] 「終末のイゼッタ」最終回を視聴

BS11で放送されてたオリジナルTVアニメ、「終末のイゼッタ」最終回を視聴。

面白かった…。実に面白かった。このアニメは、良い。素晴らしい。

内容というか基本設定としては…。第二次世界大戦当時の欧州、“っぽい感じ”の世界を舞台にしてる作品で。ドイツに相当する軍事大国が近隣諸国を次々に侵略していく中、侵略される側になった小国のお姫様が、伝説・おとぎ話の存在とされていたとある人物と出会い…みたいな話で。

監督は、 _藤森雅也 氏。Wikipediaの情報では、アクションが得意なアニメーター・監督さんのようで。

自分、恥ずかしながら「忍たま乱太郎」「ドラえもん劇場版」はほとんど見てないので、それら作品内での活躍は知らないのですが。この監督さんが作った「おまえうまそうだな」という映画は見たことがあって。「このキャラデザで、よくまあこんな動きをさせられるな…とんでもねえなあ…」とめちゃくちゃ感動したことを覚えていたり。なので、この「イゼッタ」のアクションシーンを目にして「ああ、この監督ならここまでやれるわなあ…」と納得してしまいました。

今になって考えると「おまえうまそうだな」のアクションシーンは、「カリ城」のアクションシーンを見た時と似たような感覚があった気もするなと。大塚ルパン・宮崎ルパンって見た目はちょっと可愛らしく見えるけど、動き始めると「スゲー」「カッケー」と思えてくるわけで。あの感じに近いというか。

で、「おまえ〜」が「カリ城」ポジションなら、もしかすると「イゼッタ」は、これは「ナウシカ」に相当する作品になるのかもなと。

プロペラ軍用機と並んで○○する、赤髪の白い○○。そのビジュアルイメージからしてグッとくるわけですけど。第二次世界大戦当時の暗い雰囲気が全編通して漂っていて、未来だの希望だのがあるのかないのかよー分からん状況の中で、もがいていく登場人物達。なんだけど、アクションシーンになると見ていて「うおおお…」「おいおいおいおい…」って気分になってくる。…雰囲気として「ナウシカ」に近いよなと。何より、オリジナルアニメだし。

平成の時代に、しかもTVアニメという形で、「ナウシカ」相当の作品が誕生する瞬間に立ち会えた・目撃できたというのは、これは一視聴者として幸運なことだよなと思えてきたりもして。 *1 スタッフさん、ありがとう。面白かったです。素晴らしい。

ということで、コレは見れるなら見ておいたほうがいいアニメじゃないか、と思えました。特にアクションシーン。 _外人4コマ のテンション上がっちゃってるコマみたいな気分になれます。
*1: いやまあ、「ナウシカ」級の作品というわけではなくて、この監督の作品の中でコレは「ナウシカ」ポジションになるかもなあ、ぐらいの話なのでアレですけど。

#2 [anime] 「ベイマックス」を視聴

TVで放映されてたので見てみたり。初見。内容は…説明しなくてもいいよな…。

なんというか…これもう何もかもが完璧やん。参っちゃうな…。

リターンが大きいと、ここまで作り込み・練り直しができるんだなと。それはつまりあらゆる手法が凝縮されてるわけで、この映画を分析していくだけでも色んな手管が学べそうな気もしてきたり。

2016/12/24() [n年前の日記]

#1 [linux] PIXELを試用

_Raspberry Pi という、手の平サイズの小さなPCがあるんですけど。「子供さん向けの教育用PCとしてこういうのがあったらよくね?」的に作られたらしいですが。

その Raspberry Pi 上で動いてた PIXEL というOSだかデスクトップ環境だかがPC上でも動くようになったよ、というニュースを見かけて。

_Raspberry Piの「PIXEL」が旧型PCやMacで稼働可能に - ITmedia ニュース
_PIXEL for PC and Mac - Raspberry Pi

「512MBのメモリがあれば動くから古いPCも再利用できるぜ」
「DVDやUSBメモリから起動できるのであちこち持ち歩いて使えるぜ」
「Raspberry Piと同じOSだから操作に戸惑わないぜ」
てなあたりが売り、なのかな。たぶん。

興味が湧いたので、仮想PC VMware Player 上で動かしてみたりして。仮想PCのCD/DVDドライブにPIXELのDVDのisoを指定して起動テスト。

pixel_on_vmware_ss01.png


フツーに動きました。

ちなみに、VMware Player上で仮想PCを新規作成する際、「何のOSを入れたいんや?」と尋ねてくるけど、ちとそこで悩んだり。WindowsとかLinuxとか色々選べるみたいですが、どれを選べばいいんだろうと。

PIXELというOSは Debian Linux にガワをプラスしたもの、らしくて。そして Debian としては Debian Jessie と呼ばれる版を使ってる模様。じゃあ、その Debian Jassie って何なのよとググってみたら…。 _Debian - Wikipedia によると Debain 8.0 っぽい。そして「PIXELというOSができたよ。x86版だよ」という話だから、64bit版じゃなくて32bit版ですわな。

てことは、VMware Player 上では「Linux」「Debian 8.x」を選べばいいのかなと。「Debian 8.x」と「Debian 8.x (x64)」があるのでちょっと注意。後者は64bit版なので。

カーネルバージョンを確認。 :

uname -a と打ってみたり。
Linux raspberrypi 3.16.0-4-686-pae #1 SMP Debian 3.16.36-1+deb9u2 (2016-10-19) i686 GNU/Linux
Kernelバージョンは 3.16、ってことでいいのかな。

HDDへのインストール。 :

DVDから起動できることは分かったのでHDDにインストールしてみたいなと思ったけど、そのへんどうすればいいのやら。

_公開ページのコメント欄 でそれらしい情報が。起動できるUSBメモリと、HDDを用意して、dd を使ってイメージをコピー、でいいのだろうか。でも、「そのやり方ではよろしくない」的なレスもついてるような…。

DVDのisoから起動してddでDVDの内容を仮想HDD(?)にコピーしてみたけれど、そのやり方ではHDDから起動せず。

であればと、 _Etcher なるツールを利用して起動できるUSBメモリを作成して、そちらの内容をHDDにコピーしてみたところ、この場合はHDDから起動してくれたようで。ちなみに使ったUSBメモリは2GB。HDDイメージの容量は16GBで設定。

件の記事では、再起動後にHDDから起動することを確認後、fdisk を使って2番目のパーティションを消して、またパーティションを作り直して、再起動後に resize2fs でサイズ調整してるようで、一応ソレも試してみたり。この状態なら設定等を変更しても次回起動時に変更が反映されていた。おそらくUSBメモリ起動時と同様に、2番目のパーティションに変更点を記憶してるのではないかなと。

解像度の変更方法が分からず。 :

VMware Player上でPIXELを動かすと、800x600の解像度になってしまう。ちと狭い。変更する方法はあるのかな…。

ちなみに xdpyinfo で現在の解像度等を調べることができる模様。 _電脳な日々: Linux で画面サイズ(解像度)を取得する が参考になりました。ありがたや。

試しに open-vm-tools と open-vm-tools-desktop をインストールしたら VMware Player のウインドウをリサイズして解像度変更ができるように。

_PIXEL for PC and Mac - Raspberry Pi のコメント欄で、xrandr とやらを使って解像度を変更する例が紹介されてることに気づいたり。
sudo xrandr --output Virtual1 --mode 1024x768
上記のように打ってみたら解像度が変更できた。更に arandr なるツールをインストールしたらGUIでも解像度を変更できた。が、次回起動時にはまた元に戻ってしまって。さて、どうしたら…。

これが Raspberry Piだったら /boot/config.txt を書き換えて設定したりできるらしいので、もしかするとこの場合もそのあたりを修正すればどうにかなるのだろうか。どうなんだろう。

ググってみたら ~/.xprofile だの ~/.xsessionrc に xrandr の指定を書いてしまう方法もあるようで。そっちのほうがいいのかな。

2016/12/25() [n年前の日記]

#1 [anime] 「亜人」最終回を視聴

BSで放送されてたアニメ、「亜人」の最終回を視聴。セルルックの3DCGアニメ。

面白かった…。これは面白い…。

脚本面や演出面がとにかく優秀だったのだろうな、という印象。このアニメを作ってるポリピク(ポリゴン・ピクチュアズ)というスタジオは、「ウチは工場になることを目指す」と言ってるぐらいに制作効率を追求してるスタジオらしくて、その代わり映像面は、他のスタジオ ―― サンジゲンやオレンジ等に比べるとこれといって特筆すべき点が無さそうな印象もあるのだけど。しかしそんな映像でも見ていてグイグイ引き込まれてしまったので、これはもう脚本が、というかおそらく原作からしてかなりグッドだったりするのだろうなと。ピクサーやディズニーも言ってるけど、娯楽映像商品はやっぱり脚本が一番大事、ってことを再認識させていただきました。

もっとも、映像面は〜などと書いてしまったけれど、個人的には、このくらい作れたらもう十分じゃないか、これで全然オッケーでしょう、という印象も持っていたりして。同スタジオ作品の「シドニアの騎士」「山賊のむすめローニャ」を見た時も思ったけれど、日本国内の一般的なアニメだったら全部こういう感じの3DCG映像でいいよなと。作画に相当している部分がとにかく安定した状態で提供できるわけで、このメリットは大きいはずだと。それでいて、パーティクル表現を活用したり、テクスチャを上手いこと使って不気味さを表現したクリーチャーを見せてみたり等、手描きだったら地獄を見るであろう映像もしっかりと提示できてるし。

どう考えても日本のアニメは、ポリピクをお手本にしてそっちに舵を切ったほうがいいだろうと思うわけですよ。「亜人」を見ろよ。面白いだろ。つまり3DCGでも全然イケるんだって。なんでかんで必ず手描きで作らなきゃいけないってことはないんだって。

だってさ…。 _手描きアニメで家紋の線を一本省略しただけで叩かれる んやで。こんな状況じゃもう手描きでなんか作ってられないっしょ。それでなくても本数が爆発的に増えて大変なことになってるのに、このままだとアニメーター殺されるわ。家紋なんてテクスチャをペタッと貼れば済むやん。つまり最初から3DCGで作ってれば叩かれずに済むやん。手描きのありがたみや恐ろしさがさっぱり分かってない連中になんでわざわざ手描きアニメ見せてしかもボコボコに叩かれなきゃいかんのや。お前らマゾか。さっさと全部3DCGアニメになっちまえ。

とまあ、そんなアレなことまでついつい思ってしまうぐらいに、「亜人」、面白かったです。と、感想をメモ。

2016/12/26(月) [n年前の日記]

#1 [anime][neta] 女性向けアニメのカット数ってもっと減らせないのかな

バカ妄想です。

何かの作業をしながら男性アイドルキャラが踊りまくる系の女性向けアニメをBGVで流してチラ見することがあるのですけど。ふと、なんとなく。

女性向けアニメって、もっとカット数を大胆に減らせないのかなと。例えば今の半分ぐらいに…。

カット数をドカッと減らす代わりに、各カットをアニメ雑誌に印刷されてる版権イラスト並みの仕上りにしたほうが女性アニメファンは喜んだりしないだろうかと。いやまあ、それじゃますます作るのが大変になるよ、元が取れねえよと怒られてしまうかもしれないけど。

おそらくだけど、映像のテンポというか、リズミカルなカット切替なんて、女性アニメファンはちっとも望んでないんじゃないか。まずはとにかく一切崩れてなくてモビルスーツ以上にやたらめったら線が多い端正なイケメンキャラの止め絵がバーンと画面にアップで映ることを期待してたりするんじゃないかと。極端な話、アニメタッチ風美麗カラーイラストがオマケでたくさんついてるドラマCD、みたいな商品を求められてたりしないか、などと邪推したりもするわけで。

てなことを思ったけれど、カット数を減らすのは無理なんじゃないかと思えてきたり。

会話シーンが癌になりそう。 :

カット数を減らすと、そもそも会話シーンが成立しないのではあるまいか。

と言うのも、例えば韓国ドラマを眺めていても感じるのだけど…。どうも女性向けの映像作品って、イケメンキャラが台詞を喋ってる時はそのイケメンキャラの顔が必ずアップになること、みたいな不文律があるよなと。

例えば、A,B,Cの3人のキャラが会話してたら、Aが喋るとAのアップ、Bが喋るとBのアップ、Cが喋れば…というカット割りにしないといけない。こんな制約があるのでは、カット数を減らしようがない…。

バンクを活用できないか。 :

いや待て。それならそれで手があるのでは。いわゆる _バンク を活用できないか。

コンテ段階で1カット分を描いたら、その1カットは最低限もう1回はどこかで使い回すこと、できれば3〜4回は使い回すこと、みたいな制約を与えてコンテを描いてもらうのはどうか。TVアニメは1話あたり平均300カットと言われてるけど、この制約を守れば単純計算で150カット分作画すれば1本作れるはず。もちろん、あくまで原画・動画レベルで使い回しを意識してくれ、という話で、背景を別にしたり、撮影段階で極端なエフェクトかけて、パッと見は違うカットにしていくのは全然アリ、ということでなんとかならんかと。

「そんな制約出されたらコンテなんて描けねえよ」と怒られるだろうか。でも、宮崎駿監督だって「ナウシカ」で王蟲の大群のカットをガンガン使い回してるし、庵野監督だってTV版EVAで零号機の暴走カットの作画を使い回したりしているし。宮崎駿監督や庵野監督だってやってみせているのに、君はできないと言うのか。「フッ。あの二人よりもっと鮮やかな手管を見せつけてやるぜ!」と吠えてみせる猛者は居ないのかと。

と言っても、おそらくそんなコンテを描こうとしたら悩む時間がより増えて上がりが遅くなって、制作進行さんから文句言われたり、監督から嫌味言われたり、Pから「アイツ使えねえな。とにかく仕事が遅過ぎる」と悪評を立てられちゃうよな…。となると、「ああ、分かったよ! とにかく早く上げればいいんだろ!」的にヤケクソ気味で描き飛ばす展開に。しかしそんなコンテでは、カット数が節約できてなかったり、カット制作の難易度について無頓着だったりで、後工程が地獄を見る…。

昔は、スケジュールを節約するためにコンテ段階で知恵を絞ってたけど、今はもうそんな余裕すら無くて、ますます全工程の負荷が増える流れになって、スケジュールがますます苦しくなって…。そんな悪循環があったりするのかなと。

なんでもそうだけど、評価システムがそもそも狂ってると全てが確実に狂っていく。「あの人、コンテ上げるの遅いけど、その代わり実質的なカット数めちゃくちゃ減らしてくれるから後工程がスゲー助かるんだよなあ」ぐらいの評価を下してくれる人が居れば…。などと妄想を。

構図で工夫できないか。 :

そのキャラが喋ってる時は、そのキャラの顔をアップにしないといけない、という制約があったとして。構図を工夫することでカット数を減らせないか…。

例えば、Aのイケメンキャラの肩のあたりに、Bのイケメンキャラがコテンと頭を預けていたら、AとBの顔のアップさえ描いとけばA・Bが会話をしていてもカット切替しなくて済むなと。やった。これでカット数を減らせる。しかも「キャー。○○くんの仕草、カワイイー」と女性ファンも喜んでくれそうな。

アレ? そういえば女性向けアニメって、妙にそういう不自然な構図が多いような気が…。そうか、なるほど、既に各スタッフはそういう工夫を盛り込んで作っていたのですな。今頃気づきましたスミマセン。なかなかやりますなあ。

もしかすると、その手の制約 ―― とにかくカット数を少なくしろ、という制約は、マイナス方向にばかり働くとは限らないかもなと。制約をクリアするために様々な構図・表現を無理矢理捻り出していくことで、そのジャンル独特の映像表現を身に着けていく、特異性を入手できる、そんな可能性があったりしないか。江戸時代に「歌舞伎に女を出すな!」とお上が制限を出してきたことで、歌舞伎の女形という表現が生まれたように…。

もっとも、スケジュールが無ければそれら工夫を考えてる時間的余裕も無いわけで。現状では何もかもが絵に描いた餅、なのだろうな…。

カット数を減らす以前に、そもそも本数、減らせないのかな…。

まあ、どれもこれも所詮はバカ妄想です。

2016/12/27(火) [n年前の日記]

#1 [nitijyou] 悪夢を見た

ちょっと嫌な夢を見た。PCにマルウェアが入って駆除する夢。目が覚めてからグッタリ。どうして夢の中でまで、PCのメンテナンスをせにゃあかんのや…。

2016/12/28(水) [n年前の日記]

#1 [nitijyou] 今日も悪夢を見た

幽霊っぽい何かが出てくる夢を見て、目が覚めてからグッタリ。二日続けて悪夢を見るというのは…これは何だろう…。

2016/12/29(木) [n年前の日記]

#1 [nitijyou] この日は何をしてたのだったか

忘れた…。たぶんWebサイトを見て時間を浪費してただけ、だったのでは…。

2016/12/30(金) [n年前の日記]

#1 [nitijyou] 自転車で買い物に

近所のヨークベニマルとサンドラッグまで。飲み物系を購入。

強い風と、大きめの雪がチラチラと。空は晴れてるのだけど…。

2016/12/31() [n年前の日記]

#1 [anime] 「Occultic;Nine」最終回を視聴

BS11で放送されてた「Occultic;Nine」なるアニメの最終回を視聴。内容は…オカルトアニメ? ミステリーアニメ? なのかな。どうなんだろう。

さておき。面白かった…。最終回は怒涛の展開というか。「Nine」ってそこにもかけてあったのか。やられた。うむ。これは面白い。面白いと思います。

登場人物の喋りがとにかく速いので最初は面食らうかもしれないけど、その分密度が濃い目なので、数話見てるうちに慣れてきてそこからは面白く感じるんじゃないかなと。これは早見再生できないアニメだな、標準速でちょうどいい、などと思いながら視聴してました。

一応話が終わったように見えつつも、あちこちの謎は説明されておらず、何より主人公についてのアレコレがソレだったりするわけで。放送直後に「ゲーム版を出す予定だよ!」とCMが流れていたので、おそらくゲーム版を買えば謎は解けるし、主人公のアレコレも判明するんだろうと。

しばらく前にBS11で、再放送(?)の形で流れてた「STEINS;GATE」がまさにそういう形で。「どうしてこうなったかは続編ゲームを買えば分かるよ!」というラストになってたけど。そちらは最初の放送時にトゥルーエンド相当を流してしまっていたらしいので、自分のような初見組はガックリきてしまって。しかも再放送版のラストが、「えー。そのラストは…どうなの…」てなラストで。

しかし今回は、最初に放送されたアニメ版からして「今回はここまで」になってるから不公平感は無いし、なるほどそういうラストもアリだよな、でもトゥルーエンドがありそうだな、てなラストだったのでOKではないかと思えたり。手口(?)というか構成として上手くなってる、ような気が。

「なんだよ所詮販促アニメかよ」「『あのね』商法かよ」と思ってしまうような内容・ラストではない印象も受けたし、「ここまででも十分面白い」と思うも良し、「続きが気になる。ゲーム版を買おう」と思うも良し。バランスが取れてるというか、これなら良い塩梅じゃないのかなと。

#2 [anime] 「劇場版ウルトラマンX」を視聴

TVで流れてたので見てみたり。

ググってみたら、TV版の最終回から半年後の設定、らしい。冒頭でTV版のダイジェストを見せているので、TV版を未見の人でも楽しめる作りになっていた気がする。

TV版もそういう設定だったけど、科特隊員達とスマホ(?)を通じて会話するウルトラマン…。いいな。これはアリだなあ。ウルトラマンは地球人の味方、てなイメージがどうせもうすっかり定着しちゃってるので、だったらいつでもフツーに会話させたほうが面白くなるよなと。

逆に、何を考えてるのか分からないウルトラマン、というのもアリなのかも。そもそも宇宙人だし。地球人とは異なる思考ロジックを持ってるほうがリアルさを醸し出せそう。でもまあ、ソレをウルトラマンでやる必要は無いか…。でもないか。平成ライダーと同じで、「ウルトラマンでソレをやるの?」と思われたほうが驚きがあるのかもしれない。と思ったけどそんな異質なウルトラマンでは今まで登場したウルトラマンと共闘させたりできなくなるか…。

と思ったけど、この映画もちょっとノリが違うウルトラマンがワラワラと出てきてバタバタと戦っていて。このあたり、意外とどうとでもなるもんだなと…。

さておき、特撮シーンは結構頑張ってる印象で。劇場版は予算が多いのだろうか…。

全体的には、フツーに面白かった、かなと。ああ、ウルトラマンだね、ウルトラマンXってこんなノリだった、みたいな。とんでもなく面白いわけでもないけれど、親御さんと子供さんが一緒に見てたらフツーに楽しめそうな感じの作品というか。悪くないのではないかと。

ただ、個人的にはもうちょっと笑いがあったほうが、とも思ったり。劇場で子供さんがドッと笑うイメージは湧かなくて。もっとも実際にはウケてたりしたのだろうか。どうなんだろう。

「おそ松さん」のように放送作家さんの力を借りる、みたいなことは難しいのかなあ…。

#3 [anime] 女性向けアニメは見なくていい (※ おじさんは)

思考メモ。

今まで、「女性向けアニメにも名作があったりするんじゃなかろうか」「もし見逃してしまったらもったいない」とある種の期待を寄せて、一応はTV放送されてる女性向けアニメのアレコレを眺めていたのだけど。

某アニメの実写特番を眺めて、「プロジェクト内容についての説明が全然足りてねえ…」「いきなり、『皆さん御存知の通り』と言われてもこっちは知らねえよ…説明を省くなよ…」等の不満を感じているうちに、遅まきながら今頃になって「あー、そうか」と気がついて。ようやく何か悟ったような気分になってきたり。いやまあ、「見る前に気づけよ」ぐらいのたわいない話なんだけど。

女性向けアニメは最初から見なくていいのだなと。切っていい。 *1 見る価値無し。 *2 断言してもいい。名作なんて無い。 *3

と言うのも。

どの女性向けアニメも、漫画原作を読んでファンになってる人、原作ゲームをプレイしてファンになってる人、そういう層を対象にして作られているので、アニメを通じて初めてそのタイトルに触れた人に対する気配りがほとんどないわけで。「せめてこの設定は踏まえておいて」とか、「演じてる中の人達はこういう人達ですよ。今後ともよろしく」とか、「こういう内容のプロジェクトなんですよ」とか、視聴するにあたって必要になりそうな前知識の説明すらまずしてくれない。アニメを使って新規層を呼び込むことを最初から想定していない、というか諦めてる気配があって。

一見さんお断り。それが女性向けアニメなのだなと。色々眺めてみたけれど、どうやらそういうジャンルらしいと。

もちろん、新規層の確保を綺麗サッパリ諦めた分、元からファンだった人達が喜びそうな内容で満ち溢れていて。だからそのやり方で全然問題無いというか、むしろそういう作りこそが正解とすら思えるわけで。金を落としてくれるかどうかわからない新規層より、絶対に金を落としくれるファン層を狙い撃ちする。そんなの当たり前のことだし。

でも、それもそれでなんだか寂しい(?)というか…。もうちょっと工夫すれば新規層も取り込めそうなアニメになるんじゃないのか、そのほうがリターンは増えないかとも思ってしまうわけで。こんなに線が多い作画をしてるということは、作るのは間違いなく大変だろうに、わざわざ自分達からパイを限定してしまう方向で舵を切ってもいいのだろうか、みたいな。

とは言え…。あらゆる層を意識して作ってみたら誰が見ても中途半端な出来になってさっぱり売れませんでした、てな展開はありがちだし。世の中には「二兎を追う者は一兎をも得ず」という言葉もあるわけで。それよりも一点集中的に狙いを定めて特定層にだけは百発百中でガツンとウケる出来にしたほうが全然マシだよなとも思えるわけで。

このあたり、女性向けアニメに限った話ではなく。例えば、1stから続くガンダムシリーズは男性向けアニメに分類されるだろうけど、アレだってもはや途中参加なんてほとんど不可能だろうと。ガンダムUCなんてあんなに線が多いのに、新規層の取り込みなんておそらく少しも意識してない。うたプリを見てる層にガンダムUCを見せても設定すら分からないから拷問としか思われないだろうけど逆もまた然り。ガンダムUCを見てる層がうたプリを見てもやはり拷問だろう。

つまり男性向けアニメも女性向けアニメと変わらない。既存作を熟知していて様々な知識を既に持っている人達を対象に、濃度の高い商品を打ち出して商売を成立させるという流れが男女関係なく存在していると言えるのだろうなと。

大体にして、老若男女、幅広い層にウケるアニメが見たかったら、ピクサーやディズニーのアニメでも好きなだけ見てればいいわけで…。日本のアニメにそんな万能振りを期待してどうするのだ…。日本のアニメは、リターンが小さ過ぎてピクサーやディズニーが狙ってこない、そういう隙間を狙って作られてるのだから、そこから外れた層にはウケなくて当然。

というかそもそも、おじさんが女性向けアニメを見て「これは面白い」と思えるわけがない。「女性向け」アニメなんだから。下手すると、おじさんが「面白い」と思った時点で女性向けアニメとしては大失敗してる可能性すらある。でも、女性向けアニメを作ってるのはえてしておじさん達で…ちと話がややこしい。

とかなんとかどうでもいいことをもやもや考えてしまったけれど、何にせよ、女性向けアニメは最初から切る、と自分の中で覚悟を決める(?)だけでも視聴本数が随分と減らせそうな予感。これからはちょっと気が楽になりそう。

少女漫画と女性向けアニメは別物。 :

少女漫画なら、おじさんが読んでも「これは面白い」「名作だ。紛うことなき名作だ」と思えるものが多々あって。なもんで、極めて安易に「女性向けアニメにも名作があるんじゃないの」と思ってしまって眺めてたわけだけど。

どうも少女漫画と女性向けアニメは種類が違うというか、異質なものだなと思えてきたり。

少女漫画の場合は、一つの大きなストーリーを紡いでいくものが大半で。どんなにつまらない作品でも、ちゃんとお話が用意されてるものが多い。

女性向けアニメは違っていて、男性アイドルのコンサートというか、ライブというか、イベントというか、そういうものを眺めてる感覚に近いのだろうなと。ダンスシーン・歌唱シーンが本編内に必ず挿入されていたりもするし。そして、それらダンスシーン等の合間に、ちょっとした寸劇がお飾りで挿入されている。ストーリーはほとんどあってないようなもの。

例えば、3次元の男性アイドルのコンサート映像をおじさんが見ていても、「よく動くなあ」「こんなダンス、おじさんにはできないよ」「うわあ。あんなに足が高く上がってる」「若い子は凄いねえ」てな印象が関の山。「感心」することはあっても「感動」は無い。同様に、女性向けアニメを見ていても、「よくまあこんな細かい絵を描くなあ」てな具合に感心することはあっても、そこに感動は無い。

でも、おそらくファンは、そのダンス一つを目にしただけでも、何か感動的なストーリーを脳内に思い浮かべてるのではないかと想像したりもして。「最初の頃はあんなに拙い踊りだったのに、よくぞここまで…。きっとツライ練習をずっと繰り返してここまで来たんだね…偉いよ、○○クン。尊いよ」みたいな。あるいは「最初は○○(メディア名)でしか見れなかったのに、今はTVでも映像が流れてる…育ったなあ」みたいな。まあ、そのあたりは男性が女性アイドルの成長を見ている時も似たようなソレがあるわけだけど。

あるいは、動物の求愛ポーズとしてのダンスの動きに魅力を感じてる可能性もありそうだけど。雄鳥が枝の上で羽を広げて交互に振って「パシッ、パシッ」と音を立てながら求愛ダンスをすると、雌鳥が「あら。コイツの遺伝子ってばなんだか良さそうじゃないの?」的に寄ってきたりするけれど、そういう現象に近い可能性も。

もっともこのあたりは男性向けアニメも似たようなもので。というか男性向けアニメはもっと酷い。下着だのおっぱいだの見せとくだけでガッツンガッツン食いついてくるから…。何の技術も要らない。ペロンと見せるだけで寄ってくる。男はね…チョロ過ぎるというか、単純過ぎるというか…。女性向けのアレコレが様々なテクニックを華麗に巧みに駆使しないと訴求力を持てないことに対して、男性向けは「あっ! 今おっぱい見えた!」で全部オッケーになっちゃう。ちょっとね…酷いよね…。時々嫌になる…。

閑話休題。

ダンスシーンや歌唱シーン等、「動き」「音」を含む何かしらは、静止画しか提示できない少女漫画では表現できない。その代わり、少女漫画はストーリー等を提示して商品として成立させている。そして、ストーリーがあると、ある種の普遍性だか汎用性だかを獲得できて、おじさん達が読んでも楽しめるコンテンツになる。

てなことを考えていくと…。女性向けアニメは、少女漫画ではできない表現を積極的にプッシュして、しかしその代償として、ソレ以外を削ぎ落としたジャンル、と言えるのかもしれない。ある意味では純度が高い。そして純度が高くなった分、間口が狭くなるのは、これは仕方ないよねえ、と言えたりするのかも。

と、ここまで書いて思い出したけど、「やおい」ってジャンルがあったなと…。「やおい」も純度が高かったよなあ…。アレは人を選ぶけど、「選ばれし者達」は果てしなくいつまでもソレを堪能できる、みたいなところが…。

まあ、思考メモです。こんなことをぽやぽやと考えてました、とメモ。

*1: 「切る」=「視聴しない」の意。
*2: 「おじさんは」、ですよ。
*3: 男女関係なく誰でも楽しめる方向での「名作」は、という話ですよ。そのジャンル内に限って比べた際の「名作」は、もちろんあるはずで。

#4 [nitijyou] 弟が帰省

PM06:30頃到着。道は混んでなかったとのこと。

以上、31 日分です。

過去ログ表示

Prev - 2016/12 - 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