月別アーカイブ: 2014年12月

ボードゲームのネット対戦用に Tabletop Simulator を買って使ってみた

ここではボードゲーム用のシミュレータ Tabletop Simulator を使ってみた感想とか、その過程でやったプログラミングを紹介します。

注意、Tabletop Simulator は売りもので Steam で 1,480 円です。
(改めて書き出してみると、けっこう高いな! この記事を書くモチベーションが…。
Steam のページ: http://store.steampowered.com/app/286160/?l=japanese
開発元のページ: http://www.berserk-games.com/ts/

Tabletop Simulator がどういうソフトウェアかを簡単に紹介すると「ボードゲームやカードゲームをネットワーク越しにできる」「自分が作ったカードデータも取り込める」というソフトウェアです。 というか詳しい紹介については http://tukedai.minibird.jp/blog/?p=168 のページが大変よくまとまっています。

この記事では、Tabletop Simulator 用に

  • カードデータを yaml で定義して作成するスクリプトを作成した。
  • カードを配置するボードも同様に作成した。
  • ボードの大きさを save データを修正して変更した。

という項目を記述します。

 

カードデータを yaml で定義して作成するスクリプトを作成した

Tabletop Simulator ではカードを作るためには、カードの裏の画像と表の画像を取り込む必要があります。 最終的には、このような画像を作成します。

item_card_back
カード裏の画像
item_cards
カード表の画像

カード表の画像が縮小されてて少しわかりにくいですが、カードの画像を作り、それを必要な枚数だけ並べています。? この画像を作る手順を簡単に記述すると

  1. ダミー文字を配置したテンプレートを svg ファイルで作成する。
  2. svg ファイルの文字列を置換した svg ファイルを作って inkscape で png 画像を作る。
  3. 作った png 画像を ImageMagic で指定した位置にコピーしていく。

となります。

用意したテンプレートを svg で作ったのは、フォーマットが文字列なので置換しやすそうだったからです。

用意したテンプレートファイル
https://bitbucket.org/satofumi/dungeon_sugoroku/src/default/item_card/item_template.svg

後はアイテム情報を列挙した yaml ファイルをスクリプトで読み込み、テンプレートファイルに個別に流しこんで svg ファイルを作れば、それを inkscape コマンドで png 画像が作成できます。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys, subprocess, yaml, codecs, copy


def print_help(program_name):
    print "usage:\n python " + program_name + " <yaml file> <template svg>"

if len(sys.argv) < 3:
    print_help(sys.argv[0])
    sys.exit(1)

yaml_file = sys.argv[1]
template_svg_file = sys.argv[2]


# 文字列を置換した SVG ファイルから png 画像を生成する
template_svg = open(template_svg_file).read().decode('utf-8')

for data in yaml.load_all(open(yaml_file)):
    for item in data:
        dest = copy.deepcopy(template_svg)
        name = item['name']
        output_file = name + '.png'

        # 各パラメータの置換
        dest = dest.replace('#name', name)
        dest = dest.replace('#type', item['type'] or '')
        dest = dest.replace('#cost', str(item.get('cost')))
        dest = dest.replace('#text1', item['text1'] or '')
        dest = dest.replace('#text2', item['text2'] or '')
        #dest = dest.replace('#flavor', item['flavor'])
        #dest = dest.replace('#image', item['image'])

        dest = dest.replace('#hp', str(item.get('hp') or ''))
        dest = dest.replace('#atk', str(item.get('atk') or ''))
        dest = dest.replace('#items', str(item.get('items') or ''))
        dest = dest.replace('#exp', str(item.get('exp') or ''))
        dest = dest.replace('#score', str(item.get('score') or 0))

        # ファイルを出力して画像を生成する
        f = codecs.open('out.svg', 'w', 'utf-8')
        f.write(dest)
        f.close()
        cmd = 'inkscape -z -e ' + output_file + ' -w 406 -h 584 ' + 'out.svg'
        subprocess.call(cmd, shell=True)


cmd = 'rm out.svg'
subprocess.call(cmd, shell=True)
?

(改めて見ると小汚いコードだな…。 いずれ直そう。

で、このスクリプトを実行すると yaml で定義したぶんの画像ができるので、次に別のスクリプトで Tabletop Simulator が読み込める画像を作ります。 そのスクリプトはこんな感じです。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys, subprocess, yaml


def print_help(program_name):
    print "usage:\n python " + program_name + " <yaml file> <output file>"

if len(sys.argv) < 3:
    print_help(sys.argv[0])
    sys.exit(1)

yaml_file = sys.argv[1]
cards_template_file = sys.argv[2]


def card_position(index):
    x = index % 10
    y = index / 10
    return (406 + 3) * x, (584 + 3) * y

def add_card_image(dest_image_file, card_image_file, x, y):
    cmd = 'convert ' + dest_image_file + ' ' + card_image_file + ' -gravity northwest -geometry ' + '+' + str(x) + '+' + str(y) + ' -composite out.jpg'
    subprocess.call(cmd, shell=True)

    cmd = 'mv out.jpg ' + dest_image_file
    subprocess.call(cmd, shell=True)

# yaml ファイルから名前と枚数を読み込み、順に配置する
total_index = 0
for data in yaml.load_all(open(yaml_file)):
    for item in data:
        card_image_file = item['name'] + '.png'
        print 'add ' + card_image_file
        number = item.get('number') or 1
        for i in range(0, number):
            x, y = card_position(total_index)
            total_index += 1
            add_card_image(cards_template_file, card_image_file, x, y)

 

(なんだろな、この「とりあえず作りました」的なコードは…。 いや、とりあえずで作ったんだけど。

カードを配置するボードも同様に作成した

ゲームのキャラクター毎に個別のカード置き場を作る必要があったので、同様にボード用の svg テンプレートファイルを定義して文字列を置換しました。

ボードの大きさを save データを修正して変更した

で、ここまでやって実際に Tabletop Simulator に画像を取り込んでみたのですが、ボードは大きすぎたので、保存データの JSON ファイル中の Scale を 1.0 から 0.5 に変更してサイズを小さくしました。 保存データは My Document / My Games / Tabletop Simulator / Saves 以下にあります。

2014-12-29_00002
変更前のスナップショット

ボードはこんなに大きくなくていい…。

2014-12-29_00001
変更後のスナップショット

(使わないパネルは、DEL キーで削除してもオッケーです。

あと、追記

◇取り込んだ画像はキャッシュされるので、「なんでリンク先の画像を変更したのに表示内容が変わらないんじゃい!」って思ったら My Document / My Games / Tabletop Simulator / Mods / Images 以下のファイルを削除してみましょう。

◇Tabletop Simulator は自作ゲームをネットワーク越しに遊んで評価するために購入したけど、結局まだネットワーク越しではゲームしてないです。 あと、ぶっちゃけるとマウス越しのコマとかの操作は面倒です。

◇自作ゲームを自分で何度かプレイしてみたけど、あんまり面白くなかった…。

自作ゲームのプロジェクト: https://bitbucket.org/satofumi/dungeon_sugoroku/wiki/Home
(Tabletop Simulator 用の保存データがダウンロードできます。

 

マスコットアプリ文化祭に応募した作品を振り返る

マスコットアプリ文化祭の〆切はまだだけど、自分が応募した作品を開発者視点で振り返ってコメントしようと思う。 ウソは好きじゃないので、本音で書きます。

 

◇マスコットアプリ文化祭を知ったきっかけ

プロ生ちゃんのTwitter でのつぶやきのリツイートを見たんだと思う。 あんまりキャラ萌えしない方なので、「へー、こんなのやってるんだ。がんばってるなー」 くらいの気分で開催ページを見に行った。 で、概要だけ読んで戻ろうと思ってたんだけど、

? 「ちょっと待って? 大沖さんの特別4コマ入り限定グッズがもらえんの?」

ってのに気付いてしまったので、参加することにした。

? 「ひらめきはつめちゃん、いいよね!」

はつめちゃんの発するおやじギャグは、とっても良いと思います。

 

◇「那珂ちゃんの楽屋」の応募

大沖さんのグッズが含まれる「キャラクターコンプリート賞」をもらうには、全てのキャラクターを使う必要がある。 なので、各キャラクターの利用規約を見に行ったんだけど…、

キャラクターの数だけ利用規約があって、割と大変だった!

多くのキャラクターの利用規約は、「非営利目的なら使ってもいいよ」 になってて 「みんなに使ってほしい」 って気持ちがあらわれてたんだけど、

? 「読むの、めんどくさい…」

って思ったのをよく覚えている。
このときは、クリエイティブ・コモンズ・ライセンスのありがたみを強く感じた。

で、キャラクター全員を使ったアプリを何にするか悩んだんだけど、結果として全てのキャラクターが含まれている画像を、ウィンドウシッターとして利用する、という暴挙にでることにした。 (ウィンドウシッターとは、フォーカスのあるウィンドウの上などにマスコットを表示するアプリ)

mascots_screenshot
マスコットアプリ文化祭のテーマ

ウィンドウシッターのアプリ部分は過去に作っていたので、テーマ作成でやったことは画像を縮小して、立ち位置の高さのオフセットを調整するだけ、だった。
ただ、さすがに手抜きすぎなんじゃね? と思ったらしく、応募前にキャラクター部分をクリックすると、各キャラのセリフが順に表示されるように Lua スクリプトを調整した。

ちなみに、画像がウィンドウ幅を超えて表示されるのを抑制してないので、キャラクター画像をドラッグして表示位置をずらすと、クエリちゃんがはみ出したりする。 まぁ、クエリちゃんは空を飛べるので大丈夫だと思う。 (Unity ちゃんは…)

koshikake_too_right_clipped
(Ubuntu で動かしてます)

あとは、美雲あんずちゃんの画像が公開されてたので、その中の SD 画像を用いたテーマも作った。

sd_anzu_screenshot
応募した時点の最初のバージョン

最初に応募した時点では、この画像が表示されるだけのテーマだったんだけど、目パチ用のセルを Gimp で作って追加するなどの更新を繰り返した結果、

起動するとセリフを表示してウィンクするという、あざといテーマに仕上がった!

調べた所によると、あんずちゃんは「あざとかわいい」キャラクターらしいので、設定に沿った良いテーマになったと思う。

koshikake_sd_anzu_startup
よりあざとくなったバージョン

あと、あまり関係ない話としては、SD あんずちゃんに満足したので、プロ生ちゃんと美雲このはちゃんのテーマを途中まで作ってたんだけど公開しないことになりそう。 SD じゃない絵は、縮小すると良さが薄れる気がするので…。

それに、東北ずん子のテーマはアプリには含まれてるけど、マスコットアプリ文化祭の期間中に更新しなかったので、東北ずん子のテーマは応募作品として申請してない…。 (ずん子ちゃんにも目パチを追加してたり、胸元をクリックしたときのセリフを用意してたりとか、処理スクリプトは頑張ってるんだけど)

koshikake_characters
ずん子ちゃんのセリフは、胸元をクリックしたときのものです。

全体的にテーマを作っていて思ったのは「キャラクターの決め台詞があったらなー」 ということ。 テーマに使ったセリフは、各キャラクターの Twitter の発言をもとに考えて作ったけど、テーマのスクリプトを調整するより時間がかかった。

那珂ちゃんの楽屋のページ
(バグ報告や要望があれば、気軽にお知らせ下さい)

 

◇「ウィンドウ・アスレチック」の応募

で、作品を1つ投稿して調子に乗ったらしく、以前から作りたかったアプリを1つ作ることにした。 簡単に説明すると、デスクトップ上を、キャラクターが走ったり、ウィンドウをよじのぼったりするアプリ。 作り終えてからコメントで知ったけど「しめじ」と同じようなことができるアプリです。

最初は、プロ生ちゃんがウィンドウの上を走るだけのテーマを作った。 たまにプロ生ちゃんが転んで起き上がるようになるモーションを追加したときに、「ドジっ娘か…、あざといな」 と思った。 動きがあるアプリは作ってて楽しかった。 最初にちゃんと動いたときは、自分で作ってるのに 「すげー、動いたよ!」とか思ったりしたし。

pronama_screenshot

このプロ生ちゃんのテーマも、落下中のアニメーション用にドット絵を追加したり、右向きの画像は左向きの画像を反転したものからヘアピンのドット部分を消すとか少しずつ改良を加え、直近のバージョンでは、ウィンドウ端でジャンプするようになってたりする。 よりアクティブに動いて、いい感じだと思う。

ちなみに、タスクバーを左側などにしていると、プロ生ちゃんはウインドウ端から飛び降りた時に画面外まで落下し続けてしまい、あたかもパラシュートなしのダイビングを見ているような感じでとても切ない気持ちになる。 心が強くない人は、アプリ実行時に注意してほしい。

で、次に東北ずん子ちゃんのテーマを作った。
このテーマを作ろうと思った時は、

? 「なにか、こう…、アプリの可能性を示せるようなテーマを作りたいんだ…」

とか、ろくろを回すポーズでしゃべってそうなことを考えていたように思う。
で、自転車でサイクリングロードを走っているときに

? 「はっ! 降ってくるずんだ餅をずん子ちゃんが食べ続けるとか、最高にシュールじゃね!」

とか思い、そのノリのまま仕様を決めた結果、少しだけシュールなテーマになった。

zunko_screenshot

さっそく作ったものを知人に試してもらったが、

「あの緑のやつって豆じゃなくて、ずんだ餅なの?」

っていうコメントをもらったので、改善してずんだ餅が自己主張するように変更した。

2014-12-03 02.47.33
改良した結果、少しシュールになった。

私は、プログラマとして誤解が起きないような表現をすることは、とても大事だと思っています。
あと、東北ずん子のテーマも改良がなされ、最新版ではずんだ餅が積み上がるようになっている。

2014-12-03 02.47.39
さらに、もう少しだけシュールになった。

ずんだ餅を積み上げるための変更を Lua スクリプトに施しながら、「あー、なんで私はずんだ餅を積み上げようとしてるんだ?」 とか 「Box2D を取り込めばよかったかも」 とか思ったりしたのも、今となっては良い思い出だ。

☆ ウィンドウ・アスレチックについては、マスコットアプリ文化祭の参加キャラクターの顔アイコンが転がるテーマもマスコットアプリ文化祭応募作品として配布されているので、是非 動作させてみてほしいと思います。(MtCedar さま作

「転がーるず」のテーマ配布ページ

ちなみに私は、初見でお茶を吹いて頭を抱えるくらいのインパクトを受けました。

ウィンドウ・アスレチックのページ
(バグ報告や要望があれば、気軽にお知らせ下さい)

 

◇「ばってりもにたー」の応募

ここまできたら、過去に作ったアプリで、ひと通り応募するノリになったらしく、ノート PC なんかのバッテリー表示するアプリに SD あんずちゃんの絵を適用することにした。

anzu_charging

ベースとなる画像を追加するだけのつもりだったけど、髪の毛がバッテリー表示部分より後ろになるのが気に喰わなかったので 「バッテリー表示を描画してからマスコットを描画するように」 っていう変更を行った。

あと、この記事を書いてて充電中かどうかの表示の切り替わりが Windows で遅いという問題があるのを思い出したが…、とりあず気にしないことにしようと思った。
私は主に Ubuntu を使っている人なのです。

ばってりーもにたーのページ
(バグ報告や要望があれば、気軽にお知らせ下さい!)

 

◇「テーマ時計」の応募

最後に応募したのは、画像差し替えられる時計だ。 プロ生ちゃんのテーマを追加した。
やっぱり使える素材が多いというのは、利用キャラクターを選ぶ大きな要因になると思う。

qtmclock_pronama_screenshot

このアプリでは、テーマを作成するためのツールを過去に自作していたので、それを使ってテーマを作った。 テーマを作成するツールを作った当時は

? 「うっはー、このパーツ位置の調整ツール、最高じゃね!」

などと思っていたはずだが、実際に今になって使ってみると

? 「使い方がわからん! なにこの残念ツール!」

って思った。
自分のスキルが上がって、要求レベルが上がったんだと信じたいです。

あと、このアプリも応募するにあたって、テーマを一覧から選ぶ機能を追加で実装したりした。

qtmclock_change_theme

マスコットアプリ文化祭は、作りたかったアプリを作ったり、過去のアプリに修正を行う機会になったという意味で、私にとっては有意義だった。

このテーマ時計について印象深いやりとりは、このアプリを知人に試してもらったところ、

「え? Windows 7 なら、そういうのはガジェットで実現できるでしょ?」

って言われことですね。
とりあえず、「Linux や Mac でも動くから、ガジェットでなくていいんだ!」 って自分に言い聞かせることで動揺を隠すことには成功しました。

あと、このテーマ時計のソースコードは少し読みづらかったので、過去の自分に会う機会があればコーディングについて少しお説教したいと思いました。

テーマ時計のページ
(バグ報告や要望があれば、気軽にお知らせ下さい)

 

◇まとめ

  • 大沖さんグッズほしさで参加したけど、参加したら各キャラクターに親近感がわいた。
  • アプリを作ったり、過去のアプリを修正する良い機会になった。
  • 見てるだけより、参加した方が楽しめる!

 

◇最後に

今現在は、クエリちゃんを用いた「マスコットが応援してくれるプログラマ用チケット管理システム」を作ろうと思っています。 マスコットアプリ文化祭の〆切に間に合う気はしませんが、とにかく作り始めます。
作り始めないと完成しないので。