File Coverage

blib/lib/Collision/2D/Entity/Rect.pm
Criterion Covered Total %
statement 62 64 96.8
branch 24 28 85.7
condition 41 60 68.3
subroutine 9 10 90.0
pod 0 4 0.0
total 136 166 81.9


line stmt bran cond sub pod time code
1             package Collision::2D::Entity::Rect;
2 7     7   37 use strict;
  7         15  
  7         321  
3 7     7   34 use warnings;
  7         13  
  7         631  
4              
5             require DynaLoader;
6             our @ISA = qw(DynaLoader Collision::2D::Entity);
7             bootstrap Collision::2D::Entity::Rect;
8              
9 198     198   514 sub _p{4} #low priority
10 7     7   36 use overload '""' => sub{'rect'};
  7     159   12  
  7         58  
  159         421  
11 2     2 0 639 sub typename{'rect'}
12              
13             sub new{
14 860     860 0 2848 my ($package, %params) = @_;
15 860   100     14642 my $self = __PACKAGE__->_new (
      100        
      50        
      50        
      50        
      50        
16             @params{qw/x y/},
17             $params{xv} || 0,
18             $params{yv} || 0,
19             $params{relative_x} || 0,
20             $params{relative_y} || 0,
21             $params{relative_xv} || 0,
22             $params{relative_yv} || 0,
23             @params{qw/w h/},
24             );
25 860         2983 return $self;
26             }
27              
28             sub intersect_rect{
29 4     4 0 6 my ($self, $other) = @_;
30             return (
31 4   33     161 ($self->x < $other->x + $other->w)
32             && ($self->y < $other->y + $other->h)
33             && ($self->x + $self->w > $other->x)
34             && ($self->y + $self->h > $other->y));
35             }
36              
37             sub _collide_rect{
38 40     40   2671 my ($self, $other, %params) = @_;
39 40         95 my $xv = $self->relative_xv;
40 40         75 my $yv = $self->relative_yv;
41 40         90 my $x1 = $self->relative_x;
42 40         70 my $y1 = $self->relative_y;
43 40         77 my $x2 = $x1 + ($xv * $params{interval});
44 40         62 my $y2 = $y1 + ($yv * $params{interval});
45 40         76 my $sw = $self->w;
46 40         72 my $sh = $self->h;
47 40         64 my $ow = $other->w;
48 40         62 my $oh = $other->h;
49            
50             #start intersected?
51 40 100 100     311 return $self->null_collision($other) if (
      100        
      100        
52             $y1+$sh > 0 and
53             $x1+$sw > 0 and
54             $x1 < $ow and
55             $y1 < $oh
56             );
57             #miss entirely?
58 32 50 66     428 return if ( $x1+$sw < 0 and $x2+$sw < 0
      66        
      33        
      66        
      33        
      66        
      33        
59             or $x1 > $ow and $x2 > $ow
60             or $y1+$sh < 0 and $y2+$sh < 0
61             or $y1 > $oh and $y2 > $oh
62             );
63 32         53 my $best_time = $params{interval}+1;
64 32         28 my $best_axis;
65            
66 32 100       80 if ($x1+$sw < 0){ #hit on left of $other
67 15         21 my $time = -($x1+$sw)/$xv;
68 15         25 my $yatt = $y1+$yv*$time;
69 15 100 100     56 if ($yatt + $sh > 0 and $yatt < $oh){
70 6         46 $best_time = $time;
71 6         9 $best_axis = 'x';
72             }
73             }
74 32 100       63 if ($y1+$sh < 0){ #hit on bottom of $other
75 15         25 my $time = -($y1+$sh)/$yv;
76 15 50       32 if ($time<$best_time){
77 15         19 my $xatt = $x1+$xv*$time;
78 15 100 100     75 if ($xatt + $sw > 0 and $xatt < $ow){
79 6         8 $best_time = $time;
80 6         12 $best_axis = 'y';
81             }
82             }
83             }
84 32 100       61 if ($x1 > $ow){ #hit on right of $other
85 15         23 my $time = -($x1 - $ow)/$xv;
86 15 50       29 if ($time<$best_time){
87 15         27 my $yatt = $y1+$yv*$time;
88 15 100 100     68 if ($yatt + $sh > 0 and $yatt < $oh){
89 7         10 $best_time = $time;
90 7         13 $best_axis = 'x';
91             }
92             }
93             }
94 32 100       56 if ($y1 > $oh){ #hit on right of $top
95 15         25 my $time = -($y1 - $oh)/$yv;
96 15 50       30 if ($time<$best_time){
97 15         20 my $xatt = $x1+$xv*$time;
98 15 100 100     59 if ($xatt + $sw > 0 and $xatt < $ow){
99 7         9 $best_time = $time;
100 7         11 $best_axis = 'y';
101             }
102             }
103             }
104            
105 32 100       71 if ($best_time <= $params{interval}){
106 26         91 return Collision::2D::Collision->new(
107             axis => $best_axis,
108             time => $best_time,
109             ent1 => $self,
110             ent2 => $other,
111             );
112             }
113 6         17 return;
114             }
115              
116             sub contains_point{
117 0     0 0   my ($self, $point) = @_;
118 0   0       return ($point->x > $self->x
119             and $point->y > $self->y
120             and $point->x < $self->x + $self->w
121             and $point->y < $self->y + $self->h);
122             }
123              
124             3
125              
126             __END__
127             =head1 NAME
128              
129             Collision::2D::Entity::Rect - A rectangle entity.
130              
131             =head1 DESCRIPTION
132              
133             This is an entity with height and width.
134             Attributes (x, y) is one corner of the rect, whereas (x+w,y+h)
135             is the opposite corner.
136              
137             =head1 ATTRIBUTES
138              
139             =head2 w, h
140              
141             Width and height of the rectangle.
142              
143             =head1 METHODS
144              
145             Anything in L<Collision::2D::Entity>.
146              
147             =head2 collide
148              
149             See L<< Collision::2D::Entity->collide|Collision::2D::Entity/collide >>
150              
151             print 'boom' if $rect->collide($rect);
152             print 'zing' if $rect->collide($circle);
153             print 'yotz' if $rect->collide($grid);
154            
155             =head2 intersect
156              
157             See L<< Collision::2D::Entity->intersect|Collision::2D::Entity/intersect >>
158              
159             print 'bam' if $rect->intersect($rect);
160             # etc..
161              
162