![a5e575e7ad2f768acca72975a4187950.png](https://img-blog.csdnimg.cn/img_convert/a5e575e7ad2f768acca72975a4187950.png)
打地鼠(HitHamster)是一款非常有趣的游戏。游戏规则很简单,把冒出头来的地鼠给全部打下去就算成功。本文会详细地介绍如何利用Matlab的Psychtoolbox工具包来实现打地鼠游戏的编写。
这个教程很有趣的一点是,我们会同时用Matlab GUI和Matlab Psychtoolbox两种实验编程框架,这样的对比是一种创新,方便大家从两种不同的角度来领略实验编程的奥义。
一个萝卜一个坑,我们先来看一个坑的时候,地鼠冒头被打的情况。
在写代码之前,我们要准备好材料,包括背景图片,锤子(松开的状态)、锤子(击打的状态)、地鼠(正常的&带坑的)、地鼠(被打晕的&带坑的)和地鼠出没的坑。
模块一:确定背景颜色
一上来先确定背景颜色的RGB参数,我们打开背景图片看一下:
![05dd885ebe9646b12bf779ba91a459b1.png](https://img-blog.csdnimg.cn/img_convert/05dd885ebe9646b12bf779ba91a459b1.png)
我们可以借助微信的截图功能来完成颜色识别。微信一旦开启截图功能,它会自动获取鼠标所在位置的RGB值。如果是苹果mac系统的微信,它是以十六进制显示的数值。当前背景颜色显示的是#C4DE52,需要借助在线的颜色转换,比如下面这个网站来实现:
RGB颜色值与十六进制颜色码转换工具www.sioe.cn这个背景颜色的RGB值为196, 222, 82。
模块二:准备好坑和地鼠图片
地鼠出没的坑的图像是这样的:
![ace78d833d660fc8e9aee3a92476612e.png](https://img-blog.csdnimg.cn/img_convert/ace78d833d660fc8e9aee3a92476612e.png)
我们的主角地鼠是这样的:
![01aaa90e663f961ead0a6798b12289fb.png](https://img-blog.csdnimg.cn/img_convert/01aaa90e663f961ead0a6798b12289fb.png)
一旦被锤子击中,就会出现晕眩的画面:
![b547c98a5616a8d3e8d932ac0829d1b2.png](https://img-blog.csdnimg.cn/img_convert/b547c98a5616a8d3e8d932ac0829d1b2.png)
这相当于给了被试一个反馈,地鼠已被击中!
有了背景和坑,就可以预先布置好场景,形成整个游戏的背景。第一段代码,我们要实现的是:布置好游戏的背景画面。
我们试着先用Matlab GUI来实现这个游戏场景的布置,然后再用Matlab+Psychtoolbox做一个镜像,这样对比的好处是可以横向比价两者的利弊。
Matlab GUI的代码:
% function y = guiGame_HitHamster(~)
% clear
clc; clear; close all;
% prepare bkground color
bkgColor = [196, 222, 82]/255;
% get the screen size, for the iMac Pro, it is [1 1 2560 1440]
rect = get(0 , 'ScreenSize');
width_Screen = rect(3);
height_Screen = rect(4);
% prepare
materialFolderName = 'Materials';
pngFileName_Hole = 'Hole.png';
pngPathName_Hole = sprintf('%s/%s', materialFolderName, pngFileName_Hole);
[imgMat_Hole colorMap_Hole alphaData_Hole] = imread(pngPathName_Hole);
% get the row number, column number for the imgMat_Hole
width_imgMat_Hole = size(imgMat_Hole,2);
height_imgMat_Hole = size(imgMat_Hole,1);
% create a figure
% prepare the width and height for the current fig
width_hFigure = 1024;
height_hFigure = 768;
posX_hFigure = (width_Screen - width_hFigure)/2 + 1;
posY_hFigure = (height_Screen - height_hFigure)/2 + 1;
hFigure = figure(1);
set(hFigure, 'position',[posX_hFigure posY_hFigure width_hFigure height_hFigure], 'MenuBar','none'); % .. centerize ..
% create an axes for bkground picture, with bkground color
hAxes_BKGround = axes('parent',hFigure);
set(hAxes_BKGround, 'units','pixels', 'position',[1 1 1024 768], 'color',bkgColor, 'xtick',[], 'ytick',[]);
% create an axes for the hole
% prepare the posX and posY for hAxes_Hole01
posX_hAxes_Hole01 = (width_hFigure - width_imgMat_Hole)/2 + 1;
posY_hAxes_Hole01 = (height_hFigure - height_imgMat_Hole)/2 + 1;
hAxes_Hole01 = axes('parent',hFigure);
set(hAxes_Hole01, 'units','pixels', 'position',[posX_hAxes_Hole01 posY_hAxes_Hole01 width_imgMat_Hole height_imgMat_Hole]);
hImage_Hole01 = imshow(imgMat_Hole,'parent',hAxes_Hole01);
set(hImage_Hole01,'AlphaData',alphaData_Hole);
% assign y
y = 1;
% end
我们来看看效果:
![3d320813dce5a634323e0b69a898c004.png](https://img-blog.csdnimg.cn/img_convert/3d320813dce5a634323e0b69a898c004.png)
模块三:准备好锤子(感谢金果果的友情支持♥️)
锤子也有两种状态,一种是普通状态:
![3aef9ed27fd4a29c51758cde4549718f.png](https://img-blog.csdnimg.cn/img_convert/3aef9ed27fd4a29c51758cde4549718f.png)
还有一种是击打状态:
![166c5a6d482084c91476cdedbd6717c3.png](https://img-blog.csdnimg.cn/img_convert/166c5a6d482084c91476cdedbd6717c3.png)
我们来看看,能不能通过窗口移动函数WindowButtonMotionFcn来实现锤子随着鼠标移动的效果?
function y = guiGame_HitHamster(~)
% clear
% clc; clear; close all;
% state zone
mState_Hammer = 0; % 0 == Off vs. 1 == Hit
% prepare bkground color
bkgColor = [196, 222, 82]/255;
% get the screen size, for the iMac Pro, it is [1 1 2560 1440]
rect = get(0 , 'ScreenSize');
width_Screen = rect(3);
height_Screen = rect(4);
% prepare image Hole + image HammerOff
materialFolderName = 'Materials';
% Hole
pngFileName_Hole = 'Hole.png';
pngPathName_Hole = sprintf('%s/%s', materialFolderName, pngFileName_Hole);
[imgMat_Hole colorMap_Hole alphaData_Hole] = imread(pngPathName_Hole);
% get the row number, column number for the imgMat_Hole
width_imgMat_Hole = size(imgMat_Hole,2);
height_imgMat_Hole = size(imgMat_Hole,1);
% HammerOff
pngFileName_HammerOff = 'HammerOff.png';
pngPathName_HammerOff = sprintf('%s/%s', materialFolderName, pngFileName_HammerOff);
[imgMat_HammerOff colorMap_HammerOff alphaData_HammerOff] = imread(pngPathName_HammerOff);
% get the row number, column number for the imgMat_HammerOff
width_imgMat_HammerOff = size(imgMat_HammerOff,2);
height_imgMat_HammerOff = size(imgMat_HammerOff,1);
% HammerHit
pngFileName_HammerHit = 'HammerHit.png';
pngPathName_HammerHit = sprintf('%s/%s', materialFolderName, pngFileName_HammerHit);
[imgMat_HammerHit colorMap_HammerHit alphaData_HammerHit] = imread(pngPathName_HammerHit);
% get the row number, column number for the imgMat_HammerHit
width_imgMat_HammerHit = size(imgMat_HammerHit,2);
height_imgMat_HammerHit = size(imgMat_HammerHit,1);
% create a figure
% prepare the width and height for the current fig
width_hFigure = 1024;
height_hFigure = 768;
posX_hFigure = (width_Screen - width_hFigure)/2 + 1;
posY_hFigure = (height_Screen - height_hFigure)/2 + 1;
hFigure = figure(1);
set(hFigure, 'position',[posX_hFigure posY_hFigure width_hFigure height_hFigure], 'MenuBar','none'); % .. centerize ..
% create an axes for bkground picture, with bkground color
hAxes_BKGround = axes('parent',hFigure);
set(hAxes_BKGround, 'units','pixels', 'position',[1 1 1024 768], 'color',bkgColor, 'xtick',[], 'ytick',[]);
% create an axes for the hole
% prepare the posX and posY for hAxes_Hole01
posX_hAxes_Hole01 = (width_hFigure - width_imgMat_Hole)/2 + 1;
posY_hAxes_Hole01 = (height_hFigure - height_imgMat_Hole)/2 + 1;
hAxes_Hole01 = axes('parent',hFigure);
set(hAxes_Hole01, 'units','pixels', 'position',[posX_hAxes_Hole01 posY_hAxes_Hole01 width_imgMat_Hole height_imgMat_Hole]);
hImage_Hole01 = imshow(imgMat_Hole,'parent',hAxes_Hole01);
set(hImage_Hole01, 'AlphaData', alphaData_Hole);
% create an axes for HammerOff and HammerHit
posX_hAxes_HammerOff = width_hFigure + 1;
posY_hAxes_HammerOff = height_hFigure + 1;
hAxes_HammerOff = axes('parent',hFigure);
set(hAxes_HammerOff, 'units','pixels', 'position',[posX_hAxes_HammerOff posY_hAxes_HammerOff width_imgMat_HammerOff height_imgMat_HammerOff]);
hImage_HammerOff = imshow(imgMat_HammerOff,'parent',hAxes_HammerOff);
set(hImage_HammerOff, 'AlphaData', alphaData_HammerOff);
% create an axes for HammerOff and HammerHit
posX_hAxes_HammerHit = width_hFigure + 1;
posY_hAxes_HammerHit = height_hFigure + 1;
hAxes_HammerHit = axes('parent',hFigure);
set(hAxes_HammerHit, 'units','pixels', 'position',[posX_hAxes_HammerHit posY_hAxes_HammerHit width_imgMat_HammerHit height_imgMat_HammerHit]);
hImage_HammerHit = imshow(imgMat_HammerHit,'parent',hAxes_HammerHit);
set(hImage_HammerHit, 'AlphaData', alphaData_HammerHit);
% Binding Mechanism
set(hFigure, 'WindowButtonMotionFcn', @hFigure_WindowButtonMotionFcn);
set(hFigure, 'WindowButtonDownFcn',@hFigure_WindowButtonDownFcn);
set(hFigure, 'WindowButtonUpFcn',@hFigure_WindowButtonUpFcn);
% function 1 --> hFigure_WindowButtonMotionFcn
function hFigure_WindowButtonMotionFcn(hObject, eventData, hs)
posMouse = get(hAxes_BKGround,'CurrentPoint') ;%获得句柄
posX_Mouse = round(posMouse(1) * width_hFigure);
posY_Mouse = round(posMouse(3) * height_hFigure);
% let the hammer follow the mouse
if ~mState_Hammer
set(hAxes_HammerHit, 'position',[width_hFigure + 1 height_hFigure + 1 width_imgMat_HammerHit height_imgMat_HammerHit]);
set(hAxes_HammerOff, 'position',[posX_Mouse-80 posY_Mouse-70 width_imgMat_HammerOff height_imgMat_HammerOff]);
else
set(hAxes_HammerOff, 'position',[width_hFigure + 1 height_hFigure + 1 width_imgMat_HammerOff height_imgMat_HammerOff]);
set(hAxes_HammerHit, 'position',[posX_Mouse - 80 posY_Mouse - 70 width_imgMat_HammerHit height_imgMat_HammerHit]);
end
end
% function 2 --> hFigure_WindowButtonDownFcn
function hFigure_WindowButtonDownFcn(hObject, eventData, hs)
posMouse = get(hAxes_BKGround,'CurrentPoint') ;%获得句柄
posX_Mouse = round(posMouse(1) * width_hFigure);
posY_Mouse = round(posMouse(3) * height_hFigure);
set(hAxes_HammerOff, 'position',[width_hFigure + 1 height_hFigure + 1 width_imgMat_HammerOff height_imgMat_HammerOff]);
set(hAxes_HammerHit, 'position',[posX_Mouse - 80 posY_Mouse - 70 width_imgMat_HammerHit height_imgMat_HammerHit]);
% state_Hammer from 0 to 1
mState_Hammer = 1;
end
% function 3 --> hFigure_WindowButtonUpFcn
function hFigure_WindowButtonUpFcn(hObject, eventData, hs)
posMouse = get(hAxes_BKGround,'CurrentPoint') ;%获得句柄
posX_Mouse = round(posMouse(1) * width_hFigure);
posY_Mouse = round(posMouse(3) * height_hFigure);
set(hAxes_HammerHit, 'position',[width_hFigure + 1 height_hFigure + 1 width_imgMat_HammerHit height_imgMat_HammerHit]);
set(hAxes_HammerOff, 'position',[posX_Mouse - 80 posY_Mouse - 70 width_imgMat_HammerOff height_imgMat_HammerOff]);
% state_Hammer from 1 to 0
mState_Hammer = 0;
end
% assign y
y = 1;
end
我们来看一下效果:
![f8770ccf4d3e0bf48f34745ee2ecd706.png](https://img-blog.csdnimg.cn/img_convert/f8770ccf4d3e0bf48f34745ee2ecd706.png)
这个截图是看不到鼠标的,我们需要借助一行代码把鼠标去掉。
set(gcf, 'Pointer', 'custom', 'PointerShapeCData', NaN(16,16));
整个程序的框架就这样搭建好了,有了这个框架之后,我们就可以做一些基本的扩展:
(a)地鼠的坑,从1个扩展成3个;
(b)地鼠出现的次数,从1次扩展为3次;
(c)地鼠出现的位置也是随机的,会均匀分布在3个位置上。
一个标准的心理学实验编程分为四个步骤:
(1)准备指导语和刺激材料;
(2)刺激矩阵生成;
(3)大框架和每个试次的实验流程;
(4)实验文件和文件夹分发。
·首先,因为我们现在这个是demo,所以一切先从一个简单的指导语“Hit the Hammer to Start the Game”开始;
专门制作了一个坐标轴控件 来放置指导语:
% hAxes_Text Start
hAxes_Text = axes('parent',hFigure);
width_hAxes_Text = 400;
height_hAxes_Text = 60;
posX_hAxes_Text = width_hFigure/2-width_hAxes_Text/2;
posY_hAxes_Text = height_hFigure/2-height_hAxes_Text/2-200;
set(hAxes_Text, 'units','pixels', 'position',[posX_hAxes_Text posY_hAxes_Text width_hAxes_Text height_hAxes_Text]);
set(hAxes_Text, 'color',bkgColor, 'xtick',[], 'ytick',[], 'xcolor',bkgColor, 'ycolor',bkgColor);
axis([1 width_hAxes_Text 1 height_hAxes_Text]);
text(width_hAxes_Text/2,height_hAxes_Text/2,'Hit the Hammer to Start the Game', 'HorizontalAlign','center', 'color','k', 'fontsize',24);
在坐标轴上用text就可以写指导语,这里是通过点击让指导语消失+开启Game的。点击的机制后边我们会介绍,这里有一个技巧,就是点击让指导语消失的方法,我们用的是把坐标轴移到窗口之外,通过下面这句代码:
set(hAxes_Text, 'position',[width_hFigure+1 height_hFigure+1 width_hAxes_Text height_hAxes_Text]);
我们之所以设定trialIndex = 0,就是希望在点击的时候,有一个判断 if trialIndex == 0这段代码就是专门为指导语准备的;等trialIndex = trialIndex + 1之后,就正式进入到trial实验试次阶段;每次还会判断trialIndex的上限, if trialIndex < trialNum,如果是符合的就按照正常流程走,如果不符合,说明程序到头了,请出结束指导语坐标轴。
·其次,刺激矩阵,我们本来是要写一个函数来完成的,现在先虚拟一个只有两列信息的刺激矩阵:
trialID_Array = [1;2;3];
pos_Array = [2;1;3]; % rand virtually
cjMatrix = [trialID_Array pos_Array]; % get cjMatrix virtually
·再次,实验的大框架是:实验指导语 + trial的循环 + 结束语;trial的循环并不是按照传统的for循环,或者while循环来实现trialIndex递进的,这部分需要专门解释一下:
Matlab GUI,本身是事件驱动的,因此每次的点击相当于一个触发事件,我们用的恰恰就是这个事件来实现trialIndex的递增。
一开始
% trialNum
trialIndex = 0;
trialNum = 3;
这里的trialIdnex设定为0代表的是指导语,而trialNum设定trial总数是3个。
在整个程序中是会绑定hFigure和windowbuttondownfcn函数:
% Binding Mechanism
set(hFigure, 'WindowButtonDownFcn',@hFigure_WindowButtonDownFcn);
这样就可以在hFigure_WindowButtonDownFcn函数中实现每次点击鼠标trialIndex = trialIndex + 1;
·没有最后,因为第4步暂时还不需要做 下面把代码晒出来:
function y = guiGame_HitHamster(~)
% clear
% clc; clear; close all;
% column
trialID_Column = 1;
pos_Column = 2;
% trialNum
trialIndex = 0;
trialNum = 3;
trialID_Array = [1;2;3];
pos_Array = [2;1;3]; % rand virtually
cjMatrix = [trialID_Array pos_Array]; % get cjMatrix virtually
% state zone
mState_Hammer = 0; % 0 == Off vs. 1 == Hit
% prepare bkground color
bkgColor = [196, 222, 82]/255;
% get the screen size, for the iMac Pro, it is [1 1 2560 1440]
rect = get(0 , 'ScreenSize');
width_Screen = rect(3);
height_Screen = rect(4);
% prepare image Hole + image HammerOff
materialFolderName = 'Materials';
% Hole
pngFileName_Hole = 'Hole.png';
pngPathName_Hole = sprintf('%s/%s', materialFolderName, pngFileName_Hole);
[imgMat_Hole colorMap_Hole alphaData_Hole] = imread(pngPathName_Hole);
% get the row number, column number for the imgMat_Hole
width_imgMat_Hole = size(imgMat_Hole,2);
height_imgMat_Hole = size(imgMat_Hole,1);
% HamsterOK
pngFileName_HamsterOK = 'HamsterOK.png';
pngPathName_HamsterOK = sprintf('%s/%s', materialFolderName, pngFileName_HamsterOK);
[imgMat_HamsterOK colorMap_HamsterOK alphaData_HamsterOK] = imread(pngPathName_HamsterOK);
% get the row number, column number for the HamsterOK
width_imgMat_HamsterOK = size(imgMat_HamsterOK,2);
height_imgMat_HamsterOK = size(imgMat_HamsterOK,1);
% HamsterDizzy
pngFileName_HamsterDizzy = 'HamsterDizzy.png';
pngPathName_HamsterDizzy = sprintf('%s/%s', materialFolderName, pngFileName_HamsterDizzy);
[imgMat_HamsterDizzy colorMap_HamsterDizzy alphaData_HamsterDizzy] = imread(pngPathName_HamsterDizzy);
% get the row number, column number for the HamsterOK
width_imgMat_HamsterDizzy = size(imgMat_HamsterDizzy,2);
height_imgMat_HamsterDizzy = size(imgMat_HamsterDizzy,1);
% HammerOff
pngFileName_HammerOff = 'HammerOff.png';
pngPathName_HammerOff = sprintf('%s/%s', materialFolderName, pngFileName_HammerOff);
[imgMat_HammerOff colorMap_HammerOff alphaData_HammerOff] = imread(pngPathName_HammerOff);
% get the row number, column number for the imgMat_HammerOff
width_imgMat_HammerOff = size(imgMat_HammerOff,2);
height_imgMat_HammerOff = size(imgMat_HammerOff,1);
% HammerHit
pngFileName_HammerHit = 'HammerHit.png';
pngPathName_HammerHit = sprintf('%s/%s', materialFolderName, pngFileName_HammerHit);
[imgMat_HammerHit colorMap_HammerHit alphaData_HammerHit] = imread(pngPathName_HammerHit);
% get the row number, column number for the imgMat_HammerHit
width_imgMat_HammerHit = size(imgMat_HammerHit,2);
height_imgMat_HammerHit = size(imgMat_HammerHit,1);
% create a figure
% prepare the width and height for the current fig
width_hFigure = 1024;
height_hFigure = 768;
posX_hFigure = (width_Screen - width_hFigure)/2 + 1;
posY_hFigure = (height_Screen - height_hFigure)/2 + 1;
hFigure = figure(1);
set(hFigure, 'position',[posX_hFigure posY_hFigure width_hFigure height_hFigure]);
set(hFigure, 'MenuBar','none', 'numbertitle','off', 'toolbar','none', 'name', 'Psychology Game: Hit Hamster'); %
% Hide the pointer cursor
% set(gcf, 'Pointer', 'custom', 'PointerShapeCData', NaN(16,16));
% create an axes for bkground picture, with bkground color
hAxes_BKGround = axes('parent',hFigure);
set(hAxes_BKGround, 'units','pixels', 'position',[1 1 1024 768], 'color',bkgColor, 'xtick',[], 'ytick',[]);
% hAxes_Text Start
hAxes_Text = axes('parent',hFigure);
width_hAxes_Text = 400;
height_hAxes_Text = 60;
posX_hAxes_Text = width_hFigure/2-width_hAxes_Text/2;
posY_hAxes_Text = height_hFigure/2-height_hAxes_Text/2-200;
set(hAxes_Text, 'units','pixels', 'position',[posX_hAxes_Text posY_hAxes_Text width_hAxes_Text height_hAxes_Text]);
set(hAxes_Text, 'color',bkgColor, 'xtick',[], 'ytick',[], 'xcolor',bkgColor, 'ycolor',bkgColor);
axis([1 width_hAxes_Text 1 height_hAxes_Text]);
text(width_hAxes_Text/2,height_hAxes_Text/2,'Hit the Hammer to Start the Game', 'HorizontalAlign','center', 'color','k', 'fontsize',24);
% hAxes_Text Start
hAxes_Text_Bye = axes('parent',hFigure);
width_hAxes_Text_Bye = 400;
height_hAxes_Text_Bye = 60;
% posX_hAxes_Text_Bye = width_hFigure/2-width_hAxes_Text_Bye/2;
posX_hAxes_Text_Bye = width_hFigure + 1;
% posY_hAxes_Text_Bye = height_hFigure/2-height_hAxes_Text_Bye/2-200;
posY_hAxes_Text_Bye = height_hFigure + 1;
set(hAxes_Text_Bye, 'units','pixels', 'position',[posX_hAxes_Text_Bye posY_hAxes_Text_Bye width_hAxes_Text_Bye height_hAxes_Text_Bye]);
set(hAxes_Text_Bye, 'color',bkgColor, 'xtick',[], 'ytick',[], 'xcolor',bkgColor, 'ycolor',bkgColor);
axis([1 width_hAxes_Text_Bye 1 height_hAxes_Text_Bye]);
text(width_hAxes_Text_Bye/2,height_hAxes_Text_Bye/2,'Good Job!', 'HorizontalAlign','center', 'color','k', 'fontsize',24);
% draw the BKGround Holes first
horizontal_Interval = 50;
vertical_Interval = 50;
% create an axes for the hole01
% prepare the posX and posY for hAxes_Hole01
posX_hAxes_Hole01 = (width_hFigure - width_imgMat_Hole)/2 + 1 - horizontal_Interval - width_imgMat_Hole;
posY_hAxes_Hole01 = (height_hFigure - height_imgMat_Hole)/2 + 1;
%
hAxes_Hole01 = axes('parent',hFigure);
set(hAxes_Hole01, 'units','pixels', 'position',[posX_hAxes_Hole01 posY_hAxes_Hole01 width_imgMat_Hole height_imgMat_Hole]);
hImage_Hole01 = imshow(imgMat_Hole,'parent',hAxes_Hole01);
set(hImage_Hole01, 'AlphaData', alphaData_Hole);
% create an axes for the hole02
% prepare the posX and posY for hAxes_Hole02
posX_hAxes_Hole02 = (width_hFigure - width_imgMat_Hole)/2 + 1;
posY_hAxes_Hole02 = (height_hFigure - height_imgMat_Hole)/2 + 1;
%
hAxes_Hole02 = axes('parent',hFigure);
set(hAxes_Hole02, 'units','pixels', 'position',[posX_hAxes_Hole02 posY_hAxes_Hole02 width_imgMat_Hole height_imgMat_Hole]);
hImage_Hole02 = imshow(imgMat_Hole,'parent',hAxes_Hole02);
set(hImage_Hole02, 'AlphaData', alphaData_Hole);
% create an axes for the hole03
% prepare the posX and posY for hAxes_Hole03
posX_hAxes_Hole03 = (width_hFigure - width_imgMat_Hole)/2 + 1 + horizontal_Interval + width_imgMat_Hole;
posY_hAxes_Hole03 = (height_hFigure - height_imgMat_Hole)/2 + 1;
%
hAxes_Hole03 = axes('parent',hFigure);
set(hAxes_Hole03, 'units','pixels', 'position',[posX_hAxes_Hole03 posY_hAxes_Hole03 width_imgMat_Hole height_imgMat_Hole]);
hImage_Hole03 = imshow(imgMat_Hole,'parent',hAxes_Hole03);
set(hImage_Hole03, 'AlphaData', alphaData_Hole);
% summarize the posInfos for all these holes
pos_Hole01 = [posX_hAxes_Hole01 posY_hAxes_Hole01 width_imgMat_Hole height_imgMat_Hole];
pos_Hole02 = [posX_hAxes_Hole02 posY_hAxes_Hole02 width_imgMat_Hole height_imgMat_Hole];
pos_Hole03 = [posX_hAxes_Hole03 posY_hAxes_Hole03 width_imgMat_Hole height_imgMat_Hole];
pos_Holes_Cells = {pos_Hole01; pos_Hole02; pos_Hole03};
% create an axes for the hamsterOK
posX_hAxes_HamsterOK = posX_hAxes_Hole01;
posY_hAxes_HamsterOK = posY_hAxes_Hole01;
hAxes_HamsterOK = axes('parent',hFigure);
set(hAxes_HamsterOK, 'units','pixels', 'position',[posX_hAxes_HamsterOK posY_hAxes_HamsterOK width_imgMat_HamsterOK height_imgMat_HamsterOK]);
hImage_HamsterOK = imshow(imgMat_HamsterOK,'parent',hAxes_HamsterOK);
set(hImage_HamsterOK, 'AlphaData', alphaData_HamsterOK);
set(hAxes_HamsterOK, 'position',[width_hFigure+1 height_hFigure+1 width_imgMat_HamsterOK height_imgMat_HamsterOK]);
% create an axes for the hamsterDizzy
posX_hAxes_HamsterDizzy = posX_hAxes_Hole01;
posY_hAxes_HamsterDizzy = posY_hAxes_Hole01;
hAxes_HamsterDizzy = axes('parent',hFigure);
set(hAxes_HamsterDizzy, 'units','pixels', 'position',[posX_hAxes_HamsterDizzy posY_hAxes_HamsterDizzy width_imgMat_HamsterDizzy height_imgMat_HamsterDizzy]);
hImage_HamsterDizzy = imshow(imgMat_HamsterDizzy,'parent',hAxes_HamsterDizzy);
set(hImage_HamsterDizzy, 'AlphaData', alphaData_HamsterDizzy);
set(hAxes_HamsterDizzy, 'position',[width_hFigure+1 height_hFigure+1 width_imgMat_HamsterDizzy height_imgMat_HamsterDizzy]);
% create an axes for HammerOff and HammerHit
posX_hAxes_HammerOff = width_hFigure + 1;
posY_hAxes_HammerOff = height_hFigure + 1;
hAxes_HammerOff = axes('parent',hFigure);
set(hAxes_HammerOff, 'units','pixels', 'position',[posX_hAxes_HammerOff posY_hAxes_HammerOff width_imgMat_HammerOff height_imgMat_HammerOff]);
hImage_HammerOff = imshow(imgMat_HammerOff,'parent',hAxes_HammerOff);
set(hImage_HammerOff, 'AlphaData', alphaData_HammerOff);
% create an axes for HammerOff and HammerHit
posX_hAxes_HammerHit = width_hFigure + 1;
posY_hAxes_HammerHit = height_hFigure + 1;
hAxes_HammerHit = axes('parent',hFigure);
set(hAxes_HammerHit, 'units','pixels', 'position',[posX_hAxes_HammerHit posY_hAxes_HammerHit width_imgMat_HammerHit height_imgMat_HammerHit]);
hImage_HammerHit = imshow(imgMat_HammerHit,'parent',hAxes_HammerHit);
set(hImage_HammerHit, 'AlphaData', alphaData_HammerHit);
% Binding Mechanism
set(hFigure, 'WindowButtonMotionFcn', @hFigure_WindowButtonMotionFcn);
set(hFigure, 'WindowButtonDownFcn',@hFigure_WindowButtonDownFcn);
set(hFigure, 'WindowButtonUpFcn',@hFigure_WindowButtonUpFcn);
% function 1 --> hFigure_WindowButtonMotionFcn
function hFigure_WindowButtonMotionFcn(hObject, eventData, hs)
posMouse = get(hAxes_BKGround,'CurrentPoint') ;%»ñµÃ¾ä±ú
posX_Mouse = round(posMouse(1) * width_hFigure);
posY_Mouse = round(posMouse(3) * height_hFigure);
% let the hammer follow the mouse
if ~mState_Hammer
set(hAxes_HammerHit, 'position',[width_hFigure + 1 height_hFigure + 1 width_imgMat_HammerHit height_imgMat_HammerHit]);
set(hAxes_HammerOff, 'position',[posX_Mouse-80 posY_Mouse-70 width_imgMat_HammerOff height_imgMat_HammerOff]);
else
set(hAxes_HammerOff, 'position',[width_hFigure + 1 height_hFigure + 1 width_imgMat_HammerOff height_imgMat_HammerOff]);
set(hAxes_HammerHit, 'position',[posX_Mouse - 80 posY_Mouse - 70 width_imgMat_HammerHit height_imgMat_HammerHit]);
end
end
% function 2 --> hFigure_WindowButtonDownFcn
function hFigure_WindowButtonDownFcn(hObject, eventData, hs)
posMouse = get(hAxes_BKGround,'CurrentPoint') ;%»ñµÃ¾ä±ú
posX_Mouse = round(posMouse(1) * width_hFigure);
posY_Mouse = round(posMouse(3) * height_hFigure);
set(hAxes_HammerOff, 'position',[width_hFigure + 1 height_hFigure + 1 width_imgMat_HammerOff height_imgMat_HammerOff]);
set(hAxes_HammerHit, 'position',[posX_Mouse - 80 posY_Mouse - 70 width_imgMat_HammerHit height_imgMat_HammerHit]);
% state_Hammer from 0 to 1
mState_Hammer = 1;
%
if trialIndex == 0
% let the Start Game instruction disappear
set(hAxes_Text, 'position',[width_hFigure+1 height_hFigure+1 width_hAxes_Text height_hAxes_Text]);
pause(0.5);
trialIndex = trialIndex + 1;
% get the pos info. from the cjMatrix
thisPosID = cjMatrix(trialIndex, pos_Column);
thisPosInfo = pos_Holes_Cells{thisPosID};
% show the HamsterOK
set(hAxes_HamsterOK, 'position',thisPosInfo);
else
% get the pos info. from the cjMatrix .. again, not change ..
thisPosID = cjMatrix(trialIndex, pos_Column);
thisPosInfo = pos_Holes_Cells{thisPosID};
inField_hAxes_Hole01 = posX_Mouse > posX_hAxes_Hole01 & posX_Mouse < posX_hAxes_Hole01 + width_imgMat_HamsterOK & posY_Mouse > posY_hAxes_Hole01 & posY_Mouse < posY_hAxes_Hole01 + height_imgMat_HamsterOK;
inField_hAxes_Hole02 = posX_Mouse > posX_hAxes_Hole02 & posX_Mouse < posX_hAxes_Hole02 + width_imgMat_HamsterOK & posY_Mouse > posY_hAxes_Hole02 & posY_Mouse < posY_hAxes_Hole02 + height_imgMat_HamsterOK;
inField_hAxes_Hole03 = posX_Mouse > posX_hAxes_Hole03 & posX_Mouse < posX_hAxes_Hole03 + width_imgMat_HamsterOK & posY_Mouse > posY_hAxes_Hole03 & posY_Mouse < posY_hAxes_Hole03 + height_imgMat_HamsterOK;
inFields_hAxes_Holes_Cells = {inField_hAxes_Hole01; inField_hAxes_Hole02; inField_hAxes_Hole03};
this_inField = inFields_hAxes_Holes_Cells{thisPosID};
if this_inField % hit
set(hAxes_HamsterOK, 'position',[width_hFigure+1 height_hFigure+1 width_imgMat_HamsterOK height_imgMat_HamsterOK]);
set(hAxes_HamsterDizzy, 'position',thisPosInfo);
pause(0.5);
set(hAxes_HamsterDizzy, 'position',[width_hFigure+1 height_hFigure+1 width_imgMat_HamsterOK height_imgMat_HamsterOK]);
if trialIndex < trialNum
% turn to the next trial
trialIndex = trialIndex + 1;
% get the pos info. from the cjMatrix
thisPosID = cjMatrix(trialIndex, pos_Column);
thisPosInfo = pos_Holes_Cells{thisPosID};
% show the HamsterOK
set(hAxes_HamsterOK, 'position',thisPosInfo);
else
% show the bye bye
posX_hAxes_Text_Bye = width_hFigure/2-width_hAxes_Text_Bye/2;
% posX_hAxes_Text_Bye = width_hFigure + 1;
posY_hAxes_Text_Bye = height_hFigure/2-height_hAxes_Text_Bye/2-200;
% posY_hAxes_Text_Bye = height_hFigure + 1;
set(hAxes_Text_Bye, 'units','pixels', 'position',[posX_hAxes_Text_Bye posY_hAxes_Text_Bye width_hAxes_Text_Bye height_hAxes_Text_Bye]);
end
else % not hit
end
end
end
% function 3 --> hFigure_WindowButtonUpFcn
function hFigure_WindowButtonUpFcn(hObject, eventData, hs)
posMouse = get(hAxes_BKGround,'CurrentPoint') ;%»ñµÃ¾ä±ú
posX_Mouse = round(posMouse(1) * width_hFigure);
posY_Mouse = round(posMouse(3) * height_hFigure);
set(hAxes_HammerHit, 'position',[width_hFigure + 1 height_hFigure + 1 width_imgMat_HammerHit height_imgMat_HammerHit]);
set(hAxes_HammerOff, 'position',[posX_Mouse - 80 posY_Mouse - 70 width_imgMat_HammerOff height_imgMat_HammerOff]);
% state_Hammer from 1 to 0
mState_Hammer = 0;
end
% assign y
y = 1;
end