A preliminary exploration of OpenGL: 3D maze game (1) - scene roaming

Using OpenGL to design a maze game, the basic functions include:

  • The maze contains at least 10*10 Cells.
  • Control the character's roaming in the scene through the keyboard.
  • Support collision detection, characters will not pass through walls.
  • Textured walls and floors.
  • Two-dimensional auxiliary maps are supported.

First, the main body of the program is designed. The program should include a drawing module, a logic control module, and a callback function module. The drawing module mainly realizes the drawing of graphics, including three-dimensional maze drawing and two-dimensional small map drawing; the logic control module mainly realizes the determination of the wall position and collision detection; the callback function module mainly realizes the operation of using the keyboard to complete the perspective conversion and roaming the scene.

The first is scene roaming: there are two ways to achieve scene roaming. One is to fix the position of the camera and transform the entire scene. For example, when the character moves forward, it is actually realized by translating the entire scene backward. It is achieved by rotating the entire scene in reverse; another way is to make the camera move in the scene, and set the position of the camera through the gluLookAt() function, which can arbitrarily specify the position and orientation of the camera.

The following demo implements roaming by moving the viewpoint around the scene:


First define some variables:
static float angle = 0.0, ratio;//angle rotation angle around the y-axis, ratio window aspect ratio
static float x = 0.0f, y = 1.75f, z = 5.0f;//Camera position
static float lx = 0.0f, ly = 0.0f, lz = -1.0f;//The line of sight direction, initially set to the negative direction along the Z axis
static GLint snowman_display_list;//Snowman display list index

About the gluLookAt() function:
The gluLookAt() function provides a simple and intuitive way to set the position and orientation of the camera. It has three sets of parameters, each of which consists of three floating-point numbers. The first three parameters indicate the position of the camera, the second group of parameters defines the direction the camera is looking at, and the last group indicates the upward vector, which is usually set to (0.0, 1.0, 0.0). That is to say, the camera is not tilted. Set to (0.0, ‐1.0, 0.0) if you want to see all objects upside down.

The variables x, y, z mentioned above represent the position of the camera, corresponding to the first set of vectors. The second set of parameters, the viewing direction, is obtained by adding the vector defining the line of sight to the position of the camera:
//define the observation method
void changeSize(int w, int h)
{
	// divide by 0
	if (h == 0)
		h = 1;
	ratio = 1.0f*w / h;
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	
	//Set the viewport to the full window size
	glViewport(0, 0, w, h);

	//Set the visible space
	gluPerspective(45, ratio, 1, 1000);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	gluLookAt(x, y, z, x + lx, y + ly, z + lz, 0.0f, 1.0f, 0.0f);
}

The following defines the display list, draws the snowman, initializes the scene, and renders the scene:
//Define the display list, draw the snowman, initialize the scene, render the scene
void drawSnowMan ()
{
	glColor3f(1.0f, 1.0f, 1.0f);

	// draw the body
	glTranslatef(0.0f, 0.75f, 0.0f);
	glutSolidSphere(0.75f, 20, 20);

	//draw header
	glTranslatef(0.0f,1.0f,0.0f);
	glutSolidSphere(0.25f,20,20);
	
	// draw eyes            
	glPushMatrix();
	glColor3f(0.0f,0.0f,0.0f);
	glTranslatef(0.05f,0.10f,0.18f);
	glutSolidSphere(0.05f,10,10);
	glTranslatef(-0.1f,0.0f,0.0f);
	glutSolidSphere(0.05f,10,10);
	glPopMatrix();

	// draw nose
	glColor3f(1.0f,0.5f,0.5f);
	glRotatef(0.0f,1.0f,0.0f,0.0f);
	glutSolidCone(0.08f,0.5f,10,2);
}

GLuint createDL()
{
	GLuint snowManDL;

	// Generate a display list number
	snowManDL = glGenLists(1);

	//Start displaying the list
	glNewList(snowManDL, GL_COMPILE);

	drawSnowMan ();

	glEndList();

	return (snowManDL);
}

void initScenne()
{
	glEnable(GL_DEPTH_TEST);
	snowman_display_list = createDL();
}

void renderScene(void)
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	// draw the ground
	glBegin(GL_QUADS);
	glVertex3f(-100.0f, 0.0f, -100.0f);
	glVertex3f(-100.0f, 0.0f, 100.0f);
	glVertex3f(100.0f, 0.0f, 100.0f);
	glVertex3f(100.0f, 0.0f, -100.0f);
	glEnd();

	// draw 36 snowmen
	for (int i= -3; i< 3; i++)
		for (int j = -3; j< 3; j++) {
			glPushMatrix();
			glTranslatef(i*10.0, 0, j*10.0);
			glCallList(snowman_display_list);
			glPopMatrix();
		}
	glutSwapBuffers();
}

Set the keyboard callback function. Use the left and right arrow keys to rotate the camera to change the line of sight. The up and down arrow keys move the camera back and forth along the line of sight:
//keyboard response
//The left and right keys rotate the camera, the up and down keys move the camera
void inputKey(int key, int x, int y) {
	switch (key)
	{
	case GLUT_KEY_LEFT:
		angle -= 0.01f;
		orientMe(angle);
		break;
	case GLUT_KEY_RIGHT:
		angle += 0.01f;
		orientMe(angle);
		break;
	case GLUT_KEY_UP:
		moveMeFlat(1);
		break;
	case GLUT_KEY_DOWN:
		moveMeFlat(-1);
		break;
	default:
		break;
	}
}

The angle variable changes when the left and right arrow keys are pressed, and orientMe is called. This function will rotate the camera, changing the direction of the line of sight:
//rotate the camera
void orientMe(float ang)
{
	lx = sin (ang);
	lz = -cos (ang);
	glLoadIdentity();
	gluLookAt(x, y, z, x + lx, y + ly, z + lz, 0.0f, 1.0f, 0.0f);
}

The function moveMeFlat moves the camera back and forth along the line of sight:
//move the camera
void moveMeFlat(int direction)
{
	x = x + direction*(lx)*0.1;
	z = z + direction * (lz) * 0.1;
	glLoadIdentity();
	gluLookAt(x, y, z, x + lx, y + ly, z + lz, 0.0f, 1.0f, 0.0f);
}

Finally complete the Main function:
int main(int argc,char **argv)
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
	glutInitWindowPosition (100, 100);
	glutInitWindowSize (640, 360);
	glutCreateWindow("snowman test");

	initScenne();
	glutSpecialFunc(inputKey);
	glutDisplayFunc(renderScene);
	glutIdleFunc (renderScene);
	glutReshapeFunc(changeSize);
	glutMainLoop();
    return 0;
}

At this point, a simple demo is completed, you can control the camera to roam in the scene through the up, down, left, and right arrow keys.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324892459&siteId=291194637