为什么我的while循环有时对Matlab中的按键不响应?

时间:2019-03-28 18:23:25

标签: matlab while-loop

我为一项新研究创建了一个游戏,我将在Matlab R2018a中使用Psychtoolbox(3.0.13,flavor beta)运行,并且退出试验时退出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 个答案:

答案 0 :(得分:1)

只想在下面发布答案,这是评论者给我的。这个问题实际上只是在我输入的200毫秒的延迟时间内,这也意味着KbCheck并不总是能够及时地注册空格键的按下。.所以这是一个简单的问题,但是这个答案使我解决了这个烦恼任务以及其他任务,谢谢!评论,答案复制如下:

”“我不知道这个Screen类,它看起来都是Psychtoolbox特有的,在这里使用的原生MATLAB很少,所以我无济于事。但是快速浏览一下文档揭示了KbCheck在那一瞬间会检查密钥是否被按下。因此,当执行该段代码时,您需要将密钥按下。由于您在那里也要等待0.2 s,因此按键盘上的键将变得具有挑战性。在正确的时间输入密钥。请尝试保持按下状态直到程序停止。抱歉,我没有使用此工具箱的改进建议。– Cris Luengo“