glut编程例子 linux,glut键盘鼠标响应 - OpenGL编程学习实战教程_Linux编程_Linux公社-Linux系统门户网站...

对于一个游戏来说,能够和玩家进行交互是很重要的。通过键盘、鼠标和手柄,游戏

程序接受玩家的各项指令,从而做出反应。在控制台程序中,我们可以使用kbhit()函数来判断玩家是否有输入,如果有,再调用getch函数就可以接受到玩家的输入信息。

如:

if (kbhit() != 0)                                      //按下一个键

{

c=getch();

ProcessInput(c);

}

else

{

GameRun();

}

glut也同样给我们提供了处理键盘鼠标事件的方法,是通过注册回调函数来实现的。

下面就介绍一下这些函数。

1. void glutKeyboardFunc(void(*func)(unsigned char key,int x,int y));

这个函数可以用来处理键盘上可以用ascii码表示的键按下的事件,key就是这个键ascii码,x和y则是键摁下时鼠标相对于窗口左上角的位置。

具体用法:

在main函数里,调用glutKeyboardFunc(&ProcessKeyboard),这样就注册了一个函数ProcessKeyboard。

再完成函数体:

这样,编译运行程序后,按下p键,就能够实时截图了!

2. void glutSpecialFunc(void (*func)(int key,int x,int y));

这个函数是用来处理一些特殊键(如:F1,F2,etc)摁下的事件。参数key是这个键编号,在glut.h中预定义了这些常量:

#define GLUT_KEY_F1          1

#define GLUT_KEY_F2          2

#define GLUT_KEY_F3          3...

还有很多,大家可以自己打开glut.h找到自己需要的。

同样,x和y也是当前鼠标的位置。

具体实现:

main函数里,glutSpecialFunc(&ProcessSpecialKeyboead);

void ProcessSpecialKeyboead(int key, int x, int y)

{

if (key == GLUT_KEY_F1)

{

SnapScreen(400,400,"data/screen.bmp");

}

if (key == GLUT_KEY_F2)

{

exit(0);

}

}

当摁下F1键,可以截图;摁下F2键,就会关闭程序。

3.  void glutMouseFunc(void(*func)(int button,int state,int x,int y));

这个函数用来处理鼠标左右键和中键摁下的事件。

其中button保存的是摁下的鼠标键的键位信息。

在glut.h中,有定义:

#define GLUT_LEFT_BUTTON    0

#define GLUT_MIDDLE_BUTTON  1

#define GLUT_RIGHT_BUTTON    2

参数state表示这个事件发生是这个键是摁下还是松开。

#define GLUT_DOWN        0

#define GLUT_UP          1

参数x和y则表示当前鼠标的位置。

具体实现:

main函数里,glutMouseFunc(&ProcessMouse);

void ProcessMouse(int button,int state,int x,int y)

{

if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)

{

SnapScreen(x,WinHeight-y,"data/screen.bmp");

//把glut坐标转化成OpenGL内的坐标

//因为得到的x,y是相对于屏幕左上角的坐标,

//而SnapScreen函数内的glReadPixels函数处理的是按屏幕左下角为原点的//坐标系的坐标,所以这里需要转化一下。

}

}

4.  void glutMotionFunc(void(*func)(int x,int y));

这个函数是处理当鼠标键摁下时,鼠标拖动的事件。当鼠标拖动时,将每一帧都调用一次这个函数。

5.  void glutPassiveMotionFunc(void (*func)(int x,int y));

这个函数是处理当没有鼠标键摁下时,鼠标拖动的事件。当鼠标拖动时,将每一帧都调用一次这个函数。同上面的差不多。

6.  void glutEntryFunc(void(*func)(int state));

这个函数则是处理鼠标离开和进入窗口的事件。参数state的值在glut.h中有定义:

#define GLUT_LEFT        0

#define GLUT_ENTERED      1

好,那么在介绍了这些函数后,大家应该可以使用glut来制作一些游戏了,如连连看,俄罗斯方块等。

附本节全部代码:

#include

#include

#include

#include

#include

#include

#include

#include

#define PI 3.1415926

#define BITMAP_ID 0x4D42

using std::vector;

int WinWidth,WinHeight;

int LoadBitmap(const char *file)

{

unsigned int ID;      //纹理的id

int width,height;

byte *image;          //接受图像数据

FILE *fp;            //文件指针

BITMAPFILEHEADER FileHeader;    //接受位图文件头

BITMAPINFOHEADER InfoHeader;    //接受位图信息头

fp=fopen(file,"rb");

if (fp == NULL)

{

printf("Exception: Fail to open file!\n");

return -1;

}

fread(&FileHeader, sizeof(BITMAPFILEHEADER), 1, fp);

if(FileHeader.bfType != BITMAP_ID)  //确保文件是一个位图文件,效验文件类型

{

printf("Exception: This file is not a bmp file!\n");

fclose(fp);

return -1;

}

fread(&InfoHeader, sizeof(BITMAPINFOHEADER), 1, fp);

width=InfoHeader.biWidth;

height=InfoHeader.biHeight;

InfoHeader.biSizeImage = width*height*3;

fseek(fp, FileHeader.bfOffBits, SEEK_SET);  //将文件指针移动到实际图像数据处

image=(byte *)malloc(sizeof(byte)*InfoHeader.biSizeImage); //申请空间

if (image == NULL)

{

free(image);

printf("Exception: No enough space!\n");

return -1;

}

fread(image, 1, InfoHeader.biSizeImage, fp);

fclose(fp);

glGenTextures(1, &ID);

glBindTexture(GL_TEXTURE_2D, ID);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);

gluBuild2DMipmaps(GL_TEXTURE_2D, 3, width,

height, GL_BGR_EXT, GL_UNSIGNED_BYTE,

image);

return ID;

}

vector V_ID;          //用来保存生成的纹理id

int now,cnt;                        //now是当前所使用的纹理在vector中的下标

//cnt是用来计时的变量

bool SnapScreen(int width,int height,const char *file)

{

byte *image;          //接受图像数据

FILE *fp;            //文件指针

BITMAPFILEHEADER FileHeader;    //接受位图文件头

BITMAPINFOHEADER InfoHeader;    //接受位图信息头

FileHeader.bfType=BITMAP_ID;                                                  //ID设置为位图的id号

FileHeader.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);      //实际图像数据的位置在文件头和信息头之后

FileHeader.bfReserved1=0;                                                    //必须设置为0

FileHeader.bfReserved2=0;                                                    //必须设置为0

FileHeader.bfSize=height*width*24+FileHeader.bfOffBits;                      //BMP图像文件大小

InfoHeader.biXPelsPerMeter = 0;                                              //水平分辨率,这里暂时设为0就是

InfoHeader.biYPelsPerMeter = 0;                                              //垂直分辨率,这里暂时设为0就是

InfoHeader.biClrUsed = 0;                                                    //图像使用的颜色,这里暂时设为0就是

InfoHeader.biClrImportant = 0;                                                //重要的颜色数,这里暂时设为0就是                        //垂直分辨率,这里暂时设为0就是

InfoHeader.biPlanes=1;                //必须设置为1

InfoHeader.biCompression=BI_RGB;                                              //设置为BI_RGB时,表示图像并没有彩色表

InfoHeader.biBitCount=24;                                                    //图像的位数

InfoHeader.biSize=sizeof(BITMAPINFOHEADER);                                  //结构体的大小

InfoHeader.biHeight=height;

InfoHeader.biWidth=width;

InfoHeader.biSizeImage=height*width*4;

image=(byte *)malloc(sizeof(byte)*InfoHeader.biSizeImage);

if (image == NULL)

{

free(image);

printf("Exception: No enough space!\n");

return false;

}

//像素格式设置4字节对齐

glPixelStorei(GL_UNPACK_ALIGNMENT,4);

//接收出像素的数据

glReadPixels(0,0,width,height,GL_BGR_EXT,GL_UNSIGNED_BYTE,image);

fp=fopen(file,"wb");

if (fp == NULL)

{

printf("Exception: Fail to open file!\n");

return false;

}

fwrite(&FileHeader, sizeof(BITMAPFILEHEADER), 1, fp);

fwrite(&InfoHeader, sizeof(BITMAPINFOHEADER), 1, fp);

fwrite(image, InfoHeader.biSizeImage, 1, fp);

free(image);

fclose(fp);

return true;

}

void Draw()

{

glClearColor(0.0,0.0,0.0,0.0);

glClear(GL_COLOR_BUFFER_BIT);

glEnable(GL_TEXTURE_2D);

glBindTexture(GL_TEXTURE_2D, V_ID[now]);

glEnable(GL_BLEND);

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

if (cnt <= 50)

glColor4f(1.0,1.0,1.0,(float)cnt/50.0);

else

glColor4f(1.0,1.0,1.0,1.0-((float)cnt-50.0)/50.0);

glBegin(GL_QUADS);

glTexCoord2f(0.0f, 0.0f);glVertex2f(-1,-1);

glTexCoord2f(1.0f, 0.0f);glVertex2f(1,-1);

glTexCoord2f(1.0f, 1.0f);glVertex2f(1,1);

glTexCoord2f(0.0f, 1.0f);glVertex2f(-1,1);

glEnd();

glDisable(GL_TEXTURE_2D);

glutSwapBuffers();

}

void Update()

{

cnt++;

if (cnt >= 100)              //当cnt加到100的时候,换下一张图片

{

now++;

now%=V_ID.size();        //保证now值的正确性

cnt=0;                    //将cnt值置0,开始下一个图片的显示

}

glutPostRedisplay();

}

void Reshape(int w,int h)

{

WinWidth=w;

WinHeight=h;

w=w>h?h:w;

glViewport(0,0,(GLsizei)w,(GLsizei)w);

}

void init()

{

int n,i;

char str[100],file[100];

V_ID.clear();                        //清空容器

FILE *fp;

fp=fopen("data/data.txt","r");

fscanf(fp,"%d",&n);

while (n--)

{

fscanf(fp,"%s",str);

sprintf(file,"data/%s",str);

i=LoadBitmap(file);

if (i == -1)                      //读取图片失败

continue;

else

V_ID.push_back(i);            //把图片的id放到V_ID的末尾保存起来

}

fclose(fp);

now=0;

}

void ProcessKeyboard(unsigned char key,int x,int y)

{

if (key == 'p')

{

SnapScreen(WinWidth,WinHeight,"data/screen.bmp");

}

}

void ProcessSpecialKeyboead(int key, int x, int y)

{

if (key == GLUT_KEY_F1)

{

SnapScreen(WinWidth,WinHeight,"data/screen.bmp");

}

if (key == GLUT_KEY_F2)

{

exit(0);

}

}

void ProcessMouse(int button,int state,int x,int y)

{

if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)

{

SnapScreen(x,WinHeight-y,"data/screen.bmp");  //把glut坐标转化成OpenGL内的坐标

}

}

int main(int argc, char *argv[])

{

WinWidth=400;

WinHeight=400;

glutInit(&argc, argv);

glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);

glutInitWindowPosition(100, 100);

glutInitWindowSize(WinWidth, WinHeight);

glutCreateWindow("HelloOpenGL");

glutReshapeFunc(&Reshape);

glutIdleFunc(&Update);

glutDisplayFunc(&Draw);

glutKeyboardFunc(&ProcessKeyboard);

glutSpecialFunc(&ProcessSpecialKeyboead);

glutMouseFunc(&ProcessMouse);

init();

glutMainLoop();

return 0;

}0b1331709591d260c1c78e86d0c51c18.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值