Box2D

 view release on metacpan or  search on metacpan

examples/breakable.pl  view on Meta::CPAN

    my $p = $body1->GetPosition();
    $bodyDef->position->Set( $p->x, $p->y );
    $bodyDef->angle( $body1->GetAngle() );

    my $fixtureDef = Box2D::b2FixtureDef->new();
    $fixtureDef->shape( $self->shape2 );
    $fixtureDef->density(1.0);
    $fixtureDef->restitution(0.5);
    my $body2 = $self->world->CreateBody($bodyDef);
    $self->piece2( $body2->CreateFixtureDef($fixtureDef) );

    my $center1 = $body1->GetWorldCenter();
    my $center2 = $body2->GetWorldCenter();

    my $velocity1 = Box2D::b2Math::b2CrossSV2( $self->angularVelocity,
        $center1 - $center );
    my $velocity2 = Box2D::b2Math::b2CrossSV2( $self->angularVelocity,
        $center2 - $center );

    $body1->SetAngularVelocity( $self->angularVelocity );
    $body1->SetLinearVelocity($velocity1);

    $body2->SetAngularVelocity( $self->angularVelocity );
    $body2->SetLinearVelocity($velocity2);

    $self->body2($body2);
}

sub Step {
    my ($self) = @_;

    if ( $self->break ) {
        $self->Break();
        $self->broke(1);
        $self->break(0);
    }

    if ( !$self->broke ) {
        $self->velocity( $self->body1->GetLinearVelocity() );
        $self->angularVelocity( $self->body1->GetAngularVelocity() );
    }
}

__PACKAGE__->meta->make_immutable();

package main;

# screen dimensions in pixels
my ( $width, $height ) = ( 300, 300 );

# pixels per meter
my $ppm = 30;

# meters per pixel
my $mpp = 1.0 / $ppm;

# frames per second
my $fps      = 60.0;
my $timestep = 1.0 / $fps;

# velocity iterations
my $vIters = 10;

# position iterations
my $pIters = 10;

my $gravity = Box2D::b2Vec2->new( 0, 9.8 );
my $world = Box2D::b2World->new( $gravity, 1 );

my $ground = make_ground();

my @breakables;

my $app = SDLx::App->new(
    width  => $width,
    height => $height,
    dt     => $timestep,
    min_t  => $timestep / 2,
    flags  => SDL_DOUBLEBUF | SDL_HWSURFACE,
    eoq    => 1,
);

$app->add_event_handler(
    sub {
        my ( $event, $app ) = @_;
        return unless $event->type == SDL_MOUSEBUTTONDOWN;
        my ( undef, $x, $y ) = @{ SDL::Events::get_mouse_state() };
        push @breakables, make_breakable( $x, $y );
    }
);

$app->add_show_handler(
    sub {
        $_->Step() foreach @breakables;
        $world->Step( $timestep, $vIters, $pIters );
        $world->ClearForces();

        $app->draw_rect( undef, 0x000000FF );
        draw_breakable($_) foreach @breakables;
        $app->update();
    }
);

$app->run();

# screen to world
sub s2w { return $_[0] * $mpp }

# world to screen
sub w2s { return $_[0] * $ppm }

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

    my $breakable = Breakable->new(
        world => $world,
        x     => s2w($x),
        y     => s2w($y),
        angle => rand(pi),
        w     => s2w( 20.0 + rand(20.0) ),
        h     => s2w( 20.0 + rand(20.0) ),
        color => [ int rand(255), int rand(255), int rand(255) ],
    );



( run in 1.614 second using v1.01-cache-2.11-cpan-96521ef73a4 )