fyrox_impl/scene/tilemap/
tile_rect.rs

1// Copyright (c) 2019-present Dmitry Stepanov and Fyrox Engine contributors.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to deal
5// in the Software without restriction, including without limitation the rights
6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7// copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in all
11// copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19// SOFTWARE.
20
21//! A structure to represent rectanglular regions within a tile set page or
22//! a tile map. See [`TileRect`] for more information.
23//! [`OptionTileRect`] is for regions that may be empty.
24
25use std::ops::{Deref, DerefMut};
26
27use crate::core::algebra::Vector2;
28
29/// This is a variation of `Rect` that is specifically designed for use with
30/// TileMap. While the y-axis of `Rect` points downward to match the y-axis
31/// of UI, the y-axis of `TileRect` points upward to match the y-axis of
32/// TileMap, TileSet, and TileMapBrush.
33///
34/// Unlike `Rect`, `TileRect` is designed to contain a WxH region of tiles,
35/// which means that `position + size` is *not* considered to be a point
36/// contained in the rect. A point is only contained in the rect if its
37/// entire 1x1 area is contained in the rect, so the left-top corner
38/// of the rect is `position + size - (1,1)`.
39#[derive(Copy, Clone, Debug, PartialEq, Eq)]
40pub struct TileRect {
41    /// The left-bottom corner of the rect.
42    pub position: Vector2<i32>,
43    /// The width and height of the rect.
44    pub size: Vector2<i32>,
45}
46
47/// An option version of `TileRect` that contains nothing.
48#[derive(Default, Copy, Clone, Debug, PartialEq, Eq)]
49pub struct OptionTileRect(Option<TileRect>);
50
51#[derive(Debug, Clone)]
52/// Iterator for the cells contained in a TileRect.
53pub struct RectIter(Vector2<i32>, TileRect);
54/// Iterator for the cells contained in an OptionTileRect.
55#[derive(Debug, Clone)]
56pub struct OptionRectIter(Option<RectIter>);
57
58impl Iterator for RectIter {
59    type Item = Vector2<i32>;
60
61    fn next(&mut self) -> Option<Self::Item> {
62        if self.0.y >= self.1.h() {
63            return None;
64        }
65        let result = self.0 + self.1.position;
66        self.0.x += 1;
67        if self.0.x >= self.1.w() {
68            self.0.x = 0;
69            self.0.y += 1;
70        }
71        Some(result)
72    }
73}
74
75impl Iterator for OptionRectIter {
76    type Item = Vector2<i32>;
77
78    fn next(&mut self) -> Option<Self::Item> {
79        self.0.as_mut()?.next()
80    }
81}
82
83impl From<RectIter> for OptionRectIter {
84    fn from(value: RectIter) -> Self {
85        Self(Some(value))
86    }
87}
88
89impl From<TileRect> for OptionTileRect {
90    fn from(source: TileRect) -> Self {
91        Self(Some(source))
92    }
93}
94impl From<Option<TileRect>> for OptionTileRect {
95    fn from(source: Option<TileRect>) -> Self {
96        Self(source)
97    }
98}
99impl Deref for OptionTileRect {
100    type Target = Option<TileRect>;
101
102    fn deref(&self) -> &Self::Target {
103        &self.0
104    }
105}
106
107impl DerefMut for OptionTileRect {
108    fn deref_mut(&mut self) -> &mut Self::Target {
109        &mut self.0
110    }
111}
112
113impl IntoIterator for OptionTileRect {
114    type Item = Vector2<i32>;
115
116    type IntoIter = OptionRectIter;
117
118    fn into_iter(self) -> Self::IntoIter {
119        self.iter()
120    }
121}
122
123impl OptionTileRect {
124    /// Create a new rectangle from two diagonally opposite corner points.
125    /// In other words, create the smallest rectangle containing both given points.
126    pub fn from_points(p0: Vector2<i32>, p1: Vector2<i32>) -> Self {
127        TileRect::from_points(p0, p1).into()
128    }
129
130    /// Iterate over the cells contained within this rect.
131    pub fn iter(&self) -> OptionRectIter {
132        OptionRectIter(self.0.map(|x| x.iter()))
133    }
134
135    /// Deflates the rectangle by the given amounts. It offsets the rectangle by `(dw, dh)` and
136    /// decreases its size by `(2 * dw, 2 * dh)`.
137    #[inline]
138    #[must_use = "this method creates new instance of OptionTileRect"]
139    pub fn deflate(&self, dw: i32, dh: i32) -> Self {
140        if let Some(rect) = &self.0 {
141            rect.deflate(dw, dh)
142        } else {
143            Self(None)
144        }
145    }
146
147    /// Clip the rectangle to the given bounds.
148    #[inline]
149    pub fn clip(&mut self, bounds: TileRect) {
150        if let Some(rect) = &self.0 {
151            *self = rect.clip_by(bounds);
152        }
153    }
154    /// Extends the rectangle so it will contain the given point.
155    #[inline]
156    pub fn push(&mut self, p: Vector2<i32>) {
157        if let Some(rect) = &mut self.0 {
158            rect.push(p);
159        } else {
160            self.0 = Some(TileRect::new(p.x, p.y, 1, 1));
161        }
162    }
163    /// Checks if the given point lies within the bounds of the rectangle.
164    #[inline]
165    pub fn contains(&self, p: Vector2<i32>) -> bool {
166        if let Some(rect) = &self.0 {
167            rect.contains(p)
168        } else {
169            false
170        }
171    }
172    /// Checks if the rectangle intersects with some other rectangle.
173    #[inline]
174    pub fn intersects(&self, other: TileRect) -> bool {
175        if let Some(rect) = &self.0 {
176            rect.intersects(other)
177        } else {
178            false
179        }
180    }
181
182    /// Extends the rectangle so it will contain the other rectangle.
183    #[inline]
184    pub fn extend_to_contain(&mut self, other: TileRect) {
185        if let Some(rect) = &mut self.0 {
186            rect.extend_to_contain(other);
187        } else {
188            self.0 = Some(other);
189        }
190    }
191    /// Returns width of the rectangle.
192    #[inline(always)]
193    pub fn w(&self) -> i32 {
194        if let Some(rect) = &self.0 {
195            rect.size.x
196        } else {
197            0
198        }
199    }
200
201    /// Returns height of the rectangle.
202    #[inline(always)]
203    pub fn h(&self) -> i32 {
204        if let Some(rect) = &self.0 {
205            rect.size.y
206        } else {
207            0
208        }
209    }
210}
211
212impl IntoIterator for TileRect {
213    type Item = Vector2<i32>;
214
215    type IntoIter = RectIter;
216
217    fn into_iter(self) -> Self::IntoIter {
218        self.iter()
219    }
220}
221
222impl TileRect {
223    /// Creates a new rectangle from X, Y, width, height.
224    #[inline]
225    pub fn new(x: i32, y: i32, w: i32, h: i32) -> Self {
226        Self {
227            position: Vector2::new(x, y),
228            size: Vector2::new(w, h),
229        }
230    }
231
232    /// Iterate over the cells contained within this rect.
233    #[inline]
234    pub fn iter(&self) -> RectIter {
235        RectIter(Vector2::new(0, 0), *self)
236    }
237
238    /// Create a new rectangle from two diagonally opposite corner points.
239    /// In other words, create the smallest rectangle containing both given points.
240    pub fn from_points(p0: Vector2<i32>, p1: Vector2<i32>) -> Self {
241        let inf = p0.inf(&p1);
242        let sup = p0.sup(&p1);
243        Self {
244            position: inf,
245            size: sup - inf + Vector2::new(1, 1),
246        }
247    }
248
249    /// Sets the new position of the rectangle.
250    #[inline]
251    pub fn with_position(mut self, position: Vector2<i32>) -> Self {
252        self.position = position;
253        self
254    }
255
256    /// Sets the new size of the rectangle.
257    #[inline]
258    pub fn with_size(mut self, size: Vector2<i32>) -> Self {
259        self.size = size;
260        self
261    }
262
263    /// Inflates the rectangle by the given amounts. It offsets the rectangle by `(-dw, -dh)` and
264    /// increases its size by `(2 * dw, 2 * dh)`.
265    #[inline]
266    #[must_use = "this method creates new instance of TileRect"]
267    pub fn inflate(&self, dw: i32, dh: i32) -> Self {
268        Self {
269            position: Vector2::new(self.position.x - dw, self.position.y - dh),
270            size: Vector2::new(self.size.x + dw + dw, self.size.y + dh + dh),
271        }
272    }
273
274    /// Deflates the rectangle by the given amounts. It offsets the rectangle by `(dw, dh)` and
275    /// decreases its size by `(2 * dw, 2 * dh)`.
276    #[inline]
277    #[must_use = "this method creates new instance of OptionTileRect"]
278    pub fn deflate(&self, dw: i32, dh: i32) -> OptionTileRect {
279        if self.size.x > dw + dw && self.size.y > dh + dh {
280            OptionTileRect(Some(TileRect {
281                position: Vector2::new(self.position.x + dw, self.position.y + dh),
282                size: Vector2::new(self.size.x - (dw + dw), self.size.y - (dh + dh)),
283            }))
284        } else {
285            OptionTileRect(None)
286        }
287    }
288
289    /// Checks if the given point lies within the bounds of the rectangle.
290    #[inline]
291    pub fn contains(&self, pt: Vector2<i32>) -> bool {
292        pt.x >= self.position.x
293            && pt.x < self.position.x + self.size.x
294            && pt.y >= self.position.y
295            && pt.y < self.position.y + self.size.y
296    }
297
298    /// Returns center point of the rectangle.
299    #[inline]
300    pub fn center(&self) -> Vector2<i32> {
301        self.position + Vector2::new(self.size.x / 2, self.size.y / 2)
302    }
303
304    /// Extends the rectangle to contain the given point.
305    #[inline]
306    pub fn push(&mut self, p: Vector2<i32>) {
307        let p0 = self.left_bottom_corner();
308        let p1 = self.right_top_corner();
309        *self = Self::from_points(p.inf(&p0), p.sup(&p1));
310    }
311
312    /// Clips the rectangle by some other rectangle and returns a new rectangle that corresponds to
313    /// the intersection of both rectangles. If the rectangles does not intersects, the method
314    /// returns none.
315    #[inline]
316    #[must_use = "this method creates new instance of OptionTileRect"]
317    pub fn clip_by(&self, other: TileRect) -> OptionTileRect {
318        let mut clipped = *self;
319
320        if other.x() + other.w() <= self.x()
321            || other.x() >= self.x() + self.w()
322            || other.y() + other.h() <= self.y()
323            || other.y() >= self.y() + self.h()
324        {
325            return OptionTileRect::default();
326        }
327
328        if clipped.position.x < other.position.x {
329            clipped.size.x -= other.position.x - clipped.position.x;
330            clipped.position.x = other.position.x;
331        }
332
333        if clipped.position.y < other.position.y {
334            clipped.size.y -= other.position.y - clipped.position.y;
335            clipped.position.y = other.position.y;
336        }
337
338        let clipped_right_top = clipped.right_top_corner();
339        let other_right_top = other.right_top_corner();
340
341        if clipped_right_top.x > other_right_top.x {
342            clipped.size.x -= clipped_right_top.x - other_right_top.x;
343        }
344        if clipped_right_top.y > other_right_top.y {
345            clipped.size.y -= clipped_right_top.y - other_right_top.y;
346        }
347
348        clipped.into()
349    }
350
351    /// Checks if the rectangle intersects with some other rectangle.
352    #[inline]
353    pub fn intersects(&self, other: TileRect) -> bool {
354        if other.position.x < self.position.x + self.size.x
355            && self.position.x < other.position.x + other.size.x
356            && other.position.y < self.position.y + self.size.y
357        {
358            self.position.y < other.position.y + other.size.y
359        } else {
360            false
361        }
362    }
363
364    /// Offsets the given rectangle and returns a new rectangle.
365    #[inline]
366    #[must_use = "this method creates new instance of TileRect"]
367    pub fn translate(&self, translation: Vector2<i32>) -> Self {
368        Self {
369            position: Vector2::new(
370                self.position.x + translation.x,
371                self.position.y + translation.y,
372            ),
373            size: self.size,
374        }
375    }
376
377    /// Extends the rectangle so it will contain the other rectangle.
378    #[inline]
379    pub fn extend_to_contain(&mut self, other: TileRect) {
380        let p0 = self.left_bottom_corner();
381        let p1 = self.right_top_corner();
382        let o0 = other.left_bottom_corner();
383        let o1 = other.right_top_corner();
384        *self = Self::from_points(p0.inf(&o0), p1.sup(&o1));
385    }
386
387    /// Returns the top left corner of the rectangle.
388    #[inline(always)]
389    pub fn left_top_corner(&self) -> Vector2<i32> {
390        Vector2::new(self.position.x, self.position.y + self.size.y - 1)
391    }
392
393    /// Returns the top right corner of the rectangle.
394    #[inline(always)]
395    pub fn right_top_corner(&self) -> Vector2<i32> {
396        Vector2::new(
397            self.position.x + self.size.x - 1,
398            self.position.y + self.size.y - 1,
399        )
400    }
401
402    /// Returns the bottom right corner of the rectangle.
403    #[inline(always)]
404    pub fn right_bottom_corner(&self) -> Vector2<i32> {
405        Vector2::new(self.position.x + self.size.x - 1, self.position.y)
406    }
407
408    /// Returns the bottom left corner of the rectangle.
409    #[inline(always)]
410    pub fn left_bottom_corner(&self) -> Vector2<i32> {
411        self.position
412    }
413
414    /// Returns width of the rectangle.
415    #[inline(always)]
416    pub fn w(&self) -> i32 {
417        self.size.x
418    }
419
420    /// Returns height of the rectangle.
421    #[inline(always)]
422    pub fn h(&self) -> i32 {
423        self.size.y
424    }
425
426    /// Returns horizontal position of the rectangle.
427    #[inline(always)]
428    pub fn x(&self) -> i32 {
429        self.position.x
430    }
431
432    /// Returns vertical position of the rectangle.
433    #[inline(always)]
434    pub fn y(&self) -> i32 {
435        self.position.y
436    }
437}
438
439#[cfg(test)]
440mod tests {
441    use super::*;
442    #[test]
443    fn iter() {
444        let mut iter = TileRect::new(2, 3, 3, 2).iter();
445        assert_eq!(iter.next(), Some(Vector2::new(2, 3)));
446        assert_eq!(iter.next(), Some(Vector2::new(3, 3)));
447        assert_eq!(iter.next(), Some(Vector2::new(4, 3)));
448        assert_eq!(iter.next(), Some(Vector2::new(2, 4)));
449        assert_eq!(iter.next(), Some(Vector2::new(3, 4)));
450        assert_eq!(iter.next(), Some(Vector2::new(4, 4)));
451        assert_eq!(iter.next(), None);
452    }
453    #[test]
454    fn intersects1() {
455        let rect1 = TileRect::new(-1, -2, 4, 6);
456        let rect2 = TileRect::new(2, 3, 2, 2);
457        assert!(rect1.intersects(rect2));
458    }
459    #[test]
460    fn intersects2() {
461        let rect1 = TileRect::new(0, 0, 4, 6);
462        let rect2 = TileRect::new(-1, -2, 2, 3);
463        assert!(rect1.intersects(rect2));
464    }
465    #[test]
466    fn not_intersects1() {
467        let rect1 = TileRect::new(-1, -2, 3, 4);
468        let rect2 = TileRect::new(3, 3, 2, 2);
469        assert!(!rect1.intersects(rect2));
470    }
471    #[test]
472    fn not_intersects2() {
473        let rect1 = TileRect::new(-1, -2, 3, 4);
474        let rect2 = TileRect::new(2, 1, 2, 2);
475        assert!(!rect1.intersects(rect2));
476    }
477    #[test]
478    fn from_points1() {
479        let rect = TileRect::from_points(Vector2::new(-1, -2), Vector2::new(2, 1));
480        assert_eq!(rect, TileRect::new(-1, -2, 4, 4));
481    }
482    #[test]
483    fn from_points2() {
484        let rect = TileRect::from_points(Vector2::new(-1, 1), Vector2::new(2, -2));
485        assert_eq!(rect, TileRect::new(-1, -2, 4, 4));
486    }
487    #[test]
488    fn rect_extend_to_contain() {
489        let mut rect = TileRect::new(0, 0, 1, 1);
490
491        rect.extend_to_contain(TileRect::new(1, 1, 1, 1));
492        assert_eq!(rect, TileRect::new(0, 0, 2, 2));
493
494        rect.extend_to_contain(TileRect::new(-1, -1, 1, 1));
495        assert_eq!(rect, TileRect::new(-1, -1, 3, 3));
496
497        rect.extend_to_contain(TileRect::new(10, -1, 1, 15));
498        assert_eq!(rect, TileRect::new(-1, -1, 12, 15));
499    }
500    #[test]
501    fn rect_push2() {
502        let mut rect = TileRect::new(0, 0, 1, 1);
503
504        rect.push(Vector2::new(1, 1));
505        assert_eq!(rect, TileRect::new(0, 0, 2, 2));
506
507        rect.push(Vector2::new(-1, -1));
508        assert_eq!(rect, TileRect::new(-1, -1, 3, 3));
509
510        rect.push(Vector2::new(10, -1));
511        assert_eq!(rect, TileRect::new(-1, -1, 12, 3));
512    }
513    #[test]
514    fn option_rect_extend_to_contain() {
515        let mut rect = OptionTileRect::default();
516
517        rect.extend_to_contain(TileRect::new(1, 1, 1, 1));
518        assert_eq!(rect.unwrap(), TileRect::new(1, 1, 1, 1));
519
520        rect.extend_to_contain(TileRect::new(-1, -1, 1, 1));
521        assert_eq!(rect.unwrap(), TileRect::new(-1, -1, 3, 3));
522
523        rect.extend_to_contain(TileRect::new(10, -1, 1, 15));
524        assert_eq!(rect.unwrap(), TileRect::new(-1, -1, 12, 15));
525    }
526    #[test]
527    fn option_rect_push() {
528        let mut rect = OptionTileRect::default();
529
530        rect.push(Vector2::new(1, 1));
531        assert_eq!(rect.unwrap(), TileRect::new(1, 1, 1, 1));
532
533        rect.push(Vector2::new(-1, -1));
534        assert_eq!(rect.unwrap(), TileRect::new(-1, -1, 3, 3));
535
536        rect.push(Vector2::new(10, -1));
537        assert_eq!(rect.unwrap(), TileRect::new(-1, -1, 12, 3));
538    }
539    #[test]
540    fn option_rect_clip() {
541        let rect = OptionTileRect::from(TileRect::new(0, 0, 10, 10));
542
543        let mut r = rect;
544        r.clip(TileRect::new(2, 2, 1, 1));
545        assert_eq!(r.unwrap(), TileRect::new(2, 2, 1, 1));
546
547        let mut r = rect;
548        r.clip(TileRect::new(0, 0, 15, 15));
549        assert_eq!(r.unwrap(), TileRect::new(0, 0, 10, 10));
550
551        // When there is no intersection.
552        let mut r = OptionTileRect::default();
553        r.clip(TileRect::new(0, 0, 10, 10));
554        assert!(r.is_none());
555        let mut r = rect;
556        r.clip(TileRect::new(-2, 1, 1, 1));
557        assert!(r.is_none());
558        let mut r = rect;
559        r.clip(TileRect::new(11, 1, 1, 1));
560        assert!(r.is_none());
561        let mut r = rect;
562        r.clip(TileRect::new(1, -2, 1, 1));
563        assert!(r.is_none());
564        let mut r = rect;
565        r.clip(TileRect::new(1, 11, 1, 1));
566        assert!(r.is_none());
567    }
568
569    #[test]
570    fn rect_with_position() {
571        let rect = TileRect::new(0, 0, 1, 1);
572
573        assert_eq!(
574            rect.with_position(Vector2::new(1, 1)),
575            TileRect::new(1, 1, 1, 1)
576        );
577    }
578
579    #[test]
580    fn rect_with_size() {
581        let rect = TileRect::new(0, 0, 1, 1);
582
583        assert_eq!(
584            rect.with_size(Vector2::new(10, 10)),
585            TileRect::new(0, 0, 10, 10)
586        );
587    }
588
589    #[test]
590    fn rect_inflate() {
591        let rect = TileRect::new(0, 0, 1, 1);
592
593        assert_eq!(rect.inflate(5, 5), TileRect::new(-5, -5, 11, 11));
594    }
595
596    #[test]
597    fn rect_deflate() {
598        let rect = TileRect::new(-5, -5, 11, 11);
599
600        assert_eq!(rect.deflate(5, 5), TileRect::new(0, 0, 1, 1).into());
601        assert_eq!(rect.deflate(6, 5), OptionTileRect::default());
602    }
603
604    #[test]
605    fn rect_contains() {
606        let rect = TileRect::new(0, 0, 10, 10);
607
608        assert!(rect.contains(Vector2::new(0, 0)));
609        assert!(rect.contains(Vector2::new(0, 9)));
610        assert!(rect.contains(Vector2::new(9, 0)));
611        assert!(rect.contains(Vector2::new(9, 9)));
612        assert!(rect.contains(Vector2::new(5, 5)));
613
614        assert!(!rect.contains(Vector2::new(0, 10)));
615    }
616
617    #[test]
618    fn rect_center() {
619        let rect = TileRect::new(0, 0, 10, 10);
620
621        assert_eq!(rect.center(), Vector2::new(5, 5));
622    }
623
624    #[test]
625    fn rect_push() {
626        let mut rect = TileRect::new(10, 10, 10, 10);
627
628        rect.push(Vector2::new(0, 0));
629        assert_eq!(rect, TileRect::new(0, 0, 20, 20));
630
631        rect.push(Vector2::new(0, 20));
632        assert_eq!(rect, TileRect::new(0, 0, 20, 21));
633
634        rect.push(Vector2::new(20, 20));
635        assert_eq!(rect, TileRect::new(0, 0, 21, 21));
636
637        rect.push(Vector2::new(30, 30));
638        assert_eq!(rect, TileRect::new(0, 0, 31, 31));
639    }
640
641    #[test]
642    fn rect_getters() {
643        let rect = TileRect::new(0, 0, 2, 2);
644
645        assert_eq!(rect.left_bottom_corner(), Vector2::new(0, 0));
646        assert_eq!(rect.left_top_corner(), Vector2::new(0, 1));
647        assert_eq!(rect.right_bottom_corner(), Vector2::new(1, 0));
648        assert_eq!(rect.right_top_corner(), Vector2::new(1, 1));
649
650        assert_eq!(rect.x(), 0);
651        assert_eq!(rect.y(), 0);
652        assert_eq!(rect.w(), 2);
653        assert_eq!(rect.h(), 2);
654    }
655
656    #[test]
657    fn rect_clip_by() {
658        let rect = TileRect::new(0, 0, 10, 10);
659
660        assert_eq!(
661            rect.clip_by(TileRect::new(2, 2, 1, 1)).unwrap(),
662            TileRect::new(2, 2, 1, 1)
663        );
664        assert_eq!(
665            rect.clip_by(TileRect::new(0, 0, 15, 15)).unwrap(),
666            TileRect::new(0, 0, 10, 10)
667        );
668
669        // When there is no intersection.
670        assert!(rect.clip_by(TileRect::new(-2, 1, 1, 1)).is_none());
671        assert!(rect.clip_by(TileRect::new(11, 1, 1, 1)).is_none());
672        assert!(rect.clip_by(TileRect::new(1, -2, 1, 1)).is_none());
673        assert!(rect.clip_by(TileRect::new(1, 11, 1, 1)).is_none());
674    }
675
676    #[test]
677    fn rect_translate() {
678        let rect = TileRect::new(0, 0, 10, 10);
679
680        assert_eq!(
681            rect.translate(Vector2::new(5, 5)),
682            TileRect::new(5, 5, 10, 10)
683        );
684    }
685}