Вводы клавиатуры MATLAB не обновляются в игре Pong

Я пытаюсь воссоздать «понг» в MATLAB, и до сих пор мне удавалось сгенерировать фигуру, нарисовать корт, нарисовать весла и нарисовать мяч. На данный момент я пытаюсь обновить положение лепестков (перемещать их вверх и вниз) с помощью ввода с клавиатуры. Я пытаюсь использовать встроенные функции MATLAB "KeyPressFcn" и "KeyReleaseFcn", чтобы сделать это, но по какой-то причине лепестки все еще не двигаются. Мой код ниже. Может ли кто-нибудь увидеть, что я делаю неправильно?

% 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

person electronicaneer    schedule 03.02.2017    source источник


Ответы (1)


Я думаю, что есть простое решение проблемы.

Вызовите функцию drawnow в конце цикла while.
Вы также можете добавить команду паузы, например 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

Проблема в том, что Matlab блокирует все события при выполнении замкнутого цикла. Добавление drawnow или pause позволяет Matlab реагировать на событие.


Проблема также может быть связана с переменными Правила области.
Убедитесь, что оператор end основной функции находится в последней строке кода файла.

Проверьте следующее (полный код):

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
person Rotem    schedule 03.02.2017
comment
Я попробовал, но это не сработало. Проблема, с которой я сталкиваюсь, заключается в том, что значения left_bottom и right_bottom не увеличиваются, как должны. Когда я нажимаю соответствующие клавиши, эти значения должны измениться на 0,05, и это позволит лепесткам перемещаться вверх и вниз с этим приращением. Я даже оставил ; после каждого из них в цикле while, чтобы увидеть, изменяется ли значение (они инициализируются в 5), и это не так, но я не вижу, где разрыв между ключевыми прослушивателями и обновлением этих переменных в пока цикл. - person electronicaneer; 04.02.2017
comment
Скопируйте и вставьте полный код... Когда я нажимаю клавишу 'q', красная лопатка перемещается вверх. - person Rotem; 04.02.2017
comment
Спасибо! Таким образом, основные изменения, которые вы сделали, заключались в добавлении паузы, но также вы обернули всю программу функцией PongGame. Почему это заставляет его работать правильно? - person electronicaneer; 04.02.2017
comment
Правила области действия: По умолчанию переменная типа left_input видна только функции keyUp. left_input внутри keyUp и снаружи keyUp — разные переменные с одинаковыми именами. Обернув программу функцией, сделайте переменные вида Global в обернутой функции. - person Rotem; 04.02.2017