せらぴんブログ

サークル「せらぴん」のうのはな透です。やっぱり眼鏡っ娘が好き!!

同人スケジューリングサービス作ってみた

f:id:yuphiel:20150426161302j:plain

「同人秘書」(β)なるものを作ってみました。
そうです、ワシが育てた。

おかげさまで予想以上に多くの方に見ていただけたようで、公開初日で登録ユーザ数が150強でした。現在もゆるやかにですが増え続けています。ほぼノー宣伝からのスタートでこれはすごい状況だと思います。ありがとうございます!!
当面は説明の充実などに取り組み、より多くの人に使ってもらえる、ユーザが定着するサービスを目指します。

なぜ作ったか?

私自身同人活動をやっていますが、どうも〆切ギリギリにならないと着手しないというか、所謂「ケツに火がついて初めて慌てる」人間です。
なんとかケツ火人間から脱却するために、同人秘書を作りました。

誰がターゲットか?

マンガ、イラスト、小説を執筆する方。特に以下に該当する方。

  • 執筆初心者
  • 事前の計画通りに執筆できないとお悩みの方
  • 自分の執筆ペースを把握したいという方

逆に自分の執筆ペースを正確に把握しており、事前の計画を守るためのノウハウを確立している方には、利用価値が低いと思います。

続きを読む

転職しました

先月31日、今まで勤めていたソフトウェア会社を退社し、新しいソフトウェア会社に転職しました。

転職の理由は主に下記の通り。

  • 長時間労働が多く、趣味の時間を確保しにくい
  • 今年入院してしまったため、長時間労働に耐えられる体調か怪しい
  • 別の言語・フレームワークを経験したい

総合すると、楽になりたかった。
転職先は受託開発と自社開発システムと自社開発ゲームをやるような、やや緩めの会社なので、心機一転頑張っていこうと思います。
転職に伴い、埼玉から東京に引っ越す予定です。GW終わりには引っ越すのであしからず。

先々の不安もあるにはありますが、引き続き頑張ってまいります。
これからも変わらずのご愛顧よろしくお願いいたします。

civ4初めてみましたレポ

ねんがんの しぶふぉーを てにいれたぞ!

第一回「小屋を建てれば勝てるゲームなんでしょ?」

島マップ、難易度最弱(Settler)でプレイ。指導者はランダムで選んだ結果始皇帝だった。
体験版などで得た以下の知識を元にプレイを進める。

  • 開拓者(Settler)を使って街を建てる
  • 労働者(Worker)を使って街の周りに農場・鉱山・小屋を建てる
  • 研究をひたすら進める

これだけ。
だが島マップなので開拓が早晩行き詰まる。
しょうがないのでひたすら小屋を建てるプレイに走る。
理由は「小屋を建てればお金が手に入るんだよね!」という単純な認識だったから。
都市の建築物は進められるものを適当に建てていった。

「土地が狭すぎるし、すぐ下に見える他の島にも開拓しに行きたいなぁ」と思っていたが、
残念なことに海の渡り方がわからなかったので数百年以上二の足を踏むことに。
そして19~20世紀あたりになってようやくユニットを船に載せることを覚えたため南の島に攻め込む。
ここで他国(日本だったかな)と鉢合わせになり戦争突入。
そうこうしているうちに画面右上に「XX Turns left」の文字が表示されて慌て始めるも時すでに遅し。
2050年が到来し、時間勝利できず敗北。

ちなみに外交は一切と言っていいほどしませんでした。頑なに鎖国。頑なに技術交換拒否。

以下、第ニ~四回まで続く。

続きを読む

何も考えない直訳ほどナンセンスな名付けはない

大規模PJでは画面IDを元にクラス名設計をする場合が多々あります。
それはそれで鬱屈とするのですが、それよりも厄介なのが画面名を直訳してクラス名をつける*1というパターン。

この“直訳”というのがミソで、例えば下記のような画面があったとします。

  • ユーザ編集画面
  • ユーザ更新確認画面
  • ユーザ画像設定画面
  • エントリ登録画面
  • エントリ保存更新確認画面
  • コメント新規作成画面

これが、こうなる。

  • EditUserController
  • ConfirmUpdateUserController
  • ConfigureUserImageController
  • RegistEntryController
  • SaveUpdateEntryController
  • NewCreateCommentController

さて、ツッコミどころが何個見つけられたかな?!
おかしいのはクラス名だけでなくて、メソッド名も往々にして悲惨なことになってたりします。例えば、

  • EditUserController#EditUser()

「ユーザ編集画面でユーザ以外の何を編集するんだよ!!」と言わずにはいられないこのセンス。Edit()で十分だと思いませんか。思ってください。あとこういうのも過去に見たけど目眩がした。

  • EditUserController#Save()

なんでわざわざ単語変えるんだ?!
え? ボタン名が「保存ボタン」だからだって?
……そうか、お前がそう思うんなら、そうなんだろうな。

けどこのPJで一番笑えないなぁと思うのは「直訳するときは単語のブレとかがあるといけないからPJ用の単語表を見て対応する単語を使ってね♥」てルールがあるという点に尽きると思う。
その辞書に「保存-Save」「登録-Regist」「設定-Configure」「編集-Edit」「更新-Update」と次々単語が追加されて、それらが機械的に消化されていく。本末転倒とはよくいったものだなぁ……と。

美しい名付けは美しい設計から生まれる

こういう「同じ意味の違う単語が平然と現れる」「メソッド名が過度に説明しすぎ」な名付けっていうのは、余計なことに意識がそれてしまいがちです。
シンプルイズベスト、わかりやすくシンプルな設計をすれば、自ずとクラス名・メソッド名はわかりやすくシンプルなものになるはずなのです。RailsURIなどはその典型です。

クラス名・メソッド名・URI設計。名付けと設計のセンスは磨いておいて損はないですよ。

*1:そもそも“1画面1Controller”の時点で、Struts時代に引きずられているということで、出発点からしてすでに……。

眼鏡時空12でます!!

明日は2月14日ですね、2月14日といえば?

そう!眼鏡時空12ですね!!

というわけで、明日の眼鏡時空12にサークル参加します!

新刊「眼鏡ッ娘、生存戦略ス。」

モバマス眼鏡ドル×めがねっ娘教団(+久米田節)本/全年齢/200円


【眼鏡】「【モバマス】眼鏡時空12 表紙&サンプル【めがねっ娘教団】」イラスト/うのはな透 [pixiv]

眼鏡っ娘の百合ンチュールアニメを堪能しようとしたら思いがけず第一話で死んでしまう眼鏡っ娘を目の当たりにした上条春菜。
なだめる荒木比奈、理論を打ち立てる池袋晶葉。そこに突如現れるめがねっ娘教団。教団幹部が提唱した眼鏡っ娘に優しい世界”計画その全貌、そしてその展望は――?!」

往年のかってに改蔵のノリで描きました。タブーとも言える“眼鏡っ娘の死”を焦点に当てた渾身の一作です。キミよ、眼鏡っ娘の死に噎び泣け!!

作品自体はギャグ漫画ですが、普段血涙を流しながら「眼鏡を殺すな!!」と噎び泣いてるうのはなの心を一生懸命形にしました! ぜひ手にとってください。


以下既刊。

艦これ一般向「眼鏡は艤装に入りますか?」

霧島・榛名/一般向/200円
やっとの思い出で霧島を迎えた提督と榛名。しかしこの霧島、何やら眼鏡に一家言あるようで――。

艦これ成年向「提督、轟沈。」

霧島/成年向/100円
Sな霧島に徹頭徹尾責めらたい!そんなM提督向けの本です。

モバマス成年向「眼鏡の裏に――」

上条春菜/成年向/400円
ライブ終了後、熱の冷めない春菜にPが性的な要求を突きつける。春菜はPの言われるがままにスカートをたくしあげ――。


明日は大田区産業プラザPioでボクと握手!!

あ、眼鏡時空は当日参加型イベントなので眼鏡本持ってる人はぜひ参加してボクに本買わせてください!!!!

ヤマモト撮影会参加します

追伸。明日Pio9:30~から「妄想戦士ヤマモト原作再現撮影会」参加します。


2015年2月14日 妄想戦士ヤマモト原作再現撮影会 出演者&撮影者募集中 - TwiPla

めがねっ娘教団員で参加予定です。
なお、興味がある人は着の身着のままご参加ください!!

DXRubyでポーカーを作った

この記事はDXRuby Advent Calender 2014の11日目の記事です……のはずがもう日を跨いでいます。ごめんなさい!!

前回はみれいゆーさんの「DXRubyで成長曲線と父母遺伝の再現、描写」でした。専門的な内容であまりわかってないのですが、これを利用すれば人生シミュレーションが作れそうな気がしました。

さて今回の内容ですが、「DXRubyでポーカーを作った」ということで、過去に自分の作ったゲームと工夫した点を紹介します!! もっとスゴイ読み応えのある記事書きたかったけど用意できませんでした!! ゆるして!!

f:id:yuphiel:20141212021147j:plain

これは今年の1月に作ったテキサス・ホールデムのゲーム、通称「うのはなポーカー」です。

※現在はこちらからダウンロードできます。

プレイヤー表示部が若干オサレになりました。プレイヤー名は某マスの眼鏡ドルになってます。ゆくゆくはアニメーションぬるぬるの眼鏡ドルポーカーにしたいなぁ、と夢想してます。

工夫した点

MVCを意識した

え? 一年前に似たような記事を見たって? 気にするな!!

ゲーム本体はControllerがmain.rb、Viewがview.rb、Modelがその他のソース(game.rb, pot.rb, player.rb, routine.rb, scorer.rb)と分かれています。Controllerはキー入力に応じてModelの各関数を呼び出すことに徹しているし、ViewはModelの内容を描写することに徹しています。

以下が汎用コントローラクラスになります。

# ゲームとビューを操作するコントローラ
class Controller
	# シグナル:コマンドなし
	NO_COMMAND = 0
	# シグナル:ゲーム終了
	GAMEOVER = -1
	# シグナル:ゲームリセット
	RESTART = 1
	
	def initialize
		@timer = Timer.new
		@game = Game.new(@timer)
		@game.startGame
		@drawer = Drawer.new(@game, @timer)
		@keyCommand = {K_RETURN => @game.method(:bet),
                               K_R => Controller.method(:restart),
                               K_ESCAPE => Controller.method(:gameover)}
		Input.setKeyRepeat( K_LCONTROL, 60, 1 )
	end
	
	# コントローラ更新(描写・ゲーム更新・タイマーカウント)
	# サブコントローラがある場合、描写・サブコントローラ更新・タイマーカウントを行う
	def update
		signal = NO_COMMAND
		@timer.update unless @child.kind_of?(TimerStopController)
		if @child
			result = {signal: NO_COMMAND, child: @child}.merge(@child.update)
			@child = result[:child]
			signal = result[:signal]
		else
		  @keyCommand.each_key {|key|
			  if Input.keyPush?(key)
			  	signal = execute(key)
			  	break
			  end
		  }
		end
		result = {child: @child}.merge(@drawer.draw(@game, @child))
		signal = execute(result[:command]) if result[:command]
		@child = result[:child] if result[:child]
		return signal
	end
	
	# キーが押された、あるいはビューからコマンドがあった場合、ゲーム操作メソッドを実行する
	def execute(key)
		result = {signal: NO_COMMAND, command: nil, child: nil}.merge(@keyCommand[key].call)
		@keyCommand[key] = result[:command] if result[:command]
		@child = result[:child]
		return result[:signal]
	end
	
	# ゲームを終了させる
	def self.gameover
		return {signal: GAMEOVER}
	end
	
	# ゲームをリセットする
	def self.restart
		return {signal: RESTART}
	end
end

ゲームのループ内で回し続けるのがupdateメソッド、キーが押された時に実行されるのがexecuteメソッドです。押されたキーと実行するメソッドの対応をkeyCommandフィールドで保持しています。
また、Modelからだけでなく、ViewであるDrawerからもCommandを受け取れるようになっています。これは「Drawerの方でアニメーションを描ききったら、次の処理に自動的に映る」という操作と「アニメーション終わるまで待つの面倒だから、Returnキー押してスキップする」という操作を一つの流れで行えるようにと意図したものです。
実際に、ゲーム内でNPCのベットはキーを押さなくてもポンポン進んでいきます。らくちん!!

Test::Unitによるテストを用意した

class TC_Scorer < Test::Unit::TestCase
	include Scorer
  
	def testHand
		assert_equal(Hand::STRAIGHT_FLUSH, getHand(getCards("SA,SK,SQ,SJ,ST"))[0])
		assert_equal(Hand::FOUR_CARDS, getHand(getCards("SA,CA,DA,HA,SK"))[0])
		assert_equal(Hand::FULL_HOUSE, getHand(getCards("SA,CA,DA,SK,CK"))[0])
		assert_equal(Hand::FLUSH, getHand(getCards("SA,SK,SQ,SJ,S9"))[0])
		assert_equal(Hand::STRAIGHT, getHand(getCards("SA,SK,SQ,SJ,CT"))[0])
		assert_equal(Hand::THREE_CARDS, getHand(getCards("SA,CA,DA,SK,SQ"))[0])
		assert_equal(Hand::TWO_PAIR, getHand(getCards("SA,CA,SK,CK,SQ"))[0])
		assert_equal(Hand::ONE_PAIR, getHand(getCards("SA,CA,SK,SQ,SJ"))[0])
		assert_equal(Hand::NO_PAIR, getHand(getCards("SA,SK,SQ,SJ,C9"))[0])
	end

先日Rspecでテストしよう!的な記事がありましたが、それに先駆けてTest::Unitでのテストを試しておきました。テキサス・ホールデムの中でも複雑で、かつ独立させやすい以下の2点についてテストしています。

  • 手役(特定の7枚からスーテッドを抽出する、ペアを抽出する、役を決定する など)
  • ポッド(誰かがオールインした場合の賞金の分配が正しく行われているか)

これからテストを増やしていくとしたら、AIの部分に取り組みたいです。このAIクッッッッッソ弱いねん……。

強化したい点

オンライン対戦

ここ数日はACに向けてオンライン化を考えており、「ゲーム本体はできてるんだから楽勝でしょ楽勝!」とか恐れ多くも考えていたわけですが、案の定無理でした!!
「対戦ルームを作る」「対戦ルームに参加する」「クライアントの入力を受け付ける」「サーバからクライアントへ情報を投げつける」「ショーダウン後に各プレイヤーの入力を待って同期を図る」など、当初の予想よりボリュームが増大しそうだったので、今回は断念しました。来年までにはできているといいですね。

アニメーション

「アニメがヌルヌル動くゲームを作りたい!!」が私のゲーム作りの原動力なので、アニメーションできるように頑張ります。さしあたってはSpliteともっと友達になりたい。

ということで

拙作うのはなポーカー、お時間に余裕のある方はぜひお試しください。


明日は(というかもう今日だけど)fourxzさんの「DXRuby、IntelliJで入力補完の巻」です。おたのしみに!

ワールドトリガーのアニメ第5話がヤバい

今書いてます。
今書きました(@15/3/2)

どんな酷さ?


【SHIROBAKO】第18話 感想…新人声優が一瞬でベテランの演技に!!w音響監督すげえぇぇ!! : あにこ便

SHIROBAKO 18話で似たようなエピソードがありました。

『これ、緊迫したシーンの”敵機だ!!”ってセリフですよ?…なのに4秒も使ってる!!』
『てーっきだーーー(4秒)』

下のpostにもありますが、ワールドトリガーのアニメは全体的に尺を伸ばし気味なようです。

でも5話はそれでも酷いと思うなぁ……

  • 前半は登場人物の8割が「仁さんが本部に来るなんて珍しいなぁ」としか言わない
  • 対する仁の台詞は8割が「エリートですから」
  • 後半はおっさんが重苦しい雰囲気で何も喋らない
  • 喋ったら喋ったで3秒以上開けないとしゃべり出さない

お前らはトークンパッシングか!!

どうしてこうなった

私個人としてはワルトリ5話そのものよりも、『いかにしてこの様なクソ尺アニメが出来上がったのか』のほうが興味あります。

SHIROBAKO 18話に照らし合わせると演出のミスに見えなくもない。
しかし多分演出のせいではないと思うんです。5話はそもそも分量が少なすぎる。
では脚本のせい?
いやいやシリーズ構成のせい?
やっぱり監督*1のせい?

こうして考えるとアニメの制作現場って大変なんだなぁ、と思います。
そして制作現場の苦労に思いを馳せるきっかけとなったSHIROBAKOはやっぱり偉大だった。

*1:東映作品には監督はおらず、シリーズディレクターがいます。