怎么用psychotoolbox写一个贪吃蛇?

贪吃蛇是一个非常经典简单的游戏

小蛇 > 吃东西 > 变大蛇

那怎么变成计算机语言呢?

首先我们来理理这个逻辑

  1. 只要咱们的小蛇不撞死或者撑死,游戏就一直进行
  2. 这是一条非常好动的蛇,不死不歇
  3. 这条蛇非常听玩家的话,指哪儿去哪儿
  4. 真天上掉馅饼,随机落下食物
  5. 吃掉食物,丑小蛇变大蟒蛇

再转化一下,主要三个模块

  • 移动 > 曲线坐标的变化
  • 食物 > 随机点坐标
  • 吃 > 点坐标与曲线头部坐标重叠,曲线尾部坐标改变

然后我们来理一理这个过程

1
2
3
4
5
6
循环
随机食物
蛇身向前移动
if 方向指令 则 改变方向
if 蛇头坐标=食物左边 则 蛇尾坐标改变
更新界面

基本的框架有了,最好再加上碰撞判定,让小蛇随时能够结束劳碌的一生。

然后转换成psychtoolbox的代码(可直接复制粘贴到matlab编辑器中,当然得先安装psychtoolbox3)

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
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
%matlab psychtoolbox3
function TBX_snake
AssertOpenGL;

% Get the list of screens and choose the one with the highest screen number.
% Screen 0 is, by definition, the display with the menu bar. Often when
% two monitors are connected the one without the menu bar is used as
% the stimulus display. Chosing the display with the highest dislay number is
% a best guess about where you want the stimulus displayed.
screens=Screen('Screens');
screenNumber=max(screens);

% Find the color values which correspond to white and black: Usually
% black is always 0 and white 255, but this rule is not true if one of
% the high precision framebuffer modes is enabled via the
% PsychImaging() commmand, so we query the true values via the
% functions WhiteIndex and BlackIndex:
white=WhiteIndex(screenNumber);
black=BlackIndex(screenNumber);

% Round gray to integral number, to avoid roundoff artifacts with some
% graphics cards:
gray=round((white+black)/2);
ScreenRct = [100 100 700 700];
M = zeros( ScreenRct(3) - ScreenRct(1) ,ScreenRct(4) - ScreenRct(2) );
S = size(M,1) ;
% This makes sure that on floating point framebuffers we still get a
% well defined gray. It isn't strictly neccessary in this demo:
if gray == white
gray=white / 2;
end
KbName('UnifyKeyNames');
escapeKey = KbName('ESCAPE');
% Contrast 'inc'rement range for given white and gray values:
inc=white-gray;

% Open a double buffered fullscreen window and select a gray background
% color:

% Use realtime priority for better timing precision:

w=Screen('OpenWindow',screenNumber, gray , ScreenRct);
priorityLevel=MaxPriority(w);
Priority(priorityLevel);

Stage = zeros(50);
Snak.loc = size(Stage)/2 ;
Snak.direct= 'l';
Snak.predirect = Snak.direct;
Snak.lenth = 5;

Snak.body = [[Snak.loc(1):Snak.loc(1)+Snak.lenth]' repmat( Snak.loc(2), Snak.lenth+1 ,1) ];
Snak.food = [];%randperm(length(Stage),1);
Snak.crash = false;
while true
% for i=1:movieDurationFrames
% M(randperm(N,100))=255;

[Stage, Snak] = snak_food(Stage, Snak);
[Stage, Snak ]=updateSnake(Stage, Snak );
if Snak.crash

break
end
M = magnify( Stage ,S);

% T = Screen('MakeTexture', w, M );
% Screen('DrawTexture', w, T);
Screen('Putimage',w,M)

[secs, keyCode, deltaSecs] = KbWait([], [],GetSecs+0.08);
% [ keyIsDown, ~, keyCode ] = KbCheck;
keyCode = find(keyCode, 1); % 37:40

if ~isempty(keyCode)
if keyCode == escapeKey
disp escape!
break;
else
switch keyCode
case 37
Snak.direct= 'l';
case 38
Snak.direct= 'u';
case 39
Snak.direct= 'r';
case 40
Snak.direct= 'd';
end
end
end

Screen('Flip', w ,[],1);

end



if ~Snak.crash
sca;
else
msgbox 'crashed!'
end
Priority(0);


end

function [Stage, Snak] = snak_food(Stage, Snak)

if ~isempty(Snak.food)
return
end
freeStage = Stage==0;
idx = randperm(sum(freeStage,'all'),1) ;
[x,y] = find(freeStage) ;

Stage(x(idx) , y(idx)) = 0.5;

Snak.food = [x(idx) , y(idx)];

% Snak.food = [x(idx),y(idx)];


end

function [Stage, Snak ]=updateSnake(Stage, Snak )
% Snak.loc = [0 0 ] ;
% Snak.direct= 'l';
loc = Snak.loc;


fprintf('pre=%s ; now=%s \n',Snak.predirect,Snak.direct);

linearIndold = sub2ind([size(Stage)], Snak.body(:,1) ,Snak.body(:,2) );
d={'u' 'd';'l' 'r'};

nd = intersect( [{Snak.direct} {Snak.predirect}] , d(1,:)) ;
if length(nd)>1
Snak.direct = Snak.predirect ;
end
nd = intersect( [{Snak.direct} {Snak.predirect}] , d(2,:)) ;
if length(nd)>1
Snak.direct = Snak.predirect ;
end
Snak.predirect = Snak.direct ;

switch Snak.direct
case 'u'
loc(1) = loc(1)-1;
case 'd'
loc(1) = loc(1)+1;
case 'l'
loc(2) = loc(2)-1;
case 'r'
loc(2) = loc(2)+1;
end


Snak.body = [loc ; Snak.body ] ;

Snak.loc = loc ;
if ~isequal(Snak.loc, Snak.food)
Snak.body(end,:) = [] ;
try
if Stage(loc(1),loc(2))==1
Snak.crash = true;
end
catch
Snak.crash = true;
end

else

Snak.food=[];

end


if Snak.crash
return
end

linearInd = sub2ind([size(Stage)], Snak.body(:,1) ,Snak.body(:,2) );

Stage(linearIndold) = 0;
Stage(linearInd) = 1;


end

function M = magnify( Stage, S )
N = floor( S/size(Stage,1));


M = resizem(Stage,N);


M = M*255;

% color
M = repmat(M,1,1,3);
M(:,:,3) = ones(size(M,1));


end

下一次,我们带来eprime版本的贪吃蛇

怎么用psychotoolbox写一个贪吃蛇?

https://neurospider.cn/post/54493/

Author

SuperSpider

Posted on

2021-06-16

Updated on

2022-05-04

Licensed under