@@ -223,6 +223,141 @@ class MyGame extends FlameGame with HasCollisionDetection {
223
223
```
224
224
225
225
226
+ ## Ray casting and Ray tracing
227
+
228
+ Ray casting and ray tracing are methods for sending out rays from a point in your game and
229
+ being able to see what these rays collide with and how they reflect after hitting
230
+ something.
231
+
232
+
233
+ ### Ray casting
234
+
235
+ Ray casting is the operation of casting out one or more rays from a point and see if they hit
236
+ anything, in Flame's case, hitboxes.
237
+
238
+ We provide two methods for doing so, ` raycast ` and ` raycastAll ` . The first one just casts out
239
+ a single ray and gets back a result with information about what and where the ray hit, and some
240
+ extra information like the distance, the normal and the reflection ray. The second one, ` raycastAll ` ,
241
+ works similarly but sends out multiple rays uniformly around the origin, or within an angle
242
+ centered at the origin.
243
+
244
+ To use the ray casting functionality you have to have the ` HasCollisionDetection ` mixin on your
245
+ game. After you have added that you can call ` collisionDetection.raycast(...) ` on your game class.
246
+
247
+ Example:
248
+
249
+ ``` dart
250
+ class MyGame extends FlameGame with HasCollisionDetection {
251
+ @override
252
+ void update(double dt) {
253
+ super.update(dt);
254
+ final ray = Ray2(
255
+ origin: Vector2(0, 100),
256
+ direction: Vector2(1, 0),
257
+ );
258
+ final result = collisionDetection.raycast(ray);
259
+ }
260
+ }
261
+ ```
262
+
263
+ In this example one can see that the ` Ray2 ` class is being used, this class defines a ray from an
264
+ origin position and a direction (which are both defined by ` Vector2 ` s). This particular ray starts
265
+ from ` 0, 100 ` and shoots a ray straight to the right.
266
+
267
+ The result from this operation will either be ` null ` if the ray didn't hit anything, or a
268
+ ` RaycastResult ` which contains:
269
+ - Which hitbox the ray hit
270
+ - The intersection point of the collision
271
+ - The reflection ray, i.e. how the ray would reflect on the hitbox that it hix
272
+ - The normal of the collision, i.e. a vector perpendicular to the face of the hitbox that it hits
273
+
274
+ If you are concerned about performance you can pre create a ` RaycastResult ` object that you send in
275
+ to the method with the ` out ` argument, this will make it possible for the method to reuse this
276
+ object instead of creating a new one for each iteration. This can be good if you do a lot of
277
+ ray casting in your ` update ` methods.
278
+
279
+
280
+ #### raycastAll
281
+
282
+ Sometimes you want to send out rays in all, or a limited range, of directions from an origin. This
283
+ can have a lot of applications, for example you could calculate the field of view of a player or
284
+ enemy, or it can also be used to create light sources.
285
+
286
+ Example:
287
+
288
+ ``` dart
289
+ class MyGame extends FlameGame with HasCollisionDetection {
290
+ @override
291
+ void update(double dt) {
292
+ super.update(dt);
293
+ final origin = Vector2(200, 200);
294
+ final result = collisionDetection.raycastAll(
295
+ origin,
296
+ numberOfRays: 100,
297
+ );
298
+ }
299
+ }
300
+ ```
301
+
302
+ In this example we would send out 100 rays from (200, 200) uniformingly spread in all directions.
303
+
304
+ If you want to limit the directions you can use the ` startAngle ` and the ` sweepAngle ` arguments.
305
+ Where the ` startAngle ` (counting from straight up) is where the rays will start and then the rays
306
+ will end at ` startAngle + sweepAngle ` .
307
+
308
+ If you are concerned about performance you can re-use the ` RaycastResult ` objects that are created
309
+ by the function by sending them in as a list with the ` out ` argument.
310
+
311
+
312
+ ### Ray tracing
313
+
314
+ Ray tracing is similar to ray casting, but instead of just checking what the ray hits you can
315
+ continue to trace the ray and see what its reflection ray (the ray bouncing off the hitbox) will
316
+ hit and then what that casted reflection ray's reflection ray will hit and so on, until you decide
317
+ that you have traced the ray for long enough. If you imagine how a pool ball would bounce on a pool
318
+ table for example, that information could be retrieved with the help of ray tracing.
319
+
320
+ Example:
321
+
322
+ ``` dart
323
+ class MyGame extends FlameGame with HasCollisionDetection {
324
+ @override
325
+ void update(double dt) {
326
+ super.update(dt);
327
+ final ray = Ray2(
328
+ origin: Vector2(0, 100),
329
+ direction: Vector2(1, 1)..normalize()
330
+ );
331
+ final results = collisionDetection.raytrace(
332
+ ray,
333
+ maxDepth: 100,
334
+ );
335
+ for (final result in results) {
336
+ if (result.intersectionPoint.distanceTo(ray.origin) > 300) {
337
+ break;
338
+ }
339
+ }
340
+ }
341
+ }
342
+ ```
343
+
344
+ In the example above we send out a ray from (0, 100) diagonally down to the right and we say that we
345
+ want it the bounce on at most 100 hitboxes, it doesn't necessarily have to get 100 results since at
346
+ some point one of the reflection rays might not hit a hitbox and then the method is done.
347
+
348
+ The method is lazy, which means that it will only do the calculations that you ask for, so you have
349
+ to loop through the iterable that it returns to get the results, or do ` toList() ` to directly
350
+ calculate all the results.
351
+
352
+ In the for-loop it can be seen how this can be used, in that loop we check whether the current
353
+ reflection rays intersection point (where the previous ray hit the hitbox) is further away than 300
354
+ pixels from the origin of the starting ray, and if it is we don't care about the rest of the results
355
+ (and then they don't have to be calculated either).
356
+
357
+ If you are concerned about performance you can re-use the ` RaycastResult ` objects that are created
358
+ by the function by sending them in as a list with the ` out ` argument.
359
+
360
+
226
361
## Comparison to Forge2D
227
362
228
363
If you want to have a full-blown physics engine in your game we recommend that you use
0 commit comments