読者です 読者をやめる 読者になる 読者になる

鳥小屋.txt

ゲーム作ったり、Web的なことしたり、ぐだぐだしたりしますねヽ(・x・)ノ

かぼちゃ育成日記#3 - もうすぐ折り返し

f:id:ru_shalm:20131208130255j:plain

前回までのあらすじ

前話:かぼちゃ育成日記#2 - あと一ヶ月です - 鳥小屋.txt

毎年恒例の元旦制作に乗り出したRuたん。
しかし、その先には多くの罠(ゲーム、オフトゥン etc.)が潜んでいた!
負けるなRuたん! 完全に予定より遅れているからこのままだと間に合わないのでは!?
盛りだくさんの課題を抱えて戦い抜け!!

やっぱり明日から本気出す。

今週の進捗報告

f:id:ru_shalm:20131208125926j:plain

背景変えて進んでる感出してみた。

先週から変わったのはー

  • 左下にプレイヤーの残りライフ(ハートの個数)が表示されるように
  • 敵の周りにライフバー(円みたいなやつ)が表示されるように
  • 敵が弾を撃てるように
  • プレイヤー/敵のライフが0になると爆発する
  • 背景をスクロールできるように

ですね。抱えてたタスク全部消費できてない(´・ω・`)
ホントはプレイヤーの各スキルの実装とか、プレイヤー/敵が死んだらゲームオーバーとかゲームクリアとかの表示を出せるところまで行きたかったです。何よりキャラをそろそろ仮画像じゃなくしたい。

以下、今回の進捗でいろいろあったこと

円形のライフバー

f:id:ru_shalm:20131208134943j:plain

プレイヤーのライフは左下にハートで表示しちゃったんですけど、画面が狭いので画面上の決まった場所にいろいろ表示するのはやめたいなーと思ってました。画面の右上に敵のライフとか表示しちゃうと狭さがやばい。

なので、やりたかったのは敵の周りをクルッと囲むように曲がってる円形のゲージです。とはいえ、まさか1ドットずつ削れた画像を大量に用意して〜っていうのは面倒すぎるので、円形の画像1枚用意しておいて、コード側で表示する分をどうにかしたいです。

[starling circular guage] [検索]

Starlingのフォーラムが出てきました> [SOLVED] Radial / circular progress bar « Starling Forum

この中に出てきてたURLの中で気になったのが、「Flassari.is » Pie mask in AS3」というページ。
三角形以上の多角形をつくるように動かしたもので円形画像をマスクして、円が少しずつ大きくなってるように見せてるみたいですね。これは使えそう。

でも、Starlingには標準ではマスク機能は無かった気もする(あったら教えて)。
Pixelmask - Starling Wiki というライブラリがあるので、これを使ってさっきの多角形作戦と組み合わせてみます!

    // 再生成
    private function update():void {
        _guage.mask = new Image(createMaskTexture());
    }

    // マスク画像の生成
    private function createMaskTexture():Texture {
        var graphics:Graphics = _guageGenerateSprite.graphics;
        graphics.clear();

        graphics.beginFill(0x000000, 1.0);
        // ↓ 例のサイトの多角形描画する処理です
        drawPieMask(graphics, _per, 64, 64, 64, -Math.PI / 2);
        graphics.endFill();

        var bitmapdata:BitmapData = new BitmapData(128, 128, true, 0x00000000);
        bitmapdata.draw(_guageGenerateSprite);
        var texture:Texture = Texture.fromBitmapData(bitmapdata);
        bitmapdata.dispose();
        return texture;
    }

こんな感じ。もともと_guageにはゲージ用の円形画像がaddChildされています。ただこの作りだとゲージ量が変わるたびにテクスチャ作る感じになってるので、ゲージがウィンウィンするとやばいかもしれないですね。。。一回作った画像はキャッシュするとかしたほうがいいかもしれない。やばくなったらやります。

爆発エフェクト

f:id:ru_shalm:20131208133308j:plain

こういうドカーン!みたいなエフェクトを出したかったのです。
でもStarlingのパーティクルシステムよくわかんないので、僕はEffekseerで画像出力したやつを使ってます。パラパラアニメみたいに1コマずつ変わるやつ。ツクラーなので。

f:id:ru_shalm:20131208133732j:plain

で、こういう画像を扱うときはTextureAtlasを使うと便利そうです。MovieClipに流しこむだけで勝手にアニメーションしてくれますし、速度的にも有利らしい(?)です。
ただ、この出力した画像のTextureAtlas用XMLを自分で作るのは面倒すぎる。でも世の中のソフトはもっと大きさが違う画像を一個ずつ読み込んだりする用途に使うっぽくて、今回のエフェクトを手作業で読み込ませるのは結局面倒そう。

どうせ全部同じ大きさ=規則的に位置ずらしたXMLが必要なだけなのでRubyでサクっと出力させます。

# coding: utf-8

require 'rexml/document'

# TextureAtlas用のXMLを生成する
# @param width [Integer] 1コマの幅
# @param height [Integer] 1コマの高さ
# @param split_x [Integer] 横に敷き詰めている枚数
# @param split_y [Integer] 縦に敷き詰めている枚数
# @param options [Hash] その他オプション
# @return [REXML::Document] XMLドキュメント
def create_atlas_xml(width, height, split_x, split_y, options = {})
  # オプションの確認
  options[:max] ||= split_x * split_y
  options[:name] ||= 'normal'
  options[:image_path] ||= 'texture.png'

  # ドキュメントを生成
  doc = REXML::Document.new

  # Rootの作成
  root = REXML::Element.new('TextureAtlas')
  root.add_attribute('imagePath', options[:image_path])
  doc.add_element(root)

  # 子要素の作成
  num_format = "%0#{options[:max].to_s.size}d"
  options[:max].to_i.times do |i|
    child = REXML::Element.new('SubTexture')
    child.add_attribute('name', "#{options[:name]}_#{sprintf(num_format, i)}")
    child.add_attribute('x', (i % split_x) * width)
    child.add_attribute('y', (i / split_x) * height)
    child.add_attribute('width', width)
    child.add_attribute('height', height)
    root.add_element(child)
  end

  # ドキュメントを返す
  doc
end

if ARGV.empty?
  # ヘルプの表示
  puts 'hoge 幅x高さ 横の個数 縦の個数'
  puts '詳しくはソースを見よう!'
else
  # オプションの受け取り
  require 'optparse'
  options = {}
  parser = OptionParser.new
  parser.on('-m VAL', '--max VAL') {|v| options[:max] = v.to_i}
  parser.on('-n VAL', '--name VAL') {|v| options[:name] = v}
  parser.on('-i VAL', '--image_path VAL') {|v| options[:image_path] = v}
  parser.on('-o VAL', '--output VAL') {|v| options[:output] = v}
  parser.parse!(ARGV)

  # 引数チェック
  width_height = ARGV[0]
  if width_height =~ /\A(\d+)x(\d+)\z/
    width = $1.to_i
    height = $2.to_i
  end
  split_x = ARGV[1].to_i
  split_y = ARGV[2].to_i

  # 生成
  doc = create_atlas_xml(width, height, split_x, split_y, options)

  # 出力
  if options[:output]
    File.open(options[:output], 'w') do |f|
      doc.write(f, 2)
    end
  else
    doc.write($stdio, 2)
  end
end
ruby create_atlas_xml.rb 8x8 64 64 -n dead -i dead01.png -o dead01.xml

これで途中で「っべー、エフェクトでかすぎて読み込むの遅すぎるわー。エフェクトのサイズ小さくするわー」みたいになったときでも簡単に再生成できるね!やったねRuたん!

次回予告

  • キャラの画像つくる
  • ステージ開始→ガシ!ボカ!→ステージクリア/ゲームオーバー の流れをつくる
  • プレイヤーの各スキル(今回の残り)
  • タイトル画面→ステージ選択
  • セーブデータの保存

そろそろステージの中身作れる段階まで持っていかないと間に合わなさそうですね……頑張ってください!!