Skip to content

Commit

Permalink
This doesn't actually work.
Browse files Browse the repository at this point in the history
But I thought is was an interesting idea.
  • Loading branch information
jtpalmer committed Aug 17, 2010
1 parent d67cbfb commit 010ef14
Show file tree
Hide file tree
Showing 2 changed files with 154 additions and 99 deletions.
14 changes: 14 additions & 0 deletions lib/Games/Maze/SDL/Model/Maze.pm
Expand Up @@ -161,6 +161,20 @@ sub paths {
}; };
} }


sub cell_borders {
my ( $self, $x, $y ) = @_;

my $min_x = ( $x - 1 ) * $self->cell_width;
my $min_y = ( $y - 1 ) * $self->cell_height;

return {
min_x => $min_x + 1,
min_y => $min_y + 1,
max_x => $min_x + $self->cell_height,
max_y => $min_y + $self->cell_width,
};
}

no Moose; no Moose;
__PACKAGE__->meta->make_immutable; __PACKAGE__->meta->make_immutable;


Expand Down
239 changes: 140 additions & 99 deletions lib/Games/Maze/SDL/Model/Player.pm
Expand Up @@ -10,18 +10,10 @@ use POSIX 'floor';


with 'Games::Maze::SDL::Role::Observable'; with 'Games::Maze::SDL::Role::Observable';


has 'x' => ( has 'maze' => (
is => 'rw', is => 'rw',
isa => 'Num', isa => 'Games::Maze::SDL::Model::Maze',
lazy_build => 1, required => 1,
init_arg => undef,
);

has 'y' => (
is => 'rw',
isa => 'Num',
lazy_build => 1,
init_arg => undef,
); );


has 'width' => ( has 'width' => (
Expand All @@ -42,7 +34,27 @@ has 'direction' => (
default => 'south', default => 'south',
); );


has 'velocity' => ( has 'x' => (
is => 'rw',
isa => 'Num',
lazy_build => 1,
init_arg => undef,
);

has 'y' => (
is => 'rw',
isa => 'Num',
lazy_build => 1,
init_arg => undef,
);

has 'velocity_x' => (
is => 'rw',
isa => 'Num',
default => 0,
);

has 'velocity_y' => (
is => 'rw', is => 'rw',
isa => 'Num', isa => 'Num',
default => 0, default => 0,
Expand All @@ -54,16 +66,16 @@ has 'max_velocity' => (
default => 0.1, default => 0.1,
); );


has 'acceleration' => ( has 'acceleration_y' => (
is => 'rw', is => 'rw',
isa => 'Num', isa => 'Num',
default => 0, default => 0,
); );


has 'maze' => ( has 'acceleration_x' => (
is => 'rw', is => 'rw',
isa => 'Games::Maze::SDL::Model::Maze', isa => 'Num',
required => 1, default => 0,
); );


sub _build_x { sub _build_x {
Expand All @@ -78,7 +90,7 @@ sub _build_y {
- $self->height / 2; - $self->height / 2;
} }


after qw( x y direction velocity ) => sub { after qw( x y direction velocity_x velocity_y ) => sub {
my $self = shift; my $self = shift;


if (@_) { if (@_) {
Expand All @@ -90,110 +102,139 @@ after 'direction' => sub {
my $self = shift; my $self = shift;


if (@_) { if (@_) {
$self->velocity( $self->velocity * 0.3 ); my $d = shift;
$self->acceleration(0.0001); if ( $d eq 'north' ) {
$self->acceleration_x(0);
$self->acceleration_y(-0.0001);
}
if ( $d eq 'south' ) {
$self->acceleration_x(0);
$self->acceleration_y(0.0001);
}
if ( $d eq 'west' ) {
$self->acceleration_x(-0.0001);
$self->acceleration_y(0);
}
if ( $d eq 'east' ) {
$self->acceleration_x(0.0001);
$self->acceleration_y(0);
}

$self->notify_observers( { type => 'turned' } ); $self->notify_observers( { type => 'turned' } );
} }
}; };


sub move { sub velocity {
my ( $self, undef, $dt ) = @_; my ($self) = @_;


my ( $x, $y ) = ( $self->x, $self->y ); my $vx = $self->velocity_x;
my ( $a, $v ) = ( $self->acceleration, $self->velocity ); my $vy = $self->velocity_y;
my $d = $self->direction;


if ( $a == 0 ) { return sqrt( $vx * $vx + $vy * $vy );
$v = $v * 0.9; }
}
else {
$v = $v + $dt * $a;
}


if ( $v < 0.001 ) { sub move {
$v = $self->velocity(0); my ( $self, undef, $dt ) = @_;
$self->notify_observers( { type => 'stopped' } );
}
else {
if ( $v > $self->max_velocity ) {
$v = $self->max_velocity;
}
$self->velocity($v);
}


return if $v == 0; my %d = ( x => $self->x, y => $self->y );
my %v = ( x => $self->velocity_x, y => $self->velocity_y );
my %a = ( x => $self->acceleration_x, y => $self->acceleration_y );


my $cell_x = floor( $self->x / $self->maze->cell_width ) + 1; my $cell_x = floor( $self->x / $self->maze->cell_width ) + 1;
my $cell_y = floor( $self->y / $self->maze->cell_height ) + 1; my $cell_y = floor( $self->y / $self->maze->cell_height ) + 1;
my $paths = $self->maze->paths( $cell_x, $cell_y );

foreach my $dimension (qw( x y )) {
$cell_x = ( $cell_x - 1 ) * $self->maze->cell_width; my ( $d, $v, $a ) = map { $_->{$dimension} } \( %d, %v, %a );
$cell_y = ( $cell_y - 1 ) * $self->maze->cell_height;

if ( $a == 0 ) {
my $cell_y_min = $cell_y + 1; $v = $v * 0.9;
my $cell_y_max = $cell_y + $self->maze->cell_width - $self->width;
my $cell_x_min = $cell_x + 1;
my $cell_x_max = $cell_x + $self->maze->cell_height - $self->width;

if ( $d eq 'south' ) {
my $new_y = $y + $v * $dt;
if ( $new_y > $cell_y_max ) {
if ( $paths->{$d} ) {
$new_y = $cell_y_max if $x > $cell_x_max;
$new_y = $cell_y_max if $x < $cell_x_min;
}
else {
$new_y = $cell_y_max;
}
} }
$self->y($new_y); else {
} $v = $v + $dt * $a;
elsif ( $d eq 'north' ) {
my $new_y = $y - $v * $dt;
if ( $new_y < $cell_y_min ) {
if ( $paths->{$d} ) {
$new_y = $cell_y_min if $x > $cell_x_max;
$new_y = $cell_y_min if $x < $cell_x_min;
}
else {
$new_y = $cell_y_min;
}
} }
$self->y($new_y);
} my $direction = $v <=> 0;
elsif ( $d eq 'east' ) { if ( abs($v) < 0.00000001 ) {
my $new_x = $x + $v * $dt; $v = 0;
if ( $new_x > $cell_x_max ) {
if ( $paths->{$d} ) {
$new_x = $cell_x_max if $y > $cell_y_max;
$new_x = $cell_x_max if $y < $cell_y_min;
}
else {
$new_x = $cell_x_max;
}
} }
$self->x($new_x); elsif ( abs($v) > $self->max_velocity ) {
$v = $direction * $self->max_velocity;
}

$d += $v * $dt;

my $set_d = $dimension;
my $set_v = 'velocity_' . $dimension;
$self->$set_d($d);
$self->$set_v($v);
} }
elsif ( $d eq 'west' ) {
my $new_x = $x - $v * $dt; my $paths = $self->maze->paths( $cell_x, $cell_y );
if ( $new_x < $cell_x_min ) { my $borders = $self->maze->cell_borders( $cell_x, $cell_y );
if ( $paths->{$d} ) {
$new_x = $cell_x_min if $y > $cell_y_max; my %limits = (
$new_x = $cell_x_min if $y < $cell_y_min; x => {
-1 => [ $paths->{west}, $borders->{min_x} ],
1 => [ $paths->{east}, $borders->{max_x} - $self->width ],
},
y => {
-1 => [ $paths->{north}, $borders->{min_y} ],
1 => [ $paths->{south}, $borders->{max_y} - $self->width ],
}
);

my @dimensions = abs($v{y}) > abs($v{x})
? ([qw( x y )], [qw( y x )])
: ([qw( y x )], [qw( x y )]);
foreach my $dimensions (@dimensions) {
my ( $dimension, $other_dimension ) = @$dimensions;

%d = ( x => $self->x, y => $self->y );
%v = ( x => $self->velocity_x, y => $self->velocity_y );

my ( $d, $v, $l ) = map { $_->{$dimension} } \( %d, %v, %limits );

my ( $other_d, $other_l )
= map { $_->{$other_dimension} } \( %d, %limits );

my $other_d_min = $other_l->{-1}->[1];
my $other_d_max = $other_l->{1}->[1];

my $direction = $v <=> 0;

next if $v == 0;

my ( $path, $limit ) = @{ $l->{$direction} };

if ( ( $d <=> $limit ) == $direction ) {
if ( !$path ) {
$d = $limit;
$v = 0;
} }
else { elsif ( $other_d > $other_d_max || $other_d < $other_d_min ) {
$new_x = $cell_x_min; $d = $limit;
$v = 0;
} }
} }
$self->x($new_x);
my $set_d = $dimension;
my $set_v = 'velocity_' . $dimension;
$self->$set_d($d);
$self->$set_v($v);
} }


$self->notify_observers( { type => 'moved' } ); if ( $self->velocity_x == 0 && $self->velocity_y == 0 ) {
$self->notify_observers( { type => 'stopped' } );
}
else {
$self->notify_observers( { type => 'moved' } );
}
} }


sub stop { sub stop {
my ($self) = @_; my ($self) = @_;
$self->acceleration(0); $self->acceleration_x(0);
$self->acceleration_y(0);
} }


no Moose; no Moose;
Expand Down

0 comments on commit 010ef14

Please sign in to comment.