Skip to content

Commit

Permalink
Moving ent->collide_whatever methods to ent->_collide_whatever. They …
Browse files Browse the repository at this point in the history
…should only be used internally anyways. Also, some doc overhaul
  • Loading branch information
zach morgan committed Mar 25, 2010
1 parent c64f744 commit 9017f01
Show file tree
Hide file tree
Showing 9 changed files with 135 additions and 55 deletions.
4 changes: 2 additions & 2 deletions lib/Collision/2D.pm
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,13 @@ sub dynamic_collision{
}

#now, we sort by package name. This is so we can find specific routine in predictable namespace.
#for example, p comes before r, so point-rect collisions are at $point->collide_rect
#for example, p comes before r, so point-rect collisions are at $point->_collide_rect
my $swapped;
if ($ent1->_p > $ent2->_p ){
($ent1, $ent2) = ($ent2, $ent1);
$swapped=1
}
my $method = "collide_$ent2";
my $method = "_collide_$ent2";

$ent1->normalize($ent2);
my $collision = $ent1->$method($ent2, %params);
Expand Down
2 changes: 1 addition & 1 deletion lib/Collision/2D/Collision.pm
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ This vector will not be normal (normal means of length 1).
L<Collision::2D::normalize_vec($v)|Collision::2D/normalize_vec>
is provided for that purpose.
=item maxis
=item vaxis
Again, the axis of collision. If you call this, it will always return the mathematical
form [$x,$y]. If the axis existed as 'x' or 'y', it is translated to [$x,$y].
Expand Down
33 changes: 21 additions & 12 deletions lib/Collision/2D/Entity.pm
Original file line number Diff line number Diff line change
Expand Up @@ -54,25 +54,19 @@ L<dynamic_collision|Collision::2D/dynamic_collision>
=head2 relative_x, relative_y, relative_xv, relative_yv
You shouldn't worry about these. Move along now.
Relative position and velocity in space.
these are necessary if you want to do collisions directly through entity methods,
$circ1->collide_circle($circ2);
$circ1->_collide_circle($circ2);
In this case, both the absolute and relative position and velocity of $circ2
is not used. The relative attributes of $circ1 are assumed to be relative to $circ2.
=head1 METHODS
=head2 normalize
$self->normalize($other); # $other isa entity
This compares the absolute attributes of $self and $other.
It only sets the relative attributes of $self.
This is necessary to call collide_*($other) methods on $self.
=head2 collide
my $collision = $self->collide ($other_entity, interval=>4);
Expand All @@ -81,6 +75,15 @@ Detect collision with another entity. $self must be normalized to $other.
Takes interval as a parameter. Returns a collision if there is a collision.
Returns undef if there is no collision.
With the collide method, the entity order is preserved.
Consider this example:
my $collision1 = $panel->collide($droplet);
my $collision2 = $droplet->collide($panel);
If these objects collide, then its C<$collision1->ent1> will be C<$panel>, and
C<$collision2->ent1> will be C<$droplet>.
=head2 intersect
my $t_or_f = $self->intersect ($other_entity);
Expand All @@ -89,10 +92,16 @@ Detect intersection (overlapping) with another entity.
Takes interval as a parameter. Returns a collision if there is a collision.
Returns undef if there is no collision.
Relative vectors are not considered for intersection, so $self need not be normalized to $other.
Relative vectors and velocity are not considered for intersection.
=head2 normalize
You probably shouldn't use this directly. At all.
Relative vectors are handled automatically
in C<dynamic_collision> and in C<$ent1->collide($ent2)>
$self->normalize($other); # $other isa entity
This compares the absolute attributes of $self and $other.
It only sets the relative attributes of $self.
This is necessary to call _collide_*($other) methods on $self.
38 changes: 16 additions & 22 deletions lib/Collision/2D/Entity/Circle.pm
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ sub intersect_rect{
return 0;
}

sub collide_rect{
sub _collide_rect{
my ($self, $rect, %params) = @_;
my @collisions;

Expand Down Expand Up @@ -139,7 +139,7 @@ sub collide_rect{
relative_yv => -$self->relative_yv,
radius => $self->radius,
);
my $collision = $new_relative_circle->collide_point ($origin_point, interval=>$params{interval});
my $collision = $new_relative_circle->_collide_point ($origin_point, interval=>$params{interval});
next unless $collision;
#$_->{collision} =
push @collisions, Collision::2D::Collision->new(
Expand Down Expand Up @@ -180,7 +180,7 @@ sub collide_rect{
relative_xv => $self->relative_xv,
relative_yv => $self->relative_yv,
);
my $collision = $rpt->collide_rect($rect, interval=>$params{interval});
my $collision = $rpt->_collide_rect($rect, interval=>$params{interval});
next unless $collision;
push @collisions, new Collision::2D::Collision(
time => $collision->time,
Expand Down Expand Up @@ -211,7 +211,7 @@ sub collide_rect{
# roots (where circle intersects on the x axis) are at
# ( -B ± sqrt(B**2 - 4AC) ) / 2A
#Then, see which intercept, if any, is the closest after starting point
sub collide_point{
sub _collide_point{
my ($self, $point, %params) = @_;
#x1,etc. is the path of the point, relative to $self.
#it's probably easier to consider the point as stationary.
Expand Down Expand Up @@ -265,7 +265,7 @@ sub collide_point{
}

#Say, can't we just use the point algorithm by transferring the radius of one circle to the other?
sub collide_circle{
sub _collide_circle{
my ($self, $other, %params) = @_;
my $double_trouble = Collision::2D::Entity::Circle->new(
relative_x => $self->relative_x,
Expand All @@ -279,7 +279,7 @@ sub collide_circle{
my $pt = Collision::2D::Entity::Point->new(
#y=>44,x=>44, #these willn't be used, as we're doing all relative calculations
);
my $collision = $double_trouble->collide_point($pt, %params);
my $collision = $double_trouble->_collide_point($pt, %params);
return unless $collision;

return Collision::2D::Collision->new(
Expand Down Expand Up @@ -311,28 +311,22 @@ Each point on the circle is this distance from the center, at C<< ($circ->x, $ci
=head1 METHODS
In any of these collide_* methods, relative coordinates must be set. See L<Entity|Collision::2D::Entity> for more info.
Anything in L<Collision::2D::Entity>.
=head2 collide_point
=head2 collide
$self->normalize ($pt);
$self->collide_point($pt, interval=>1);
See L<Collision::2D::Entity->collide($v)|Collision::2D::Entity/collide>
=head2 collide_circle
print 'boom' if $circle->collide($rect);
print 'zing' if $circle->collide($circle);
print 'yotz' if $circle->collide($grid);
=head2 intersect
$self->normalize ($circ);
$self->collide_circle($circ, interval=>1);
=head2 collide_rect
$self->normalize ($rect);
$self->collide_rect($rect, interval=>1);
=head2 intersect, intersect_point, intersect_circle, intersect_rect
See L<Collision::2D::Entity->intersect($v)|Collision::2D::Entity/intersect>
print 'bam' if $circle->intersect($rect);
# etc..
Detect intersection (overlap) with other entities. Time and velocity
are not considered.
14 changes: 9 additions & 5 deletions lib/Collision/2D/Entity/Grid.pm
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ sub collide_point{
return $best_collision
}

sub collide_rect{
sub _collide_rect{
my ($self, $rect, %params) = @_;
my $rx = -$self->relative_x; #relative loc of rect to grid
my $ry = -$self->relative_y;
Expand Down Expand Up @@ -259,7 +259,7 @@ sub collide_rect{
}


sub collide_circle{
sub _collide_circle{
my ($self, $circle, %params) = @_;
my $rx = -$self->relative_x; #relative loc of circle to grid
my $ry = -$self->relative_y;
Expand Down Expand Up @@ -328,11 +328,15 @@ Grids provide a speedup of precisely O(n^n^18)
=over
=item add, add_circle, add_rect, add_point
=item intersect($ent), collide($ent)
Pretty much the same as in L<Collision::2D::Entity>. Returns the first collision or intersection
with a child of the grid. Perhaps in the future, this will be more versatile
with respect to the nature of the grid children.
=item collide, collide_circle, collide_rect, collide_point
=item add, add_circle, add_rect, add_point
=item intersect, intersect_circle, intersect_point, intersect_rect
Add stuff to the grid
=back
Expand Down
39 changes: 37 additions & 2 deletions lib/Collision/2D/Entity/Point.pm
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,14 @@ sub new{
}

#I daresay, 2 points mayn't collide
sub collide_point{
sub _collide_point{
return;
}


#Here, $self is assumed to be normalized.

sub collide_rect{
sub _collide_rect{
my ($self, $rect, %params) = @_;
#if we start inside rect, return the null collision, so to speak.
#if ($rect->contains_point($self)){
Expand Down Expand Up @@ -141,3 +141,38 @@ sub collide_rect{
}

2

__END__
=head1 NAME
Collision::2D::Entity::Rect - A rectangle entity.
=head1 DESCRIPTION
This is a point entity.
Attributes (x, y) are the location of this point. See L<Collision::2D::Entity>.
Points can not collide with other points. Use a very small circle instead.
=head1 ATTRIBUTES
Anything in L<Collision::2D::Entity>.
=head1 METHODS
Anything in L<Collision::2D::Entity>.
=head2 collide
See L<Collision::2D::Entity->collide($v)|Collision::2D::Entity/collide>
print 'boom' if $point->collide($rect);
print 'zing' if $point->collide($circle);
print 'yotz' if $point->collide($grid);
=head2 intersect
See L<Collision::2D::Entity->intersect($v)|Collision::2D::Entity/intersect>
print 'bam' if $point->intersect($rect);
# etc..
40 changes: 39 additions & 1 deletion lib/Collision/2D/Entity/Rect.pm
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ sub intersect_rect{
&& ($self->y + $self->h > $other->y));
}

sub collide_rect{
sub _collide_rect{
my ($self, $other, %params) = @_;
my $xv = $self->relative_xv;
my $yv = $self->relative_yv;
Expand Down Expand Up @@ -121,3 +121,41 @@ sub contains_point{
}

3

__END__
=head1 NAME
Collision::2D::Entity::Rect - A rectangle entity.
=head1 DESCRIPTION
This is an entity with height and width.
Attributes (x, y) is one corner of the rect, whereas (x+w,y+h)
is the opposite corner.
=head1 ATTRIBUTES
=head2 w, h
Width and height of the rectangle.
=head1 METHODS
Anything in L<Collision::2D::Entity>.
=head2 collide
See L<Collision::2D::Entity->collide($v)|Collision::2D::Entity/collide>
print 'boom' if $rect->collide($rect);
print 'zing' if $rect->collide($circle);
print 'yotz' if $rect->collide($grid);
=head2 intersect
See L<Collision::2D::Entity->intersect($v)|Collision::2D::Entity/intersect>
print 'bam' if $rect->intersect($rect);
# etc..
14 changes: 7 additions & 7 deletions t/02-dynamic.t
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use Collision::2D ':all';
use Test::More tests => 145;
use Test::Number::Delta;

#First do rect-point collisions. the method is $point->collide_rect($rect,...)
#First do rect-point collisions. the method is $point->_collide_rect($rect,...)
{
my $andy = hash2rect {x=>-1, y=>-1, h=>2, w=>2};
my $bullet1 = hash2point { x=>-51, y=>0, xv=>100, yv=>16 }; #wild miss
Expand Down Expand Up @@ -70,7 +70,7 @@ use Test::Number::Delta;

}

#now circle-point collisions. The method is $circle->collide_point($point,...)
#now circle-point collisions. The method is $circle->_collide_point($point,...)
{
my $pie = hash2circle { x=>0, y=>0, radius=>1 };#the unit pie
my $raisinH = hash2point { x=>-2, y=>0, xv=>1 };
Expand Down Expand Up @@ -224,11 +224,11 @@ use Test::Number::Delta;
$square2->normalize($square1);
$square1->normalize($square2);
#horizontal:
my $collision = $square1->collide_rect($square2, interval=>2);
my $collision = $square1->_collide_rect($square2, interval=>2);
ok($collision, 'squares collide h1');
delta_ok($collision->time, 1, 'squares collide at t=1');
is($collision->axis, 'x', 'vcollide axis is x');
$collision = $square2->collide_rect($square1, interval=>2);
$collision = $square2->_collide_rect($square1, interval=>2);
ok($collision, 'squares collide h2');
delta_ok($collision->time, 1, 'squares collide at t=1');
is($collision->axis, 'x', 'vcollide axis is x');
Expand All @@ -237,11 +237,11 @@ use Test::Number::Delta;
my $square3 = hash2rect {x=>0, y=>-4, h=>2,w=>2, yv=>2};
$square3->normalize($square1);
$square1->normalize($square3);
$collision = $square1->collide_rect($square3, interval=>2);
$collision = $square1->_collide_rect($square3, interval=>2);
ok($collision, 'squares collide v1');
delta_ok($collision->time, .5, 'squares vcollide at t=.5');
is($collision->axis, 'y', 'vcollide axis is y');
$collision = $square3->collide_rect($square1, interval=>2);
$collision = $square3->_collide_rect($square1, interval=>2);
ok($collision, 'squares collide v2');
delta_ok($collision->time, .5, 'squares vcollide at t=.5');
is($collision->axis, 'y', 'vcollide axis is y');
Expand All @@ -268,7 +268,7 @@ use Test::Number::Delta;
my $collision = dynamic_collision ($rect, $circ, interval=>2);
#warn ("x=".(200+$_));
delta_ok ($collision->time, 1);
#warn join ',',@{normalize_vec($collision->maxis)};
#warn join ',',@{normalize_vec($collision->vaxis)};
is_deeply (normalize_vec($collision->vaxis), [0,1]);
}
}
Expand Down
Loading

0 comments on commit 9017f01

Please sign in to comment.