ふりこ

見た目にしょぼいサンプルを乱発しております。

ワイヤーアクションを作ろうと思ったら、なにはともあれ振り子の動きが必要だ。

require 'dxruby'

# ワイヤーの情報
wx = 320
wy = 0
length = 220
line_image = Image.new(1, 1, [255,255,255])

# 自キャラ
x = 100
y = 0
dx = dy = 0
image = Image.new(10, 10, [255,255,255])

Window.loop do
  # 重力で加速
  dy += 0.2

  # ワイヤーの原点から移動後の自キャラまでの角度
  angle = Math.atan2((y + dy) - wy, (x + dx) - wx)

  # 移動前の座標
  tx = x
  ty = y

  # ワイヤーの位置・長さと角度から自キャラの位置を算出
  x = Math.cos(angle) * length + wx
  y = Math.sin(angle) * length + wy

  # 位置の差分を移動量とする
  dx = x - tx
  dy = y - ty

  # 描画
  Window.draw(x - image.width / 2, y - image.height / 2, image)
  Window.drawEx(wx, wy, line_image,
                :centerx=>0.0, :centery=>0.5,
                :angle=>angle/Math::PI*180, :scalex=>length)
end

このアルゴリズムはかなり手抜きで、普通に動かした後でワイヤーの距離まで引き戻し、移動量をそこまでにする。まあ、見たまんまなのだが。
こうするとキャラの移動量がワイヤーの長さを半径とした円周と違う方向を向いているぶんだけロスとなって削られ、空気抵抗やら摩擦やらの計算をしていないのに振り子運動はだんだん小さくなっていく。
ゲームであればそれっぽく動いて見えればそれでOKなので、きちんとした振り子計算と摩擦計算で作る意味は無い。
やるなら自分の移動量をワイヤーに平行・垂直なベクトルに分割して、垂直なほうの長さ分だけ円周に沿って動かすから、円周と移動量の比率を取って角度を割り出し、ワイヤーのロック位置から自キャラの位置を算出する?みたいな感じに?なるかな?数学はよくわからん。
あとは自キャラからワイヤーを射出してみたり、ジャンプできるようにしたり、ワイヤーをゴムみたいに伸びたり縮んだりするようにしたりするとゲーム性が出てくるかもしれない。


ところで以前のレーザーの時にも使ったが、今回もコードの最後で使ってるワザは「1ピクセル画像を引き伸ばして線にする」というものだ。
ImageオブジェクトにImage#lineで描いてWindow.drawするのではなく、1ピクセルのImageを作ってWindow.drawExで回転拡大するとこういうことができる。
どっちが良い、というわけではないが、使い分けるとラクができる。
2点の座標を指定するメソッドを作ってMath.atan2を使って角度を求めれば、Window.drawLineとかが実現できると思う。
問題点は色ごとにImageが必要になるところで、内部でハッシュを作ってhash[r*256*256+g*256+b]=Image.new(1,1,[r,g,b])みたいな感じにすれば少しはマシか。グラデーションとかすると悲惨なことになるかもしれないが。