File Coverage

blib/lib/Collision/2D/Collision.pm
Criterion Covered Total %
statement 37 42 88.1
branch 5 8 62.5
condition 2 2 100.0
subroutine 7 8 87.5
pod 2 4 50.0
total 53 64 82.8


line stmt bran cond sub pod time code
1             package Collision::2D::Collision;
2              
3 7     7   33 use strict;
  7         17  
  7         220  
4 7     7   33 use warnings;
  7         11  
  7         204  
5 7     7   36 use Carp qw/carp croak confess/;
  7         13  
  7         1643  
6             require DynaLoader;
7             our @ISA = qw(DynaLoader);
8             bootstrap Collision::2D::Collision;
9              
10             #this might be of use for calculating bounce vectors based on axes of collision.
11             # http://www.members.shaw.ca/mathematica/ahabTutorials/2dCollision.html
12              
13             sub new{
14 227     227 0 752 my ($package,%params) = @_;
15 227         1859 return __PACKAGE__->_new (@params{qw/ent1 ent2 time axis/})
16             }
17              
18              
19 0     0 0 0 sub does_mario_defeat_goomba{}
20              
21             #unless 'elasticity' is a param, assume it's totally elastic
22             #This just adds a negatively scaled axis of collision
23             # to the relative velocity
24             # (The scalar depends on elasticity and some trig.)
25             # If 'relative' is param, return that.
26             # Else use it & ent2 to find the resulting absolute velocity.
27              
28             #Also, for now we assume that ent2 has infinite mass.
29 7     7   15291 use Math::Trig qw/acos/;
  7         178337  
  7         3942  
30              
31             sub bounce_vector{
32 4     4 1 626 my ($self,%params) = @_;
33 4   100     20 my $elasticity = $params{elasticity} // 1;
34 4         16 my $axis = $self->vaxis;
35 4 50       12 unless ($axis){
36 0         0 confess 'no bounce vector because no axis.';
37 0         0 return [0,0];
38             }
39            
40 4         15 my $axis_len = sqrt($axis->[0]**2 + $axis->[1]**2);
41 4         41 my $rxv = $self->ent1->xv - $self->ent2->xv;
42 4         31 my $ryv = $self->ent1->yv - $self->ent2->yv;
43 4         11 my $rv_len = sqrt($rxv**2 + $ryv**2);
44 4         9 my $dot = $rxv*$axis->[0] + $ryv*$axis->[1];
45 4 50       19 unless ($rv_len){
46             #warn "FOO FOO ". $self->time;
47             #warn $rv_len;
48 0         0 return [0,0];
49             }
50 4         21 my $angle = acos($dot / ($axis_len * $rv_len));
51            
52 4         69 my $axis_scalar = $rv_len * cos($angle) / $axis_len;
53 4         10 $axis_scalar *= -1 * (1+$elasticity);
54            
55 4         7 my $r_bounce_xv = $rxv + ($axis_scalar * $axis->[0]);
56 4         8 my $r_bounce_yv = $ryv + ($axis_scalar * $axis->[1]);
57            
58 4 100       24 if ($params{relative}){
59 2         11 return [$r_bounce_xv, $r_bounce_yv]
60             }
61            
62 2         21 return [$r_bounce_xv + $self->ent2->xv, $r_bounce_yv + $self->ent2->yv]
63             }
64              
65             sub invert{
66 1     1 1 3 my $self = shift;
67 1         6 my $axis = $self->axis;
68 1 50       4 if (ref($axis) eq 'ARRAY'){
69 0         0 $axis = [-$axis->[0], -$axis->[1]]
70             }
71             else{ #x or y
72 1         25 $self->ent2->normalize($self->ent1);
73             }
74 1         9 return Collision::2D::Collision->new(
75             ent1=>$self->ent2,
76             ent2=>$self->ent1,
77             time=>$self->time,
78             axis => $axis,
79             )
80            
81             }
82              
83             __END__
84             =head1 NAME
85              
86             Collision::2D::Collision - An object representing a collision betwixt 2 entities
87              
88             =head1 DESCRIPTION
89              
90             =head1 ATTRIBUTES
91              
92             =over
93              
94             =item time
95              
96             The time of collision. For example, consider a point-circle collision,
97             where the point is moving towards the circle.
98             $collision->time is the B<exact> moment of collision between the two.
99              
100             =item axis
101              
102             The axis of collision. Basically a vector from one entity to the other.
103             It depends entirely on how they collide.
104              
105             If the collision involves a vertical or horizontal line, the axis will be
106             'x' or 'y'. If it's between a point or corner and a circle, it will be
107             an arrayref, of the form [$x,$y].
108              
109             This vector will not be normal (normal means of length 1).
110             L<Collision::2D::normalize_vec($v)|Collision::2D/normalize_vec>
111             is provided for that purpose.
112              
113             =item vaxis
114              
115             Again, the axis of collision. If you call this, it will always return the vector
116             form [$x,$y]. If the axis existed as 'x' or 'y', it is translated to [$x,$y].
117              
118             This vector will not be normal (normal means of length 1).
119             L<Collision::2D::normalize_vec($v)|Collision::2D/normalize_vec>
120             is provided for that purpose.
121              
122             =item ent1, ent2
123              
124             $collision->ent1
125              
126             This is to provide some context for L</axis>. This is useful because
127             dynamic_collision doesn't preserve the order of your entities. If you would
128             like for the order to be preserved, use the C<< entity->collide($ent2) >> method,
129             or use the keep_order parameter in C<dynamic_collision>.
130              
131             =back
132              
133             =head1 METHODS
134              
135             =over
136              
137             =item bounce_vector
138              
139             my $bouncevec = $co->bounce_vector (elasticity => .8);
140              
141             Assuming that C<< $co->ent2 >> has infinite mass, the C<< $co->bounce_vector >> is
142             the resulting velocity of C<< $co->ent1 >>. The elasticity parameter is 1 by default.
143              
144             =item invert
145              
146             my $other_collision = $self->invert();
147              
148             This returns the inverse of this collision. That is, the time remains,
149             but ent1 and ent2 are swapped, and the axis is inversed. This does not effect $self.
150