cyross-ruby-miyako 2.0.5.1 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. data/README +1092 -929
  2. data/Rakefile +7 -7
  3. data/defines.h +144 -144
  4. data/extern.h +29 -29
  5. data/install_miyako.rb +87 -87
  6. data/lib/Miyako/API/audio.rb +572 -198
  7. data/lib/Miyako/API/basic_data.rb +825 -573
  8. data/lib/Miyako/API/bitmap.rb +534 -507
  9. data/lib/Miyako/API/choices.rb +481 -475
  10. data/lib/Miyako/API/collision.rb +486 -460
  11. data/lib/Miyako/API/diagram.rb +586 -561
  12. data/lib/Miyako/API/drawing.rb +151 -151
  13. data/lib/Miyako/API/exceptions.rb +105 -0
  14. data/lib/Miyako/API/fixedmap.rb +462 -428
  15. data/lib/Miyako/API/font.rb +430 -403
  16. data/lib/Miyako/API/input.rb +456 -447
  17. data/lib/Miyako/API/layout.rb +636 -433
  18. data/lib/Miyako/API/map.rb +583 -529
  19. data/lib/Miyako/API/map_event.rb +222 -198
  20. data/lib/Miyako/API/modules.rb +357 -109
  21. data/lib/Miyako/API/movie.rb +166 -154
  22. data/lib/Miyako/API/parts.rb +276 -189
  23. data/lib/Miyako/API/plane.rb +205 -166
  24. data/lib/Miyako/API/screen.rb +341 -325
  25. data/lib/Miyako/API/shape.rb +443 -443
  26. data/lib/Miyako/API/sprite.rb +771 -752
  27. data/lib/Miyako/API/sprite_animation.rb +490 -481
  28. data/lib/Miyako/API/sprite_list.rb +1135 -0
  29. data/lib/Miyako/API/spriteunit.rb +168 -147
  30. data/lib/Miyako/API/story.rb +350 -300
  31. data/lib/Miyako/API/textbox.rb +770 -725
  32. data/lib/Miyako/API/utility.rb +419 -388
  33. data/lib/Miyako/API/viewport.rb +189 -139
  34. data/lib/Miyako/API/yuki.rb +1226 -996
  35. data/lib/Miyako/EXT/miyako_cairo.rb +62 -62
  36. data/lib/Miyako/EXT/raster_scroll.rb +138 -138
  37. data/lib/Miyako/EXT/slides.rb +157 -157
  38. data/lib/Miyako/miyako.rb +201 -171
  39. data/lib/Miyako/miyako_require_only.rb +35 -0
  40. data/miyako_basicdata.c +590 -590
  41. data/miyako_bitmap.c +1225 -1225
  42. data/miyako_collision.c +403 -403
  43. data/miyako_drawing.c +187 -187
  44. data/miyako_font.c +334 -334
  45. data/miyako_hsv.c +830 -830
  46. data/miyako_input_audio.c +254 -0
  47. data/miyako_layout.c +191 -191
  48. data/miyako_no_katana.c +1078 -1074
  49. data/miyako_sprite2.c +431 -0
  50. data/miyako_transform.c +438 -438
  51. data/miyako_utility.c +288 -288
  52. data/sample/Animation1/m1ku.rb +68 -68
  53. data/sample/Animation2/lex.rb +96 -96
  54. data/sample/Diagram_sample/diagram_sample_yuki2.rb +328 -386
  55. data/sample/Room3/blue.rb +297 -297
  56. data/sample/Room3/ending.rb +180 -180
  57. data/sample/Room3/green.rb +220 -220
  58. data/sample/Room3/main.rb +119 -119
  59. data/sample/Room3/main_component.rb +59 -59
  60. data/sample/Room3/red.rb +227 -227
  61. data/sample/Room3/room3.rb +25 -27
  62. data/sample/Room3/title.rb +184 -184
  63. data/sample/ball_action_sample.rb +204 -204
  64. data/sample/blit_rop.rb +70 -70
  65. data/sample/cairo_sample.rb +25 -25
  66. data/sample/circle_collision_test.rb +66 -66
  67. data/sample/collision_test.rb +33 -33
  68. data/sample/collision_test2.rb +108 -108
  69. data/sample/fixed_map_test/fixed_map_sample.rb +140 -140
  70. data/sample/fixed_map_test/readme.txt +72 -72
  71. data/sample/map_test/chara.rb +58 -58
  72. data/sample/map_test/main_parts.rb +69 -69
  73. data/sample/map_test/main_scene.rb +153 -153
  74. data/sample/map_test/map_manager.rb +75 -75
  75. data/sample/map_test/map_test.rb +23 -23
  76. data/sample/map_test/oasis.rb +71 -71
  77. data/sample/map_test/readme.txt +89 -89
  78. data/sample/map_test/route.rb +157 -157
  79. data/sample/map_test/town.rb +74 -74
  80. data/sample/polygon_test.rb +35 -35
  81. data/sample/rasterscroll.rb +24 -24
  82. data/sample/takahashi.rb +42 -42
  83. data/sample/textbox_sample.rb +189 -189
  84. data/sample/transform.rb +54 -54
  85. data/sample/utility_test.rb +73 -73
  86. data/sample/utility_test2.rb +61 -61
  87. data/sample/utility_test3.rb +64 -64
  88. data/sample/utility_test4.rb +73 -73
  89. data/uninstall_miyako.rb +19 -19
  90. data/win/miyako_no_katana.so +0 -0
  91. metadata +7 -2
@@ -1,460 +1,486 @@
1
- # -*- encoding: utf-8 -*-
2
- =begin
3
- --
4
- Miyako v2.0
5
- Copyright (C) 2007-2009 Cyross Makoto
6
-
7
- This library is free software; you can redistribute it and/or
8
- modify it under the terms of the GNU Lesser General Public
9
- License as published by the Free Software Foundation; either
10
- version 2.1 of the License, or (at your option) any later version.
11
-
12
- This library is distributed in the hope that it will be useful,
13
- but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
- Lesser General Public License for more details.
16
-
17
- You should have received a copy of the GNU Lesser General Public
18
- License along with this library; if not, write to the Free Software
19
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
- ++
21
- =end
22
-
23
- module Miyako
24
- #==矩形当たり判定領域(コリジョン)クラス
25
- # コリジョンの範囲は、元データ(スプライト等)の左上端を[0.0,0.0]として考案する
26
- # コリジョンで使用する値は、実数での設定が可能
27
- class Collision
28
- extend Forwardable
29
-
30
- # コリジョンの範囲([x,y,w,h])
31
- attr_reader :rect
32
- # 移動時イベントブロック配列
33
-
34
- #===コリジョンのインスタンスを作成する
35
- # 幅・高さが0以下のときは例外が発生する
36
- # 内部では、矩形当たり判定相手の時でも対応できるように矩形情報に変換して同時に持っている。
37
- # そのとき、引数circumがtrueのときは、円を矩形の外接円と認識して、内部の矩形(正方形)の長さを算出する。
38
- # circumがfalseのときは、円を矩形の内接円と認識して、内部の矩形(正方形)の長さを算出する。
39
- #_rect_:: コリジョンを設定する範囲
40
- #_circum_:: 矩形当たり判定とみなす時、円を外接円とするときはtrueを設定する。デフォルトはtrue
41
- #返却値:: 作成されたコリジョン
42
- def initialize(rect, circum = true)
43
- @rect = Rect.new(*(rect.to_a[0..3]))
44
- raise MiyakoError, "Illegal width! #{@rect[2]}" if @rect[2] < Float::EPSILON
45
- raise MiyakoError, "Illegal height! #{@rect[3]}" if @rect[3] < Float::EPSILON
46
- w = @rect[2].to_f
47
- h = @rect[2].to_f
48
- @center = Point.new(@rect[0].to_f + w / 2.0, @rect[1].to_f + h / 2.0)
49
- @radius = circum ? Math.sqrt(w ** 2 + h ** 2) / 2.0 : [w, h].min / 2.0
50
- end
51
-
52
- #===当たり判定を行う(領域が重なっている)
53
- #_pos1_:: 自分自身の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)
54
- #_c2_:: 判定対象のコリジョンインスタンス
55
- #_pos2_:: c2の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)
56
- #返却値:: 1ピクセルでも重なっていれば true を返す
57
- def collision?(pos1, c2, pos2)
58
- return Collision.collision?(self, pos1, c2, pos2)
59
- end
60
-
61
- #===当たり判定を行う(領域がピクセル単位で隣り合っている)
62
- #_pos1_:: 自分自身の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)
63
- #_c2_:: 判定対象のコリジョンインスタンス
64
- #_pos2_:: c2の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)
65
- #返却値:: 領域が隣り合っていれば true を返す
66
- def meet?(pos1, c2, pos2)
67
- return Collision.meet?(self, pos1, c2, pos2)
68
- end
69
-
70
- #===当たり判定を行う(どちらかの領域がもう一方にすっぽり覆われている))
71
- #_pos1_:: 自分自身の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)
72
- #_c2_:: 判定対象のコリジョンインスタンス
73
- #_pos2_:: c2の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)
74
- #返却値:: 領域が覆われていれば true を返す
75
- def cover?(pos1, c2, pos2)
76
- return Collision.cover?(self, pos1, c2, pos2)
77
- end
78
-
79
- #===当たり判定を行う(領域が重なっている)
80
- #_c1_:: 判定対象のコリジョンインスタンス(1)
81
- #_pos1_:: c1の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)
82
- #_c2_:: 判定対象のコリジョンインスタンス(2)
83
- #_pos2_:: c2の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)
84
- #返却値:: 1ピクセルでも重なっていれば true を返す
85
- def Collision.collision?(c1, pos1, c2, pos2)
86
- l1 = pos1[0] + c1.rect[0]
87
- t1 = pos1[1] + c1.rect[1]
88
- r1 = l1 + c1.rect[2] - 1
89
- b1 = t1 + c1.rect[3] - 1
90
- l2 = pos2[0] + c2.rect[0]
91
- t2 = pos2[1] + c2.rect[1]
92
- r2 = l2 + c2.rect[2] - 1
93
- b2 = t2 + c2.rect[3] - 1
94
- v = 0
95
- v |= 1 if l1 <= l2 && l2 <= r1
96
- v |= 1 if l1 <= r2 && r2 <= r1
97
- v |= 2 if t1 <= t2 && t2 <= b1
98
- v |= 2 if t1 <= b2 && b2 <= b1
99
- return v == 3
100
- end
101
-
102
- #===当たり判定を行う(領域がピクセル単位で隣り合っている)
103
- #_c1_:: 判定対象のコリジョンインスタンス(1)
104
- #_pos1_:: c1の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)
105
- #_c2_:: 判定対象のコリジョンインスタンス(2)
106
- #_pos2_:: c2の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)
107
- #返却値:: 領域が隣り合っていれば true を返す
108
- def Collision.meet?(c1, pos1, c2, pos2)
109
- l1 = pos1[0] + c1.rect[0]
110
- t1 = pos1[1] + c1.rect[1]
111
- r1 = l1 + c1.rect[2]
112
- b1 = t1 + c1.rect[3]
113
- l2 = pos2[0] + c2.rect[0]
114
- t2 = pos2[1] + c2.rect[1]
115
- r2 = l2 + c2.rect[2]
116
- b2 = t2 + c2.rect[3]
117
- v = 0
118
- v |= 1 if r1 == l2
119
- v |= 1 if b1 == t2
120
- v |= 1 if l1 == r2
121
- v |= 1 if t1 == b2
122
- return v == 1
123
- end
124
-
125
- #===当たり判定を行う(どちらかの領域がもう一方にすっぽり覆われている))
126
- #_c1_:: 判定対象のコリジョンインスタンス(1)
127
- #_pos1_:: c1の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)
128
- #_c2_:: 判定対象のコリジョンインスタンス(2)
129
- #_pos2_:: c2の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)
130
- #返却値:: 領域が覆われていれば true を返す
131
- def Collision.cover?(c1, pos1, c2, pos2)
132
- l1 = pos1[0] + c1.rect[0]
133
- t1 = pos1[1] + c1.rect[1]
134
- r1 = l1 + c1.rect[2]
135
- b1 = t1 + c1.rect[3]
136
- l2 = pos2[0] + c2.rect[0]
137
- t2 = pos2[1] + c2.rect[1]
138
- r2 = l2 + c2.rect[2]
139
- b2 = t2 + c2.rect[3]
140
- v = 0
141
- v |= 1 if l1 >= l2 && r2 <= r1
142
- v |= 2 if t1 >= t2 && b2 <= b1
143
- v |= 4 if l2 >= l1 && r1 <= r2
144
- v |= 8 if t2 >= t1 && b1 <= b2
145
- return v & 3 == 3 || v & 12 == 12
146
- end
147
-
148
- #== インスタンスの内容を解放する
149
- #返却値:: なし
150
- def dispose
151
- @rect = nil
152
- end
153
- end
154
-
155
- #==円形当たり判定領域(サークルコリジョン)クラス
156
- # 円形の当たり判定を実装する。
157
- # コリジョンは中心位置と半径で構成され、円形当たり判定同士で衝突判定を行う
158
- # コリジョンで使用する値は、実数での設定が可能
159
- class CircleCollision
160
- extend Forwardable
161
-
162
- # コリジョンの中心点([x,y])
163
- attr_reader :center
164
- # コリジョンの半径
165
- attr_reader :radius
166
- # 移動時イベントブロック配列
167
-
168
- #===コリジョンのインスタンスを作成する
169
- # コリジョンの半径が0もしくはマイナスのとき例外が発生する
170
- # 内部では、矩形当たり判定相手の時でも対応できるように矩形情報に変換して同時に持っている。
171
- # そのとき、引数circumがtrueのときは、円を矩形の外接円と認識して、内部の矩形(正方形)の長さを算出する。
172
- # circumがfalseのときは、円を矩形の内接円と認識して、内部の矩形(正方形)の長さを算出する。
173
- #_center_:: コリジョンを設定する範囲
174
- #_radius_:: コリジョンの半径
175
- #_circum_:: 矩形当たり判定とみなす時、円を外接円とするときはtrueを設定する。デフォルトはtrue
176
- #返却値:: 作成されたコリジョン
177
- def initialize(center, radius, circum = true)
178
- raise MiyakoError, "illegal radius! #{radius}" if radius < Float::EPSILON
179
- @center = Point.new(*(center.to_a[0..1]))
180
- @radius = radius
181
- if circum
182
- rad = @radius.to_f / Math.sqrt(2.0)
183
- @rect = Rect.new(@center[0]-rad, @center[1]-rad, rad*2.0, rad*2.0)
184
- else
185
- @rect = Rect.new(@center[0]-@radius, @center[1]-@radius, @radius*2.0, @radius*2.0)
186
- end
187
- end
188
-
189
- #===当たり判定間の距離を算出する
190
- #_pos1_:: 自分自身の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)
191
- #_c2_:: 判定対象のコリジョンインスタンス
192
- #_pos2_:: c2の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)
193
- #返却値:: 1ピクセルでも重なっていれば true を返す
194
- def interval(pos1, c2, pos2)
195
- return CircleCollision.interval(self, pos1, c2, pos2)
196
- end
197
-
198
- #===当たり判定を行う(領域が重なっている)
199
- #_pos1_:: 自分自身の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)
200
- #_c2_:: 判定対象のコリジョンインスタンス
201
- #_pos2_:: c2の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)
202
- #返却値:: 1ピクセルでも重なっていれば true を返す
203
- def collision?(pos1, c2, pos2)
204
- return CircleCollision.collision?(self, pos1, c2, pos2)
205
- end
206
-
207
- #===当たり判定を行う(領域がピクセル単位で隣り合っている)
208
- #_pos1_:: 自分自身の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)
209
- #_c2_:: 判定対象のコリジョンインスタンス
210
- #_pos2_:: c2の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)
211
- #返却値:: 領域が隣り合っていれば true を返す
212
- def meet?(pos1, c2, pos2)
213
- return CircleCollision.meet?(self, pos1, c2, pos2)
214
- end
215
-
216
- #===当たり判定を行う(どちらかの領域がもう一方にすっぽり覆われている))
217
- #_pos1_:: 自分自身の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)
218
- #_c2_:: 判定対象のコリジョンインスタンス
219
- #_pos2_:: c2の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)
220
- #返却値:: 領域が覆われていれば true を返す
221
- def cover?(pos1, c2, pos2)
222
- return CircleCollision.cover?(self, pos1, c2, pos2)
223
- end
224
-
225
- #===当たり判定間の距離を算出する
226
- # 2つの当たり判定がどの程度離れているかを算出する。
227
- # 返ってくる値は、衝突していなければ正の実数、衝突していれば負の実数で返ってくる
228
- #_c1_:: 判定対象のコリジョンインスタンス(1)
229
- #_pos1_:: c1の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)
230
- #_c2_:: 判定対象のコリジョンインスタンス(2)
231
- #_pos2_:: c2の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)
232
- #返却値:: 当たり判定間の距離
233
- def CircleCollision.interval(c1, pos1, c2, pos2)
234
- #2点間の距離を求める
235
- d = Math.sqrt((((c1.center[0].to_f + pos1[0].to_f) - (c2.center[0].to_f + pos2[0].to_f)) ** 2) +
236
- (((c1.center[1].to_f + pos1[1].to_f) - (c2.center[1].to_f + pos2[1].to_f)) ** 2))
237
- #半径の和を求める
238
- r = c1.radius.to_f + c2.radius.to_f
239
- distance = d - r
240
- return distance.abs < Float::EPSILON ? 0.0 : distance
241
- end
242
-
243
- #===当たり判定を行う(領域が重なっている)
244
- #_c1_:: 判定対象のコリジョンインスタンス(1)
245
- #_pos1_:: c1の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)
246
- #_c2_:: 判定対象のコリジョンインスタンス(2)
247
- #_pos2_:: c2の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)
248
- #返却値:: 1ピクセルでも重なっていれば true を返す
249
- def CircleCollision.collision?(c1, pos1, c2, pos2)
250
- #2点間の距離を求める
251
- d = (((c1.center[0] + pos1[0]) - (c2.center[0] + pos2[0])) ** 2) +
252
- (((c1.center[1] + pos1[1]) - (c2.center[1] + pos2[1])) ** 2)
253
- #半径の和を求める
254
- r = (c1.radius + c2.radius) ** 2
255
- return d <= r
256
- end
257
-
258
- #===当たり判定を行う(領域がピクセル単位で隣り合っている)
259
- # 但し、実際の矩形範囲が偶数の時は性格に判定できない場合があるため注意
260
- #_c1_:: 判定対象のコリジョンインスタンス(1)
261
- #_pos1_:: c1の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)
262
- #_c2_:: 判定対象のコリジョンインスタンス(2)
263
- #_pos2_:: c2の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)
264
- #返却値:: 領域が隣り合っていれば true を返す
265
- def CircleCollision.meet?(c1, pos1, c2, pos2)
266
- #2点間の距離を求める
267
- d = (((c1.center[0] + pos1[0]) - (c2.center[0] + pos2[0])) ** 2) +
268
- (((c1.center[1] + pos1[1]) - (c2.center[1] + pos2[1])) ** 2)
269
- #半径の和を求める
270
- r = (c1.radius + c2.radius) ** 2
271
- return d == r
272
- end
273
-
274
- #===当たり判定を行う(どちらかの領域がもう一方にすっぽり覆われている))
275
- #_c1_:: 判定対象のコリジョンインスタンス(1)
276
- #_pos1_:: c1の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)
277
- #_c2_:: 判定対象のコリジョンインスタンス(2)
278
- #_pos2_:: c2の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)
279
- #返却値:: 領域が覆われていれば true を返す
280
- def CircleCollision.cover?(c1, pos1, c2, pos2)
281
- #2点間の距離を求める
282
- d = ((c1.center[0] + pos1[0]) - (c2.center[0] + pos2[0])) ** 2 +
283
- ((c1.center[1] + pos1[1]) - (c2.center[1] + pos2[1])) ** 2
284
- #半径の差分を求める
285
- r = c1.radius ** 2 - 2 * (c1.radius * c2.radius) + c2.radius ** 2
286
- return d <= r
287
- end
288
-
289
- #== インスタンスの内容を解放する
290
- #返却値:: なし
291
- def dispose
292
- @point = nil
293
- end
294
- end
295
-
296
- #==コリジョン管理クラス
297
- # 複数のコリジョンと元オブジェクトを配列の様に一括管理できる
298
- # 当たり判定を一括処理することで高速化を図る
299
- class Collisions
300
- include Enumerable
301
- extend Forwardable
302
-
303
- #===コリジョンのインスタンスを作成する
304
- # points引数の各要素は、以下の3つの条件のどれかに適合する必要がある。しない場合は例外が発生する
305
- # 1)[x,y]の要素を持つ配列
306
- # 2)Point構造体、Rect構造体、もしくはSquare構造体
307
- # 3)x,yメソッドを持つ
308
- #_collisions_:: コリジョンの配列。デフォルトは []
309
- #_points_:: 位置情報の配列。デフォルトは []
310
- #返却値:: 作成されたインスタンス
311
- def initialize(collisions=[], points=[])
312
- @collisions = Array.new(collisions).zip(points)
313
- end
314
-
315
- #===コリジョンと位置情報を追加する
316
- # point引数は、以下の3つの条件のどれかに適合する必要がある。しない場合は例外が発生する
317
- # 1)[x,y]の要素を持つ配列
318
- # 2)Point構造体、Rect構造体、もしくはSquare構造体
319
- # 3)x,yメソッドを持つ
320
- #_collisions_:: コリジョン
321
- #_point_:: 位置情報
322
- #返却値:: 自分自身を返す
323
- def add(collision, point)
324
- @collisions << [collision, point]
325
- return self
326
- end
327
-
328
- #===インスタンスに、コリジョンと位置情報の集合を追加する
329
- # points引数の各要素は、以下の3つの条件のどれかに適合する必要がある。しない場合は例外が発生する
330
- # 1)[x,y]の要素を持つ配列
331
- # 2)Point構造体、Rect構造体、もしくはSquare構造体
332
- # 3)x,yメソッドを持つ
333
- #_collisions_:: コリジョンの配列
334
- #_points_:: 位置情報の配列
335
- #返却値:: 自分自身を返す
336
- def append(collisions, points)
337
- @collisions.concat(collisions.zip(points))
338
- return self
339
- end
340
-
341
- #===インデックス形式でのコリジョン・本体の取得
342
- #_idx_:: 配列のインデックス番号
343
- #返却値:: インデックスに対応したコリジョンと位置情報との対。
344
- #インデックスが範囲外の時はnilが返る
345
- def [](idx)
346
- return @collisions[idx]
347
- end
348
-
349
- #===コリジョン・本体の削除
350
- #_idx_:: 配列のインデックス番号
351
- #返却値:: 削除したコリジョンと本体との対
352
- #インデックスが範囲外の時はnilが返る
353
- def delete(idx)
354
- return @collisions.delete_at(idx)
355
- end
356
-
357
- #===インデックス形式でのコリジョン・本体の取得
358
- #_idx_:: 配列のインデックス番号
359
- #返却値:: インデックスに対応したコリジョンと本体との対
360
- def clear
361
- @collisions.clear
362
- return self
363
- end
364
-
365
- #===タッピングを行う
366
- # ブロックを渡すことにより、タッピングを行う
367
- # ブロック内の引数は、|コリジョン,本体|の2が渡される
368
- #返却値:: 自分自身を返す
369
- def each
370
- @collisions.each{|cb| yield cb[0], cb[1] }
371
- return self
372
- end
373
-
374
- #===タッピングを行う
375
- # ブロックを渡すことにより、タッピングを行う
376
- # ブロック内の引数は、|コリジョン,本体|の2が渡される
377
- #_idx_:: 配列のインデックス
378
- #返却値:: 自分自身を返す
379
- def tap(idx)
380
- yield @collisions[idx][0], @collisions[idx][1]
381
- return self
382
- end
383
-
384
- #===当たり判定を行う(配列のどれかの領域が重なっている)
385
- # 重なったコリジョンが一つでもあれば、最初に引っかかったコリジョンを返す
386
- # 重なったコリジョンが無い場合はnilを返す
387
- #_c_:: 判定対象のコリジョンインスタンス
388
- #_pos_:: cの位置(Point/Rect/Square構造体、もしくは2要素の配列)
389
- #返却値:: コリジョンと本体の対。
390
- def collision?(c, pos)
391
- return @collisions.detect{|cc| c.collision?(pos, cc[0], cc[1])}
392
- end
393
-
394
- #===当たり判定を行う(配列のどれかの領域がピクセル単位で隣り合っている)
395
- # 隣り合ったコリジョンが一つでもあれば、最初に引っかかったコリジョンを返す
396
- # 隣り合ったコリジョンが無い場合はnilを返す
397
- #_c_:: 判定対象のコリジョンインスタンス
398
- #_pos_:: cの位置(Point/Rect/Square構造体、もしくは2要素の配列)
399
- #返却値:: 隣り合っていれば true を返す
400
- def meet?(c, pos)
401
- return @collisions.detect{|cc| c.meet?(pos, cc[0], cc[1])}
402
- end
403
-
404
- #===当たり判定を行う(どちらかの領域がもう一方にすっぽり覆われている))
405
- # 覆われたコリジョンが一つでもあれば、最初に引っかかったコリジョンを返す
406
- # 覆われたコリジョンが無い場合はnilを返す
407
- #_c_:: 判定対象のコリジョンインスタンス
408
- #_pos_:: cの位置(Point/Rect/Square構造体、もしくは2要素の配列)
409
- #返却値:: 領域が覆われていれば true を返す
410
- def cover?(c, pos)
411
- return @collisions.detect{|cc| c.cover?(pos, cc[0], cc[1])}
412
- end
413
-
414
- #===当たり判定を行う(領域が重なっている)
415
- # 重なったコリジョンが一つでもあれば、すべてのコリジョンの配列を返す
416
- # 重なったコリジョンが無い場合はnilを返す
417
- #_c_:: 判定対象のコリジョンインスタンス
418
- #_pos_:: cの位置(Point/Rect/Square構造体、もしくは2要素の配列)
419
- #返却値:: コリジョンと本体の対の配列。
420
- def collision_all?(c, pos)
421
- return @collisions.select{|cc| c.collision?(pos, cc[0], cc[1])}
422
- end
423
-
424
- #===当たり判定を行う(領域がピクセル単位で隣り合っている)
425
- # 隣り合ったコリジョンが一つでもあれば、すべてのコリジョンの配列を返す
426
- # 隣り合ったコリジョンが無い場合はnilを返す
427
- #_c_:: 判定対象のコリジョンインスタンス
428
- #_pos_:: cの位置(Point/Rect/Square構造体、もしくは2要素の配列)
429
- #返却値:: コリジョンと本体の対の配列。
430
- def meet_all?(c, pos)
431
- return @collisions.select{|cc| c.meet?(pos, cc[0], cc[1])}
432
- end
433
-
434
- #===当たり判定を行う(どちらかの領域がもう一方にすっぽり覆われている))
435
- # 覆われたコリジョンが一つでもあれば、すべてのコリジョンの配列を返す
436
- # 覆われたコリジョンが無い場合はnilを返す
437
- #_c_:: 判定対象のコリジョンインスタンス
438
- #_pos_:: cの位置(Point/Rect/Square構造体、もしくは2要素の配列)
439
- #返却値:: コリジョンと本体の対の配列。
440
- def cover_all?(c, pos)
441
- return @collisions.select{|cc| c.cover?(pos, cc[0], cc[1])}
442
- end
443
-
444
- #===インデックス形式でのコリジョン・本体の取得
445
- # 判定に引っかかったコリジョンが一つでもあれば、すべてのコリジョンの配列を返す
446
- # 当たり判定に引っかかったコリジョンが無い場合はnilを返す
447
- #_idx_:: 配列のインデックス番号
448
- #返却値:: インデックスに対応したコリジョンと本体との対
449
- def [](idx)
450
- return [@collisions[idx], @bodies[idx]]
451
- end
452
-
453
- #===オブジェクトを解放する
454
- #返却値:: なし
455
- def dispose
456
- @collisions.clear
457
- @collisions = nil
458
- end
459
- end
460
- end
1
+ # -*- encoding: utf-8 -*-
2
+ =begin
3
+ --
4
+ Miyako v2.1
5
+ Copyright (C) 2007-2009 Cyross Makoto
6
+
7
+ This library is free software; you can redistribute it and/or
8
+ modify it under the terms of the GNU Lesser General Public
9
+ License as published by the Free Software Foundation; either
10
+ version 2.1 of the License, or (at your option) any later version.
11
+
12
+ This library is distributed in the hope that it will be useful,
13
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
+ Lesser General Public License for more details.
16
+
17
+ You should have received a copy of the GNU Lesser General Public
18
+ License along with this library; if not, write to the Free Software
19
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
+ ++
21
+ =end
22
+
23
+ module Miyako
24
+ #==矩形当たり判定領域(コリジョン)クラス
25
+ # コリジョンの範囲は、元データ(スプライト等)の左上端を[0.0,0.0]として考案する
26
+ # コリジョンで使用する値は、実数での設定が可能
27
+ class Collision
28
+ extend Forwardable
29
+
30
+ # コリジョンの範囲([x,y,w,h])
31
+ attr_reader :rect
32
+ # 移動時イベントブロック配列
33
+
34
+ #===コリジョンのインスタンスを作成する
35
+ # 幅・高さが0以下のときは例外が発生する
36
+ # 内部では、矩形当たり判定相手の時でも対応できるように矩形情報に変換して同時に持っている。
37
+ # そのとき、引数circumがtrueのときは、円を矩形の外接円と認識して、内部の矩形(正方形)の長さを算出する。
38
+ # circumがfalseのときは、円を矩形の内接円と認識して、内部の矩形(正方形)の長さを算出する。
39
+ #_rect_:: コリジョンを設定する範囲
40
+ #_circum_:: 矩形当たり判定とみなす時、円を外接円とするときはtrueを設定する。デフォルトはtrue
41
+ #返却値:: 作成されたコリジョン
42
+ def initialize(rect, circum = true)
43
+ @rect = Rect.new(*(rect.to_a[0..3]))
44
+ raise MiyakoValueError, "Illegal width! #{@rect[2]}" if @rect[2] < Float::EPSILON
45
+ raise MiyakoValueError, "Illegal height! #{@rect[3]}" if @rect[3] < Float::EPSILON
46
+ w = @rect[2].to_f
47
+ h = @rect[2].to_f
48
+ @center = Point.new(@rect[0].to_f + w / 2.0, @rect[1].to_f + h / 2.0)
49
+ @radius = circum ? Math.sqrt(w ** 2 + h ** 2) / 2.0 : [w, h].min / 2.0
50
+ end
51
+
52
+ def initialize_copy(obj) #:nodoc:
53
+ @rect = @rect.dup
54
+ @center = @center.dup
55
+ end
56
+
57
+ #===当たり判定を行う(領域が重なっている)
58
+ #_pos1_:: 自分自身の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)
59
+ #_c2_:: 判定対象のコリジョンインスタンス
60
+ #_pos2_:: c2の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)
61
+ #返却値:: 1ピクセルでも重なっていれば true を返す
62
+ def collision?(pos1, c2, pos2)
63
+ return Collision.collision?(self, pos1, c2, pos2)
64
+ end
65
+
66
+ #===当たり判定を行う(領域がピクセル単位で隣り合っている)
67
+ #_pos1_:: 自分自身の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)
68
+ #_c2_:: 判定対象のコリジョンインスタンス
69
+ #_pos2_:: c2の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)
70
+ #返却値:: 領域が隣り合っていれば true を返す
71
+ def meet?(pos1, c2, pos2)
72
+ return Collision.meet?(self, pos1, c2, pos2)
73
+ end
74
+
75
+ #===当たり判定を行う(どちらかの領域がもう一方にすっぽり覆われている))
76
+ #_pos1_:: 自分自身の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)
77
+ #_c2_:: 判定対象のコリジョンインスタンス
78
+ #_pos2_:: c2の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)
79
+ #返却値:: 領域が覆われていれば true を返す
80
+ def cover?(pos1, c2, pos2)
81
+ return Collision.cover?(self, pos1, c2, pos2)
82
+ end
83
+
84
+ #===当たり判定を行う(領域が重なっている)
85
+ #_c1_:: 判定対象のコリジョンインスタンス(1)
86
+ #_pos1_:: c1の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)
87
+ #_c2_:: 判定対象のコリジョンインスタンス(2)
88
+ #_pos2_:: c2の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)
89
+ #返却値:: 1ピクセルでも重なっていれば true を返す
90
+ def Collision.collision?(c1, pos1, c2, pos2)
91
+ l1 = pos1[0] + c1.rect[0]
92
+ t1 = pos1[1] + c1.rect[1]
93
+ r1 = l1 + c1.rect[2] - 1
94
+ b1 = t1 + c1.rect[3] - 1
95
+ l2 = pos2[0] + c2.rect[0]
96
+ t2 = pos2[1] + c2.rect[1]
97
+ r2 = l2 + c2.rect[2] - 1
98
+ b2 = t2 + c2.rect[3] - 1
99
+ v = 0
100
+ v |= 1 if l1 <= l2 && l2 <= r1
101
+ v |= 1 if l1 <= r2 && r2 <= r1
102
+ v |= 2 if t1 <= t2 && t2 <= b1
103
+ v |= 2 if t1 <= b2 && b2 <= b1
104
+ return v == 3
105
+ end
106
+
107
+ #===当たり判定を行う(領域がピクセル単位で隣り合っている)
108
+ #_c1_:: 判定対象のコリジョンインスタンス(1)
109
+ #_pos1_:: c1の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)
110
+ #_c2_:: 判定対象のコリジョンインスタンス(2)
111
+ #_pos2_:: c2の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)
112
+ #返却値:: 領域が隣り合っていれば true を返す
113
+ def Collision.meet?(c1, pos1, c2, pos2)
114
+ l1 = pos1[0] + c1.rect[0]
115
+ t1 = pos1[1] + c1.rect[1]
116
+ r1 = l1 + c1.rect[2]
117
+ b1 = t1 + c1.rect[3]
118
+ l2 = pos2[0] + c2.rect[0]
119
+ t2 = pos2[1] + c2.rect[1]
120
+ r2 = l2 + c2.rect[2]
121
+ b2 = t2 + c2.rect[3]
122
+ v = 0
123
+ v |= 1 if r1 == l2
124
+ v |= 1 if b1 == t2
125
+ v |= 1 if l1 == r2
126
+ v |= 1 if t1 == b2
127
+ return v == 1
128
+ end
129
+
130
+ #===当たり判定を行う(どちらかの領域がもう一方にすっぽり覆われている))
131
+ #_c1_:: 判定対象のコリジョンインスタンス(1)
132
+ #_pos1_:: c1の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)
133
+ #_c2_:: 判定対象のコリジョンインスタンス(2)
134
+ #_pos2_:: c2の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)
135
+ #返却値:: 領域が覆われていれば true を返す
136
+ def Collision.cover?(c1, pos1, c2, pos2)
137
+ l1 = pos1[0] + c1.rect[0]
138
+ t1 = pos1[1] + c1.rect[1]
139
+ r1 = l1 + c1.rect[2]
140
+ b1 = t1 + c1.rect[3]
141
+ l2 = pos2[0] + c2.rect[0]
142
+ t2 = pos2[1] + c2.rect[1]
143
+ r2 = l2 + c2.rect[2]
144
+ b2 = t2 + c2.rect[3]
145
+ v = 0
146
+ v |= 1 if l1 >= l2 && r2 <= r1
147
+ v |= 2 if t1 >= t2 && b2 <= b1
148
+ v |= 4 if l2 >= l1 && r1 <= r2
149
+ v |= 8 if t2 >= t1 && b1 <= b2
150
+ return v & 3 == 3 || v & 12 == 12
151
+ end
152
+
153
+ #== インスタンスの内容を解放する
154
+ #返却値:: なし
155
+ def dispose
156
+ @rect = nil
157
+ end
158
+ end
159
+
160
+ #==円形当たり判定領域(サークルコリジョン)クラス
161
+ # 円形の当たり判定を実装する。
162
+ # コリジョンは中心位置と半径で構成され、円形当たり判定同士で衝突判定を行う
163
+ # コリジョンで使用する値は、実数での設定が可能
164
+ class CircleCollision
165
+ extend Forwardable
166
+
167
+ # コリジョンの中心点([x,y])
168
+ attr_reader :center
169
+ # コリジョンの半径
170
+ attr_reader :radius
171
+ # 移動時イベントブロック配列
172
+
173
+ #===コリジョンのインスタンスを作成する
174
+ # コリジョンの半径が0もしくはマイナスのとき例外が発生する
175
+ # 内部では、矩形当たり判定相手の時でも対応できるように矩形情報に変換して同時に持っている。
176
+ # そのとき、引数circumがtrueのときは、円を矩形の外接円と認識して、内部の矩形(正方形)の長さを算出する。
177
+ # circumがfalseのときは、円を矩形の内接円と認識して、内部の矩形(正方形)の長さを算出する。
178
+ #_center_:: コリジョンを設定する範囲
179
+ #_radius_:: コリジョンの半径
180
+ #_circum_:: 矩形当たり判定とみなす時、円を外接円とするときはtrueを設定する。デフォルトはtrue
181
+ #返却値:: 作成されたコリジョン
182
+ def initialize(center, radius, circum = true)
183
+ raise MiyakoValueError, "illegal radius! #{radius}" if radius < Float::EPSILON
184
+ @center = Point.new(*(center.to_a[0..1]))
185
+ @radius = radius
186
+ if circum
187
+ rad = @radius.to_f / Math.sqrt(2.0)
188
+ @rect = Rect.new(@center[0]-rad, @center[1]-rad, rad*2.0, rad*2.0)
189
+ else
190
+ @rect = Rect.new(@center[0]-@radius, @center[1]-@radius, @radius*2.0, @radius*2.0)
191
+ end
192
+ end
193
+
194
+ def initialize_copy(obj) #:nodoc:
195
+ @rect = @rect.dup
196
+ @center = @center.dup
197
+ end
198
+
199
+ #===当たり判定間の距離を算出する
200
+ #_pos1_:: 自分自身の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)
201
+ #_c2_:: 判定対象のコリジョンインスタンス
202
+ #_pos2_:: c2の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)
203
+ #返却値:: 1ピクセルでも重なっていれば true を返す
204
+ def interval(pos1, c2, pos2)
205
+ return CircleCollision.interval(self, pos1, c2, pos2)
206
+ end
207
+
208
+ #===当たり判定を行う(領域が重なっている)
209
+ #_pos1_:: 自分自身の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)
210
+ #_c2_:: 判定対象のコリジョンインスタンス
211
+ #_pos2_:: c2の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)
212
+ #返却値:: 1ピクセルでも重なっていれば true を返す
213
+ def collision?(pos1, c2, pos2)
214
+ return CircleCollision.collision?(self, pos1, c2, pos2)
215
+ end
216
+
217
+ #===当たり判定を行う(領域がピクセル単位で隣り合っている)
218
+ #_pos1_:: 自分自身の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)
219
+ #_c2_:: 判定対象のコリジョンインスタンス
220
+ #_pos2_:: c2の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)
221
+ #返却値:: 領域が隣り合っていれば true を返す
222
+ def meet?(pos1, c2, pos2)
223
+ return CircleCollision.meet?(self, pos1, c2, pos2)
224
+ end
225
+
226
+ #===当たり判定を行う(どちらかの領域がもう一方にすっぽり覆われている))
227
+ #_pos1_:: 自分自身の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)
228
+ #_c2_:: 判定対象のコリジョンインスタンス
229
+ #_pos2_:: c2の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)
230
+ #返却値:: 領域が覆われていれば true を返す
231
+ def cover?(pos1, c2, pos2)
232
+ return CircleCollision.cover?(self, pos1, c2, pos2)
233
+ end
234
+
235
+ #===当たり判定間の距離を算出する
236
+ # 2つの当たり判定がどの程度離れているかを算出する。
237
+ # 返ってくる値は、衝突していなければ正の実数、衝突していれば負の実数で返ってくる
238
+ #_c1_:: 判定対象のコリジョンインスタンス(1)
239
+ #_pos1_:: c1の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)
240
+ #_c2_:: 判定対象のコリジョンインスタンス(2)
241
+ #_pos2_:: c2の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)
242
+ #返却値:: 当たり判定間の距離
243
+ def CircleCollision.interval(c1, pos1, c2, pos2)
244
+ #2点間の距離を求める
245
+ d = Math.sqrt((((c1.center[0].to_f + pos1[0].to_f) - (c2.center[0].to_f + pos2[0].to_f)) ** 2) +
246
+ (((c1.center[1].to_f + pos1[1].to_f) - (c2.center[1].to_f + pos2[1].to_f)) ** 2))
247
+ #半径の和を求める
248
+ r = c1.radius.to_f + c2.radius.to_f
249
+ distance = d - r
250
+ return distance.abs < Float::EPSILON ? 0.0 : distance
251
+ end
252
+
253
+ #===当たり判定を行う(領域が重なっている)
254
+ #_c1_:: 判定対象のコリジョンインスタンス(1)
255
+ #_pos1_:: c1の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)
256
+ #_c2_:: 判定対象のコリジョンインスタンス(2)
257
+ #_pos2_:: c2の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)
258
+ #返却値:: 1ピクセルでも重なっていれば true を返す
259
+ def CircleCollision.collision?(c1, pos1, c2, pos2)
260
+ #2点間の距離を求める
261
+ d = (((c1.center[0] + pos1[0]) - (c2.center[0] + pos2[0])) ** 2) +
262
+ (((c1.center[1] + pos1[1]) - (c2.center[1] + pos2[1])) ** 2)
263
+ #半径の和を求める
264
+ r = (c1.radius + c2.radius) ** 2
265
+ return d <= r
266
+ end
267
+
268
+ #===当たり判定を行う(領域がピクセル単位で隣り合っている)
269
+ # 但し、実際の矩形範囲が偶数の時は性格に判定できない場合があるため注意
270
+ #_c1_:: 判定対象のコリジョンインスタンス(1)
271
+ #_pos1_:: c1の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)
272
+ #_c2_:: 判定対象のコリジョンインスタンス(2)
273
+ #_pos2_:: c2の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)
274
+ #返却値:: 領域が隣り合っていれば true を返す
275
+ def CircleCollision.meet?(c1, pos1, c2, pos2)
276
+ #2点間の距離を求める
277
+ d = (((c1.center[0] + pos1[0]) - (c2.center[0] + pos2[0])) ** 2) +
278
+ (((c1.center[1] + pos1[1]) - (c2.center[1] + pos2[1])) ** 2)
279
+ #半径の和を求める
280
+ r = (c1.radius + c2.radius) ** 2
281
+ return d == r
282
+ end
283
+
284
+ #===当たり判定を行う(どちらかの領域がもう一方にすっぽり覆われている))
285
+ #_c1_:: 判定対象のコリジョンインスタンス(1)
286
+ #_pos1_:: c1の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)
287
+ #_c2_:: 判定対象のコリジョンインスタンス(2)
288
+ #_pos2_:: c2の位置(Point/Rect/Square構造体、2要素以上の配列、もしくはx,yメソッドを持つインスタンス)
289
+ #返却値:: 領域が覆われていれば true を返す
290
+ def CircleCollision.cover?(c1, pos1, c2, pos2)
291
+ #2点間の距離を求める
292
+ d = ((c1.center[0] + pos1[0]) - (c2.center[0] + pos2[0])) ** 2 +
293
+ ((c1.center[1] + pos1[1]) - (c2.center[1] + pos2[1])) ** 2
294
+ #半径の差分を求める
295
+ r = c1.radius ** 2 - 2 * (c1.radius * c2.radius) + c2.radius ** 2
296
+ return d <= r
297
+ end
298
+
299
+ #== インスタンスの内容を解放する
300
+ #返却値:: なし
301
+ def dispose
302
+ @point = nil
303
+ end
304
+ end
305
+
306
+ #==コリジョン管理クラス
307
+ # 複数のコリジョンと元オブジェクトを配列の様に一括管理できる
308
+ # 当たり判定を一括処理することで高速化を図る
309
+ class Collisions
310
+ include Enumerable
311
+ extend Forwardable
312
+
313
+ #===コリジョンのインスタンスを作成する
314
+ # points引数の各要素は、以下の3つの条件のどれかに適合する必要がある。しない場合は例外が発生する
315
+ # 1)[x,y]の要素を持つ配列
316
+ # 2)Point構造体、Rect構造体、もしくはSquare構造体
317
+ # 3)x,yメソッドを持つ
318
+ #_collisions_:: コリジョンの配列。デフォルトは []
319
+ #_points_:: 位置情報の配列。デフォルトは []
320
+ #返却値:: 作成されたインスタンス
321
+ def initialize(collisions=[], points=[])
322
+ @collisions = Array.new(collisions).zip(points)
323
+ end
324
+
325
+ def initialize_copy(obj) #:nodoc:
326
+ @collisions = @collisions.dup
327
+ end
328
+
329
+ def deep_dup_collision #:nodocs:
330
+ @collisions = @collisions.deep_dup
331
+ return self
332
+ end
333
+
334
+ #===要素も複製した複製インスタンスを返す
335
+ #返却値:: 複製したインスタンスを返す
336
+ def deep_dup
337
+ ret = self.dup
338
+ ret.deep_dup_collision
339
+ end
340
+
341
+ #===コリジョンと位置情報を追加する
342
+ # point引数は、以下の3つの条件のどれかに適合する必要がある。しない場合は例外が発生する
343
+ # 1)[x,y]の要素を持つ配列
344
+ # 2)Point構造体、Rect構造体、もしくはSquare構造体
345
+ # 3)x,yメソッドを持つ
346
+ #_collisions_:: コリジョン
347
+ #_point_:: 位置情報
348
+ #返却値:: 自分自身を返す
349
+ def add(collision, point)
350
+ @collisions << [collision, point]
351
+ return self
352
+ end
353
+
354
+ #===インスタンスに、コリジョンと位置情報の集合を追加する
355
+ # points引数の各要素は、以下の3つの条件のどれかに適合する必要がある。しない場合は例外が発生する
356
+ # 1)[x,y]の要素を持つ配列
357
+ # 2)Point構造体、Rect構造体、もしくはSquare構造体
358
+ # 3)x,yメソッドを持つ
359
+ #_collisions_:: コリジョンの配列
360
+ #_points_:: 位置情報の配列
361
+ #返却値:: 自分自身を返す
362
+ def append(collisions, points)
363
+ @collisions.concat(collisions.zip(points))
364
+ return self
365
+ end
366
+
367
+ #===インデックス形式でのコリジョン・本体の取得
368
+ #_idx_:: 配列のインデックス番号
369
+ #返却値:: インデックスに対応したコリジョンと位置情報との対。
370
+ #インデックスが範囲外の時はnilが返る
371
+ def [](idx)
372
+ return @collisions[idx]
373
+ end
374
+
375
+ #===コリジョン・本体の削除
376
+ #_idx_:: 配列のインデックス番号
377
+ #返却値:: 削除したコリジョンと本体との対
378
+ #インデックスが範囲外の時はnilが返る
379
+ def delete(idx)
380
+ return @collisions.delete_at(idx)
381
+ end
382
+
383
+ #===インデックス形式でのコリジョン・本体の取得
384
+ #_idx_:: 配列のインデックス番号
385
+ #返却値:: インデックスに対応したコリジョンと本体との対
386
+ def clear
387
+ @collisions.clear
388
+ return self
389
+ end
390
+
391
+ #===タッピングを行う
392
+ # ブロックを渡すことにより、タッピングを行う
393
+ # ブロック内の引数は、|コリジョン,本体|の2が渡される
394
+ #返却値:: 自分自身を返す
395
+ def each
396
+ @collisions.each{|cb| yield cb[0], cb[1] }
397
+ return self
398
+ end
399
+
400
+ #===タッピングを行う
401
+ # ブロックを渡すことにより、タッピングを行う
402
+ # ブロック内の引数は、|コリジョン,本体|の2が渡される
403
+ #_idx_:: 配列のインデックス
404
+ #返却値:: 自分自身を返す
405
+ def tap(idx)
406
+ yield @collisions[idx][0], @collisions[idx][1]
407
+ return self
408
+ end
409
+
410
+ #===当たり判定を行う(配列のどれかの領域が重なっている)
411
+ # 重なったコリジョンが一つでもあれば、最初に引っかかったコリジョンを返す
412
+ # 重なったコリジョンが無い場合はnilを返す
413
+ #_c_:: 判定対象のコリジョンインスタンス
414
+ #_pos_:: cの位置(Point/Rect/Square構造体、もしくは2要素の配列)
415
+ #返却値:: コリジョンと本体の対。
416
+ def collision?(c, pos)
417
+ return @collisions.detect{|cc| c.collision?(pos, cc[0], cc[1])}
418
+ end
419
+
420
+ #===当たり判定を行う(配列のどれかの領域がピクセル単位で隣り合っている)
421
+ # 隣り合ったコリジョンが一つでもあれば、最初に引っかかったコリジョンを返す
422
+ # 隣り合ったコリジョンが無い場合はnilを返す
423
+ #_c_:: 判定対象のコリジョンインスタンス
424
+ #_pos_:: cの位置(Point/Rect/Square構造体、もしくは2要素の配列)
425
+ #返却値:: 隣り合っていれば true を返す
426
+ def meet?(c, pos)
427
+ return @collisions.detect{|cc| c.meet?(pos, cc[0], cc[1])}
428
+ end
429
+
430
+ #===当たり判定を行う(どちらかの領域がもう一方にすっぽり覆われている))
431
+ # 覆われたコリジョンが一つでもあれば、最初に引っかかったコリジョンを返す
432
+ # 覆われたコリジョンが無い場合はnilを返す
433
+ #_c_:: 判定対象のコリジョンインスタンス
434
+ #_pos_:: cの位置(Point/Rect/Square構造体、もしくは2要素の配列)
435
+ #返却値:: 領域が覆われていれば true を返す
436
+ def cover?(c, pos)
437
+ return @collisions.detect{|cc| c.cover?(pos, cc[0], cc[1])}
438
+ end
439
+
440
+ #===当たり判定を行う(領域が重なっている)
441
+ # 重なったコリジョンが一つでもあれば、すべてのコリジョンの配列を返す
442
+ # 重なったコリジョンが無い場合はnilを返す
443
+ #_c_:: 判定対象のコリジョンインスタンス
444
+ #_pos_:: cの位置(Point/Rect/Square構造体、もしくは2要素の配列)
445
+ #返却値:: コリジョンと本体の対の配列。
446
+ def collision_all?(c, pos)
447
+ return @collisions.select{|cc| c.collision?(pos, cc[0], cc[1])}
448
+ end
449
+
450
+ #===当たり判定を行う(領域がピクセル単位で隣り合っている)
451
+ # 隣り合ったコリジョンが一つでもあれば、すべてのコリジョンの配列を返す
452
+ # 隣り合ったコリジョンが無い場合はnilを返す
453
+ #_c_:: 判定対象のコリジョンインスタンス
454
+ #_pos_:: cの位置(Point/Rect/Square構造体、もしくは2要素の配列)
455
+ #返却値:: コリジョンと本体の対の配列。
456
+ def meet_all?(c, pos)
457
+ return @collisions.select{|cc| c.meet?(pos, cc[0], cc[1])}
458
+ end
459
+
460
+ #===当たり判定を行う(どちらかの領域がもう一方にすっぽり覆われている))
461
+ # 覆われたコリジョンが一つでもあれば、すべてのコリジョンの配列を返す
462
+ # 覆われたコリジョンが無い場合はnilを返す
463
+ #_c_:: 判定対象のコリジョンインスタンス
464
+ #_pos_:: cの位置(Point/Rect/Square構造体、もしくは2要素の配列)
465
+ #返却値:: コリジョンと本体の対の配列。
466
+ def cover_all?(c, pos)
467
+ return @collisions.select{|cc| c.cover?(pos, cc[0], cc[1])}
468
+ end
469
+
470
+ #===インデックス形式でのコリジョン・本体の取得
471
+ # 判定に引っかかったコリジョンが一つでもあれば、すべてのコリジョンの配列を返す
472
+ # 当たり判定に引っかかったコリジョンが無い場合はnilを返す
473
+ #_idx_:: 配列のインデックス番号
474
+ #返却値:: インデックスに対応したコリジョンと本体との対
475
+ def [](idx)
476
+ return [@collisions[idx], @bodies[idx]]
477
+ end
478
+
479
+ #===オブジェクトを解放する
480
+ #返却値:: なし
481
+ def dispose
482
+ @collisions.clear
483
+ @collisions = nil
484
+ end
485
+ end
486
+ end