KMC活動ブログ

京大マイコンクラブの活動の様子を紹介します!!

お詫び 【KMCアドベントカレンダー25日目】

こんばんは、KMC 2回生のprimeです。 投稿が遅くなった事をお詫び申し上げます。

この記事は今年もやります!KMCアドベントカレンダー!! - KMC活動ブログの25日目の記事です。 昨日24日目の記事はpossumさんの祝 京都市バスICカード利用開始! (FeliCaのはなし) 【KMCアドベントカレンダー24日目】 - KMC活動ブログでした。

お詫び

残念ながらprimeの多忙により"Brainf*ck + リフレクション = BFmeta"の記事が完成しておりません。ここにお詫び申し上げます。

原因

KMCアドベントカレンダー 2014年12月26日の記事は、 prime (id:PrimeNumber) さんの"Brainf*ck + リフレクション = BFmeta"です。

追記

記事が完成しました

Brainf*ck + リフレクション = BFmeta 【KMCアドベントカレンダー26日目】 - prime's diary

祝 京都市バスICカード利用開始! (FeliCaのはなし) 【KMCアドベントカレンダー24日目】

こんばんは、KMC 6回生のpossumです。 投稿が遅くなった事をお詫び申し上げます。

この記事は"今年もやります!KMCアドベントカレンダー!!" (KMC活動ブログ)の24日目の記事です。 昨日23日目の記事はlastcatさんの"盆栽日記……のはずが。"でした。

さて、本日2014年12月24日は京都市バスが交通系ICカードの利用を開始した記念すべき日ですね!

"【広報資料】平成26年12月24日から市バスでもICカードが使えます!!" (京都市交通局)

交通系ICカードにはソニーが開発したFeliCa (ふぇりか)という技術方式が用いられています。 そこで本日は同じくFeliCaが用いられている京都大学の学生証についてお話しします。

京都大学の学生証について

京都大学の学生証は

  • 図書館やパーソナルコンピュータ端末の利用証
  • 学内施設への入退館認証
  • 証明書自動発行機の利用
  • 京大生協組合員証 (生協での電子マネー利用)

などの役割を兼ねているため、1枚のカードに複数のサービスの情報が載っている事になります。

それぞれのサービスがばらばらに読み書きしていては効率が悪いので、FeliCaを利用した個人認証用フォーマットとしてFCFというものがあり、京大の学生証もこのフォーマットを利用しています。 お持ちの方は学生証の裏面にFCFのロゴマークが確認できるでしょう。

参考: FCF推進フォーラム

フォーマットがFCFであることは判明しましたが、残念ながらFCFに関する技術的仕様を見つける事ができませんでした。 ただしFeliCaのカードであることには違いないので、FeliCaを扱うためのライブラリとして有名なfelicalibを利用して中身を見てみましょう。

準備

以下の環境を用意しました。

手順

  1. FeliCaの公式サイトからNFCネットインストーラをダウンロードしてドライバをインストールする
  2. felicalibをダウンロードして展開する
    • Version 0.4.2を使用
  3. リーダにカードを載せ、felicalibに同梱されているFelicaDump.exeを実行する
    • 非暗号化領域の情報を文字列で書き出してくれます。
    • 載せた時に1でインストールしたランチャが立ち上がりますがどいてもらいました。
    • FelicaDump.exe > file というようにリダイレクトしてファイルに書き出すと後で見やすいです。

学生証の中身

FelicaDump.exeを実行すると以下のように整形された結果が出力されます。

# IDm: XX XX XX XX XX XX XX XX 
# PMm: XX XX XX XX XX XX XX XX 

# System code: 8688
# Number of area = 1
# Area: 0000 - FFFE
# Number of service code = 0

# System code: FE00
# Number of area = 15
# Area: 0000 - FFFE
# Area: 1A80 - 1AFF
# Area: 1A81 - 1AFF
# Area: 1B00 - 1B3F
# Area: 1B01 - 1B3F
# Area: 1B40 - 1B7F
# Area: 1B41 - 1B7F
# Area: 42C0 - 42FF
# Area: 42C1 - 42FF
# Area: 4300 - 433F
# Area: 4301 - 433F
# Area: 4340 - 437F
# Area: 4341 - 437F
# Area: 50C0 - 50FF
# Area: 50C1 - 50FF
# Number of service code = 19
# Serivce code = 1A88 : Random Access R/W (Protected)
1A88:0000 XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX 
1A88:0001 XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX 
1A88:0002 XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX 
1A88:0003 XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX 
(以下略)

順に見て行きましょう。

IDm, PMm

IDmは製造IDのことで、カードごとに付与される8バイトのIDです。読み書きするシステムがカードを識別するために使います。 先頭2バイトが製造者コード、続く6バイトがカードの識別番号です。 IDmを利用して個人認証を行うシステムもあるようですが、FCF推進フォーラムによればセキュリティ上の観点から推奨されないそうです。

PMmは製造パラメータが格納されており、先頭2バイトが製品を特定するためのICコード、後の6バイトがカードと通信する時のタイムアウト時間を決定するパラメータです。

FeliCaファイルシステム

FeliCaファイルシステムはシステム・エリア・サービス・ブロックデータという4種類のノードから成ります。

  • 物理カードの中に複数の論理カードを格納する事ができ、論理カードのことをシステムと呼びます。
  • システムの中には複数のエリアがあり、エリアはその中にエリア、サービス、ブロックデータを保持します。
    • エリアを利用して階層化できるということですね。
  • データが書き込まれるのはブロックデータですが、これへのアクセス方法・権限をサービスが握っています。

従ってFelicaDump.exeを使った結果では

  • システムコードが 0x86880xFE00 の2つのシステムが存在する
  • システム 0x8688
    • エリア: 1個
    • サービス: 0個
  • システム 0xFE00
    • エリア: 15個
    • サービス: 19個

ということがわかります。

システムコードの下にエリアの数とエリアの一覧、サービスの数が続きます。 次いでサービスの列挙が始まり、サービスコード以下がブロックデータに記載されているデータです。

参考: FeliCa 技術情報

学生情報

全サービスの情報を解析したかったところですが、締め切りが迫っているため名前や学籍番号の記載されているサービスを見てみましょう。 0xFE00 のシステムにあるサービスコード 0x1A8B の領域は以下のようになっています。

1A8B:0000 30 31 30 30 30 30 30 30 30 30 38 32 00 00 30 32 
1A8B:0001 B8 C1 B8 B6 DD 20 D5 B3 C0 DE C1 00 00 00 00 00 
1A8B:0002 32 36 30 31 30 30 34 38 31 39 33 34 31 30 31 36 
1A8B:0003 31 39 34 32 31 32 31 35 58 58 58 58 58 58 58 58 

中身の文字コードはShift-JISでフォーマットは次の通りです。

  • 0バイト目から2バイト: カードの利用者区分
    • 0x3031 は文字列で"01"のことで、この場合学部生ですね。
    • 02や03だと修士・博士になります。
  • 2バイト目から12バイト: 学籍番号
  • 14バイト目から1バイト: 再発行回数
  • 15バイト目から1バイト: 性別
    • 男性・女性がそれぞれどの値なのかはわかりませんでした。
  • 16バイト目から16バイト: 半角カナの氏名
  • 32バイト目から8バイト: 学校ID(?)
  • 40バイト目から8バイト: カード発行年月日
  • 48バイト目から8バイト: カード失効年月日
  • 56バイト目から8バイト: カードを作った業者用の管理コード(?)

参考: FCFカードダンプサンプルソフト (下記参照)

なお、京都大学の学生・教職員の方に限りますが、上記のような泥臭い事をしなくてもこのサービスのブロックデータを簡単に読み出せるツールが公開されています。

【学内限定】ICカード読み取りソフト(FCFdumpソフト)

まとめ

今回はfelicalibを利用して学生証の中身を軽く眺めてみました。 普段何気なく利用している魔法のカードもこういう泥臭いことが書いてあるのだと実感できますね。

他のサービスには食堂の利用情報(利用した食堂とプリペイドカードでのチャージ/支払い)が記載されているように見えましたがまだよくわかっていません。今後の課題です。

いよいよKMCアドベントカレンダーも(予定の上では)明日で最終日です。 KMCアドベントカレンダー 2014年12月25日の記事は、 prime (id:PrimeNumber) さんの"Brainf*ck + リフレクション = BFmeta"です。

それでは皆さん良い夜を!メリー・クリスマス!

八ツ橋シューティングについて(後編) 【KMCアドベントカレンダー22日目】

この記事は 今年もやります!KMCアドベントカレンダー!! - KMC活動ブログ の 22 日目の記事です。

昨日の記事は wacky 君の イケてると思う dotfiles の管理方法 - KMC活動ブログ でした。

おはようございます。KMC5回生のhideyaです。
最近のマイブームは物理メモ帳にメモを取りながらゲームをすることです。マッピングとか。

この記事は?

KMCが2014年の京都大学11月祭(NF)に出展したゲームの1つ、「八ツ橋シューティング」の製作において製作者が考えていた事などを紹介しようというものです。

この記事には前編 ( 八ツ橋シューティングについて(前編) 【KMCアドベントカレンダー18日目】 - KMC活動ブログ ) がありますので、そちらを読んでいない方は先にそちらに目を通す事をオススメします。

前編ではこのゲームのコンセプトとそれを盛り込むに至った理由などを解説しました。
後編ではそのレベルデザインに関して考えたことなどについて解説します。同じシステムのゲームでもレベルデザイン如何で名作にもクソゲーにも別のゲームにもなりますので、コンセプトを活かす・殺さないレベルデザインというのは非常に重要です。

前提条件

さて、各ステージのレベルデザインを具体的に見ていく前に前提条件、すなわちこのゲームではどういう楽しさを提供したいと考えていたか、またどのプレイヤー層を対象にするかなどをはっきりさせておきます。

このゲームで提供したい楽しみというのは、前編でも書いたとおりショットの使い分けの楽しさです。

f:id:kmc-log:20141219040740p:plain

もうちょっと掘り下げると、目的(ステージのボスを倒すこと、高いスコアを得ること、目の前の敵に殺されないこと)を達成するためには手札(移動と2種類のショット)をどのように駆使すればいいか?というのを考えて実行し、その結果に一喜一憂する楽しさです。
それとは別に、STGやアクションゲームなどで一般的な楽しみであるところの敵を倒す楽しさ敵の攻撃を切り抜ける楽しさも勿論疎かにはできません。

そして対象とするプレイヤー層ですが、主な対象は日頃STGをそこまでやらない人(ゲーム自体をそこまでやらない人も含む)になります。
理由は前編でも書いたとおり、このゲームの特徴の1つである「敵の色分け」STG慣れしていない人に対する思考の誘導を目的としたコンセプトであるということです。

f:id:kmc-log:20141219041745p:plain

それとこのゲームが学祭で展示するゲームだということもあります。
学祭でゲームを遊ぶお客さんは(例年の傾向を見る限りでは)そこそこにゲームをする人、日頃ゲームをあまりやらない人が多く、ガチガチのゲーマーというのはごく少数です。そういう人(非ガチ勢)に遊んでもらう事が分かってるんだったら、そういう人が楽しめるようにしたいという考えです。
勿論、そういった傾向に屈せず一部のガチ勢向きに骨太なゲームを出すのも素晴らしい事です。
私は展示会場で自分のゲームを遊んでもらうことにこの上ない幸せを感じるので、多くの人に楽しく遊んで貰う(そしてその様子を見て私が楽しむ)事を重視しているだけの話です。もちろん、日頃STGを遊ぶ人にも楽しいと思ってもらえるように努力はしています。
私はこうやって非ガチ勢向けを意識したゲームばかり作ってきたので、骨太な調整をするスキルが伸びてないように思うのが悩みどころですが、それはまた別の話。

また、学祭で展示するとなると、あまり長いゲームにすると回転が悪くなるため良くありません。
開発期間が限られてる(コンセプトがまとまったのが6月、開発開始が8月、学祭が11月末)のもあり、ステージは全部で3ステージくらいがまぁ妥当なラインだろうという見通しが立ちます。

まとめると、

  • ショットの使い分けの楽しさを重視した感じで
  • 日頃STGをそこまで触らない人向きに
  • 3ステージくらいの長さで

ということになります。

各ステージ解説

それでは、各場面のレベルデザイン的な意図などを解説していきます。あと元ネタの解説とか。

ステージ1

最初のステージなので、安心して操作練習が出来るように平和に作りました。
とりあえずSTGの基本操作である撃って避けるという事を習得して貰えればこのステージの役割は達成です。
ショットの使い分けはまだあまり要求していません。正面ショットだけでも普通に進めるけど、所々でワイドショットも撃ってみると効率良く倒せて気持ちいいよ、くらいのバランスを目指しました。 実際にはワイドショットがほとんど要らない感じになってしまったので、2面へのステップアップという観点からすればもう少しワイドショットを撃ちたくなる場面を作るべきだった、というように思っています。

比較的簡単な難易度にしつつ、かつプレイヤーを退屈させないように色んなパターンを用意する。正直なところ作っていて一番難しく、一番考えさせられたステージでした。

また、私は最初のステージから作り始めます。1面でどの程度の事までやらせたか、というのがないと次の面でどの程度のステップから始めればいいのか分からなくなってしまうためです。経験を積んで感覚が掴めれば、逆の順番でもいけるようになるのでしょうが。

最初の敵

f:id:kmc-log:20141223111730p:plain

初心者向けを意識したレベルデザインをする場合、最初の敵には殺意を全く持たせないのが私のジャスティスです。
この敵も、登場してから画面上側でしばらく留まり、しばらくするとUターンして帰っていきます。ニッキ味であり 攻撃もしてこないので、わざとで無い限りこいつにはやられないでしょう。
これは、「撃って避ける」のうち「撃つ」部分からまずは覚えて貰うという意図です。最初からいきなり「避ける」部分までも同時に要求するのは少々スパルタンじゃないでしょうか、という考えです。物を教える時は一つずつの方が伝わりやすいという信条です。
少々丁寧すぎやしないか、と思う人も居ると思われますが、正直なところ自分でも少しそう感じます。

最初の敵弾

f:id:kmc-log:20141223104007p:plain

↑の敵を出せば敵を撃つ部分はもう慣れたと思うので、そろそろ敵からも撃たせます。
「こいつはさっきまでの雑魚とは少し違う」という感じを出すために、ちょっと大きな八ツ橋です。色も違います。抹茶味。
そこまではすぐに考えついたのですが、さてどういう攻撃をさせようかしら、というのがあまり浮かばなかったので、とりあえずレイフォース1面最初の赤い中型機そっくりの動きをさせました。パクリなのかオマージュなのか、その辺の境界って難しいですよね。
結論から言うとこれは(私としては)失敗でした。レイフォースではこの敵の前に大抵ザコ敵が弾を少し撃つのですが、八ツ橋STGではコレが最初の敵弾です。最初の敵弾にしてはちょっと派手すぎて面食らうだろう、と私は思います。
(ほぼ)同じ敵の動きでも、そこに至るまでの文脈で意味合いなどが変わってしまうのですよね、という教訓を再確認しました。

イチゴ味

f:id:kmc-log:20141223104248p:plain

行動パターンは最初の殺意が無い敵と同じなのですが、少しイチゴ味の八ツ橋が混じっています。そしてそれらは攻撃してきます。
ココで、「イチゴ味は(ニッキ味と違って)危ない」という事がうっすらとでも伝わればいいな、という意図です。実際どれだけのプレイヤーに伝わったかは分かりません。アンケートでも取りたい所なのですが流石に無理です。
1面の最初の方だということもあり、攻撃自体はぬるいです。とはいえ、一緒に出てくる大きな八ツ橋に夢中になって食らいついていると少し危ないかもしれないですね。それもまたSTGにはよくあること。必要な教育です。

うねうね

そんなこんなでしばらく戦いを繰り広げ、だいぶ慣れてきたあたりでアクセントを付けます。

f:id:kmc-log:20141223104434p:plain

蛇状の八ツ橋です。最近よく使われる表現を借りれば、「なるほど、そういうのもあるのか」です。凄くかわいいですね。
実際はダライアスバーストのシトーヒ(通称スカイフィッシュ)が元ネタだったり。そこそこ打ち込まないと倒せない(=打ち込み感があって楽しい)のも倒すと先端から順番にパンパンパン……と爆発していって気持ちいいのも元ネタの通りですが、この八ツ橋は蛇行しながら真下に向かうだけなので元ネタと違って殺意は全然無いです。
プレイヤーとの勝負という観点ではこの八ツ橋は仕事をしませんが、プレイヤーに満足感を与えるという観点ではいい仕事をしている、そんな子に育てたつもりです。

ボス

1ボスです。

f:id:kmc-log:20141223104720p:plain

黒ごま味(無敵)の八ツ橋がくっついているので、正面から攻撃を当てないとダメージが通りません。
STGにおける「撃つ」という要素の一種です。
斜めからワイドショットを当てれば(時間はかかるものの)やや安全に倒せますが、それをやった人はほとんどいませんでした。それに気がつく能力のある人は正面で普通に避けられるのでしょう。

f:id:kmc-log:20141223104712p:plain

絶妙に殺意のないばら撒き(8方向×2)。なんか大変そうだけど避けられた、俺ツエーという感じを出したかったのですが、ちょっとやる気無さすぎたかも。

f:id:kmc-log:20141223104840p:plain

ガードしている時は斜めからワイドショットを当ててね、というメッセージを込めていたのですが、横にはみ出してる部分に正面ショットを打ち込む人がほとんどでした。別解が出てしまいましたが、特に潰さなくていいやと思ったのでそのままです。
あと、正面ショットが真正面から黒八ツ橋の当たり判定を通り抜けたりして大変でした。ショットの弾速を少し落としたり、当たり判定を少し広げたりして対処しています。
攻撃をガードしてくる発想の元はグラディウスIIのクリスタルコアです。正面にショートレーザーを2本撃つのも似ていますね。
たまに暫くの間相手のターンになる、というメリハリがあってこのパターンは(元ネタ、八ツ橋共に)好きです。時間がかかって面倒なのは確かなので、八ツ橋では効率よく撃ちこめばこのパターンが来る前に倒せるようにしています。

ステージ2

地形を出します。私が地形の有るSTGが好きだからです。
私は地形に当たって死ぬのが好きで、このゲームも地形に当たったら死ぬのですが、その要素は地形STGに必須では無いと考えています。R-TYPE DELTAはそれまでのシリーズと違って地形接触によるミスがありませんが、それでも十二分に楽しい作品だと思います。
それはさておき、この面はゲームテンポがステージ1よりも少しゆっくりめになるように意識しました。地形で動きにくいからゆっくりめにしないとしんどいよね、とかいうテキトーな考えです。

このステージから、ショットの使い分けを明確に意識させます。地形があると製作者の意図通りにプレイヤーを誘導しやすくていいですね。あまり自由度が無いのも困りものですが。
ワイドショットが壁に当たっても爆発するので、当てやすくなってかなり使いやすいです。それに気づいた感動のあまり地形に激突して散っていったお客さんが居たとか。製作者冥利に尽きる話です。
ワイドショットが使いやすくなった関係上、テキトーに作ると正面ショットが要らなくなってしまうのでそこはある程度意識しました。

前座

地形が有るステージですが、最初はしばらく地形が出てきません。
面が変わった所でいきなり地形を出すと心の準備が追いつかないだろう、というのもあるかもしれませんが、私の場合は単にグラディウスの影響を受けているだけだと思います。グラディウス外伝は私がSTG好きになるキッカケとなった作品の1つです。
あとテンポをステージ1よりもゆっくりめにし、かつステージ1より手強い敵にしようという事で大型機の比率高めで構成しています。重厚感。八ツ橋だけど。

Hello, Geo

地形が出てきます。私はこの瞬間に凄くテンションが上がるのですが、そう感じるのは変な方向へ訓練された人だけでしょう。
製作中も凄くテンションが上って、この辺りから開発のスピードが加速していったのを覚えています。テンションが上がりすぎてキツイ地形が多めになってしまったのが反省点です。前編で出てきた非ゲーマーの彼にテストプレイして貰ったら怒られました。その時からはある程度はマシになっているけど。

f:id:kmc-log:20141223105028p:plain

分かる人には分かる、露骨にワイドショットを要求してくるこの感じ。ここまで分かりやすくしてみて、その意図が果たしてどの程度の人に伝わったのか。

f:id:kmc-log:20141223105159p:plain

序盤の地形パターンがレイディアントシルバーガンの3-B序盤そのまんまです。横の敵の動くルートも似ています。
シルバーガンでの最初の地形もコレなのでちょうどいいかな、と思ってついやってしまったのですが、何を思ったか本家よりも地形が大きいです。落ち着け私。
左右の壁の間に入る部分で壁に激突する人が結構いました。まぁ確かに狭い。

砲台とか

f:id:kmc-log:20141223105513p:plain

八ツ橋が壁にくっついて砲台になっている、というビジョンはかなり初期から見えていました。
地形の関係もあって、正面に回りたくない感じ。ワイドショットを使えというメッセージです。 右側の明らかに殺意が無い位置にいる砲台はスコアラーへ向けた餌です。右からくる雑魚をワイドショットで捌いていると勝手に沈んでいる事が多いのですが。 それだけだと単調なので、浮かんでいる回転砲台なども設置(左上隅)。正面ショットじゃないと撃ち込みにくい配置にしています。
ある程度放っておくと下の通路に弾を撃ってきて狭くて避けづらい、というようにタイミングを調整しています。初期角度を弄るだけで難易度が変わってくるのは面白いですね。
うまい人はココまでの処理がスムーズなのでこの敵もすぐ処理できるけど、初心者はやはり後手に回りがちなので↑に引っかかって辛くなる、と。STGの理ですね。この辺りの概念ももうちょっと伝わりやすくする工夫を盛り込みたいところなのですが。

ボス

f:id:kmc-log:20141223105740p:plain

地形の中を動き回る八ツ橋を相手にするボス。
なんとなくボンバーマンの事を考えていたら浮かんだネタです。

動き自体は単純なのだけど、動く方向がランダムなので色んな状況が生まれてその対応が楽しいボスです。このゲーム最大の見所だと私は思います。

実際はかなりの強敵です。
読めない動きに対応しつつ、地形に当たらないように動きながら相手を撃たなければならない。最大の敵は地形です。
しかも敵も弾を撃ってくる。抹茶味の攻撃は正直カスだけど、イチゴ味の攻撃が壁を通り抜けてプレイヤーに飛んでくるので非常に危ないです。
戦闘開始前にイチゴ味の正面に陣取っておき、戦闘開始から速攻で撃ちこんでおいてイチゴ味をさっさと落とすのがセオリー。そういう対策を考える、という要素が織り込めたのも非常にそれっぽくて満足。
片方を倒した時点でもう片方を発狂パターンにしても良かったのですが、バニラ感を重視して却下。

大抵のプレイヤーはココやそれまでの地形でゲームオーバー。ココを抜けられたプレイヤーのほとんどは最後までクリアー出来たのではないでしょうか。
修正する機会があれば、ステージ2全体を易化したいところですね。

ステージ3

ステージ2が地形まみれだったので、お口直し等の意味を込めて地形が無いです。ステージ4があったら地形のあるステージになっていたでしょう。ステージの偶奇で性質が変わるとか沙羅曼蛇かよ(色々違う)。
まぁ本音を言えば時間が無かったので地形パターンとか考えてられなかったのですが。道中を半日×2で作り、曲を1日で書き、ボスを半日で作るという疾走感に溢れた開発でした。真似しちゃダメですよ。

ステージ2と雰囲気を変えるために、ステージ3はちょっとハイテンポ寄りです。
このステージの主題も「(ショットを適切に使うことによる)敵の効率的な排除」なので、ノリノリでショットを撃ちこんで行きましょう。
処理が遅れて行くと、比較的ハイテンポでやってくる敵達に押されて辛くなります。

周りから寄ってくる八ツ橋

f:id:kmc-log:20141223110454p:plain

自機の方に少しずつ近づいてくる八ツ橋です。すぐに害は無いものの、さっさと落とさないと弾を撃つ他の敵を排除しにくくなったり、逃げ場が失われたりして面倒です。
元ネタはイメージファイト5面の肉塊(で合ってるんだろうか)。元ネタは耐久力がなく、八ツ橋はそこそこ硬いという違いはありますが、果たす役割は同じです。

下からくるぞ

f:id:kmc-log:20141223110559p:plain

ステージ1の蛇腹八ツ橋の再登場です。リソースの使い回しは適切にやると労力を軽減できるので良いですね。時間が無い時はなおさら。

かわいいこの子を再登場させたいという想いと、後ろから敵を出したいという想いが重なった結果このパターンが産まれました。
前述の寄ってくる八ツ橋が割と画面横側からも出てくるので、後ろから来る心の準備くらいは出来てるかなーとか思っていたのですが、実際には全然そんな事はなく、多くのお客さん(ココまで来れた人は少なかったけど)に嫌な初見殺しをしてしまって猛省。
後ろから敵を出すのは危険行為でおいそれとやってはいけない事だと、少し考えれば分かることだったのに。

くるくる

f:id:kmc-log:20141223110710p:plain

黒ごま味八ツ橋が周りを回り、ガードしつつ弾を撃ちます。本体は弾を撃たないけど、回りが一応決まった方向に弾を撃っているので抹茶味。
敵がグルグル回転しているとテンション上がりますよね。この辺りはよくある要素なので、特定の元ネタを挙げる意味は薄いですが、私は超連射68kの2面のミサイル出すザコとかそんなアトモスフィアを意識して作りました。あとファンタジーゾーンのボランダ(2面ボス)とか。

ボス

f:id:kmc-log:20141223110752p:plain

バトルガレッガより、「銀河一後方に強い戦闘機」ことブラックハート……は、あまり意識していません。偶然の一致というかなんというか、です。
ココまでこの記事を読んだ人には、ブラックハートを始めとして似たようなキャラが生八ツ橋に見える呪いがかかっています。

時間もなかったので凝ったギミックができず、単純に攻撃を激しくする方向で個性をつけるしかありませんでした。まぁラスボスだし、という言い訳は成立しますけど。
ただ、前編で書いたように私は弾幕STGが好きではないので、そういう方向ではない方向で攻撃を激しくしようとしました。中途半端な結果に終わってしまった感じがありますが。
弾を避ける事しか考えない、というのが嫌だったので、子機を射出する攻撃を多めに織り込んで子機を適切に撃ち落としていくのを重視する感じに。それでも割と適当に撃ってれば勝手に撃ち落とせてしまう感じになってしまって、練り込みが足りない。うー。

倒すとパカっと割れます。レイフォース3面ボスかよ。

いいからプレイさせろ

とまぁここまで長々と喋ってきましたが、百聞は一見に如かず、実際にプレイしてみないと分かりにくいかと思います。
ここで冬コミの宣伝を……と行きたいのですが、不運ながらKMCはC87のサークル抽選に落選してしまったので、皆様に八ツ橋シューティングをお届けすることが出来ません。オーマイガッ。
もし遊んでみたいと思われた方は、C88(受かれば)、あるいは適当なタイミングで一般公開するまでお待ちくださいませ。

最後に

というわけでこのような事を考えながら製作した「八ツ橋シューティング」、学祭では中々多くのお客さんに楽しんでもらえたようで私としては大変幸せでした。
今回の学祭で一番印象的だった出来事は、そこそこゲームを遊んでいそうな二人組のお兄さん達が初見で2ボスで散り、2回目も2ボスで散り、3回目で3ボスを倒しゲームクリアーしていった事です。
ゲームを一度触った後に、2回目3回目のプレイをしてもらう事の障壁の高さというものはゲーム製作者の方々はよくご存知かと思います。
↑の出来事はその障壁を乗り越えられたという一例であり、私に確かな手応えを感じさせてくれました。
(小学生くらいのお客さんは空気も読まずに延々とプレイするので、さっさと次の人に変われと頻繁に思うのですがそれは別の話)
またKMC内のSTG仲間でも結構しっかりとプレイしてくれた人が居るので、中々の出来になったのではないかと思います。
ただ、敵の色分けなどの仕組みがどれほどの効果を発揮したかというのが中々評価できないので、その辺りはちょっと消化不良感ではあります。

強引なまとめですが、このような事を考えながらゲーム製作をしている人が居るということが何かの参考になれば幸いです。

やたら長い文章をココまで読んで下さり、ありがとうございました。Thank you for Playing!

あと記事を書くのが遅れてマジですいませんでした(現在、12/22 の35時くらい)。

WE ARE NOW RUSHING INTO...

KMCアドベントカレンダーの明日の記事は、 lastcat 君の 盆栽日記 です。
BE ON YOUR GUARD!

イケてると思う dotfiles の管理方法

イケてると思う dotfiles の管理方法

この記事は、今年もやります!KMCアドベントカレンダー!! - KMC活動ブログの21日目の記事です。 昨日の20日目の記事はReturn Value Optimization (RVO)の話 【KMCアドベントカレンダー20日目】 - KMC活動ブログでした。

KMC5回生の wacky です。今日は dotfiles の管理方法についての話をします。

dotfiles を管理していないと

何らかの UNIX を長いこと使っていると、ホームディレクトリには自分の書いた .zshrc.tmux.conf などの設定ファイルがたくさん転がっていると思います。そして、長いこと UNIX を使っている人であれば、自分が単一のサーバにしかログインしない、というのは稀でしょう。当然、自分のログインするサーバ全てのホームディレクトリには .zshrc.tmux.conf のコピーが転がっていることになります。

さて、ここで .zshrc の設定を更新したくなったとしましょう。どこかのサーバで設定を変更したあと scp などで設定ファイルを他のサーバに移すことになりますが、大抵の場合、この「scp で設定ファイルを移す」という作業は面倒臭くてサボってしまうことが多いです。そのようなことが重なると、A というサーバでは a という更新が加えられていて、B というサーバでは b という変更が加えられていて……という状況が発生することになります。

dotfiles の管理に Git を使う

というわけで、.zshrc.tmux.conf を管理するのにバージョン管理システムを使おう、という発想が出てきます(今回は Git を使うことにします)。しかし、ホームディレクトリ全体を Git レポジトリにするわけにはいかないので(してる人を見たことはありますが)、 $HOME/.dotfiles などに Git レポジトリを作り、その中に zshrctmux.conf などを置き、 $HOME/.zshrc から $HOME/.dotfiles/zshrcシンボリックリンクを張ることになると思います。

この方法であれば、 dotfiles を更新したあとはとりあえず commit & push しておけばよく、後で別のサーバの設定ファイルが古いなー、と思ったらその時に pull する、ということが出来るようになります。

デプロイが面倒臭い

dotfiles の管理に Git を使うのは良いのですが、どうやってシンボリックリンクを張るのか、までは考えていませんでした。 dotfiles の中身が増えてくると、手作業でシンボリックリンクを張るのは骨の折れる作業です。作業ミスも増えるでしょう。また、 emacsプラグインCask で管理するなどのことをしていると「$HOME/.emacs.d/Cask が更新されたら cask を実行したい」などの要望が出てきます。自力でスクリプトMakefile を書くのも良いですが、もう少し良い方法を考えたいものです。

デプロイに ansible を使う

というわけで、ここで構成管理ツールである ansible を導入してみたいと思います。似たようなものに chef がありますが、今回は以下の2つの理由から ansible を選択しています。

  • サーバに特別なソフトをインストールする必要がないこと
    • 特別なソフトはいらない、といっても sshd と python2 がないと動きません
    • ansible は手元のマシンにさえインストールされていれば OK です
  • サーバで sudo を使う権限がなくとも動かせること

以下でいくつか例を見ていきましょう。

$HOME/.tmux.conf のデプロイ

.dotfiles/roles/tmux/files/tmux.conf

好きな設定を書いてください。

.dotfiles/roles/tmux/tasks/main.yml

---
- action: copy src=tmux.conf dest=~/.tmux.conf mode=0644

tmux.conf$HOME/.tmux.conf にコピーする、という内容です。

.dotfiles/hosts

[test]
localhost ansible_python_interpreter=/usr/bin/python2

自分自身へデプロイする場合の設定です。 Arch Linux などの python が python3 へのシンボリックリンクになっているシステムでは ansible_python_interpreter の設定を行ない、python2 を使うことを明示する必要があります。

.dotfiles/test.yml

---
- hosts: test
  roles:
    - tmux

ここまで色々と設定を書いたら、あとは

$ cd $HOME/.dotfiles
$ ansible-playbook -i hosts test.yml

とすればあとは勝手にやってくれます。

emacs の設定のデプロイ

.dotfiles/roles/emacs/files/init.el

.dotfiles/roles/emacs/files/Cask

好きな設定を書いてください。

.dotfiles/roles/emacs/handlers/main.yml

---
- name: exec_cask
  action: command ~/.cask/bin/cask chdir=~/.emacs.d

exec_cask というハンドラを定義しています。

.dotfiles/roles/emacs/task/main.yml

- shell: curl -fsSkL https://raw.github.com/cask/cask/master/go | python3 creates=~/.cask
- action: file path=~/.emacs.d mode=0755 state=directory
- action: copy src=init.el dest=~/.emacs.d/init.el mode=0644
- action: copy src=Cask dest=~/.emacs.d/Cask mode=0644
  notify:
  - exec_cask

cask をインストールし、 $HOME/.emacs.d というディレクトリを作成したあと、 init.elCask をコピーし、Cask が更新された場合は先ほど定義した exec_cask を呼びだします。

.dotfiles/hosts

先ほどと同じです。

.dotfiles/test.yml

---
- hosts: test
  roles:
    - emacs

ここまで色々と設定を書いたら、あとは先ほどと同様に

$ cd $HOME/.dotfiles
$ ansible-playbook -i hosts test.yml

とすればあとは勝手にやってくれます。

まとめ

dotfiles の管理には ansible を使うことができます。今日の話では触れませんでしたが、ansible は jinja2 というテンプレートを用いることもできます。ansible を実行した祭にはデプロイ先の情報を取得することができるので、うまく設定すればデプロイ先の OS に合わせて設定ファイルを変える、ということもできるようになります。

wacky612/dotfiles に自分の dotfiles があるので参考にしてみてください。

次回予告

明日12月22日(月)のKMCアドベントカレンダーは、 hideyaさんによる「八ツ橋シューティングについて 後編」です。

Return Value Optimization (RVO)の話 【KMCアドベントカレンダー20日目】

Return Value Optimization (RVO) の話

この記事は、今年もやります!KMCアドベントカレンダー!! - KMC活動ブログの20日目の記事です。 昨日の19日目の記事はRustは開発中だけど面白い!【KMCアドベントカレンダー19日目】 - KMC活動ブログでした。

KMC3回生のhatsusatoです。 当初はC++のrvalue周りの話をしようと考えていたのですが、rvalueの解説記事は他にたくさんあるしなあ……、と渋っていたら天啓が来たのでRVOの話をします。

RVOとは

Return Value Optimization (RVO)とは、C++におけるコンパイラ最適化技術の名前です。 その名の通り、関数の戻り値に対して余分なコピーや一時オブジェクトを削減する最適化を施します。 コピーコンストラクタには副作用のある処理を書くこともできるので、コピーを削減するRVOがあるのとないのとでは、最終的な実行コードが異なることがあります。 しかし、C++の規格においてRVOは例外的に、たとえ実行コードが変わってしまうとしても行ってよい最適化として認められています。 実際には、コピーやムーブなどにおいてよほど変な処理を書かないかぎり、問題になることはありません。 この機能はよくあるC++コンパイラ(GCCとかClangとかMSVCとか)にはだいたい備わっていて、普段誰もが何気なくお世話になっています。

RVOのしくみ

最適化が適用される主な状況は、関数の戻り値などの一時オブジェクトをreturn文で戻すときです。

#include <iostream>
struct A {
  A(int i = 0) : x(i) {}
  A(const A&) { std::cout << "copy"; }
  int x;
};
A rvo() {
  return A();
}
int main() {
  A a = rvo();  // copy が呼ばれない
  A b = a;  // copy が呼ばれる
  return 0;
}
  • RVOの例

考えてみれば関数(rvo)の戻り値(A())は、その関数の呼び出し元の受け取り先の変数(a)に値を伝えたあとは破棄するだけの一時オブジェクトなので、戻り値を返す(return A())際に直接受け取り先(a)に書き込んでも問題ないはずです。 このような状況において、RVOが実装されているコンパイラでは余分なコピーや一時オブジェクトを削減してくれます。

void rvo(A* _result) {
  new (_result) A();
  return;
}
int main() {
  char a[sizeof(A)];
  rvo(reinterpret_cast<A*>(a));
  reinterpret_cast<A*>(a)->~A();
  return 0;
}

まるでメンバ関数における暗黙のthisポインタのように、関数の引数に戻り値を格納する先の変数へのアドレスを渡します。 そしてそのアドレスの先の上にオブジェクトを構築することで、関数内部での一時オブジェクト生成を呼び出し元のオブジェクト生成とみなすことができます。 このようにしてRVOは実現されています。

さらにNRVO

RVOをさらに推し進めたNamed Return Value Optimization (NRVO)というものがあります。 これはRVOよりも強力な最適化を施しますが、実装されているコンパイラは限られています。 先のRVOではreturn文で戻していたのは一時オブジェクトでしたが、NRVOは名前のついたローカル変数を戻すときに働く最適化です。

A nrvo(int y) {
  A a;
  a.x += y;
  return a;
}
  • NRVOの例

最終的に戻す変数(a)のすべてを、暗黙に受け取った戻り値の格納先(_result)で置き換えることでNRVOを実現しています。

void nrvo(A* _result, int y) {
  new (_result) A();
  _result->x += y;
  return;
}

戻り値として返したいオブジェクトはすべて_resultで表せないと行けないので、すべてのreturn文で戻すオブジェクトが同じオブジェクトでないと最適化が働きません。 同様のことはRVOにも言えます。 同じオブジェクトを返したからと言って最適化が適用されるかどうかはコンパイラによりますが。

A not_nrvo() {
  A a, b;
  return true ? a : b;
}
  • NRVO最適化が適用できない例

まとめ

RVO(およびNRVO)はC++コンパイラにおいて人知れず働き、コードを壊さない範囲でラジカルな最適化を行い、C++のコードを高速化しているのです。

次回予告

明日12月21日(日)のKMCアドベントカレンダーは、 wackyさんによる「イケてると思うdotfilesの管理方法」です。

参考文献

Rustは開発中だけど面白い!【KMCアドベントカレンダー19日目】

あ…これゲームの紹介みたいなタイトルだわ…

この記事は、今年もやります!KMCアドベントカレンダー!! - KMC活動ブログの19日目の記事です。

また、昨日18日目の記事は八ツ橋シューティングについて(前編) 【KMCアドベントカレンダー18日目】 - KMC活動ブログでした。

みなさんこんばんは。KMC二回生のnendokiです。MacBookからMac OS Xを削除するものに鉄槌を下す仕事をしています。

ところで、流行り廃りがあまりにも激しく、あらゆるドキュメントはジンバブエドルのごとくちり紙になることで有名なIT業界ですが、その流れはもっと根本的な、プログラミング言語にまで押し寄せているようですね。

少し前には無数のJS(など)に変換するための言語(いわゆるAltJS)がこの世に産み落とされ、Apple社がSwiftというプログラム言語を発表したことも記憶に新しいかと思います。

今回はタイトルの通りRustというプログラミング言語を紹介します。RustはFirefoxで有名なMozillaが開発主体となっている言語で、2010年ごろ発表だとか2012年にバージョン0.1が公開されたとか(wikipediaより)で割と最近の言語だと思います。印象としてはC++の文法に関数型言語の概念を足してモダンで安全になった言語って感じなので、ビルド環境を整えさえすれば気軽に書き始めることができます。

書き手の時間もないので、Rustの書き方とか機能とかチュートリルとかは該当記事に譲るとして、せめて何が面白いのかなーくらいをつらつら書いていきます。開発中なのでこの仕様はすぐに変わるかもしれません。

参照

Rustの公式ページでは、言語デザインについての哲学についての言及(The Rust Design FAQ)がなされています。

そこにはメモリの安全性は譲れないといった感じの強めの文章が目に飛び込んでくることから、値の扱いについてが言語設計の中心にあることがわかります。実際にプログラマはデータをコピーを減らしつつメモリ上にどう載せるかを考えてプログラムを書くことになります。

特徴的な例として、Rustではポインタは使わない代わりに、nullが許容されない参照を用いることになります。

参照にはlifetimeというラベルのようなものが与えられており、これは値が生成された場所に対して静的に決められます。このlifetimeは関数の返り値とか構造体への格納を行うときに明示する必要があります。逆に言えば、lifetimeのおかげで参照を抱えた構造体といったC++的には微妙極まりないものでも安全に扱うことができるわけですね。

もう一つ、参照には面白い概念があります。それがborrowingと呼ばれるしくみで、大雑把には変数が参照によって参照されている場合、参照元の変数を書き換えることを禁止する仕組みです。参照のスコープを外れることで、参照元の変数は再び書き換え可能になります。この機能は、同じ変数を同時に書き換えたり、使用中に突然値が変わるようなものを防ぐことになるため、マルチプロセスなプログラムを作るときには強力な仕組みとなるでしょう。

box

「lifetimeがあれば参照だって返せるし安全高速だよ✩」と言われても値を作って返す系の関数にはまるで意味がないだろ馬鹿野郎という話になりますね。実際、ポインタを排して参照だけとするとヒープ領域を操作することができません。boxはヒープ領域へのポインタを表す型です。デアドレスも参照と同じ演算子を使います。

このbox、式に対してboxとつけるだけでヒープ上に確保されたことになるお手軽演算子でもあります。余談ですが、古いドキュメントとかでは~演算子が割り当てられたりしています。

boxはヒープ領域へのポインタという書き方は少しだけ正確ではなく、正しくはヒープ領域へのuniqueポインタです。boxを他の変数へコピーすると、元の変数が失効し、参照できなくなります。普通にスコープアウトした場合にメモリを開放すれば良いので、安全に扱うことができそうですね。

ところで、関数へはどのように渡せば良いでしょうか。関数の引数はコピーとして与えられるので、普通に与えたら壊れます。この場合は、boxそのものか一度デアドレスしたものへの参照を与えてやることになります。参照とboxの仕組みが若干ぶつかっている気がしますが、そこは今後に期待ですね。

boxの機能は非常によく使うもののため、幾つかの便利構文があります。その一つにlet boxのように書くことで気軽にunboxできます。以下の例はあまり意味のあるものではありませんが、box内部の値を、boxを破壊することなく取り出しています。box内部への参照が欲しい場合は、let box refと書くことができます。

    let x = box 1u;
    let box y = x;

このbox refという記法はパターンマッチ内でも使うことができるため、boxを含んだenumといったものも簡単に扱えるわけですね。

便利なenum

Cの機能にあったenumとかC++11で新しくなった*1enumとかからさらに進化したenumです。いわゆる関数型プログラミングお馴染みの代数的データ型が採用されています。要するに強い型付けがなされるtagged unionですね。

C++とかでoptional型を作ろうとすると非常に面倒くさいらしいですが、Rustなら以下の通りです。

enum Option<T> {
    None,
    Some(T),
}

Some(T)というのは、T型の値を持つSomeという値になるわけですね。取り出す時にはパターンマッチを使います。

fn is_some<T>(x: &Option<T> ) -> bool {
    match *x {
        Some(_) => true,
        None => false
    }
}

Someの値を使いたいときは_をxとかに置き換えればいいです。コピーコストが怖い場合はref xとか、boxの中身が欲しい場合はbox refとか書くと幸せですね。

ちなみに、Option型は、unsatableながら便利な関数が多いので一度見てみると良いかもしれません。

trait

haskellの型クラスのようなものです(完)。とはいかないので簡単に述べると、未知の型に対して関数を宣言したり実装したりすることができます。オブジェクト指向的に使いたい場合は、構造体を宣言してすぐにその構造体に対してtraitを設定することになります。Javaでいうインターフェースのような使い方をしたい場合は、traitとして適当なインターフェース名にして、他の構造体に対応する実装をimplで個別に与えてやる形になります。

この時、第一引数がself&self&mut selfの場合は、インスタンスメソッドになり、それ以外の場合はクラスメソッドになります。ちなみキャストの関係はself->&self<-&mut selfなので、特にメンバ変数を変更する必要がない場合は&selfで、どうしても変更する必要がある場合は&mut selfだけを実装するのがオススメだそうです。

C++で言う所のtype traitsなのでしょうか。まあ扱いやすくなっていると思います。

まとめ

三つだけかよとお思いの方もいらっしゃるかと思いますが、単純に私のHPが尽きました。チュートリアルにはもっと魅力的な機能がわかりやすく解説されているのでオススメです。

参照だけで十分だとか静的型検査なんて必要ないとのたまう軟弱な言語と比べれば、いかに安全さと速さを求めているかがなんとなくわかるとおもいます。

さて、次回はhatsusatoさんの「C++11 の rvalueの話」だそうです。C++を軽くドついたあとのになってしまい、少し申し訳ないですね。

それでは。

八ツ橋シューティングについて(前編) 【KMCアドベントカレンダー18日目】

この記事は 今年もやります!KMCアドベントカレンダー!! - KMC活動ブログ の 18 日目の記事です。

昨日の記事は spi8823 君の Unity4.6で実装されたuGUIを触ってみた【KMCアドベントカレンダー17日目】 - なんかのあれ でした。

おはようございます。KMC5回生のhideyaです。
KMCでの主な活動は、ゲーム製作と良心です。

この記事は?

KMCが2014年の京都大学11月祭(NF)に出展したゲームの1つ、「八ツ橋シューティング」の製作において製作者が考えていた事などを紹介しようというものです。

f:id:kmc-log:20141219035707p:plain

↑こんな見た目のゲームです。

シューティングゲーム(以下、STG)としての特徴

  • 敵が全て同じ見た目(生八ツ橋)
  • 敵が性質毎に色分けされている
  • 2種類のショット

くらいだと思っています。
弾幕STGではありません。私は弾避けが下手なので、弾幕STGはプレイしてると苦しいのであまり好きじゃないんですよ。それでも良い作品はプレイしていて楽しいですが。

各コンセプトを組み込むに至った理由などについて書いていきます。

敵が全て同じ見た目

2年ほど前に、鳩サブレディウス ( http://nekogames.jp/g.html?gid=HATOSABURE ) をプレイしたのがきっかけです。

敵キャラも自機も敵弾もパワーアップカプセルも見た目が全て鳩サブレというとても思い切った作品です。
その結果として必要なリソース(この場合は画像)がかなり削減できる上、ギャグ的な意味でかなりの存在感を発揮しておりなるほどなぁと感心し、この手法は使えるかもしれないと思いました。

この時はまだ八ツ橋シューティングの八の字すらありませんでした。

八ツ橋

私の通学路に、2軒の八ツ橋屋が向かい合わせになっている場所があります。

f:id:kmc-log:20141219035647p:plain

激戦区って感じですね。毎日この間の道を通っていると、八ツ橋について思いを馳せるようになるのは当然なわけで。
その結果、「硬八ツ橋と生八ツ橋の対立」というネタが浮かび上がりました。

この時点で八ツ橋シューティングの八ツ橋の部分までは来ました。
とはいえシューティングになるとは特に思ってませんでしたし、そもそもこのネタでマトモに作品を一本作るかどうかすら真面目に考えてませんでした。

敵の色分け

少々小話をはさみます。

私は他人がゲームをプレイしているのを見るのが好きです。幼少時から兄がゲームをプレイしているのを見て楽しんでました。
特に自分が好きな作品を他人が遊んでいるのを見るのは楽しいもので、KMCの部員にゲームを遊ばせて眺めるという遊びを日頃からしていました。いわゆる布教です。もしくはゲームセンターCXです。

そんな私の布教に良く付き合ってくれる某部員が居るのですが、彼は日頃からよくゲームを遊ぶ、いわゆる「ゲーマー」ではなく、ゲームに対する慣れがあまりありません。
そのため、彼のプレイを見ていると私が苦もなく抜けた部分で詰まったり、マジかと思う行動を取ったりして、彼本来のキャラも相まって見ていてとても楽しいです。
しかし彼のプレイを見ることは楽しいだけではなくて、結構勉強になるのです。

彼にとあるSTGを遊ばせていた時のことです。そのSTGは戻り復活性のパターン構築ゲーで、彼は同じポイントで何度も何度もリトライを繰り返しました。
横で見ながらなぜ上手くいかないかを考察してみたところ、彼のプレイには以下の問題点がありました。

  • 敵の性質を覚えていない・分かっていない
    • → 弾を撃たない敵に夢中になって、危険な敵の処理が遅れてそいつに追い詰められる
  • 敵の出現・行動パターンをあまり覚えていない
    • 覚えていても、そのパターンに対応できる動きをしない
  • ゲームオーバーになったら頭を冷やさずにすぐにリトライする
    • = 死因を振り返らない

ここで大事なのは、これらは彼自身の身体能力(動体視力や反射神経など)や操作能力(当然そこまで上手くはないのですが、その場面を切り抜けるには十分だと感じました)に依らないものであり、むしろゲームを攻略する上で必要な思考が出来ていないのが原因である、という事です。
↑に挙げたものはSTGに限らずアクション系のゲームを普段プレイする人は無意識のうちにやっている事が多いです(もちろん全員がそうしているとは限りませんし、一番下なんかは私もよく怠りますが)。
彼自身は謎解きなどが好きであり、頭を使うのには慣れているはずの人です。にも関わらずそうした思考が出来ていない(ように見えた)のは、こういった思考がゲームをやらない人には馴染みのないものであるからだ、と私は考えました。
そこでホワイトボードを用いて敵の性質の解説をし、敵がどの順番で出てくるかを思い出させ、その局面でどう動くべきかをクイズ形式で答えさせる、という形で手助けをしてみました。
もちろん私は正解パターンを知っていましたが、それを教えてはお互い何も面白くないのであくまでも「思考の誘導」に留め、彼自身に正解を考えさせました。
その結果、何度かの試行錯誤の末に数回に一回はその場面を抜けられるようになりました。そこまでの疲労もあってその後のボスでギブアップとなってしまったのですが、敵の動き等を分析してそれに合った行動を考える、というSTGの(パズル的な側面での)楽しさを感じてくれたのではないでしょうか。

さて、↑の小話で何が言いたかったかというと、ゲームを攻略するための思考プロセスというものは誰しもが持っている訳でもなく、プレイしていればすぐ習得できるとも限らない、ということです。
そこで私は、ゲームに慣れてない人でもこのような思考をできるように誘導する仕掛けがあれば、そういった人にもその辺りの楽しさが伝わりやすいのではないかと考えました。
その結果、STGにおいて先程の「敵の性質を覚えていない・分かっていない」という部分の対抗策となる仕掛けとして「敵の性質がパッと見で分かるようにする」というものを考えました。
敵の色や形でどんな事をしてくるかがすぐに分かるようにすれば、それに対応した動きが初心者でもしやすいのではないか、という事です。
もちろん、見た目の違う敵は違う動きをする、色が違う敵は何かが違う、というのは当然のように行われる事ですが、それをもっと徹底して初見でも分かるくらいにしたらどうなるかなー、と。

3本の矢

ここまで3つのアイデア(同じ見た目の敵、硬/生八ツ橋の対立、敵の色分け)が浮かぶ過程を長々と書きましたが、すぐにそれらが合体して1つのゲーム案となった訳ではありません。

さて、今年の6月、私はかの有名作、レイディアントシルバーガン(Xbox Live Arcade版)を今更になって遊んでいました。
そのステージ3-B、狭い通路の中を赤・青・黄色の三角形状の敵機が列になって向かってくる場面に差し掛かった時です。

――こいつら、生八ツ橋に見える。

なぜそのような突飛な発想を持ったか今でも分かりませんが、その瞬間に↑の3つのアイデアが1つになりました。
硬八ツ橋を操作して生八ツ橋達を撃ち落とすSTG。敵がことごとく生八ツ橋なのは(すごく鳩サブレディウスのパクリっぽいけど)見た目として十分面白いだろう。しかも生八ツ橋なら色んな味という名目で色分けができる!!

f:id:kmc-log:20141219041745p:plain

↑特性(攻撃の種類)ごとの色んな味。

ここまでキレイにアイデア達が噛み合ってしまったら、作るしかない。八ツ橋シューティング誕生の瞬間です。

余談ですが、そんなことを考えている間に私の操作する自機はスコア稼ぎに失敗した挙句、安全地帯に入り忘れてボスのレーザーに焼かれていました。

2種類のショット

その時遊んでいたレイディアントシルバーガンは7(+1)種類もの多彩な武器を使い分けるSTGであり、それらの特性を把握して適切な使いわけをするのが楽しい作品です(他にも色々素晴らしい点はあるのですが、それだけで記事が1本かけるので割愛)。
元から武器の適切な使い分けという要素は私の好物であり、丁度このような武器の使い分けをするゲームを遊んでいる時にゲームを作ろうと思ったら、武器の使い分け要素を入れたくなるのは当然の理です。

このコンセプトだけ物凄く取ってつけたようなものですが、実際その通りなので仕方ないです。

どういった武器を何種類使わせようか、という点ですが、まぁ私の技量でバランスを取りきれるのは3つくらいだろう。素直な正面ショットと、広範囲ショットと、近接攻撃みたいな「ちょっと使いにくいけど上手く使うと高威力出せたりしてドヤ顔できる武器」かなー。この辺は単なるフィーリングです。
開発の諸事情(時間とかバランスとか)により3つめのドヤ顔武器は消え、結果として以下のような2種類のショットが実装されました。

f:id:kmc-log:20141219040740p:plain

正面ショットはまぁ文字通り。
シルバーガンのように単発撃ちが出来るようにしようかな、と思ったけどそういうのが必要なゲームにするつもりはなかったから10秒で却下。
そもそもツインショットである必要も無いっちゃないのですが、単装だとなんとなくショボく見えませんか?要は只の趣味です。
いや実際には横幅を増やして当てやすくするとか、ちゃんと両方当てないと威力カスいよ、とか2連装にすることによるゲーム的な影響はあるんですが、その辺は特に考えてませんでした。

広範囲ショットは最初は爆風を起こさずに単なる散弾だったのですが、使ってて地味だったのでカリスマ性を持たせるために爆発させてみました。
キレイな爆風が出ることによって、思わず使いたくなる武装になりました(個人の感想です)。
それはそれとして群れる敵に対しての効果が大きくなったので、広範囲の多数の敵を攻撃すると強くなっていい感じになりました。
あと単なる便利武装になってコレばっかり連射してればいいや、となるとそれはそれで悲しいので、連射力と初速を抑えてちょっぴりクセのある感じにしてみたりとか。まぁ只の趣味です。

正面ショットの名前が「ストレート」ではなく「ストレト」となっているのは、マニュアル制作を担当したjf712君の魂です。ワイドの方は普通ですね。
ちなみに、私の脳内ではそれぞれ「八ツ橋バルカン」「スプレッド八ツ橋」でした。まんまシルバーガンじゃねぇか。

また、正面ショットだけで広範囲の敵を素早く処理できてしまっては広範囲ショットの意味が薄くなってしまうため、自機の移動速度はゆっくりめにしてあります。
製作者にとっては「いかに広範囲ショットも使わせるか?」がゲームシステム上のメインテーマなのでこのような調整も必要です。もちろん適切なレベルデザインも必須です(こちらについて詳しくは後編で)。

そして後編へ……

というわけで、ゲームシステム的な部分についての喋りたいことは大体書きました。
長い文章をここまで読んでくださった皆さんありがとうございます。

ところがどっこい、ゲームシステムを作っただけではゲームは完成しないわけで。
これらのシステムを活かしてプレイヤーに良いゲーム体験をしてもらう為には、レベルデザインというものをしなければなりません。
いかにして楽しくショットを使い分けて貰うか?という部分がメインですが、それ以前のSTGとして一般的な撃って倒す楽しさ攻撃を切り抜ける楽しさという部分も決して疎かにできません。
システムが同じものでも、レベルデザインが違えば主張の異なるゲームとなるでしょう。
つまり、レベルデザインにおいても色々込めてあるモノ(オマージュとかも含めて)があるわけで、それについても語らなければいけません。

とはいえ、この後に続けてしまうと文章量が酷い事になるので(え、既になってるって?)、KMCアドベントカレンダーにもう一枠取ってあります。4日後、22日目の12/22ですね。
というわけで、次回の「八ツ橋シューティングについて 後編」に続きます。
ここまででうんざりしていなければ、その時にまたお会いしましょう。それでは。

WE ARE NOW RUSHING INTO...

KMCアドベントカレンダーの明日の記事は、 nendoki さんの rustとか です。
BE ON YOUR GUARD!