(1)将原单线程结构改为多线程:
考虑到客户端在接收数据时可能发生拥堵而产生卡顿的情况,将游戏部分分为两个线程,其中游戏显示部分作为主线程,而数据接收及游戏控制部分作为子线程。多线程实现如下:
#include
#include
//...
int main()
{
//...
thread Eyemessage(Message);//注册子线程Eyemessage,回调函数为Message()
}
//...
void Message()
{
//...
}
(2)实现客户端,接收信息
要想获得瞳孔的位置信息,必须与服务器端建立连接,并对接收到的信息进行解码。考虑到服务器端我们的编码形式是x坐标和y坐标共4位数字的ASCII码,因此只需将1、2位和3、4位分离再组合成各2位数字的位置信息即可。实现如下:
int main()
{
//...
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(2, 2);
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0) {
return -1;
}
sockClient = socket(AF_INET, SOCK_STREAM, 0);
SOCKADDR_IN addrSrv;
addrSrv.sin_addr.s_addr = inet_addr("127.0.0.1");
addrSrv.sin_family = AF_INET;
addrSrv.sin_port = htons(8888);
connect(sockClient, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));
//...
}
数据解码部分如下:
void get_pythonmess(int& x, int& y)
{
char recvBuf[21] = { 0 };//输入缓冲区
int count = 0;
x = 0;
y = 0;
while(1)
{
recv(sockClient, recvBuf, 20, 0);
if (recvBuf[count * 4] != 0)
{
if ((recvBuf[count * 4] == '0' && recvBuf[count * 4 + 1] == '0'))
{
continue;
}
else
{
x += (recvBuf[count * 4] - '0') * 10 + recvBuf[count * 4 + 1] - '0';
y += (recvBuf[count * 4 + 2] - '0') * 10 + recvBuf[count * 4 + 3] - '0';
count++;
if (count == 5) break;
}
}
}
x = (int)(1.0*(x + 0.5)/5) ;
y = (int)(1.0*(y + 0.5)/5);//均值滤波
}
(3)游戏开始前进行瞳孔参考中心位置进行标定
为了利用瞳孔位置进行玩家飞机的运动控制,需要找到参考点,在这里我采用的是,先进行瞳孔位置标定直到收敛到位置变化较小时,以该点作为参考点,之后的瞳孔位置与该点作差并结合一定的滤波处理输出控制信号Drrorx和Drrory。具体实现如下:
子线程回调函数Message():
void Message()
{
int x = 0; int y = 0;
int x_pre = 30; int y_pre = 20;
//参考中心获取
cout<
getch();
while (1)
{
get_pythonmess(x, y);
if ((x - x_pre) * (x - x_pre) + (y - y_pre) * (y - y_pre) < 10)
{
CenterX = x;
CenterY = y;
break;
}
else if(x*y != 0)
{
x_pre = x;
y_pre = y;
}
}
//CenterX = 12;
//CenterY = 7;
int prex = CenterX;
int prey = CenterY;
while (1)
{
get_pythonmess(x, y);
//根据不同输入进行玩家飞机的移动
Drrorx = x - CenterX;
if (x - prex < 0 && Drrorx == 0) Drrorx = -1;
else if (x - prex > 0 && Drrorx == 0) Drrorx = 1;
Drrory = y - CenterY;
if (y - prey < 0 && Drrory == 0) Drrory = -1;
else if (y - prey > 0 && Drrory == 0) Drrory = 1;
}
}
飞机控制保留原来的键盘输入控制,增加以Drrorx及Drrory为控制量的控制部分:
if (Drrorx < -e)
{
player.point.y -= PlayerSpeed;// +abs(Drror);
player.point.y = Limit_num(0, player.point.y, WindowW - 1 - PlayerBlock);
}
else if (Drrorx > e)
{
player.point.y += PlayerSpeed;// +abs(Drror);
player.point.y = Limit_num(0, player.point.y, WindowW - 1 - PlayerBlock);
}
if (Drrory < -e)
{
player.point.x -= PlayerSpeed;// +abs(Drror);
player.point.x = Limit_num(WindowH / 2, player.point.x, 7 * WindowH / 8 - 1 - PlayerBlock);
}
else if (Drrory > e)
{
player.point.x += PlayerSpeed;// +abs(Drror);
player.point.x = Limit_num(WindowH / 2, player.point.x, 7 * WindowH / 8 - 1 - PlayerBlock);
}