Почему мой цикл while не реагирует на нажатие клавиш в Matlab? - PullRequest
0 голосов
/ 28 марта 2019

Я создал игру для нового исследования, которое я буду запускать, используя Psychtoolbox (3.0.13, flavour beta) в Matlab R2018a, и условие для выхода из цикла while в пробной версии, которая иногда является нажатием пробела, иногдаработает сразу, но иногда требуется несколько нажатий клавиш для выхода.

Я попытался сделать свой код более эффективным, удалив ненужный код и вставив время ожидания, прежде чем показывать стимулы на случай, если это решит проблему.У меня есть цикл while, который требует ввода щелчков мыши вместе с нажатием пробела, чтобы удовлетворить условия выхода.Код выполняется в конце, но я просто не понимаю, почему иногда достаточно одного нажатия пробела, а в других случаях мне нужно нажать его 3 раза, чтобы выйти.У меня та же проблема в другой задаче, где я также использую щелчки мыши и нажатие клавиши пробела (и звука нет, поэтому я не думаю, что звук вызывает его) в качестве условий для выхода из цикла while.Интересно, это как-то связано с тем, как я использую структуру RECS, и могу ли я использовать более эффективный способ?Было бы замечательно, если бы кто-нибудь имел представление о том, как улучшить это в задаче.

% Start game: They play a total of 5 games. A game finishes when
% they have selected at least 1 card and pressed spacebar.

for Game = 1:5
% If ESC is pressed, quit game.
if OM.ESC == 0

% Draw wooden background
Screen('DrawTexture', OM.wid, OM.greywoodTexture);

% Show score and game counter
Screen('TextSize', OM.wid, OM.textSize);
DrawFormattedText(OM.wid, ['Score: ', num2str(OM.Score)], ...
    OM.origin(1)+750, OM.origin(2)-400);
DrawFormattedText(OM.wid, ['Game: ', num2str(Game)], ...
    OM.origin(1), OM.origin(2)-425);

% create sequence for where Randy wil be and randomise it
sequence = [1 0 0 0 0 0 0 0 0 0];
sequence = sequence(randperm(length(sequence)));

% Draw the cards upside down
for i = 1:length(RECS)
    Screen('DrawTexture', OM.wid, OM.cardsTexture, [], RECS(i).rectangles);
end

% Show the cards and get the time. If it's the first game, use 0.5
% seconds before showing to make sure the game is up to speed. (Thought
% this might help with speed later on, not sure if it does.)
if Game == 1
    WaitSecs(0.5);
end
timage = GetSecs;
Screen('Flip', OM.wid);

% set screenpress and loss to 0
Screenpress = 0;
loss = 0;

% wait for screenpress (space bar press)
while Screenpress == 0 && OM.ESC == 0 % checks for completion
    [keyIsDown, keyTime, keyCode] = KbCheck;
        if keyIsDown
            keyStroke = KbName(keyCode);
            % check if space was pressed and atleast one card was
            % selected
            if any(strcmpi(keyStroke,OM.screenKey)) && sum([RECS(:).pressed]) ~= 0
                Screenpress = 1;
                RT = round((keyTime - timage)*1000);
            elseif any(strcmpi(keyStroke,OM.exitKey))
                OM.ESC = 1;
                RT = 0;
                break;
            end
        end  

        % check if the mouse was pressed inside any of the rectangles
        % (cards)
        [mx,my,buttons] = GetMouse();  %waits for a key-press
        for i = 1:length(RECS)
            if IsInRect(mx, my, RECS(i).rectangles) == 1 && sum(buttons) > 0 && RECS(i).pressed == 0
                RECS(i).pressed = 1;
            elseif IsInRect(mx, my, RECS(i).rectangles) == 1 && sum(buttons) > 0 && RECS(i).pressed == 1
                % This is to enable de-selecting a card by double
                % clicking on it.
                RECS(i).pressed = 0;
            end
        end

        % Draw wooden background
        Screen('DrawTexture', OM.wid, OM.greywoodTexture);

        % Draw score counter
        Screen('TextSize', OM.wid, OM.textSize);
        DrawFormattedText(OM.wid, ['Score: ', num2str(OM.Score)], ...
        OM.origin(1)+750, OM.origin(2)-400);
        DrawFormattedText(OM.wid, ['Game: ', num2str(Game)], ...
        OM.origin(1), OM.origin(2)-425);

    % Draw cards with a frame around it if selected.
        for i = 1:length(RECS)
            Screen('DrawTexture', OM.wid, OM.cardsTexture, [], RECS(i).rectangles);
            if RECS(i).pressed == 1
                Screen('FrameRect', OM.wid, OM.selRecColour, RECS(i).rectangles, OM.selRecSize);
            end
        end

        % Show the selected card borders and delay against flicker
        WaitSecs(0.2); % need this delay to stop flicker
        Screen('Flip', OM.wid);

end % space was pressed, after the cards were selected. Now we need to flip the cards and show what they chose.

% if space was pressed,
% Draw wooden background
Screen('DrawTexture', OM.wid, OM.greywoodTexture);

% Draw score counter
Screen('TextSize', OM.wid, OM.textSize);
DrawFormattedText(OM.wid, ['Score: ', num2str(OM.Score)], ...
OM.origin(1)+750, OM.origin(2)-400);
DrawFormattedText(OM.wid, ['Game: ', num2str(Game)], ...
    OM.origin(1), OM.origin(2)-425);

% randomly select the 9 animals to show. Replace is set to false so
% each animal can only be shown once in one game. It needs to be 10,
% else the game won't run if they select 10 cards (just in case they
% do). 
animals = datasample(1:26, 10, 'Replace', false);

% Set card count to 0
card_count = 0;

% display animations
for i = 1:length(RECS)
    if RECS(i).pressed == 1
        % add to card_count if a card was selected
        card_count = card_count + 1;
        Screen('FrameRect', OM.wid, OM.selRecColour, RECS(i).rectangles, OM.selRecSize);

        if sequence(i) == 0 % normal animal
            t = animals(i);
            Screen('FillRect', OM.wid, OM.turnedCardColour, RECS(i).rectangles)
            Screen('DrawTexture', OM.wid, ANIMAL(t).AniTexture, [], RECS(i).animals);

        elseif sequence(i) == 1 % troll face
            Screen('FillRect', OM.wid, OM.redColour, RECS(i).rectangles)
            Screen('DrawTexture', OM.wid, OM.trollTexture, [], RECS(i).animals);
            % play giggle if Randy was selected
            PsychPortAudio('Start', OM.giggle, 1);

            loss = 1;
        end

    else
        % Show the cards upside down for the ones that weren't
        % selected.
        Screen('DrawTexture', OM.wid, OM.cardsTexture, [], RECS(i).rectangles);

    end
end


    Screen('Flip', OM.wid);
    WaitSecs(2);

    % Draw wooden background
    Screen('DrawTexture', OM.wid, OM.greywoodTexture);
    Screen('TextSize', OM.wid, OM.feedbackSize);

    % Show text after game round, and determine Score for game
    if loss == 1
        message = 'Oh no! You lost all your cards for this round...';
        DrawFormattedText(OM.wid, message, 'center', 'center', OM.textColor);
        Score = 0;

    elseif loss == 0
        message = sprintf('Well done! You''ve won %d cards this round!', card_count);
        DrawFormattedText(OM.wid, message, 'center', 'center', OM.textColor);
        Score = card_count;
    end

    % calculate the total score in the game
    OM.Score = OM.Score + Score ;

    % Draw score counter 
    Screen('TextSize', OM.wid, OM.textSize);
    DrawFormattedText(OM.wid, ['Score: ', num2str(OM.Score)], ...
    OM.origin(1)+750, OM.origin(2)-400);
    DrawFormattedText(OM.wid, ['Game: ', num2str(Game)], ...
        OM.origin(1), OM.origin(2)-425);

        Screen('Flip',OM.wid);
        WaitSecs(2); %change back to 1 second. % put to 2 seconds because is delay of showing text?

    %% Save the data file
    OM.dataFile = fopen(OM.dataFileName, 'a');
    fprintf(OM.dataFile, OM.formatString, OM.SJNB, OM.Test_session, OM.Age, OM.Date, Game, RT, card_count, loss, OM.Score);
    fclose(OM.dataFile);

    % Cleaning this.
    for i = 1:10
        RECS(i).pressed = 0;
        RECS(i).pressedCount = 0;
    end


end
end

1 Ответ

1 голос
/ 29 марта 2019

Просто хотел опубликовать ответ ниже, который мне дал комментатор. Проблема была на самом деле в периоде задержки 200 мс, который я вставил, что также означало, что KbCheck не всегда удавалось зарегистрировать нажатие клавиши пробела во времени ... так что это была простая проблема, но этот ответ заставил меня исправить это раздражение в моем задача, как и в другой, так что спасибо! Комментарий с ответом скопирован ниже:

"Я не знаю этот класс Screen, и похоже, что он все специфичен для Psychtoolbox, здесь есть небольшой собственный MATLAB, поэтому я не могу помочь. Но быстрый просмотр документов показывает, что KbCheck проверяет, что ключ не работает в этот момент. Поэтому вам нужно нажимать клавишу во время выполнения этого бита кода. Так как у вас там тоже есть ожидание 0,2 с, будет сложно нажать клавишу ключ в нужное время. Постарайтесь держать ключ нажатым до тех пор, пока программа не остановится. У меня нет предложений, как улучшить это с помощью этой панели инструментов, извините. - Cris Luengo "

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...