复习:
小球弹跳:
speedx=30;
speedy=30;
R=50;%小球半径
Screen('Preference', 'SkipSyncTests', 1);
[w,wrect]=Screen('OpenWindow',0,150,[50,50,1900,1000]);
xc=wrect(3)/2;
yc=wrect(4)/2;
rect=[300,100,300+2*R,100+2*R];
for i=1:1500
rect=rect+[speedx,speedy,speedx,speedy];
if rect(3)>=wrect(3)||rect(1)<=wrect(1) %右边界或左边界
speedx = -speedx;
end
if rect(2)<=wrect(2)||rect(4)>=wrect(4) %上边界或下边界
speedy = -speedy;
end
Screen('Filloval',w,[0,100,100],rect);
Screen('Flip',w);
[kid,~,kc]=KbCheck;
if kid==1
break;
end
end
sca;
1、PTB的时间控制
显示器的刷新率,本机为60hz,即显示器每秒钟呈现的画面数量。
测试代码:
Screen('Preference', 'SkipSyncTests', 1); %跳过同步性测试
[w,wrect]=Screen('OpenWindow',0,150,[50,50,1900,1000]); %打开屏幕
for i=1:60
Screen('Filloval',w,[0,100,100],[300,300,500,500]);
Screen('Flip',w);
end
Screen('Flip',w);
WaitSecs(2); %等待2s
sca; %关闭页面
Screen('Preference', 'SkipSyncTests', 1); 同步性测试。第三个参数如果为0,就表示不跳过同步性测试。PTB对于时间的控制精度比较高,在打开窗口的时候会做一个同步性检测,来检测电脑的单帧时长是否稳定,并且对于下面Screen('Flip',w)函数的执行也很稳定。若无法通过,可能会造成丢帧的情况,时间精度降低。
Screen('Flip',w)语句的实现分为两步,第一步等待切换窗,第二步切换。想象一个钟摆,每秒钟摆动60次,而‘Flip’函数对于画面的切换并不是随时可以切换,要先进行等待,就好比钟摆摆到左侧的时候才进行切换,如果执行该语句的时候钟摆不在左侧,即要先等待钟摆到达左侧,才能进行画面的切换。故若只有Screen('Filloval',w,[0,100,100],[300,300,500,500]),椭圆只会显示1/60秒,使用for循环,循环60次,正好可以让椭圆显示1秒。在PTB中常常使用这种方式来控制时间。优点:精度高。也正是因为这种机制,我们设置的刺激时长必须要是单帧时长(1/刷新率 秒)的整倍数。
2、检测鼠标和键盘
实时检测鼠标位置以及鼠标的按键 测试代码:
while 1
[mx,my,button]=GetMouse;
display([mx,my]);
if button(1)==1
break;
end
end
[mx,my,button]=GetMouse; 中的mx和my表示当前鼠标在屏幕的位置,button用来检测鼠标按键,“button”是一个1xN矩阵,其中N是鼠标按键。矩阵的每个元素代表一个鼠标按钮,如果按下相应的鼠标按钮则为1,否则为0。
检测键盘按键 测试代码:
keyrecord=[];
m=0;
start=GetSecs;
while 1
if GetSecs-start>2
break
end
[kid,~,kc]=KbCheck ;
m=m+1;
keyrecord(m)=kid;
end
GetSecs 获取当前的时间,利用while循环来连续检测2秒内是否有键被按下。
[kid,~,kc]=KbCheck ; 语句仅运行1ms。即检测1ms内是否有键被按下,但我们不可能在它检测的1ms内按下键盘,故采用while语句延长检测的时间。KbCheck中有四个参数,暂时只用到两个,kid就是用来检测按键,如果有键被按下,则为1,否则为0;kc用来返回这个键是什么,返回的参数是一个数字,键名与扫描码对应表如下:
如果感觉查表比较麻烦,也可以采用 KbName 这个函数查看某个键对应的扫描码,比如'A'的扫描码可以这样来看 : KbName('A')