写了个三维迷宫练练手 - 哆啦比猫的技术瞎扯 - 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