写了个三维迷宫练练手 - 哆啦比猫的技术瞎扯 - Arch Linux · ドラえもん · 实时绘制
写了个三维迷宫练练手
终于写了个像样点的 OpenGL 程序了
代码放在 https://github.com/cjxgm/clabs/blob/master/demo/Mine/opengl_learning/11_maze/
#include <GL/glut.h> #include <stdio.h> #include <stdlib.h> #include "camera.h" float spin = 0; float pos_x = 0, pos_y = 0, pos_z = 0; static const float no[] = { 0, 0, 0, 1 }; static char key[256] = {0}; static float fps = 1; static GLuint lists; #define LIST_SIZE 1 #define LIST_MAZE lists void draw_maze(void) { #define W 15 #define H 10 #define MAZE(X,Y) maze[(((Y) * W) + X)] const char maze[H*W+1] = "###############" " # #" "#### ### #####" "# # # " "# # * ### #" "# ##### # # #" "# # # # # #" "# # * ### # #" "# #" "###############"; float ground_diffuse[] = { 0.6, 0.6, 0.6, 1 }; float wall_diffuse[] = { 0.8, 0.8, 0.4, 1 }; float danger_emission[] = { 1.0, 0.6, 0.2, 1 }; int x, y; for (y=0; y<H; y++) for (x=0; x<W; x++) { glPushMatrix(); { glTranslatef(x, y, 0); switch (MAZE(x, y)) { case '#': // wall glMaterialfv(GL_FRONT, GL_DIFFUSE, wall_diffuse); glMaterialfv(GL_FRONT, GL_EMISSION, no); break; case ' ': // ground glMaterialfv(GL_FRONT, GL_DIFFUSE, ground_diffuse); glMaterialfv(GL_FRONT, GL_EMISSION, no); glScalef(1, 1, 0.1); break; case '*': // danger glMaterialfv(GL_FRONT, GL_DIFFUSE, no); glMaterialfv(GL_FRONT, GL_EMISSION, danger_emission); break; } glTranslatef(0, 0, 0.5); glutSolidCube(1.0); } glPopMatrix(); } #undef W #undef H #undef MAZE } void key_down(unsigned char k, int x, int y) { key[k] = 1; } void key_up(unsigned char k, int x, int y) { key[k] = 0; } void glWindowPos2i(int x, int y); // 奇怪,为什么没有这个会说没有声明,头文件里不是有么 void renderString(int x, int y, const char * string, void * font) { if (font == NULL) font = GLUT_BITMAP_HELVETICA_18; glWindowPos2i(x, y); while (*string) glutBitmapCharacter(font, *string++); } void render(void) { unsigned int time = glutGet(GLUT_ELAPSED_TIME); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix(); { camApply(); glTranslatef(7.5, -2, -30); glScalef(4, 4, 4); glRotatef(-90, 0, 1, 0); glRotatef(-90, 1, 0, 0); glTranslatef(-7.5, -5, 0); glCallList(LIST_MAZE); } glPopMatrix(); char buf[128]; sprintf(buf, "fps: %.2f", fps); glColor3f(0.8, 0, 0); renderString(10, 10, buf, NULL); glutSwapBuffers(); spin += 0.1; if (key[27]) exit(0); camBegin(); if (key['w']) camForward(+4 / fps); if (key['s']) camForward(-4 / fps); if (key['d']) camTurn(+90 / fps); if (key['a']) camTurn(-90 / fps); if (key['q']) camPan(+4/ fps); if (key['e']) camPan(-4 / fps); camEnd(); fps = 1000.0 / (glutGet(GLUT_ELAPSED_TIME) - time); } int main(int argc, char * argv[]) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH); glutInitWindowSize(640, 480); glutCreateWindow("Maze"); glutIdleFunc(&render); glutKeyboardFunc(&key_down); glutKeyboardUpFunc(&key_up); glMatrixMode(GL_PROJECTION); gluPerspective(45, 640.0 / 480.0, 1, 100); glMatrixMode(GL_MODELVIEW); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); glEnable(GL_CULL_FACE); /* lighting */ { float light_pos[] = { 0, 0, 0, 1 }; float white_light[] = { 1.1, 1.1, 1.1, 1 }; float ambient[] = { 0.4, 0.4, 0.4, 1 }; glLightfv(GL_LIGHT0, GL_POSITION, light_pos); glLightfv(GL_LIGHT0, GL_DIFFUSE, white_light); glLightfv(GL_LIGHT0, GL_SPECULAR, white_light); glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient); glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); } glClearColor(0, 0, 0, 0); glEnable(GL_DEPTH_TEST); glClearDepth(1.0); lists = glGenLists(LIST_SIZE); glNewList(LIST_MAZE, GL_COMPILE); draw_maze(); glEndList(); camInit(); glutMainLoop(); return 0; }
camera 的设计比较简洁,实现也很简单
#ifndef CAMERA_H #define CAMERA_H void camInit(void); void camApply(void); void camBegin(void); void camEnd(void); void camForward(float howmuch); void camPan(float howmuch); void camTurn(float howmuch); #endif
#include "camera.h" #include <GL/gl.h> static float camera[16]; void camInit(void) { glPushMatrix(); glLoadIdentity(); glGetFloatv(GL_MODELVIEW_MATRIX, camera); glPopMatrix(); } void camApply(void) { glLoadMatrixf(camera); } void camBegin(void) { glPushMatrix(); } void camEnd(void) { glPopMatrix(); } void camForward(float howmuch) { glLoadIdentity(); glTranslatef(0, 0, howmuch); glMultMatrixf(camera); glGetFloatv(GL_MODELVIEW_MATRIX, camera); } void camPan(float howmuch) { glLoadIdentity(); glTranslatef(howmuch, 0, 0); glMultMatrixf(camera); glGetFloatv(GL_MODELVIEW_MATRIX, camera); } void camTurn(float howmuch) { glLoadIdentity(); glRotatef(howmuch, 0, 1, 0); glMultMatrixf(camera); glGetFloatv(GL_MODELVIEW_MATRIX, camera); }
然后就是 makefile 了
# Generated by ADSMGCS. CC = gcc CFLAGS = -Wall -s -O2 -lglut -lGL -lGLU all: maze clean: rm -f *.o cleanall: clean rm -f maze rebuild: clean all debug: all ./maze maze: maze.o camera.o $(CC) $(CFLAGS) -o $@ $^ maze.o: maze.c camera.h $(CC) $(CFLAGS) -c -o $@ $< camera.o: camera.c camera.h $(CC) $(CFLAGS) -c -o $@ $<
现在还不知道怎样取得当前位置,以及怎样“撞墙”
凡未特殊声明(转载/翻译),所有文章均为原创。
by Giumo Xavier Clanjor (哆啦比猫/兰威举), 2010-2019.
本作品采用知识共享署名·非商业性使用·相同方式共享 3.0 中国大陆许可协议进行许可。
文中凡未特殊声明且未声明为引用的代码均以 MIT 协议授权。
blog comments powered by Disqus