mieki256's diary



2013/12/07() [n年前の日記]

#4 [dxruby][game] DXRubyで例の多関節を実験

今日もDXRubyを使って、動きを作ってみます。

今回のネタは、昔懐かしの、あの多関節を試してみようかなと。学生時代、ファミコン版でプレイしていて、必ずこの敵で何機か失ったことを思い出します。やられグセがつくと、なかなか抜け出せなくて…。

自分、この処理は、書いたことがないんですよね…。昔、隣で先輩が書いてるソレを見て、「スゴーイ。まさしくアレだー」と子供のように喜んでしまった記憶があります。さて、自分は上手く書けるだろうか…。少し不安。

とりあえず、できた…かな…と思います。こんな感じの動きで合ってますかね? 微妙に何か違う気もするけど…。
グルグル回る例のアレ
# ぐるぐる回る、あの多関節のテスト

require 'dxruby'

# ボディ部分のスプライト
class BodySpr < Sprite
  
  # 初期化処理
  def initialize(sx, sy, dist, ang, img)
    super
    @px, @py = sx, sy # 自身の座標格納用
    @cx, @cy = sx, sy # 円運動の中心座標
    @dist = dist # 円運動の半径
    @ang = ang # 円運動の角度
    self.image = img # 画像
    
    self.scale_x = 1.6 # 拡大縮小率
    self.scale_y = 1.6
  end

  attr_accessor :px, :py
  
  # 毎フレーム呼ばれる処理
  def update
    # 円運動をさせる
    rad = @ang * Math::PI / 180.0
    @px = @cx + @dist * Math.cos(rad)
    @py = @cy + @dist * Math.sin(rad)
    
    # 描画位置を設定
    self.x = @px - self.image.width / 2
    self.y = @py - self.image.height / 2
    
    @ang += 0.7
  end
end

# 腕関節一つ分のスプライト
class Arm < Sprite
  
  # 初期化処理
  def initialize(sx, sy, dist, ang, img, parent)
    super
    @px, @py = sx, sy
    @cx, @cy = sx, sy
    @parent = parent # 親を記録
    @dist = dist # 親からの距離
    @ang = ang # 自分の角度
    @angt = ang # 親と自分の角度を加算した角度
    self.image = img
    self.center_x = img.width # 回転描画の中心位置をずらす
  end

  attr_accessor :angt, :px, :py

  # 毎フレーム呼ばれる処理
  def update
    if @parent.instance_of?(BodySpr)
      # 親がボディ部分だった場合
      @ang += 1
      @angt = @ang
      self.angle = @angt
      bx = @parent.px
      by = @parent.py
    else
      # 親が腕部分だった場合
      @angt = @parent.angt + @ang # 親の角度+自分の角度を得る
      self.angle = @angt
      bx = @parent.px
      by = @parent.py
      
      @ang += 0.3 # 自分の角度を少しずつ増やしてく
      @ang = -60 if @ang > 60
    end
    
    # 自身の座標を算出
    rad = @angt * Math::PI / 180.0
    @px = bx + @dist * Math.cos(rad)
    @py = by + @dist * Math.sin(rad)
    
    # 描画位置を算出
    self.x = @px - self.image.width
    self.y = @py - self.image.height / 2
  end
end

# 画像読み込み
img = Image.load("arm.png")
imgbody = Image.load("ufo.png")

# ボディ部分の発生
cx = Window.width / 2
cy = Window.height / 2
body = BodySpr.new(cx, cy, 80, 0, imgbody)

# 腕の初期化処理
sprs = []
armmax = 4 # 腕の本数
jointmax = 12 # 関節数
dist = 22 # 関節の長さ

# 何本か腕を延ばす
armmax.times do |i|
  parent = nil
  
  # 腕一つにつき、n個スプライトを使う
  jointmax.times do |j|
    if j == 0
      # 腕の根元
      s = Arm.new(cx, cy, 32, i * (360 / armmax), img, body)
    else
      # 腕
      s = Arm.new(cx, cy, dist, 0, img, parent)
    end
    sprs.push(s) # リストに登録
    parent = s # 次の親として扱う
  end
end

# メインループ
Window.loop do
  break if Input.keyPush?(K_ESCAPE)

  body.update # ボディを移動
  Sprite.update(sprs) # 腕を移動
  
  Sprite.draw(sprs) # 腕を描画
  body.draw # ボディを描画
end
これまた長くなってしまいました。もっと短く、スッキリ書けないものか…。

一応ざっくりと説明を。

今回は、DXRubyの Spriteクラスを使ってみました。Spriteクラスを継承して、ボディ部分を担当するクラスと、腕関節一つ分を担当するクラスを作ったわけです。自分は、Rubyについては初心者なので、こういう書き方でいいのかよく分かってませんが。

腕関節には、誰が親なのか、覚えさせておきます。@parent がソレです。また、親からの距離、親の角度+自分の角度を使って、自分の位置も求めます。

図で描いたほうが分かりやすいですかね…。一応描いてみましたが…。
説明図
この、親、子、孫…という状態が、10個前後ほど、ずっと続いているわけです。

子は、親からの距離、親の角度+自分の持ってる角度で、自分の位置を決めます。図で言えば、小さい四角い点がソレですね。また、スプライト描画の回転中心位置を、この小さい四角の位置にしておけば、各関節が滑らかに繋がっているように見えるはずです。

ひょっとして、位置の求め方が分からない方が居たりするのかもしれないか…。距離と角度があれば、sin関数、cos関数を使って、位置を求めることができますよ。
x座標 = 距離 * cos(角度) + 親の位置 x
y座標 = 距離 * sin(角度) + 親の位置 y
ソース中では、 rad = @angt * Math::PI / 180.0 なんて行もありますけど。これは、度からラジアンへの変換をしています。というのも、プログラムを書く際の sin関数、cos関数は、えてして、度ではなくてラジアンを与えないといけないので…。

それにしても、Ruby って、度とラジアンの変換関数は無いのでしょうかね…? ググってみても、見つかりませんが。

さておき。

もしも、子供達全員が持っている角度が、0度だったら。この仕組みだと、どんな見た目になるでしょうか。…皆でピーンと、一直線になりますね。

子供達が持っている角度が、例えば10度だったら…。下の方に曲がっていく線になるはずです。逆に、全員が、-10度を持ってたら、上の方に曲がっていく線になるでしょう。

そして、子供達全員が持っている角度が、毎フレーム、少しずつ増えていったら…。線の曲がり具合が、時間と共に、グングン変わっていくはずです。

とまあ、こんな仕組みで、あのグルグルはできていたのではないかなあ、と思いますが、本当にコレで正解なのかどうか…。まあ、それらしく動いてるから、コレはコレでOKかなと。

長年、例のアレって、どうやって動いてたのかビミョーに気になっていたのですが。今回もどうにか実証(?)できたので、ちょっぴり嬉しいです。こんなにもお手軽に、実験を可能にしてくれる、DXRubyよ、ありがとう…。

とりあえず、画像とソースも置いときますね。Public Domain ってことで一つ。

_rolltaka.zip

おっと。書き忘れてた。一昨日の記事で、二足歩行の動きを試した際に、IKがどうとか書きましたが。今回のソレは、各関節が角度を持っていて、根元からの角度で位置決めをしていくわけですから…。概念としてはFKに近いのではないかと思います。もちろん、3Dでグリグリ動いちゃう今時のアレコレと比べると、原始的なものですが…。

以上です。

過去ログ表示

Prev - 2013/12 - Next
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31

カテゴリで表示

検索機能は Namazu for hns で提供されています。(詳細指定/ヘルプ


注意: 現在使用の日記自動生成システムは Version 2.19.6 です。
公開されている日記自動生成システムは Version 2.19.5 です。

Powered by hns-2.19.6, HyperNikkiSystem Project