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
|
|
|
|
|
|
|
|