I'm trying to make a perl terminal animation where an enitity reverses direction when it collides with another object. Here is the code I have so far:
use Term::Animation 2.0;
use Term::Animation::Entity;
use Time::HiRes qw(time);
use Data::Dumper;
use Curses;
use strict;
use warnings;
main();
sub add_animal {
my ($anim, $y) = @_;
# Add the animal to the animation
my $animal = $anim->new_entity(
type => 'animal',
position => [3, $y, 1],
shape => '*',
color => 'r',
callback_args => [1, 0, 0, 0],
die_offscreen => 0,
coll_handler => \&animal_collision,
);
}
sub animal_collision {
my ($animal, $anim) = @_;
my $collisions = $animal->collisions();
#return unless defined $collisions;
foreach my $col_obj (@{$collisions}) {
# Get the current x direction from the callback_args
my $x_dir = $animal->callback_args->[0];
# Reverse the direction
$animal->callback_args->[0] = -$x_dir;
}
}
sub add_background {
my ($anim, $screen_width, $screen_height) = @_;
my $half_width = int($screen_width / 2);
my $ground_level = int($screen_height * 0.7);
for my $y (0..($screen_height)) {
$anim->new_entity(
shape => ['|'],
position => [$half_width, $y, 21],
color => ['w'],
);
}
}
sub main {
my $anim = Term::Animation->new();
$anim->color(1);
halfdelay(1);
my $paused = 0;
while(1) {
my $screen_width = $anim->width();
my $screen_height = $anim->height();
my $half_width = int($screen_width / 2);
my $ground_level = int($screen_height * 0.7);
add_background($anim, $screen_width, $screen_height);
add_animal($anim, ($ground_level - 1));
# animation loop
while(1) {
my $current_time = time();
# run and display a single animation frame
$anim->animate() unless($paused);
# use getch to control the frame rate, and get input at the same time.
my $input = getch();
if($input eq 'q') { quit(); }
if($input eq 'r' || $input eq KEY_RESIZE()) { last; }
if($input eq 'p') { $paused = !$paused; }
}
$anim->update_term_size();
$anim->remove_all_entities();
}
$anim->end();
}
As of now, the animal object passes through the other object without any change of direction. Please let me know what is wrong with the collision detector or any other issues.
Collision detection is done for physical objects
only. Add physical => 1
to both objects. Also the model has 3 dimensions so you need to have the objects in the same z plane if you want them to collide.
use strict;
use warnings;
use Term::Animation 2.0;
use Term::Animation::Entity;
use Time::HiRes qw(time);
use Data::Dumper;
use Curses;
main();
sub add_animal {
my ($anim, $y) = @_;
# Add the animal to the animation
my $animal = $anim->new_entity(
type => 'animal',
position => [3, $y, 21],
shape => '*',
color => 'r',
callback_args => [1, 0, 0, 0],
die_offscreen => 0,
coll_handler => \&animal_collision,
physical => 1,
);
}
sub animal_collision {
my ($animal, $anim) = @_;
my $collisions = $animal->collisions();
#return unless defined $collisions;
foreach my $col_obj (@{$collisions}) {
# Get the current x direction from the callback_args
my $x_dir = $animal->callback_args->[0];
# Reverse the direction
$animal->callback_args->[0] = -$x_dir;
}
}
sub add_background {
my ($anim, $screen_width, $screen_height) = @_;
my $half_width = int($screen_width / 2);
my $ground_level = int($screen_height * 0.7);
for my $y (0..($screen_height)) {
$anim->new_entity(
shape => ['|'],
position => [$half_width, $y, 21],
color => ['w'],
physical => 1,
);
}
}
sub main {
my $anim = Term::Animation->new();
$anim->color(1);
halfdelay(1);
my $paused = 0;
while(1) {
my $screen_width = $anim->width();
my $screen_height = $anim->height();
my $half_width = int($screen_width / 2);
my $ground_level = int($screen_height * 0.7);
add_background($anim, $screen_width, $screen_height);
my $animal = add_animal($anim, ($ground_level - 1));
# animation loop
while(1) {
my $current_time = time();
# run and display a single animation frame
$anim->animate() unless($paused);
# use getch to control the frame rate, and get input at the same time.
my $input = getch();
if($input eq 'q') { quit(); }
if($input eq 'r' || $input eq KEY_RESIZE()) { last; }
if($input eq 'p') { $paused = !$paused; }
}
$anim->update_term_size();
$anim->remove_all_entities();
}
$anim->end();
}