Class: Miyako::CircleCollision

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Defined in:
lib/Miyako/API/collision.rb

Overview

円形当たり判定領域(サークルコリジョン)クラス

円形の当たり判定を実装する。 コリジョンは中心位置と半径で構成され、円形当たり判定同士で衝突判定を行う コリジョンで使用する値は、実数での設定が可能

Direct Known Subclasses

CircleCollisionEx

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(center, radius, circum = true) ⇒ CircleCollision

コリジョンのインスタンスを作成する

コリジョンの半径が0もしくはマイナスのとき例外が発生する 内部では、矩形当たり判定相手の時でも対応できるように矩形情報に変換して同時に持っている。 そのとき、引数circumがtrueのときは、円を矩形の外接円と認識して、内部の矩形(正方形)の長さを算出する。 circumがfalseのときは、円を矩形の内接円と認識して、内部の矩形(正方形)の長さを算出する。

center

コリジョンを設定する範囲

radius

コリジョンの半径

circum

矩形当たり判定とみなす時、円を外接円とするときはtrueを設定する。デフォルトはtrue

返却値

作成されたコリジョン

Raises:


269
270
271
272
273
274
275
276
277
278
279
280
# File 'lib/Miyako/API/collision.rb', line 269

def initialize(center, radius, circum = true)
  raise MiyakoValueError, "illegal radius! #{radius}" if radius < Float::EPSILON
  @center = Point.new(*(center.to_a[0..1]))
  @radius = radius
  if circum
    rad = @radius.to_f / Math.sqrt(2.0)
    @rect = Rect.new(@center[0]-rad, @center[1]-rad, rad*2.0, rad*2.0)
  else
    @rect = Rect.new(@center[0]-@radius, @center[1]-@radius, @radius*2.0, @radius*2.0)
  end
  @body = nil
end

Instance Attribute Details

#bodyObject (readonly)

関連づけられたインスタンス


252
253
254
# File 'lib/Miyako/API/collision.rb', line 252

def body
  @body
end

#centerObject (readonly)


254
255
256
# File 'lib/Miyako/API/collision.rb', line 254

def center
  @center
end

#radiusObject (readonly)

コリジョンの半径


256
257
258
# File 'lib/Miyako/API/collision.rb', line 256

def radius
  @radius
end

#rectObject (readonly)


258
259
260
# File 'lib/Miyako/API/collision.rb', line 258

def rect
  @rect
end

Class Method Details

.collision?(c1, pos1, c2, pos2) ⇒ Boolean

当たり判定を行う(領域が重なっている)

c1

判定対象のコリジョンインスタンス(1)

pos1

c1の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)

c2

判定対象のコリジョンインスタンス(2)

pos2

c2の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)

返却値

1ピクセルでも重なっていれば true を返す


385
386
387
388
389
390
391
392
# File 'lib/Miyako/API/collision.rb', line 385

def CircleCollision.collision?(c1, pos1, c2, pos2)
  #2点間の距離を求める
  d = (((c1.center[0] + pos1[0]) - (c2.center[0] + pos2[0])) ** 2) +
      (((c1.center[1] + pos1[1]) - (c2.center[1] + pos2[1])) ** 2)  #半径の和を求める

  r  = (c1.radius + c2.radius) ** 2
  return d <= r
end

.cover?(c1, pos1, c2, pos2) ⇒ Boolean

当たり判定を行う(どちらかの領域がもう一方にすっぽり覆われている))

c1

判定対象のコリジョンインスタンス(1)

pos1

c1の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)

c2

判定対象のコリジョンインスタンス(2)

pos2

c2の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)

返却値

領域が覆われていれば true を返す


416
417
418
419
420
421
422
423
# File 'lib/Miyako/API/collision.rb', line 416

def CircleCollision.cover?(c1, pos1, c2, pos2)
  #2点間の距離を求める
  d = ((c1.center[0] + pos1[0]) - (c2.center[0] + pos2[0])) ** 2 +
      ((c1.center[1] + pos1[1]) - (c2.center[1] + pos2[1])) ** 2  #半径の差分を求める

  r  = c1.radius ** 2 - 2 * (c1.radius * c2.radius) + c2.radius ** 2
  return d <= r
end

.covered?(c1, pos1, c2, pos2) ⇒ Boolean

当たり判定を行う(c1がc2に覆われている)

c1

判定対象のコリジョンインスタンス(1)

pos1

c1の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)

c2

判定対象のコリジョンインスタンス(2)

pos2

c2の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)

返却値

領域が覆われていれば true を返す


448
449
450
451
452
453
454
455
456
457
# File 'lib/Miyako/API/collision.rb', line 448

def CircleCollision.covered?(c1, pos1, c2, pos2)
  #2点間の距離を求める
  d = ((c1.center[0] + pos1[0]) - (c2.center[0] + pos2[0])) ** 2 +
      ((c1.center[1] + pos1[1]) - (c2.center[1] + pos2[1])) ** 2  #半径の差分を求める

  r1 = c1.radius
  r2 = c2.radius
  r  = r2 ** 2 - 2 * (r1 * r2) + r1 ** 2
  return r2 >= r1 && d <= r
end

.covers?(c1, pos1, c2, pos2) ⇒ Boolean

当たり判定を行う(c1がc2を覆っている)

c1

判定対象のコリジョンインスタンス(1)

pos1

c1の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)

c2

判定対象のコリジョンインスタンス(2)

pos2

c2の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)

返却値

領域が覆われていれば true を返す


431
432
433
434
435
436
437
438
439
440
# File 'lib/Miyako/API/collision.rb', line 431

def CircleCollision.covers?(c1, pos1, c2, pos2)
  #2点間の距離を求める
  d = ((c1.center[0] + pos1[0]) - (c2.center[0] + pos2[0])) ** 2 +
      ((c1.center[1] + pos1[1]) - (c2.center[1] + pos2[1])) ** 2  #半径の差分を求める

  r1 = c1.radius
  r2 = c2.radius
  r  = r1 ** 2 - 2 * (r1 * r2) + r2 ** 2
  return r1 >= r2 && d <= r
end

.interval(c1, pos1, c2, pos2) ⇒ Object

当たり判定間の距離を算出する

2つの当たり判定がどの程度離れているかを算出する。 返ってくる値は、衝突していなければ正の実数、衝突していれば負の実数で返ってくる

c1

判定対象のコリジョンインスタンス(1)

pos1

c1の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)

c2

判定対象のコリジョンインスタンス(2)

pos2

c2の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)

返却値

当たり判定間の距離


369
370
371
372
373
374
375
376
377
# File 'lib/Miyako/API/collision.rb', line 369

def CircleCollision.interval(c1, pos1, c2, pos2)
  #2点間の距離を求める
  d = Math.sqrt((((c1.center[0].to_f + pos1[0].to_f) - (c2.center[0].to_f + pos2[0].to_f)) ** 2) +
                (((c1.center[1].to_f + pos1[1].to_f) - (c2.center[1].to_f + pos2[1].to_f)) ** 2))  #半径の和を求める

  r  = c1.radius.to_f + c2.radius.to_f
  distance = d - r
  return distance.abs < Float::EPSILON ? 0.0 : distance
end

.meet?(c1, pos1, c2, pos2) ⇒ Boolean

当たり判定を行う(領域がピクセル単位で隣り合っている)

但し、実際の矩形範囲が偶数の時は性格に判定できない場合があるため注意

c1

判定対象のコリジョンインスタンス(1)

pos1

c1の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)

c2

判定対象のコリジョンインスタンス(2)

pos2

c2の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)

返却値

領域が隣り合っていれば true を返す


401
402
403
404
405
406
407
408
# File 'lib/Miyako/API/collision.rb', line 401

def CircleCollision.meet?(c1, pos1, c2, pos2)
  #2点間の距離を求める
  d = (((c1.center[0] + pos1[0]) - (c2.center[0] + pos2[0])) ** 2) +
      (((c1.center[1] + pos1[1]) - (c2.center[1] + pos2[1])) ** 2)  #半径の和を求める

  r  = (c1.radius + c2.radius) ** 2
  return d == r
end

Instance Method Details

#bind(obj) ⇒ Object

当たり判定とインスタンスを関連づける

当たり判定と、それをもとにしたインスタンスとの関連がわかりにくいときに使用する 引数にcollision=メソッドの有無を調査して、持っているときは、collision=メソッドを 自分自身を引数にして呼び出す(collision=メソッドを持っているのは現状でSpriteクラスのみ)

obj

関連づける元のインスタンス

返却値

自分自身を帰す


293
294
295
296
297
# File 'lib/Miyako/API/collision.rb', line 293

def bind(obj)
  @body = obj
  @body.collision = self if @body.class.method_defined?(:collision=)
  return self
end

#collision?(pos1, c2, pos2) ⇒ Boolean

当たり判定を行う(領域が重なっている)

pos1

自分自身の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)

c2

判定対象のコリジョンインスタンス

pos2

c2の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)

返却値

1ピクセルでも重なっていれば true を返す


321
322
323
# File 'lib/Miyako/API/collision.rb', line 321

def collision?(pos1, c2, pos2)
  return CircleCollision.collision?(self, pos1, c2, pos2)
end

#cover?(pos1, c2, pos2) ⇒ Boolean

当たり判定を行う(どちらかの領域がもう一方にすっぽり覆われている))

pos1

自分自身の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)

c2

判定対象のコリジョンインスタンス

pos2

c2の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)

返却値

領域が覆われていれば true を返す


339
340
341
# File 'lib/Miyako/API/collision.rb', line 339

def cover?(pos1, c2, pos2)
  return CircleCollision.cover?(self, pos1, c2, pos2)
end

#covered?(pos1, c2, pos2) ⇒ Boolean

当たり判定を行う(レシーバがc2に覆われている)

pos1

自分自身の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)

c2

判定対象のコリジョンインスタンス

pos2

c2の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)

返却値

領域が覆われていれば true を返す


357
358
359
# File 'lib/Miyako/API/collision.rb', line 357

def covered?(pos1, c2, pos2)
  return CircleCollision.covered?(self, pos1, c2, pos2)
end

#covers?(pos1, c2, pos2) ⇒ Boolean

当たり判定を行う(レシーバがc2を覆っている)

pos1

自分自身の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)

c2

判定対象のコリジョンインスタンス

pos2

c2の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)

返却値

領域が覆われていれば true を返す


348
349
350
# File 'lib/Miyako/API/collision.rb', line 348

def covers?(pos1, c2, pos2)
  return CircleCollision.covers?(self, pos1, c2, pos2)
end

#disposeObject

インスタンスの内容を解放する

返却値

なし


461
462
463
# File 'lib/Miyako/API/collision.rb', line 461

def dispose
  @point = nil
end

#initialize_copy(obj) ⇒ Object

:nodoc:


282
283
284
285
# File 'lib/Miyako/API/collision.rb', line 282

def initialize_copy(obj) #:nodoc:
  @rect = @rect.dup
  @center = @center.dup
end

#interval(pos1, c2, pos2) ⇒ Object

当たり判定間の距離を算出する

pos1

自分自身の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)

c2

判定対象のコリジョンインスタンス

pos2

c2の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)

返却値

1ピクセルでも重なっていれば true を返す


312
313
314
# File 'lib/Miyako/API/collision.rb', line 312

def interval(pos1, c2, pos2)
  return CircleCollision.interval(self, pos1, c2, pos2)
end

#meet?(pos1, c2, pos2) ⇒ Boolean

当たり判定を行う(領域がピクセル単位で隣り合っている)

pos1

自分自身の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)

c2

判定対象のコリジョンインスタンス

pos2

c2の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)

返却値

領域が隣り合っていれば true を返す


330
331
332
# File 'lib/Miyako/API/collision.rb', line 330

def meet?(pos1, c2, pos2)
  return CircleCollision.meet?(self, pos1, c2, pos2)
end

#to_ex(pos = [0,0]) ⇒ Object

CircleCollisionExクラスのインスタンスを生成する

自分自身に位置情報を渡してCircleCollisionExクラスのインスタンスを生成する

pos

CircleCollisionEx生成時に渡す位置。省略時は

返却値

CircleCollisionEx構造体


303
304
305
# File 'lib/Miyako/API/collision.rb', line 303

def to_ex(pos=[0,0])
  CircleCollisionEx.new(@center, @radius, pos)
end