matlab - 为什么我的 while 循环有时不响应 Matlab 中的按键?
问题描述
我为一项新研究创建了一个游戏,我将在 Matlab R2018a 中使用 Psychtoolbox(3.0.13,风味测试版)运行,并且在试用中退出我的 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
解决方案
只是想在下面发布答案,这是评论者给我的。问题实际上只是在我输入的 200 毫秒的延迟时间内,这也意味着 KbCheck 并不总是能及时注册空格键。所以这是一个简单的问题,但这个答案让我解决了这个烦恼任务以及另一个任务,所以谢谢!评论下面复制的答案:
“我不知道这个 Screen 类,而且看起来这都是 Psychtoolbox 特有的,你在这里使用的原生 MATLAB 很少,所以我帮不上忙。但是快速浏览一下文档就会发现 KbCheck检查那一刻是否按下键。因此,当执行那段代码时,您需要按下键。由于您在那里也有 0.2 秒的等待时间,因此在按下键时会变得很有挑战性正确的时间。试着按住键直到程序停止。我没有关于如何使用这个工具箱改进它的建议,抱歉。——Cris Luengo"
推荐阅读
- ios - 以编程方式在中间设置框架 CGReact x 位置,如 centerXAnchor NSLayoutConstraint
- java - Spring框架邮件确认链接错误
- ios - Objective-C - UIAlertView 不委托
- android - 错误:任务“:app:transformDexWithInstantRunSlicesApkForDebug”执行失败。无法读取 zip 文件
- jquery - jQuery Ajax GET 在 Web API 核心控制器中调用错误的方法
- elasticsearch - Elasticsearch 5.2.0 put normalizer 错误
- javascript - 是否可以让 Javascript 的 fetch() 等待响应,即使响应需要一个小时才能返回,而无需进行第二次请求尝试?
- node.js - 命名空间在节点 js 中的 soap 响应正文中未定义。
- c# - 按parentid对子记录进行分组并对linq C#的数量求和
- python - 二叉搜索树:如何在插入时定位“当前节点”