Search code examples
matlabpong

MATLAB Keyboard inputs not updating on "Pong" game


I am trying to re-create "Pong" in MATLAB, and so far I have been able to generate the figure, draw a court, draw the paddles, and draw the ball. At this point, I am trying to update the position of the paddles (move them up and down) via keyboard input. I am attempting to utilize MATLAB's built-in "KeyPressFcn" and "KeyReleaseFcn" features in order to do this, but for some reason the paddles still aren't moving. My code is below. Can anyone see what I am doing wrong?

% Create court figure, make title, set axis, draw middle dotted line and
% top/bottom lines, turn axis off
court = figure;
set(court, 'Color', 'black', 'toolbar', 'none', 'menubar', 'none');
title('ENGR 122 PONG', 'FontSize', 18, 'Color', 'w');
axis([0 14 0 12]);
line([7 7],[0 12],'LineStyle',':','LineWidth',1,'Color','yellow');
line([0 14], [12 12], 'LineStyle', '-', 'LineWidth', 3, 'Color', 'yellow');
line([0 14], [0 0], 'LineStyle', '-', 'LineWidth', 3, 'Color', 'yellow');
axis off

% Initialize inputs for left and right paddle
left_input = 0;
right_input = 0;

% Initialize ball on court
hold on
ball = plot(7, 6, 'w.', 'MarkerSize', 15);

% Initialize paddles on court, set speed
left_bottom = 5;
left_height = 2;
right_bottom = 5;
right_height = 2;
left_paddle = line([1 1], [left_bottom (left_bottom + left_height)], 'LineWidth', 5, 'Color', 'red');
right_paddle = line([13 13], [right_bottom (right_bottom + right_height)], 'LineWidth', 5, 'Color', 'blue');

% Initialize score on screen
left_score = 0;
right_score = 0;
draw_left_score = text(2, 10, num2str(left_score), 'FontSize', 25, 'Color', 'yellow');
draw_right_score = text(12, 10, num2str(right_score), 'FontSize', 25, 'Color', 'yellow');

% While neither player has scored 10 points yet
while (left_score < 10 || right_score < 10)
    % Update left and right paddle values
    left_bottom = updateLeft(left_input, left_bottom)
    right_bottom = updateRight(right_input, right_bottom);

    % Set Key listeners to figure
    set(court, 'KeyPressFcn', @keyDown, 'KeyReleaseFcn', @keyUp);

    % Update left and right paddle positions on figure
    set(left_paddle, 'YData', [left_bottom (left_bottom + left_height)]);
    set(right_paddle, 'YData', [right_bottom (right_bottom + right_height)]);

end

% Function listening for keys being pressed
function keyDown(source, event)
    if event.Key == 'q'
        left_input = 1;
    end
    if event.Key == 'a'
        left_input = -1;
    end
    if event.Key == 'o'
        right_input = 1;
    end
    if event.Key == 'l'
        right_input = -1;
    end
end

% Function listening for keys being released
function keyUp(source, event)
    if event.Key == 'q'
        left_input = 0;
    end
    if event.Key == 'a'
        left_input = 0;
    end
    if event.Key == 'o'
        right_input = 0;
    end
    if event.Key == 'l'
        right_input = 0;
    end   
end

% Function updating left paddle
function left_bottom = updateLeft(left_input, left_bottom)
    if left_input == 1
        left_bottom = left_bottom + .05;
    elseif left_input == -1
        left_bottom = left_bottom - .05;
    end
end

% Function updating right paddle
function right_bottom = updateRight(right_input, right_bottom)
    if right_input == 1
        right_bottom = right_bottom + .05;
    elseif right_input == -1
        right_bottom = right_bottom - .05;
    end
end

Solution

  • I think there is a simple solution to the problem.

    Call drawnow function at the end of the while loop.
    You can also add pause command like pause(0.01).

    % While neither player has scored 10 points yet
    while (left_score < 10 || right_score < 10)
        % Update left and right paddle values
        left_bottom = updateLeft(left_input, left_bottom);
        right_bottom = updateRight(right_input, right_bottom);
    
        % Set Key listeners to figure
        set(court, 'KeyPressFcn', @keyDown, 'KeyReleaseFcn', @keyUp);
    
        % Update left and right paddle positions on figure
        set(left_paddle, 'YData', [left_bottom (left_bottom + left_height)]);
        set(right_paddle, 'YData', [right_bottom (right_bottom + right_height)]);
    
        drawnow
    end
    

    The problem is that Matlab blocks all events when tight loop is executed. Adding drawnow or pause, enables Matlab respond to the event.


    The problem might also be related to variables Scope Rules.
    Make sure the end statement of the main function, is at the last code line of the file.

    Check the following (complete code):

    function PongGame()
    court = figure;
    set(court, 'Color', 'black', 'toolbar', 'none', 'menubar', 'none');
    title('ENGR 122 PONG', 'FontSize', 18, 'Color', 'w');
    axis([0 14 0 12]);
    line([7 7],[0 12],'LineStyle',':','LineWidth',1,'Color','yellow');
    line([0 14], [12 12], 'LineStyle', '-', 'LineWidth', 3, 'Color', 'yellow');
    line([0 14], [0 0], 'LineStyle', '-', 'LineWidth', 3, 'Color', 'yellow');
    axis off
    
    % Initialize inputs for left and right paddle
    left_input = 0;
    right_input = 0;
    
    % Initialize ball on court
    hold on
    ball = plot(7, 6, 'w.', 'MarkerSize', 15);
    
    % Initialize paddles on court, set speed
    left_bottom = 5;
    left_height = 2;
    right_bottom = 5;
    right_height = 2;
    left_paddle = line([1 1], [left_bottom (left_bottom + left_height)], 'LineWidth', 5, 'Color', 'red');
    right_paddle = line([13 13], [right_bottom (right_bottom + right_height)], 'LineWidth', 5, 'Color', 'blue');
    
    % Initialize score on screen
    left_score = 0;
    right_score = 0;
    draw_left_score = text(2, 10, num2str(left_score), 'FontSize', 25, 'Color', 'yellow');
    draw_right_score = text(12, 10, num2str(right_score), 'FontSize', 25, 'Color', 'yellow');
    
    % While neither player has scored 10 points yet
    while (left_score < 10 || right_score < 10)
        % Update left and right paddle values
        left_bottom = updateLeft(left_input, left_bottom);
        right_bottom = updateRight(right_input, right_bottom);
    
        % Set Key listeners to figure
        set(court, 'KeyPressFcn', @keyDown, 'KeyReleaseFcn', @keyUp);
    
        % Update left and right paddle positions on figure
        set(left_paddle, 'YData', [left_bottom (left_bottom + left_height)]);
        set(right_paddle, 'YData', [right_bottom (right_bottom + right_height)]);
    
        drawnow
    end
    
    % Function listening for keys being pressed
    function keyDown(source, event)
        if event.Key == 'q'
            left_input = 1;
        end
        if event.Key == 'a'
            left_input = -1;
        end
        if event.Key == 'o'
            right_input = 1;
        end
        if event.Key == 'l'
            right_input = -1;
        end
    end
    
    % Function listening for keys being released
    function keyUp(source, event)
        if event.Key == 'q'
            left_input = 0;
        end
        if event.Key == 'a'
            left_input = 0;
        end
        if event.Key == 'o'
            right_input = 0;
        end
        if event.Key == 'l'
            right_input = 0;
        end   
    end
    
    % Function updating left paddle
    function left_bottom = updateLeft(left_input, left_bottom)
        if left_input == 1
            left_bottom = left_bottom + .05;
        elseif left_input == -1
            left_bottom = left_bottom - .05;
        end
    end
    
    % Function updating right paddle
    function right_bottom = updateRight(right_input, right_bottom)
        if right_input == 1
            right_bottom = right_bottom + .05;
        elseif right_input == -1
            right_bottom = right_bottom - .05;
        end
    end
    
    end