drose2211 has asked for the wisdom of the Perl Monks concerning the following question:

SO hopefully this is the last question I will ever have to ask regarding pong in SDL. Everything works now except the paddles start in the the upper corners instead of the center and I dont understand the movement of them. I understand where the block of code is thats moving them, but they don't move very far and after I let go of the up or down arrow they snap back up to their orginal position. Them being in the upper corners of the screen isnt that big of a deal, but them not moving correctly is. If anyone knows what I need to change to have them move more than half an inch it would be greatly appreciated. The specific block that allows the arrow keys to move the paddles starts with '$app->add_event_handler'

#!/usr/bin/perl use strict; use warnings; # These will allow us to use all the modules necessary to create a GUI +. # They are all parts of the Perl SDL module. # The :: are use to seperate the name of the module and its correspond +ing member. use SDL; use SDL::Events; use SDLx::App; use SDLX::Rect; # First is to set up the screen. # The => operator is similiar to a comma. # but it treates the word to the left as a quoted word. # Even though there isn't any quotes. my $app = SDLx::App->new( width => 500, height => 500, title => 'PONG', dt => 0.04, exit_on_quit => 1, ); # The next step is to set up the paddles for each player. # This is done in a hash reference. # This is done so its possible to add information later. # The numbers may need to be changed later to fit the paddles to the s +creen. # I am not 100% sure what -> actually does. # Other than the fact its a deference operator. # h is a shortened reference to height my $player1 = { paddle => SDLx::Rect->new( 10, $app-> height / 2, 10, 40), }; my $player2 = { paddle => SDLx::Rect->new( $app-> width - 20, $app-> height / 2, 1 +0, 40) }; # This is to create the ball my $ball = { rect => SDLx::Rect->new( $app-> width / 2, $app-> height / 2, 10, +10 ), v_x => -2.3, v_y => 1.5, }; $app->add_show_handler ( sub { $app->draw_rect( [ 0, 0, $app->w, $app->h ], 0x000000FF ); $app->draw_rect( $ball->{rect}, 0xFF0000FF ); $app->draw_rect( $player1->{paddle}, 0xFF0000FF ); $app->draw_rect( $player2->{paddle}, 0xFF0000FF ); $app->update; } ); $player1 = { paddle => SDLx::Rect->new( 10, $app-> height / 2, 10, 40 ), v_y => 0, }; $app->add_move_handler( sub { my ( $step, $app ) = @_; my $paddle = $player1->{paddle}; my $v_y = $player1->{v_y}; $paddle->y( $paddle->y ( $v_y * $step ) ); }); $player2 = { paddle => SDLx::Rect->new( $app->w - 20, $app-> height / 2, 10, 40 +), v_y => 0, }; $app->add_move_handler( sub { my ( $step, $app ) = @_; my $paddle = $player2->{paddle}; my $v_y = $player2->{v_y}; if ( $ball->{rect}->y > $paddle->y ) { $player2->{v_y} =1.5; } else { $player2->{v_y} = 0; } $paddle->y( $paddle->y ( $v_y * $step ) ); }); $app->add_event_handler( sub { my ( $event, $app ) = @_; if ( $event->type == SDL_KEYDOWN ) { if ( $event->key_sym == SDLK_UP ) { $player1->{v_y} = -20; } elsif ( $event->key_sym == SDLK_DOWN ) { $player1->{v_y} = 20; } } elsif ( $event->type == SDL_KEYUP ) { if ( $event->key_sym == SDLK_UP or $event->key_sym == SDLK_DOWN ) { $player1->{v_y} = 0; } } } ); $app->add_move_handler( sub { my ( $step, $app ) = @_; my $ball_rect = $ball->{rect}; $ball_rect->x( $ball_rect->x + ($ball->{v_x} * $step) ); $ball_rect->y( $ball_rect->y + ($ball->{v_y} * $step) ); if ( $ball_rect->bottom >= $app->h ) { $ball_rect->bottom( $app->h); $ball->{v_y} *= -1; } elsif ( $ball_rect->top <= 0 ) { $ball_rect->top( 0 ); $ball->{v_y} *= -1; } elsif ( $ball_rect->right >= $app->w ) { $player1->{score}++; reset_game(); return; } elsif ( $ball_rect->left <= 0 ) { $player2->{score}++; reset_game(); return; } elsif ( check_collision( $ball_rect, $player1->{paddle} )) { $ball_rect->left( $player1->{paddle}->right ); $ball->{v_x} *= -1; } elsif ( check_collision( $ball_rect, $player2->{paddle} )) { $ball->{v_x} *= -1; $ball_rect->right( $player2->{paddle}->left ); } }); sub reset_game { $ball->{rect}->x( $app->w / 2 ); $ball->{rect}->y( $app->h / 2); } sub check_collision { my ($A, $B) = @_; return if $A->bottom < $B->top; return if $A->top > $B->bottom; return if $A->right < $B->left; return of $A->left > $B->right; return 1; } $app->run;

Replies are listed 'Best First'.
Re: Movement handlers in SDL
by poj (Abbot) on Dec 04, 2017 at 06:53 UTC

    See my reply to your previous post Re: More Pong in SDL.
    $paddle->y is a 'getter' method to get the y position of the $paddle object.
    $paddle->y(value) is a 'setter' method to set the y position of the $paddle object.

    So the code $paddle->y( $paddle->y + ( $v_y * $step ) )increment the y position by the velocity * step

    Also there is an error in line 155.

    #return of $A->left > $B->right; return if $A->left > $B->right;
    poj

      Sorry for not noticing your previous reply. If I had been a bit more observant I could have avoided that. Adding the + to both paddles placed them in the center of the screen as well as allowing them to move smoothly back and forth. Now the issue I am having is that the ball hits the paddle, but does not bounce back towards the other side. Alls it does is sit in the position where it hit the paddle. I am assuming this is some issue in the two elsif statements that check for collision with the paddles. Or possibly something wrong inside the subroutine definition? I fixed the 'return if' statement so that's not it. UPDATE...It was in the $player1 elsif statement. the two lines needed to be switched to match $player2 elsif statement.