Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Changes
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Revision history for Collision::2D
0.05 Mar 25, 2010
Collision::Grid added,
Mouse taken away,
moving to an XS struct backend,
moving to an XS struct backend,
normalize and vaxis ported to xs.
0.06 Mar 26, 2010
pod fixes
Expand Down
8 changes: 4 additions & 4 deletions README
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ Here's how to use Collision::2D
DWIMMY goodness, or the constructor
Collision::2D::Entity::Rect->new(%params).
Parameters are x, y, h, w, xv, and yv.
2. Detect collisions with
2. Detect collisions with
my $collision = Collision::2D::dynamic_collision($ent1, $ent2, interval=>1);
A Collision::2D::Collision object is returned in the event of a collision.
This will return undef if the entities do not collide.
2. Alternatively, to detect static collision, i.e. intersection,
2. Alternatively, to detect static collision, i.e. intersection,
my $intersects = Collision::2D::intersection($ent1, $ent2);
$intersects is a true or false value.

Expand All @@ -36,10 +36,10 @@ You can also look for information at:

Search CPAN
http://search.cpan.org/dist/Collision-2D/

Github
http://github.com/zpmorgan/collision-2D

irc.perl.org
#sdl

Expand Down
36 changes: 18 additions & 18 deletions lib/Collision/2D.pm
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use Collision::2D::Entity::Grid;
BEGIN {
require Exporter;
our @ISA = qw(Exporter);
our @EXPORT_OK = qw(
our @EXPORT_OK = qw(
dynamic_collision
intersection
hash2point hash2rect
Expand All @@ -33,14 +33,14 @@ our $VERSION = '0.07';
sub dynamic_collision{
my ($ent1, $ent2, %params) = @_;
$params{interval} //= 1;

#if $obj2 is an arrayref, do this for each thing in @$obj
# and return all collisions, starting with the closest
if (ref $ent2 eq 'ARRAY'){
my @collisions = map {dynamic_collision($ent1,$_,%params)} @$ent2;
return sort{$a->time <=> $b->time} grep{defined$_} @collisions;
}

#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
my $swapped;
Expand All @@ -49,7 +49,7 @@ sub dynamic_collision{
$swapped=1
}
my $method = "_collide_$ent2";

$ent1->normalize($ent2);
my $collision = $ent1->$method($ent2, %params);
return unless $collision;
Expand All @@ -70,7 +70,7 @@ sub intersection{
}
($ent1, $ent2) = ($ent2, $ent1) if ($ent1->_p > $ent2->_p );
my $method = "intersect_$ent2";

return 1 if $ent1->$method($ent2);
return 0;
}
Expand Down Expand Up @@ -142,7 +142,7 @@ sub obj2circle{
yv=>$obj->yv,
radius => $obj->radius || 1,
)

}

# x and y are be derivable from specified number of $cells?
Expand All @@ -153,11 +153,11 @@ sub obj2circle{
# do what? do + dimensions even need to be constrained?
sub hash2grid{
my $hash = shift;
my ($cell_size, $w, $h, $x, $y, $cells, $cells_x, $cells_y)
my ($cell_size, $w, $h, $x, $y, $cells, $cells_x, $cells_y)
= @{$hash}{qw/cell_size w h x y cells cells_x cells_y/};
die 'where?' unless defined $y and defined $x;
die 'require cell_size' unless $cell_size;

if ($cells) {
$w = $cell_size * $cells_x;
$h = $cell_size * $cells_y;
Expand All @@ -171,7 +171,7 @@ sub hash2grid{
}
}
die 'require some form of w and h' unless $w and $h;

return Collision::2D::Entity::Grid->new (
x=>$x,
y=>$y,
Expand All @@ -194,7 +194,7 @@ Collision::2D - Continuous 2d collision detection
my $rect = hash2rect ({x=>0, y=>0, h=>1, w=>1});
my $circle = hash2circle ({x=>0, y=>0, radius => 1});
my $collision = dynamic_collision ($rect, $circle);

#When your geometric objects do not move, it is static.
#Collision::2D is also capable of dynamic collisions, eith moving entities.
my $roach = hash2circle ({x=>-1, y=>-12, radius => .08, xv = 3, yv => 22});
Expand All @@ -204,8 +204,8 @@ Collision::2D - Continuous 2d collision detection
print "collision is at t=" . $co2->time . "\n"
print "axis of collision is (" . join(',', @{$co2->axis}) .")\n";
}
#we can also detect whether points collide with circles and rects.

#we can also detect whether points collide with circles and rects.
#these entities collide at around y=20000, x=10000, t=100:
my $tiny_rect = hash2rect {x=>15000-.00005, y=>30000-.00005, h=>.0001, w=>.0001, xv=>-50, yv=>-100};
my $accurate_bullet = hash2point { x=>-40000, y=>80100, xv=>500, yv=> -601};
Expand All @@ -219,15 +219,15 @@ dynamic collision detection between moving circles, rectangles, and points.

=head2 WHY

Typically, collision detection in games and game libraries tends to be static.
That is, they only detect overlap of motionless polygons.
Typically, collision detection in games and game libraries tends to be static.
That is, they only detect overlap of motionless polygons.
This is somewhat simple, but naive, because often the developer may want a
description of the
collision, so that he may implement a response.

Supply Collision::2D with any 2 moving entities
(L<rects|Collision::2D::Entity::Rect>,
L<circles|Collision::2D::Entity::Circle>, and
(L<rects|Collision::2D::Entity::Rect>,
L<circles|Collision::2D::Entity::Circle>, and
L<points|Collision::2D::Entity::Point>)
and an interval of time and it will return a Collision::2D::Collision object.
This $collision has attributes ->time and ->axis, which describe when and how the collision took place.
Expand All @@ -236,7 +236,7 @@ This $collision has attributes ->time and ->axis, which describe when and how th

Initially, I implemented point-rect and point-circle. I used these to compose the other types of detection.

Circle-circle is just an extension of point-circle, and it reduces to a single
Circle-circle is just an extension of point-circle, and it reduces to a single
point-circle detection.

Circle-rect and may use a bunch of calls to point-collision routines. This is a worst case, though.
Expand Down Expand Up @@ -302,7 +302,7 @@ Normalize your 2d vectors

=head1 EXPORTABLE SYMBOLS

Collision::2D doesn't export anything by default. You have to explicitly
Collision::2D doesn't export anything by default. You have to explicitly
define function names or use the :all tag.

=head1 TODO
Expand Down
18 changes: 9 additions & 9 deletions lib/Collision/2D/Collision.pm
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ require DynaLoader;
our @ISA = qw(DynaLoader);
bootstrap Collision::2D::Collision;

#this might be of use for calculating bounce vectors based on axes of collision.
#this might be of use for calculating bounce vectors based on axes of collision.
# http://www.members.shaw.ca/mathematica/ahabTutorials/2dCollision.html

sub new{
Expand All @@ -28,15 +28,15 @@ sub does_mario_defeat_goomba{}
#Also, for now we assume that ent2 has infinite mass.
use Math::Trig qw/acos/;

sub bounce_vector{
sub bounce_vector{
my ($self,%params) = @_;
my $elasticity = $params{elasticity} // 1;
my $axis = $self->vaxis;
unless ($axis){
confess 'no bounce vector because no axis.';
return [0,0];
}

my $axis_len = sqrt($axis->[0]**2 + $axis->[1]**2);
my $rxv = $self->ent1->xv - $self->ent2->xv;
my $ryv = $self->ent1->yv - $self->ent2->yv;
Expand All @@ -48,17 +48,17 @@ sub bounce_vector{
return [0,0];
}
my $angle = acos($dot / ($axis_len * $rv_len));

my $axis_scalar = $rv_len * cos($angle) / $axis_len;
$axis_scalar *= -1 * (1+$elasticity);

my $r_bounce_xv = $rxv + ($axis_scalar * $axis->[0]);
my $r_bounce_yv = $ryv + ($axis_scalar * $axis->[1]);

if ($params{relative}){
return [$r_bounce_xv, $r_bounce_yv]
}

return [$r_bounce_xv + $self->ent2->xv, $r_bounce_yv + $self->ent2->yv]
}

Expand All @@ -77,7 +77,7 @@ sub invert{
time=>$self->time,
axis => $axis,
)

}

__END__
Expand All @@ -94,7 +94,7 @@ Collision::2D::Collision - An object representing a collision betwixt 2 entities
=item time

The time of collision. For example, consider a point-circle collision,
where the point is moving towards the circle.
where the point is moving towards the circle.
$collision->time is the B<exact> moment of collision between the two.

=item axis
Expand Down
8 changes: 4 additions & 4 deletions lib/Collision/2D/Collision.xs
Original file line number Diff line number Diff line change
Expand Up @@ -112,11 +112,11 @@ co_vaxis ( self )
av_push (axis_vec, newSVnv(self->axis_x));
av_push (axis_vec, newSVnv(self->axis_y));
RETVAL = newRV_inc((SV*) axis_vec);
}
}
else { //XORY_AXIS
void** pointers = (void**)(SvIV((SV*)SvRV( self->ent1 )));
void** pointers = (void**)(SvIV((SV*)SvRV( self->ent1 )));
Entity * ent1 = (Entity*)(pointers[0]);
pointers = (void**)(SvIV((SV*)SvRV( self->ent2 )));
pointers = (void**)(SvIV((SV*)SvRV( self->ent2 )));
Entity * ent2 = (Entity*)(pointers[0]);
if (self->axis == 'x'){
AV* axis_vec = newAV();
Expand Down Expand Up @@ -169,7 +169,7 @@ co_XORY_AXIS()
RETVAL = XORY_AXIS;
OUTPUT:
RETVAL

int
co_VECTOR_AXIS()
CODE:
Expand Down
6 changes: 3 additions & 3 deletions lib/Collision/2D/Entity.pm
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ bootstrap Collision::2D::Entity;
sub typename{'entity'}


#an actual collision at t=0;
#an actual collision at t=0;
sub null_collision{
my $self = shift;
my $other = shift;
Expand Down Expand Up @@ -49,7 +49,7 @@ Collision::2D::Entity - A moving entity. Don't use this directly.
=head2 x,y,xv,yv

Absolute position and velocity in space.
These are necessary if you want to do collisions through
These are necessary if you want to do collisions through
L<dynamic_collision|Collision::2D/dynamic_collision>

dynamic_collision($circ1, $circ2);
Expand Down Expand Up @@ -100,7 +100,7 @@ Relative vectors and velocity are not considered for intersection.

=head2 normalize

You probably shouldn't use this directly. At all.
You probably shouldn't use this directly. At all.
Relative vectors are handled automatically
in C<dynamic_collision> and in C<$ent1->collide($ent2)>

Expand Down
18 changes: 9 additions & 9 deletions lib/Collision/2D/Entity.xs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ float
ent_x ( ent )
Entity *ent
CODE:
// if (items > 1 ) ent->x = SvIV(ST(1));
// if (items > 1 ) ent->x = SvIV(ST(1));
RETVAL = ent->x;
OUTPUT:
RETVAL
Expand All @@ -35,16 +35,16 @@ float
ent_y ( ent )
Entity *ent
CODE:
// if (items > 1 ) ent->y = SvIV(ST(1));
// if (items > 1 ) ent->y = SvIV(ST(1));
RETVAL = ent->y;
OUTPUT:
RETVAL

float
ent_xv ( ent )
Entity *ent
CODE:
// if (items > 1 ) ent->xv = SvIV(ST(1));
// if (items > 1 ) ent->xv = SvIV(ST(1));
RETVAL = ent->xv;
OUTPUT:
RETVAL
Expand All @@ -53,7 +53,7 @@ float
ent_yv ( ent )
Entity *ent
CODE:
// if (items > 1 ) ent->yv = SvIV(ST(1));
// if (items > 1 ) ent->yv = SvIV(ST(1));
RETVAL = ent->yv;
OUTPUT:
RETVAL
Expand All @@ -62,7 +62,7 @@ float
ent_relative_x ( ent, ... )
Entity *ent
CODE:
if (items > 1 ) ent->relative_x = SvIV(ST(1));
if (items > 1 ) ent->relative_x = SvIV(ST(1));
RETVAL = ent->relative_x;
OUTPUT:
RETVAL
Expand All @@ -71,7 +71,7 @@ float
ent_relative_y ( ent, ... )
Entity *ent
CODE:
if (items > 1 ) ent->relative_y = SvIV(ST(1));
if (items > 1 ) ent->relative_y = SvIV(ST(1));
RETVAL = ent->relative_y;
OUTPUT:
RETVAL
Expand All @@ -80,7 +80,7 @@ float
ent_relative_xv ( ent, ... )
Entity *ent
CODE:
if (items > 1 ) ent->relative_xv = SvIV(ST(1));
if (items > 1 ) ent->relative_xv = SvIV(ST(1));
RETVAL = ent->relative_xv;
OUTPUT:
RETVAL
Expand All @@ -89,7 +89,7 @@ float
ent_relative_yv ( ent, ... )
Entity *ent
CODE:
if (items > 1 ) ent->relative_yv = SvIV(ST(1));
if (items > 1 ) ent->relative_yv = SvIV(ST(1));
RETVAL = ent->relative_yv;
OUTPUT:
RETVAL
Expand Down
Loading