積んでるゲーム紹介6:ロックマンDASH2
積んでるゲーム Advent Calendar 6日目です。
今日紹介する「ロックマンDASH2」は割といわくつきの逸品です。
なにせ3回もニューゲームして、そのうち2回も同じダンジョンで詰まったゲームだからです。
最初にやったのは中学生の頃、友人から借りてプレイしました。
でもあるダンジョンで行き詰まって、どうにもいかないうちに期限が来て返してしまったのです。
「あの頃クリアできなかったDASH2を是が非でもやりたい……!!」
そう思って、大学生時代の時、たまたま中古ショップで見つけたPS版DASH2を即買い。
しかし昔やってた頃よりアクションが難しくなっており*1、
前回詰んだ箇所まで行かずに積みゲーの墓場行き……。
「ぬあぁ~~~~、もう一度やりたい! 今度こそクリアしてやる!!!」
と社会人になってからフラストレーションが溜まりはじめたが、肝心のPSがない!!
仕方ないのでPSP版を購入してPSPでプレイ。
最初に詰まったダンジョンまでは行き着いたものの、やっぱりどこへ行ったらいいかわからないうちに、PSP自体を紛失……。
と、3戦3敗という燦々たる成績を残しているわけであります。
アクションゲー下手すぎでしょ……。
「じゃあどこの遺跡で詰まったの?」と思うところでしょう。
それはね、
ニーノ島の遺跡だよ!!
あの水中ダンジョンマジでわからんかった……。
*1:人それを「アクションゲーの腕が落ちた」と言う
DxRuby::Spriteの思想を信じよ
Ruby Game Developing Advent Calendar 2016 6日目の記事です。
昨日はvivit_jcさんの「DXRubyで作ったシューティングゲームを交えて高校生向けプログラミング講座をしてきた話」でした。
実際あのプログラムを一晩で書いたって聞かされたときは「は?なんだよ天才かよ」って思いました。さすがvivitさんやね!
あと1~2日目の記事を見て「司エンジンむっちゃ面白そうやん……」ってなったので、来年あたり使ってみたい。
本日は拙作「パズルっぽいゲーム」を制作した時の、DxRubyのSpriteの設計に大変助けられたよ、というお話をします。
7年越しの落ちゲー2度目の挑戦
実は「落ちゲー*1を作ろう!」と思ったのは今回が初めてではありません。
思い返せば7年ほど前。自分のPCとVisualStudio、そしてDXライブラリを手に入れて無敵感に舞い上がった私がまず作ろうと思ったのが
「ポーカーゲーム*2」と「落ちゲー」でした。
そして旧版と「パズルっぽいゲーム」を比較した時、より短期間でよりグレードの高いものになっています。
一体どうしてでしょう?
Spriteの仕様にゲームを“合わせる”
それは私のプログラミング能力が向上したから!!
――で済ませてもいいのですが、実際はそうでもないです。
今回「パズルっぽいゲーム」の制作では、(結果論ではありますが)DxRuby::Spriteの以下の3つの特徴にトコトン乗っかる形で設計していきました。
- Spriteは継承してナンボ
- 更新したいものはすべてSprite.update()に突っ込む
- 描写したいものはすべてSprite.draw()に突っ込む
これが功を奏したのでは、と思うんですよね。
しかしこれ、言葉にすればチョー簡単ですよね?
実際に見てみましょう。下記がPuzzleField.rb(一部抜粋)。ゲームの肝となるクラスです。
# パズルフィールドクラス class PuzzleField extend Forwardable def_delegators :@fight, :attack # パズル中のメインループ処理 def process # アニメーション実行中なら消去/移動は行わない unless animating? processes = [Proc.new{ fall }, Proc.new{ erase }, Proc.new{ raising }, Proc.new{ move_player }] processes.each do |pr| # trueが返ってきた(何らかの処理が実行された)ら、そこで打ち止め break if pr.call end end update end # 描写のみを行い、内部の更新を一切行わない # ポーズ時などに使用 def draw Sprite.draw([puzzle_objects, @field_images, @chain_counter, @score, @level, @damage_counter, @back_image]) end # 各種更新処理&描写処理 def update Sprite.update([puzzle_objects, @sounds.values, @erase_sounds, @score, @level, @damage_counter, @cube_factory]) Sprite.clean(@cubes) draw end # キューブとプレイヤーの合算 def puzzle_objects [@cubes, @player].flatten end
注目すべきはupdateメソッドとdrawメソッド。
ここに突っ込んでるのはすべてSpriteを継承した各種画像オブジェクトです。
updateで座標やらを更新して、drawで書き出す。もうチョー簡単! めんどくさいこと一切なし!
めんどくさいことはprocessメソッドの中にある fall(), erase(), raising(), move_player() の四天王が一括して管理してます。
旧版ではどうやってた?
ちなみに旧版でどうやってたかというと、例えば描写が以下の通り*3。
void cField::view(){ ClearDrawScreen(); int color; for( int i=1; i<FIELD_WIDTH-1; i++ ){ for( int j=1; j<FIELD_HEIGHT; j++ ){ switch( field[i][j] ){ case FLARE: color = GetColor( 255, 80, 80 ); break; case AQUA: color = GetColor( 40, 200, 255 ); break; case GAIA: color = GetColor( 40, 160, 40 ); break; case GUST: color = GetColor( 220, 220, 220 ); break; case STELLAR: color = GetColor( 255, 250, 100 ); break; case METAL: color = GetColor( 40, 40, 60 ); break; case NEU: color = GetColor( 40, 0, 40 ); break; default: color = GetColor( 0, 0, 0 ); } DrawString( i*20,j*20,"●",color); } } DrawString( cursor.x*20,cursor.y*20,"★",GetColor( 255, 255, 255 )); DrawLine( 15, 276, 160, 276, GetColor( 255, 255, 255 ) ); DrawString( 300, 20, "ESCで終了・SHIFTで段上げ", 0xffffff ); ScreenFlip(); }
わぁすごい! 神クラスによる一括描写だ!!
ちなみに新版ではupdateまでですべての作業を終わらせて、drawはSpriteのメソッドを呼んでいるだけなので、ある意味0行です。
座標情報はオブジェクトの中に持った方がいいんじゃない?
あとrubyに関係ない設計の話ですが、旧版と新版で大きく違うなぁと思う場所がもう一点。
旧版は、ブロックや自機がどこにいるかという座標情報をfield二次元配列の順序という形で持っている。
新版は、座標情報をブロックや自機の基底クラスPuzzleObject内にPosオブジェクトとして持っている。
どちらがいいかと聞かれたら、そりゃ後者じゃないのかなって。
「配列の位置関係」という形で座標を持つと、ブロックが移動するたび配列の要素の交換が発生します。
この手の落ちゲーは何につけてもブロックや自機が動くし落下するし競り上がるしで、交換の手間が馬鹿になりません。
それより何より、添字として持つことで「Posをオブジェクトとして扱えない」という欠点もあります*4。
Posに雑にメソッドを突っ込んでいくのはいいぞー、楽しいぞー。
# 座標を表すクラス class Pos attr_accessor :x, :y def ==(o) @x == o.x && @y == o.y end def eql?(o) self == o end def +(o) Pos.new(@x+o.x, @y+o.y) end # 座標が指定する範囲内にあれば真を返す def between?(x_range, y_range) x_range.include?(@x) && y_range.include?(@y) end # 座標を指定する範囲内に収める def clamp(x_range, y_range) @x = @x.clamp(x_range) @y = @y.clamp(y_range) end # チェックすべき範囲のPos群を得る # ただしcheckedに含まれるものは除く def check_positions(checked = Set.new) result = Set.new(Pos.directions.map{|p| self + p}) result.select! {|pos| pos.between?(0..FIELD_WIDTH-1, 0..FIELD_HEIGHT-1)} result - checked end # 1歩分進むための配列を返す def self.directions [Pos.new(0,1), Pos.new(-1,0), Pos.new(0,-1), Pos.new(1,0)] end end
その他こまごまとしたこと
Sprite継承推奨法則を応用して、
Ayameを継承したMusicクラスを作り、
さらにMusicが同時に鳴らないようにJukeboxクラスを作って制御してたりします。
とまぁ、こんな感じです。
「パズルっぽいゲーム」はゲームをDLすれば雑にコードが確認できるから*5、
皆もDLして教師にするなり反面教師にするなりしてくれよな!!
明日は……あれ?! 明日誰もいないぞ!?
まぁでもきっと誰かが颯爽と現れて良記事書いてくれるでしょう。
そう期待してますんで! 頼むよ! お楽しみに!!
積んでるゲーム紹介5:ゴジラ -GODZILLA-
積んでるゲーム Advent Calendar 4日目です。
こいつはなんていうかその……。
爽快感があるかと言われるとそんなこともなく
重厚感があるかと聞かれるとそういうわけでもなく。
身も蓋もない言い方をすれば、ゴジラが街を闊歩して目標の建造物を破壊するだけ。
「ゴジラを操って街を壊す」ところがウリなんだろうけど……、個人的にはそこに楽しみを見出だせなかった。
ゲームとして捉えても、序盤は簡単すぎるし
中盤スーパーXとスーパーX2が出てくると途端に難しくなるし。
「ゴジラのファンなら絶対買い!!」みたいなノリに煽られて買ったはいいものの……。
そういう安易な動機で買うべきゲームじゃなかったと思います。
積んでるゲーム紹介4:影牢 ダークサイドプリンセス
積んでるゲーム Advent Calendar 4日目です。
今回紹介するのはPS3ソフト「影牢 ダークサイドプリンセス」です。
こいつは刻命館シリーズの1作なのですが、
私と刻命館シリーズとの出会いは「蒼魔灯」のときでした。
蒼魔灯は物語全体に漂う悲壮感と、
舞台となるお城の中世を彷彿とさせる誂えが非常に気に入っています。
ストーリー後半の地獄騎士が強いのなんのっての……。
友人から教えてもらった「ベアトラップ→バズソーLv3」必殺コンボがなければクリアできなかっただろうなぁ……。
前々から存在は知ってたし、いつかプレイしたいなぁとは思ってたんで、PS3買ってから割と早い段階で買ったんですよね。
一番期待していたベースのところ、
トラップを仕掛けてコンボを決めて侵略者をぶち殺す部分はちゃんと楽しみとして存在してると思います。
また、トラップ無効の侵略者も多く、安定したコンボが存在しないので
逆に頭を働かせる余地があるとも思います。
でも残念な点も3点ほどあります。
第一に、アーマーブレイクの条件が厳しい。
弱点となるトラップを当てなければならないのですが
どれが弱点であるかは特に明示されておらず、
事前の攻略情報なしだとまず狙ってできるものではない。
アーマーブレイク付けるなら、もっとポンポン女の子を剥かせるようにしてもよかったのでは。
第二に、捕虜が苦労が大きい割にリターンが少ない。
個人的にこれが一番辛かったかもしれない。
せっかく女の子を捉えて鳥かごに突っ込んで置けるんだから、
もうちょっと3Dで下着姿を360度上下左右から眺めるとかさぁ!!
そういう意味ではホントにやりこみ要素以上の何者でもないです
第三に、これは単に好みの問題だけど、ステージがダサい。
俺は第一ステージみたいな荒れ果てた古城が好きなんだ……。
廃工場はスチームパンク的にまだ許容できるけど、廃遊園地ってなんなんだ……。
しかもお化け屋敷暗すぎて見えねぇ。
蒼魔灯の段階で「女の子を痛め抜いて悲鳴を挙げさせまくった上で断末魔を聞く」という
リョナ向けのコンセプトは完成されていたんだから、
要素を追加するならもっと媚びてほしかった。それこそ閃乱カグラレベルで*1
積んでるゲーム紹介3:ユバの徽
積んでるゲーム Advent Calendar 3日目です。
今回紹介する「ユバの徽」はソシャゲです!!
ほら今あなた、
「ソシャゲにはクリアなんて概念ないんだから、”積んでる”って言わないだろ!?」と
思いませんでした?
逆に考えるんだ、
「すべてのソシャゲはやがて積まれる運命にある」と!!
自分の過去を振り返った時
複数のソシャゲ(スマホゲー)を並行してやった記憶がほぼありません。
「熱しやすく冷めやすい」と言えばそれまでなんでしょうが、
もしかすると「ソシャゲのリソース回復待ちの間に別のソシャゲをやり始める」という
負のスパイラルを恐れた結果なのかもしれません。
閑話休題。
ユバの徽は「艦これ」同様にソーシャル要素が少なく、
ソシャゲというよりはFree-to-Playのオンラインゲームに分類されるでしょう。
このゲームの特徴は、悪趣味なまでに徹底された死と生贄に根ざしたフレーバーです。
- 戦士のレベルを上げるには、他の戦士を生贄にしなければならない
- 戦士には保有上限があるので、どんどん生贄にしないと次がつかえる
- 祈り人(俺屍でいう神様役)にも保有上限があるので、空きがなくなったら生贄になる
- 祈り人のエピソード解放条件の1つに「進化させてから生贄にする」がある
- 1人ガチャをすると、2人のうち片方を選び、選ばれなかった方は見殺し扱いになる
- 敵を倒すとドクロがもらえる。ドクロを祭壇にささげることで祭壇レベルが上がる(艦これで言う司令部レベル)
もともと私はエログロリョナも好きだったので
「そんな思い切ったゲームが出たのか! よっしゃやったろ!!」と喜び勇んで始めました。
これに関しては1~2ヶ月くらいどっぷりハマってましたし、多少ですが課金もしました。
戦士と祈り人が契り(意味深)*1をして新たな戦士を産むシステムなんですが、
この遺伝を模したシステムを使って、いろんな遺伝子の組み合わせを実現するのが純粋に楽しいんですね*2。
ゲームバランスも序盤あたりは存外によく、
難点を挙げるとしたら、祈り人を進化させるために必要なリリースが存外に多いかな?という点くらい。
まぁでも結局は、最初のイベントが終わり、島ステージの攻略の兆しが見えない段階になって自然にフェードアウトしていきました。
戦士も6種類までは出たけど、最後の水-水系の戦士だけは出なかったなぁ……。
ちなみに、このゲームが縁で俺屍に興味を持ち、
PSゲームアーカイブスで購入に至ったのはまた別のお話。
俺屍も実は積んでるんだけどな!!
積んでるゲーム紹介2:サモンナイト4
積んでるゲーム Advent Calendar 2日目です。
今回はコンシューマーゲー。
サモンナイト4は上京してすぐにアキバの中古ショップを探し回ってやっと手に入れた一品です。
サモンナイトは1~3までは一通りプレイしていて、4もずっとやりたいと思ってて買ってみたんですよ。
ただ今回のキャラデザは従来の作品と比べるとあんまり好みじゃなくてねぇ……。
キャスト陣はむしろむっっちゃ好みなんだけどねぇ。
松岡由貴に浅川悠に後藤邑子に桑谷夏子に佐藤利奈まで出るサモンナイトなんてオラ見たことねぇ!!
買ってすぐに3~4話進めて放置、半年前に掘り出してまた3話ほど進めて現在7話ボス戦で放置中です。
いや高台から撃ってくる機械人形強すぎでしょあれ……。
まぁでもサモンナイトはなんだかんだでレベル上げすればなんとかなるだろうから、
2~3年したらいつの間にかクリアしてそう。
ちなみにサモンナイトグランテーゼも同時期に買って積んだままですね。
それにしても5と6……まだ買ってないんだけどどうしたもんかなぁ。
特に6とかCV川澄アティ先生を買わないでどうすんの?!レベルなんだけど
積んでるゲーム紹介1:Euro Truck Simulator 2
例によって例のごとく、Advent Calendarの季節がやってきたので、
性懲りもなく始めてみます。
「積んでるゲーム Advent Calender」1日目です!!
一人Advent Calendarやってるのみて羨ましくなったんじゃないんだからね!!(
去年の眼鏡っ娘は……その……なんだ……、
誰を紹介するかとか、どういう切り口で紹介するかとか
悩んでいる間に年が明けてました。スマン!!!
今年はもうちょっと雑に続けられそうなテーマを考えてみました。
積みゲーならそれこそ1年中ネタが出てきそうなくらい、
ちぎっては投げちぎっては投げしてうず高く積まれているので、
多分これなら一人でも大丈夫!!
Euro Truck Simulator 2はけんぼーさんがやってるの見て
「なんだか面白そうだなぁ!!」って言って始めたはいいものの、
操作感が滅茶苦茶難しかった。
というかカーブする時に荷台が予想外の動きをしすぎる。
初クエスト途中でバランスを崩して横転し、レッカーで運ばれたことによりマイナス資金からのスタート。
この時点で心が折れたので、以来やってないです。
ちなみにプレイ時間は26分でした。
あとこの記事書いてて思ったんだけど、Simulatorってクリアがないんだから”積む”とはちょっと違う気もするな!!