美文网首页
OpenGL初探 - 简易贪吃蛇

OpenGL初探 - 简易贪吃蛇

作者: 半邪亦正 | 来源:发表于2021-03-28 19:16 被阅读0次

本文内容包括:
1、mac中新建openGL工程
2、绘制一个简单图形
3、键盘控制
4、定时器
5、文字绘制

这次是初次学习openGL,所以用了第一版的OpenGL,用的是固定片元着色器。

代码仓库:贪吃蛇

游戏截图:

游戏截图

一、工程新建

1、首先是新建一个mac OS的APP工程

新建工程

2、添加三个库,GLUT和OpenGL是系统库,可直接添加,libGLTools是第三方库,可以从我的项目中获取并拖拽到新建的项目中,注意需要把include目录下的头文件也一并添加进去

引入三个库 头文件引入

3、这次是使用C++来编写,所以需要把新建项目中的AppDelegate.h,AppDelegate.m,main.m,ViewController.m,ViewController.h删除,并新建main. cpp文件

代码目录结构

到此为止,一个空项目创建完成,可以试试是否能编译成功。

二、OpenGL绘制简单方形

1、绘制一个简单图形需要哪些元素?比如一个三角形

a、顶点,要确定一个三角形,必须得知道三角形的三个顶点坐标

b、颜色,以什么颜色来绘制

2、这次项目使用的是GLUT库来绘制,GLUT是OpenGL Utility Toolkit,是一个处理openGL程序的工具库。

//设置当前工作目录,针对MAC OS X
    gltSetWorkingDirectory(argv[0]);
    //初始化GLUT库
    glutInit(&argc, argv);
    /*初始化双缓冲窗口,其中标志GLUT_DOUBLE、GLUT_RGBA、GLUT_DEPTH、GLUT_STENCIL分别指
     
     双缓冲窗口、RGBA颜色模式、深度测试、模板缓冲区*/
    glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA|GLUT_DEPTH|GLUT_STENCIL);
    //GLUT窗口大小,标题窗口
    glutInitWindowSize(800,600);
    glutCreateWindow("贪吃蛇");
    //注册回调函数
    glutReshapeFunc(ChangeSize);//窗口改变大小
    
    glutDisplayFunc(RenderScene);//绘制刷新
    glutKeyboardFunc(OnKeyTap);//键盘监听
    glutTimerFunc(speed,timerFunc,1);//定时回调,第一个参数是定时间隔,单位毫秒,第二个回调方法指针,第三个是回调ID,会透传给回调方法的参数
    
    //驱动程序的初始化中没有出现任何问题。
    GLenum err = glewInit();
    if(GLEW_OK != err) {
        fprintf(stderr,"glew error:%s\n",glewGetErrorString(err));
        return 1;
    }
    //调用SetupRC
    SetupRC();
    glutMainLoop(); //启动runloop

代码比较简单,思路就是初始化GLUT库,创建窗口,设置背景色,绘制图形,事件监听,看代码都有注释,不多说。

三、贪吃蛇的思路

1、以链表存放蛇块,每吃一个食物方块,链表尾部加1

//新建一个蛇块,并添加到链表后面
void newASnake(Point point, GLfloat *color) {
    SnakeObject snake = SnakeObject();
    snake.points = (GLfloat*)malloc(sizeof(GLfloat) * 12);
    snake.color = (GLfloat*)malloc(sizeof(GLfloat) * 4);
    for (int i=0; i< 4; i++) {
        snake.color[i] = color[i];
    }
    createBlock(snake.points, blockSize);
    moveTo(snake.points, point);
    snake.triangleBatch = new GLBatch();
    snake.triangleBatch->Begin(GL_TRIANGLE_FAN,4);
    snake.triangleBatch->CopyVertexData3f(snake.points);
    snake.triangleBatch->End();
    SnakeNode *newNode = (SnakeNode *)malloc(sizeof(SnakeNode));
    if (objectCount == 0) {
        SnakeHead = newNode;
    }else {
        SnakeNode *lastNode = SnakeHead;
        while (lastNode->next) {
            lastNode = lastNode->next;
        }
        lastNode->next = newNode;
    }
    newNode->snake = snake;
    newNode->next = NULL;
    
    objectCount++;
}

2、移动:以复杂度最低的方式移动,即把尾块移动到即将移动的点,这样只需移动一个块就可以达到移动的效果,而不需要把所有的块都绘制一遍。这也是为什么选用单向链表做数据结构的原因。


向右移动 向下移动

要想自动移动,还要配合定时器的使用,改方法只会调用一次,所以再执行完之后需要继续调用,达到循环调用的效果

glutTimerFunc(speed,timerFunc,1);
//定时回调,第一个参数是定时间隔,单位毫秒,第二个回调方法指针,第三个是回调ID,会透传给回调方法的参数
//定时方法
void timerFunc(int nTimerID) {
    move();
    glutTimerFunc(speed,timerFunc,1);//继续调用
}

3、碰撞检测:主要是检测两个块的顶点是否有相交


碰撞检测
//两个点是否碰到
bool isTouch(GLfloat *v, GLfloat *t) {
    Point vxy = getPoint(v);
    Point txy = getPoint(t);
    GLfloat size = blockSize*ScreenWidth*2;
    bool hTouch = vxy.x > txy.x && vxy.x < txy.x + size || vxy.x + size > txy.x && vxy.x+ size < txy.x + size;
    bool vTouch = vxy.y > txy.y && vxy.y < txy.y + size || vxy.y + size > txy.y && vxy.y+ size < txy.y + size;
    return hTouch && vTouch;
}

4、键盘监听

glutKeyboardFunc(OnKeyTap);//键盘监听
//键盘监听
void OnKeyTap(unsigned char key, int x, int y) {
    Direction nextDirection = currentDirection;
    if (key == 'w') {
        nextDirection = Up;
    }else if (key == 'd') {
        nextDirection = Right;
    }else if (key == 's') {
        nextDirection = Down;
    } else if (key == 'a') {
        nextDirection = Left;
    }
    //方向相反无法操作
    if (nextDirection == Left && currentDirection == Right || nextDirection == Right && currentDirection ==Left
        || nextDirection == Up && currentDirection == Down || nextDirection == Down && currentDirection == Up) {
        return;
    }
    currentDirection = nextDirection;
}

5、文字绘制

//打印文字
void glutPrint(float x, float y, char *text)
{
    glRasterPos2f(x,y);
    glColor3f(0, 0, 0);
    for (int i=0; text[i]; i++){
        glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24, text[i]);
    }
}

相关文章

  • OpenGL初探 - 简易贪吃蛇

    本文内容包括:1、mac中新建openGL工程2、绘制一个简单图形3、键盘控制4、定时器5、文字绘制这次是初次学习...

  • openGL

    OpenGl ES 初探 专业名词解释 OpenGL上下文[ context) 在应用程序调用任何OpenGL的指...

  • 基础知识

    OpenGL初识[https://www.jianshu.com/p/207f0a8e492f] OpenGL初探...

  • OpenGL笔记十一:GLKit初探

    前言 期待您移步上篇:OpenGL笔记十:OpenGL ES初探 GLKit 框架概述 GLKit 框架的设计⽬标...

  • (一)OpenGL初探

    OpenGL初探 开篇介绍 这篇文章,主要讲的是以下几点: 图形API简介 图形API解决什么问题 OpenGL专...

  • OpenGL初探

    关于图形API OpenGL (Open Graphics Library) 是一个跨编程语言、跨平台的编程图形程...

  • OpenGL初探

    图形API简介 OpenGL (Open Graphics Library)是一个跨编程语言、跨平台的编程图形程序...

  • OpenGL初探

    图形API OpenGL Open Graphics Library 是一个跨编程语言、跨平台的编程图形程序接⼝,...

  • OpenGL初探

    以下为个人学习过程中,记录的OpenGL的知识点。详情请咨询OpenGL Wiki。 现有图形API简介 Open...

  • OpenGL初探

    图形API简介 OpenGL (Open Graphics Library)是一个用于渲染2D、3D矢量图形的跨编...

网友评论

      本文标题:OpenGL初探 - 简易贪吃蛇

      本文链接:https://www.haomeiwen.com/subject/iltmhltx.html