赞
踩
最近开始学习图形学,试着用glut做了一个小游戏,也是之前见得蛮多的小游戏叫做见缝插针,基本上功能都实现了,可能还有些不足,之后有机会再改进,废话不多说,先上图
每次点击鼠标左键可以插入一针,每次插入完的针都会一直旋转,过程中要保证每插入一针,针与针不要碰撞,最后尽可能多的“见缝插针”
(听起来是不是很简单呢,确实也不难)
接下来就是代码部分,这里我直接把源码贴出来,还有一些里面的注意事项,以免你们拿到手不能直接运行
#include<GL/glut.h> #include<stdio.h> #include <windows.h> #include<math.h> #define MAX_CHAR 128 // ASCII字符总共只有0到127,一共128种字符 #define PI acos(-1.0) // cos (pi)=-1 求一个反余弦就得到PI #define SPEED (PI/360) // 针的旋转速度 #define NEEDLE_L 180 // 针的长度 void Init(); void Reshape(int w, int h); void myDisplay(); void myIdle(void); void MouseHit(int button, int state, int x, int y); void DrawString(const char* str); void DrawFrame(int number); void Move(int number, int x, int y); void Rotate(double* R, int num); bool Pin(double* R, int num); double radian[25] = { 0 }; //储存针的弧度 int Needle_N = 0; //针的个数 int n = 40; //多边形边数,n越大,越趋近圆 int win; //窗口返回值 int main(int argc,char*argv[]) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); glutInitWindowPosition(100, 100); glutInitWindowSize(480, 640); win=glutCreateWindow("Game Demo 左键点击开始"); //基于圆的碰撞检测做出来的游戏 Init(); glutDisplayFunc(myDisplay); glutIdleFunc(myIdle); glutReshapeFunc(Reshape); glutMouseFunc(MouseHit); glutMainLoop(); return 0; } //初始化 void Init() { glClearColor(189.0/255.0, 188.0/255.0, 187.0/ 255.0,0.0); } //调整窗口函数 void Reshape(int w, int h) { glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity();//初始化变换矩阵 gluOrtho2D(0, (double)w, 0, (double)h);//左下角(0,0),右上角(640,480) } //绘制函数 void myDisplay() { glClear(GL_COLOR_BUFFER_BIT); DrawFrame(1); Move(Needle_N, 240, 80); Move(Needle_N + 1, 240, 40); Move(Needle_N + 2, 240, 0); Rotate(radian, Needle_N); glutSwapBuffers(); } //动画函数 void myIdle(void) { myDisplay(); Sleep(10);//控制旋转快慢 } //鼠标响应 void MouseHit(int button, int state, int x, int y) { if (button== GLUT_LEFT_BUTTON&&state==GLUT_DOWN)//controlMouseHit==true { if (Pin(radian, Needle_N)) { Needle_N++; } else { glutIdleFunc(NULL); HWND hwnd = GetActiveWindow(); if (MessageBox(hwnd, "游戏结束。\n重来一局吗?", "询问", MB_YESNO | MB_ICONQUESTION) == IDYES) { Needle_N = 0; glutIdleFunc(myIdle);//重启动画 } else { glutDestroyWindow(win);//摧毁窗口,但是loop其实仍在继续 } } } } //显示文本函数 void DrawString(const char* str) { static int isFirstCall = 1; static GLuint lists; if (isFirstCall) { // 如果是第一次调用,执行初始化 // 为每一个ASCII字符产生一个显示列表 isFirstCall = 0; // 申请MAX_CHAR个连续的显示列表编号 lists = glGenLists(MAX_CHAR); // 把每个字符的绘制命令都装到对应的显示列表中 wglUseFontBitmaps(wglGetCurrentDC(), 0, MAX_CHAR, lists); } // 调用每个字符对应的显示列表,绘制每个字符 for (; *str != '\0'; ++str) glCallList(lists + *str); } //图案绘制 void DrawFrame(int number) { char str[25]; int i; _itoa_s(number, str, 10); glColor3f(70 / 255.0, 70 / 255.0, 69 / 255.0); // 绘制多边形,n足够大就会变成圆形 //也可以换成八对称画法 glBegin(GL_POLYGON); for (i = 0; i < n; ++i) glVertex2f(240 + 50 * cos(2 * PI / n * i), 400 + 50 * sin(2 * PI / n * i)); glEnd(); glColor3f(1.0, 1.0, 1.0); glRasterPos2f(240,400); DrawString(str); } // void Move(int number, int x, int y) { char str[25]; int i; _itoa_s(number, str, 10); glColor3f(70 / 255.0, 70 / 255.0, 69 / 255.0); glBegin(GL_POLYGON); for (i = 0; i < n; ++i) glVertex2f(x + 20 * cos(2 * PI / n * i), y + 20 * sin(2 * PI / n * i)); glEnd(); glColor3f(1.0, 1.0, 1.0); glRasterPos2f(x,y); DrawString(str); } //旋转函数 void Rotate(double* R, int num) { int X_NEEDLE; int Y_NEEDLE; for (int i = 0; i < num; i++) { R[i] = R[i] + SPEED; //循环一圈后。-2PI if (R[i] > 2 * PI) { R[i] = R[i] - 2 * PI; } X_NEEDLE = int(NEEDLE_L * cos(R[i]) + 240); Y_NEEDLE = int(400-NEEDLE_L * sin(R[i])); glColor3f(70 / 255.0, 70 / 255.0, 69 / 255.0); glLineWidth(3); glEnable(GL_LINE_STIPPLE); glBegin(GL_LINES); glVertex2s(X_NEEDLE, Y_NEEDLE); glVertex2s(240, 400); glEnd(); Move(i, X_NEEDLE, Y_NEEDLE); DrawFrame(1); } } //碰撞检测 bool Pin(double* R, int num) { int X_NEEDLE; int Y_NEEDLE; bool T = true; R[num] = PI / 2; X_NEEDLE = int(NEEDLE_L * cos(R[num]) + 240); Y_NEEDLE = int(400-NEEDLE_L * sin(R[num])); glColor3f(70 / 255.0, 70 / 255.0, 69 / 255.0); glLineWidth(3); glEnable(GL_LINE_STIPPLE); glBegin(GL_LINES); glVertex2s(X_NEEDLE, Y_NEEDLE); glVertex2s(240, 350); glEnd(); Move(num, X_NEEDLE, Y_NEEDLE); glutSwapBuffers(); for (int i = 0; i < num; i++) { if (fabs(R[num] - R[i]) < (PI / 15)) { T = false; break; // 不需要再次进行比较了,循环跳出 } } return T; // 如果失败返回false; }
1、我这是在vs下写的代码,由于OPENGL他文字显示没有直接的api我就写了一个,里面用到了itoa函数(这里我用这个函数把数字转换字符串)
_itoa_s(number, str, 10);
(这是vs的要求itoa写法,虽然我可以在预处理器加宏定义可以不按照他这个来写,但是我偷懒2333)
所以如果你用的不是vs或者vs没有这样的语法要求,你可以把_itoa_s
改成itoa
2、如果你发现点击后旋转速度太快,可以在myIdle函数里更改sleep,以及更改宏定义SPEED
3一定要先配置好glut!!!! 不然你不能opengl画图
我这次没有细讲每个函数有什么用,不过应该标注的比较清楚了,然后就是如果有什么问题,欢迎大家提问,我都会尽力回答的,
因为我也是刚接触opengl不久谢谢大家看我的博客
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。