Why does my while-loop sometimes not respond to a keypress in Matlab?
我已经为一项新研究创建了一个游戏,我将在Matlab R2018a中使用Psychtoolbox(3.0.13,flavor beta)运行该游戏,并提出退出我的while循环的条件(有时是空格键)立即生效,但有时需要几次按键才能退出。
我试图通过删除任何不必要的代码并在显示刺激之前放置等待时间来提高代码效率,以防此问题得以解决。我有一个while循环,需要鼠标单击旁边的空格键输入来满足退出条件。该代码确实在最后运行,但是我只是不明白为什么有时单按空格键就足够了,而有时我需要按3次退出。我在另一个任务中也遇到了同样的问题,在该任务中我还使用鼠标单击和空格键按下(并且没有声音,因此我认为声音不是由它引起的)作为退出while循环的条件。我想知道这是否与我使用RECS结构的方式有关,以及是否可以使用更有效的方式。如果有人对如何在任务中改善这一点有任何想法,那将是惊人的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 | % 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 |
只想在下面发布答案,这是评论者给我的。问题实际上只是在我输入的200毫秒的延迟时间内,这也意味着KbCheck并不总是能够及时地注册空格键的按下..所以这是一个简单的问题,但是这个答案使我解决了这一烦恼任务以及其他任务,谢谢!评论并复制了以下答案:
"我不知道这个Screen类,而且看起来这都是Psychtoolbox特有的,您在这里使用的原生MATLAB很少,所以我无济于事。但是快速浏览一下文档揭示了KbCheck在那一瞬间检查了按键是否被按下。因此,当执行那段代码时,您需要将按键按下。由于您在那里也要等待0.2 s,因此按一下该按键将变得非常困难。在正确的时间键入密钥。尝试将其保持在按下状态,直到程序停止。抱歉,我没有使用此工具箱的改进建议,抱歉。a€" Cris Luengo"