クロージャ入門

よくある面倒ランキング1位の当たり判定について。まあ(任意の範囲)―(円)間の判定ができればいいでしょう。そのためには(任意の範囲)―(点)間の最短距離が求められれば、円の半径と比べるだけで円との判定に拡張できます。(変な形したボス)―自機・(変な形したボス)―自分の弾の判定が必要なことを考えると、自機と自分の弾をそれぞれある半径の円とし、ボスの判定を円なり四角なりそれらの複合なりでいろいろ変えられるようにすればいいわけです。
ということで判定範囲の中心点と対象の座標から判定範囲との最短距離を求める関数を敵オブジェクトに持たせます。まずは一番簡単な円判定から作りましょう。円の中心と対象点の距離から円の半径rを引いたものが判定範囲と対象点との距離です。C++だとインターフェースを実装(言語自体にそんなものはないけど)してコンストラクタでrをもらってそれを使って関数を実装することになるのでしょうが、クロージャがあるとこうなります。

-- collision functions
-- Po: center point of object
-- Pt: target point pos
-- Returns: rest distance(could be negative)
local function collision_circle(r)
  return function(po, pt)
    return math.sqrt((po[1] - pt[1]) ^ 2 + (po[2] - pt[2]) ^ 2) - r
  end
end

collision_circleは半径rを引数にとり2点po, ptを引数にとりその距離からrを引いたものを返す関数を返す関数です。この文が生理的に受け付けなかったり、つい引数rの寿命が気になったりしちゃう人*1は関数型の世界へようこそ。C++0xでもラムダ式でキャプチャとかなんとかいってクロージャしてるしJavaも7で結局クロージャ入れることにしたらしいし(爆笑)慣れましょう。

self.enemy_set = {
  ball = {
    image_list = self:load_imagelist("ball", 2),
    col_func = collision_circle(16)
  },
}

collision_circle(16)は点poを中心とした半径16の円と点ptとの距離を求める関数を返す。

*1:さすがにC++だと寿命は気になる。