PTBtutorials—Animating basic shapes and dots(2)

1.Rotating Squares Demo:使用OpenGL命令,使三个不同颜色的矩形旋转 

注:这里的旋转方式比较繁琐。如果是为了简便,可以参考之后的纹理操作(将矩形绘制在纹理上,然后让纹理旋转)

(1)Screen('glPushMatrix', window)   将当前的OpenGL状态信息压入堆栈,由于堆栈空间不超过27,所以要及时利用glPopMatrix函数将堆栈信息弹出堆栈 ,以免堆栈溢出

(2)Screen('glTranslate', window, tX,tY,tZ)  在X Y Z 维度上平移tX tY tZ        tX tY tZ是在X Y Z 维度上的平移量

(3)Screen('glRotate', window, angle, rX,rY,rZ)  沿由rx、ry、rz空间向量旋转一定角度

(4)Screen('glPopMatrix', window)  将堆栈中保存的OpenGL状态信息出栈,以恢复原先状态。与glPushMatrix配对使用

对这种方式不理解。个人猜测是先位移动至矩形中心,设置旋转角度,然后再位移回去,再恢复OpenGL的最初状态。

挺麻烦的,以后直接操作纹理旋转即可。

% Our sqaures will have sides 150 pixels in length, as we are going to be     矩形的边长为150pixel,因为要绕着原点旋转,因此对X与Y坐标设置为±75
% rotating these around the origin using OpenGL commands we use -75 to +75
% for the X and Y coordinates
dim = 150 / 2;
baseRect = [-dim -dim dim dim];

% For this Demo we will draw 3 squares      矩形数量
numRects = 3;

% We will randomise the intial rotation angles of the squares. OpenGL uses  随机化旋转的初始角度(OpenGL使用的是角度而非弧度)
% Degrees (not Radians) in these commands, so our angles are in degrees
angles = rand(1, numRects) .* 360;

% We will set the rotations angles to increase by 1 degree on every frame   每帧旋转度数的变化为1
degPerFrame = 1;

% We position the squares in the middle of the screen in Y, spaced equally    设置3个矩形的中心的坐标
% scross the screen in X 
posXs = [screenXpixels * 0.25 screenXpixels * 0.5 screenXpixels * 0.75];
posYs = ones(1, numRects) .* (screenYpixels / 2);

% Finally, we will set the colors of the sqaures to red, green and blue   设置3个矩形的颜色
colors = [1 0 0; 0 1 0; 0 0 1];

% Sync us and get a time stamp      获取时间戳
vbl = Screen('Flip', window);
waitframes = 1;

% Animation loop
while ~KbCheck

    % With this basic way of drawing we have to translate each square from      这里展示的是一种基本的绘制方式。先将矩形从其屏幕位置变为[0 0],然后旋转,然后
    % its screen position, to the coordinate [0 0], then rotate it, then      回到其屏幕位置
    % move it back to its screen position.                                       以高刷新率绘制多个矩形时,这种方式并不高效。但是绘制简单任务的话,能正常工作
    % This is rather inefficient when drawing many rectangles at high            更有效的办法看纹理绘制
    % refresh rates. But will work just fine for simple drawing tasks.
    % For a much more efficient way of drawing rotated squares and rectangles
    % have a look at the texture tutorials
    for i = 1:numRects

        % Get the current squares position ans rotation angle      获取当前的位置与旋转角度
        posX = posXs(i);
        posY = posYs(i);
        angle = angles(i);

        % Translate, rotate, re-tranlate and then draw our square
        Screen('glPushMatrix', window)
        Screen('glTranslate', window, posX, posY)
        Screen('glRotate', window, angle, 0, 0);
        Screen('glTranslate', window, -posX, -posY)
        Screen('FillRect', window, colors(i,:),...
            CenterRectOnPoint(baseRect, posX, posY));
        Screen('glPopMatrix', window)

    end

    % Flip to the screen
    vbl  = Screen('Flip', window, vbl + (waitframes - 0.5) * ifi);

    % Increment the rotation angles of the sqaures now that we have drawn   每一帧旋转角度的增值
    % to the screen
    angles = angles + degPerFrame;

end

2.Mouse In Square Demo: 根据鼠标光标是否在正方形内改变正方形的颜色

思路:首先设置矩形基本属性。然后判断鼠标光标是否在矩形内,根据判断结果,采用不同颜色绘制矩形。这个判断是逐帧进行的

(1) inside=IsInRect(x,y,rect)  判断某位置(x,y)是否在矩形内,返回值为1和0,分别表示在内与在外

% Make a base Rect of 200 by 200 pixels
baseRect = [0 0 200 200];

% Define red and blue
red = [1 0 0];
blue = [0 0 1];

% Here we set the initial position of the mouse to be in the centre of the  设置光标的初始位置为屏幕中央
% screen
SetMouse(xCenter, yCenter, window);

% Sync us and get a time stamp
vbl = Screen('Flip', window);
waitframes = 1;

% Maximum priority level
topPriorityLevel = MaxPriority(window);
Priority(topPriorityLevel);

% Loop the animation until a key is pressed
while ~KbCheck

    % Get the current position of the mouse  获取鼠标状态信息
    [x, y, buttons] = GetMouse(window);

    % Center the rectangle on the centre of the screen
    centeredRect = CenterRectOnPointd(baseRect, xCenter, yCenter);

    % See if the mouse cursor is inside the square  判断光标是否在矩形内
    inside = IsInRect(x, y, centeredRect);

    % Set the color of the square to be red if the mouse is inside it or  根据判断结果决定要绘制的颜色
    % blue if the mouse is outside it
    if inside == 1
        rectColor = red;
    elseif inside == 0
        rectColor = blue;
    end

    % Draw the rect to the screen   绘制矩形
    Screen('FillRect', window, rectColor, centeredRect);

    % Draw a white dot where the mouse is  绘制点
    Screen('DrawDots', window, [x y], 10, white, [], 2);

    % Flip to the screen
    vbl  = Screen('Flip', window, vbl + (waitframes - 0.5) * ifi);

end

3.Keyboard Contingent Square Demo: 通过按键盘上的键(在本例中为四个箭头键),以交互式地在屏幕上移动正方形

思路:首先定义四个按键。然后确定一些基本属性,如基本矩形,中心点,每次按键的位移量等。然后判断是否按了箭头(若按了,则计算位移后的矩形中心点坐标,并进行绘制)

或esc键(若按了便退出)

(1)  KbNameResult=KbName(arg)  根据参数arg的类型决定返回结果,若为字符,则返回对应的扫描码;若为数值型扫描码,则返回对应的键名,若不提供参数,则1s后调用KbCheck函数。若参数为“UnifyKeyNames”,则命名方法转化为MacOX-X的方案,建议每个程序开头加入这行命令以提高效率。若参数为"KeyNames",会列出扫描码→键名的映射表

% The avaliable keys to press    定义按键
escapeKey = KbName('ESCAPE');
upKey = KbName('UpArrow');
downKey = KbName('DownArrow');
leftKey = KbName('LeftArrow');
rightKey = KbName('RightArrow');

% Get the centre coordinate of the window 获取屏幕中心点坐标
[xCenter, yCenter] = RectCenter(windowRect);

% Make a base Rect of 200 by 200 pixels  制作基本矩形
baseRect = [0 0 200 200];

% Set the color of the rect to red 设置颜色
rectColor = [1 0 0];

% Set the intial position of the square to be in the centre of the screen 设置矩形初始的中心点位置
squareX = xCenter;
squareY = yCenter;

% Set the amount we want our square to move on each button press  设置每次按键后矩形的位移量
pixelsPerPress = 10;

% Sync us and get a time stamp 获取时间戳
vbl = Screen('Flip', window);
waitframes = 1;

% Maximum priority level  设置优先级
topPriorityLevel = MaxPriority(window);
Priority(topPriorityLevel);

% This is the cue which determines whether we exit the demo  用以判断是否退出的cue
exitDemo = false;

% Loop the animation until the escape key is pressed  循环动画,直至按了esc键
while exitDemo == false

    % Check the keyboard to see if a button has been pressed  检测是否按键
    [keyIsDown,secs, keyCode] = KbCheck;

    % Depending on the button press, either move ths position of the square or exit the demo  依据按键,决定是否移动矩形或者退出
    if keyCode(escapeKey)
        exitDemo = true;
    elseif keyCode(leftKey)
        squareX = squareX - pixelsPerPress;
    elseif keyCode(rightKey)
        squareX = squareX + pixelsPerPress;
    elseif keyCode(upKey)
        squareY = squareY - pixelsPerPress;
    elseif keyCode(downKey)
        squareY = squareY + pixelsPerPress;
    end

    % We set bounds to make sure our square doesn't go completely off of        设置界限,以确保矩形不会完全移动到屏幕外
    % the screen
    if squareX < 0
        squareX = 0;
    elseif squareX > screenXpixels
        squareX = screenXpixels;
    end

    if squareY < 0
        squareY = 0;
    elseif squareY > screenYpixels
        squareY = screenYpixels;
    end

    % Center the rectangle on the centre of the screen    将矩形移动到新的中心点
    centeredRect = CenterRectOnPointd(baseRect, squareX, squareY);

    % Draw the rect to the screen  绘制
    Screen('FillRect', window, rectColor, centeredRect);

    % Flip to the screen
    vbl  = Screen('Flip', window, vbl + (waitframes - 0.5) * ifi);

end

4.Rectangle Coordinates Demo: 展示屏幕矩形是如何由其左上角和右下角坐标定义的。用键盘(箭头键)移动矩形,看看坐标是如何变化的。还显示了矩形的中心坐标以供参考

思路:与示例3基本一致,只是多了一个文本来报告点的位置

(1) DrawFormattedText(window,string, x, y,color)  绘制标准化文本 ,参数依次为 窗口指针,字符串,坐标,文本颜色

% We will be drawing some text so here we set the size we want the text to   设置字体大小
% be
Screen('TextSize', window, 30);

% The avaliable keys to press  设置按键
escapeKey = KbName('ESCAPE');
upKey = KbName('UpArrow');
downKey = KbName('DownArrow');
leftKey = KbName('LeftArrow');
rightKey = KbName('RightArrow');

% Get the centre coordinate of the window  获取中心点
[xCenter, yCenter] = RectCenter(windowRect);

% Make a base Rect of 200 by 300 pixels  设置基础矩形
baseRect = [0 0 200 300];

% Set the color of the rect to red  设置颜色
rectColor = [0.5 0.5 0.5];

% Set the intial position of the square to be in the centre of the screen  设置矩形的初始中心为屏幕中心
squareX = xCenter;
squareY = yCenter;

% Colors of the dots we will be drawing  设置要绘制的点的颜色
dotColors = [0 1 0; 1 0 0; 0 0 1];

% Set the amount we want our square to move on each button press  设置每次按键的位移量
pixelsPerPress = 10;

% Sync us and get a time stamp  时间戳
vbl = Screen('Flip', window);
waitframes = 1;

% Maximum priority level  优先级
topPriorityLevel = MaxPriority(window);
Priority(topPriorityLevel);

% This is the cue which determines whether we exit the demo  判断是否退出demo的cue
exitDemo = false;

% Loop the animation until the escape key is pressed
while exitDemo == false

    % Check the keyboard to see if a button has been pressed  检测按键
    [keyIsDown,secs, keyCode] = KbCheck;

    % Depending on the button press, either move ths position of the square  判断是否退出或移动矩形
    % or exit the demo
    if keyCode(escapeKey)
        exitDemo = true;
    elseif keyCode(leftKey)
        squareX = squareX - pixelsPerPress;
    elseif keyCode(rightKey)
        squareX = squareX + pixelsPerPress;
    elseif keyCode(upKey)
        squareY = squareY - pixelsPerPress;
    elseif keyCode(downKey)
        squareY = squareY + pixelsPerPress;
    end

    % We set bounds to make sure our square doesn't go completely off of    设置边界判断,使矩形一点都不会超出屏幕外
    % the screen. Here when the srectangles edges hit the screen then it
    % will not move off the screen at all
    if squareX < baseRect(3) / 2
        squareX = baseRect(3) / 2;
    elseif squareX > screenXpixels - baseRect(3) / 2
        squareX = screenXpixels - baseRect(3) / 2;
    end

    if squareY < baseRect(4) / 2
        squareY = baseRect(4) / 2;
    elseif squareY > screenYpixels - baseRect(4) / 2
        squareY = screenYpixels - baseRect(4) / 2;
    end

    % Center the rectangle on the centre of the screen  调整矩形位置
    centeredRect = CenterRectOnPointd(baseRect, squareX, squareY);

    % Draw the rect to the screen  绘制
    Screen('FillRect', window, rectColor, centeredRect);

    % Draw dots that show the rects coordinates  画点
    dotPositionMatrix = [squareX centeredRect(1) centeredRect(3);...
        squareY centeredRect(2) centeredRect(4)];
    Screen('DrawDots', window, dotPositionMatrix, 10, dotColors, [], 2);

    % Draw text in the upper portion of the screen with the default font in  绘制文本
    % white
    line1 = ['\n Top left corner (red dot): x = ' num2str(centeredRect(1))...
        ' y = ' num2str(centeredRect(2))];
    line2 = ['\n Bottom Right corner (blue dot): x = ' num2str(centeredRect(3))...
        ' y = ' num2str(centeredRect(4))];
    line3 = ['\n Rect Centre (green dot): x = ' num2str(squareX) ' y = ' num2str(squareY)];
    DrawFormattedText(window, [line1 line2 line3], 'center', 100, [1 1 1]);

    % Flip to the screen
    vbl  = Screen('Flip', window, vbl + (waitframes - 0.5) * ifi);

end

5.Mouse Contingent Square Demo: 将正方形的位置与鼠标的位置相关联,在矩形内部长按鼠标键以拖动矩形

思路:首先设置基本属性。重点在于鼠标的位置变动量。把“按住键并拖动”(第二帧)与“按住键但还未拖动”(第一帧)这两个状态进行比较,以确定鼠标偏移量,从而确定矩形中心

% Make a base Rect of 200 by 200 pixels
baseRect = [0 0 200 200];

% Define red
red = [1 0 0];

% Here we set the initial position of the mouse to be in the centre of the  设置鼠标初始位置为屏幕中央
% screen
SetMouse(xCenter, yCenter, window);

% We now set the squares initial position to the centre of the screen  设置矩形的初始位置
sx = xCenter;
sy = yCenter;
centeredRect = CenterRectOnPointd(baseRect, sx, sy);

% Offset toggle. This determines if the offset between the mouse and centre        便宜切换。这决定了是否设置鼠标与屏幕中心的偏移。用这个来移动方形的位置,
% of the square has been set. We use this so that we can move the position      而不必将中心转换到鼠标的位置
% of the square around the screen without it "snapping" its centre to the
% position of the mouse
offsetSet = 0;

% Sync us and get a time stamp
vbl = Screen('Flip', window);
waitframes = 1;

% Maximum priority level
topPriorityLevel = MaxPriority(window);
Priority(topPriorityLevel);

% Loop the animation until a key is pressed
while ~KbCheck

    % Get the current position of the mouse   获取鼠标位置
    [mx, my, buttons] = GetMouse(window);

    % Find the central position of the square  找到矩形中心点坐标
    [cx, cy] = RectCenter(centeredRect);

    % See if the mouse cursor is inside the square 判断鼠标是够在矩形内
    inside = IsInRect(mx, my, centeredRect);

    % If the mouse cursor is inside the square and a mouse button is being   如果鼠标在矩形内且按了鼠标键且还未设置偏移,这设置偏移量与偏移信号
    % pressed and the offset has not been set, set the offset and signal
    % that it has been set
    if inside == 1 && sum(buttons) > 0 && offsetSet == 0
        dx = mx - cx;
        dy = my - cy;
        offsetSet = 1;
    end

    % If we are clicking on the square allow its position to be modified by   如果我们点击方形,则通过移动鼠标来调整方形的位置,校正方形中心与鼠标位置的偏移
    % moving the mouse, correcting for the offset between the centre of the
    % square and the mouse position
    if inside == 1 && sum(buttons) > 0
        sx = mx - dx;
        sy = my - dy;
    end

    % Center the rectangle on its new screen position      获取新矩形位置
    centeredRect = CenterRectOnPointd(baseRect, sx, sy);

    % Draw the rect to the screen  绘制矩形
    Screen('FillRect', window, red, centeredRect);

    % Draw a white dot where the mouse cursor is   绘制鼠标所在位置的白色点
    Screen('DrawDots', window, [mx my], 10, white, [], 2);

    % Flip to the screen
    vbl  = Screen('Flip', window, vbl + (waitframes - 0.5) * ifi);

    % Check to see if the mouse button has been released and if so reset  判断鼠标键是否被放开,并重置偏移信号
    % the offset cue
    if sum(buttons) <= 0
        offsetSet = 0;
    end

end

猜你喜欢

转载自www.cnblogs.com/zxpsyneuroscience/p/12622897.html