用C写的3D迷宫

          Boss说,要看OpenGL,看了快一个月,总算出了个像样的东西,用C写了个3D迷宫, 虽然只有350行


       代码,不过边学边写,足足写了一周时间,还是小有成就感的,活活活!


               Tips:上下左右键控制前进后退转向,空格键切换俯视图,鼠标右键更换地图(虽然只写了两


       个……) 加了点音乐,免得太过单调。

    

       效果图:

               


#include<stdlib.h>
#include<stdio.h>
#include<GL/glut.h>
#include<GL/glaux.h>
#include<math.h>
#include<windows.h>

#pragma comment(lib, "glaux.lib")

#define    PX_START    1.5
#define    PY_START    1.5
#define    UNITSTEP    0.2
#define    ANGLE_START    -45

GLuint    Texture = 0 ;
float    px = PX_START ;
float    py = PY_START ;
int        angle = ANGLE_START ;            //行走方向
int        dir_x ;                //行走方向向量
int        dir_y ;
int        MAP_SIZE = 16 ;
char    **map ;
int        globalView = 0 ;    //是否查看俯视图

char    *map1[16] =
    {
        "HHHHHHHHHHHHHHHH",
        "H       H      H",
        "H H HHH H H    H",
        "H HH  H HH H H H",
        "H     H      H H",
        "HHHHHHHHHH HHH H",
        "H           H  H",
        "H HHHHH HHH HHHH",
        "H H   H   H    H",
        "H   HHHHHHH    H",
        "H H   H   H  H H",
        "H HHHHH HHHH H H",
        "H     H      H H",
        "HH HH HHHH HHH H",
        "H   H H    H   H",
        "HHHHHHHHHHHHH HH"
    };
char    *map2[25] =
    {
        "HHHHHHHHHHHHHHHHHHHHHHHHH",
        "H    H H H      HH H    H",
        "H HH   H   H  H HHH  HH H",
        "H H    HH H HHH       HHH",
        "H H   HHH HH H HH H HHHHH",
        "H HH HHHH HH H H  HH  HHH",
        "H         H H  HH   HH HH",
        "H HH HHH   H HH  HH HH HH",
        "H       H  HHH H HH HH  H",
        "HH  H H  H H HH  H  HH HH",
        "HHH   H   HH HH H  HHH  H",
        "HHH HHH H  H H  HH  HHH H",
        "HHH HHH H    HH HH  HH  H",
        "HHH H   HHHH  H  H  H H H",
        "HH    HHH HH   H H HHH  H",
        "HHHH HHHHH HHH  HH  HH  H",
        "HHH  H HHHHH   HHHH HH HH",
        "HHH  HH   HH   HHH  HH  H",
        "HHH   HHH HHH HH HHH HH H",
        "HHH HH  HHHH  HHH HH  HHH",
        "HHH H    HH  HHHH HHH HHH",
        "H   H HHH    HH  H H  HHH",
        "H     HH HH     HH    HHH",
        "H HH HHHH HHHHH     H  HH",
        "HHHHHHHHHHHHHHHHHHHHHH HH"
    };
//        加载墙纸
int        ReadImage()
{
    AUX_RGBImageRec    *TextureImage;                        //保存贴图数据的指针
    TextureImage = auxDIBImageLoad("wall.bmp");            //载入贴图数据

    glGenTextures(1, &Texture);                            // 创建一个纹理,unTexture
    glBindTexture(GL_TEXTURE_2D, Texture);                //绑定纹理,然后对该纹理区添加纹理数据

    gluBuild2DMipmaps(GL_TEXTURE_2D, 3, TextureImage->sizeX, TextureImage->sizeY,GL_RGB, GL_UNSIGNED_BYTE, TextureImage->data);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);        //设置滤波为线性滤波
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);        //线性滤波
    glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL) ;

    if (TextureImage)        //释放资源
    {
        if (TextureImage->data)
        {
            free(TextureImage->data);
        }
        free(TextureImage);
    }

    return 1;
}
//         判断是否为墙
int    wall(int x , int y)
{
    if(map[(int)x][(int)y]=='H')
        return    1 ;
    return    0 ;
}
//        计算行走方向向量
void    calcDir()
{
    if(angle<0 && angle>-180)    dir_x =  1 ;
    else    if(angle<180 && angle>0)    dir_x = -1 ;
    else    dir_x = 0 ;

    if(abs(angle) < 90)        dir_y = 1 ;
    else    if(abs(angle) > 90)        dir_y = -1 ;
    else    dir_y = 0 ;
}
//        绘制迷宫墙体
int drawCube(int x , int y)
{
    glBindTexture(GL_TEXTURE_2D, Texture);    //使用贴图纹理

    glPushMatrix();        //压入变换矩阵

    glTranslatef((float)x+0.5,(float)y+0.5,0.0f) ;
    glBegin(GL_QUADS);  //启用四边形带绘制模式绘制
        //前面
        glTexCoord2f(0.0f, 0.0f); glVertex3f(-0.5f, -0.5f,  0.5f);
        glTexCoord2f(1.0f, 0.0f); glVertex3f( 0.5f, -0.5f,  0.5f);
        glTexCoord2f(1.0f, 1.0f); glVertex3f( 0.5f,  0.5f,  0.5f);
        glTexCoord2f(0.0f, 1.0f); glVertex3f(-0.5f,  0.5f,  0.5f);
        //后面
        glTexCoord2f(0.0f, 0.0f); glVertex3f( 0.5f, -0.5f, -0.5f);
        glTexCoord2f(1.0f, 0.0f); glVertex3f(-0.5f, -0.5f, -0.5f);
        glTexCoord2f(1.0f, 1.0f); glVertex3f(-0.5f,  0.5f, -0.5f);
        glTexCoord2f(0.0f, 1.0f); glVertex3f( 0.5f,  0.5f, -0.5f);
        //上面
        glTexCoord2f(0.0f, 0.0f); glVertex3f(-0.5f,  0.5f,  0.5f);
        glTexCoord2f(1.0f, 0.0f); glVertex3f( 0.5f,  0.5f,  0.5f);
        glTexCoord2f(1.0f, 1.0f); glVertex3f( 0.5f,  0.5f, -0.5f);
        glTexCoord2f(0.0f, 1.0f); glVertex3f(-0.5f,  0.5f, -0.5f);
        //下面
        glTexCoord2f(0.0f, 0.0f); glVertex3f(-0.5f, -0.5f, -0.5f);
        glTexCoord2f(1.0f, 0.0f); glVertex3f( 0.5f, -0.5f, -0.5f);
        glTexCoord2f(1.0f, 1.0f); glVertex3f( 0.5f, -0.5f,  0.5f);
        glTexCoord2f(0.0f, 1.0f); glVertex3f(-0.5f, -0.5f,  0.5f);
        //右面
        glTexCoord2f(0.0f, 0.0f); glVertex3f( 0.5f, -0.5f,  0.5f);
        glTexCoord2f(0.0f, 1.0f); glVertex3f( 0.5f, -0.5f, -0.5f);
        glTexCoord2f(1.0f, 1.0f); glVertex3f( 0.5f,  0.5f, -0.5f);
        glTexCoord2f(1.0f, 0.0f); glVertex3f( 0.5f,  0.5f,  0.5f);
        //左面
        glTexCoord2f(0.0f, 0.0f); glVertex3f(-0.5f, -0.5f, -0.5f);
        glTexCoord2f(0.0f, 1.0f); glVertex3f(-0.5f, -0.5f,  0.5f);
        glTexCoord2f(1.0f, 1.0f); glVertex3f(-0.5f,  0.5f,  0.5f);
        glTexCoord2f(1.0f, 0.0f); glVertex3f(-0.5f,  0.5f, -0.5f);

    glEnd();
    glPopMatrix(); //弹出变换矩阵
    return 1;
}
//        绘制迷宫地板
int    drawFloor(int x , int y)
{
    glPushMatrix();        //压入变换矩阵
    glDisable(GL_TEXTURE_2D) ;
    glColor3f(0.7,0.7,0.7) ;
    glTranslatef((float)x+0.5,(float)y+0.5,0.0f) ;
    glBegin(GL_QUADS);  //启用四边形带绘制模式绘制
        glVertex3f(-0.5f, -0.5f,  -0.5f);
        glVertex3f( 0.5f, -0.5f,  -0.5f);
        glVertex3f( 0.5f,  0.5f,  -0.5f);
        glVertex3f(-0.5f,  0.5f,  -0.5f);
    glEnd();
    glEnable(GL_TEXTURE_2D) ;
    glPopMatrix() ;
    return    1 ;
}
//        标明当前位置和方向
int    drawPlayer()
{
    glPushMatrix() ;
    glDisable(GL_TEXTURE_2D) ;
    glColor3f(0.2,0.8,0.2) ;
    glTranslatef(px,py,0.0f) ;
    glRotatef(angle,0.0,0.0,1.0) ;
    glBegin(GL_QUADS);  //启用四边形带绘制模式绘制
        glVertex3f(-0.2f, -0.4f,  1.0f) ;
        glVertex3f( 0.2f, -0.4f,  1.0f) ;
        glVertex3f( 0.0f,  0.0f,  1.0f) ;
        glVertex3f( 0.0f,  0.4f,  1.0f) ;
        glEnd();
    glEnable(GL_TEXTURE_2D) ;
    glPopMatrix() ;
    return    1 ;
}
//        绘制迷宫
void    drawMap()
{
    int    x , y ;

    for( x = 0 ; x < MAP_SIZE ; x++ )
        for( y = 0 ; y < MAP_SIZE ; y++)
            if(map[x][y] == 'H')
                drawCube(x,y) ;
            else
                drawFloor(x,y) ;
    drawPlayer() ;
}
//        初始化绘制环境
void    init()
{
    glEnable(GL_CULL_FACE);                        //启用裁剪
    glCullFace(GL_BACK);                           //背面裁剪(背面不可见)
    glShadeModel(GL_FLAT) ;
    glEnable(GL_AUTO_NORMAL) ;
    glEnable(GL_TEXTURE_2D);
    ReadImage() ;
    calcDir() ;
    map = map1 ;
    MAP_SIZE = 16 ;
    PlaySound("BACK.wav",NULL,SND_ASYNC|SND_LOOP);
}
//        绘制函数
void    display(void)
{
    glClearColor(1.0,1.0,1.0,1.0) ;
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT) ;            // 清空颜色数据和深度数据

    if(px>(MAP_SIZE-1) && px<MAP_SIZE && py>(MAP_SIZE-3) && py<(MAP_SIZE-2))
    {
        PlaySound("YEAH.wav",NULL,SND_ASYNC);
        MessageBox(NULL , "Escaped    !    " , "Message" , MB_ICONASTERISK);
        PlaySound("BACK.wav",NULL,SND_ASYNC|SND_LOOP);
        px = PX_START ;
        py = PY_START ;
        angle = ANGLE_START ;
        calcDir() ;
    }

    glMatrixMode(GL_MODELVIEW) ;
    glLoadIdentity() ;
    drawMap() ;

    glMatrixMode(GL_PROJECTION) ;
    glLoadIdentity() ;
    glEnable(GL_DEPTH_TEST) ;
    gluPerspective(90,1.0,0.01,16.0) ;
    if(globalView == 0)
        gluLookAt(px,py,0.0f,px+dir_x,py+dir_y,0.0f,0.0f,0.0f,1.0f) ;
    else    
        gluLookAt(px,py,7.0f,px,py,0.0f,0.0f,1.0f,0.0) ;

    glutSwapBuffers();
}
//        地图选择
void    MenuFunc(int data)
{
    switch(data)
    {
        case    1:    map = map1 ;    MAP_SIZE = 16 ;    break ;
        case    2:    map = map2 ;    MAP_SIZE = 25 ;    break ;
        case    3:    map    = map2 ;    MAP_SIZE = 25 ;    break ;
        default    :    break ;
    }
    angle = ANGLE_START ;
    px = PX_START ;
    py = PY_START ;
    calcDir() ;
}
//        控制移动
void    aheadAndBack(float pos)
{
    float    step_x = pos * UNITSTEP * dir_x ;
    float    step_y = pos * UNITSTEP * dir_y ;
    if(wall(px+step_x , py) == 0)
        px += step_x ;
    if(wall(px , py+step_y) == 0)
        py += step_y ;
}
//        键盘事件
void    keyboard(unsigned char key, int x, int y)
{
    if(key==' ')
        globalView = (globalView + 1) % 2 ;
}
//        键盘事件
void    special(int key , int x , int y)
{
    if(globalView == 0)            //俯视图屏蔽方向控制
        switch(key)
        {
            case    GLUT_KEY_UP :    aheadAndBack(1.0) ;        break ;
            case    GLUT_KEY_DOWN :    aheadAndBack(-1.0) ;    break ;    //向后走相当于向前走-1
            case    GLUT_KEY_LEFT :    angle += 45 ;    if(angle > 180)        angle = -135 ;     calcDir() ;    break ;
            case    GLUT_KEY_RIGHT :angle -= 45 ;    if(angle < -180)    angle = 135 ;        calcDir() ;      break ;
            default    :    break ;
        }
}
//        空闲时调用
void    idle(void)
{
    Sleep(10) ;
    glutPostRedisplay() ;
}
//        窗口调整
void    reshape(GLsizei    w , GLsizei    h)
{
    glViewport(0,0,w,h) ;
    glMatrixMode(GL_PROJECTION) ;
    glLoadIdentity() ;
    glMatrixMode(GL_MODELVIEW) ;
    glLoadIdentity() ;
}
//        主函数
int    main(int    argc , char** argv)
{
    glutInit(&argc,argv) ;
    glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB) ;
    glutInitWindowSize(800,800) ;
    glutInitWindowPosition(150,150) ;
    glutCreateWindow("Maze") ;
    init() ;
    glutReshapeFunc(reshape) ;
    glutDisplayFunc(display) ;
    glutSpecialFunc(special) ;
    glutKeyboardFunc(keyboard) ;
    glutIdleFunc(idle);

    glutCreateMenu(MenuFunc);
    glutAddMenuEntry("Ordinary",1);
    glutAddMenuEntry("Medium",2);
    glutAddMenuEntry("Maddening",3);
    glutAttachMenu(GLUT_RIGHT_BUTTON);

    glutMainLoop() ;
    return(0) ;
}

  


版权声明:本文为crazyingBird原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。