프로젝트

나도 메이커! 메이커스 여러분들의 작품/프로젝트를 공유하는 공간입니다.

쿠키먹기 게임

2015-12-19 23:30:54

#include<GLU.h>
#include<glut.h>
#include<GL.h>
#include<glaux.h>
#include<stdlib.h>
#include<math.h>
#include<string>

#define PI 3.14159265359

void display();
void init();
void drawChar();
void drawSphere();

float randomDouble(float a, float b);
void reshape(int w, int h);
void keyboard(unsigned char key, int x, int y);
void doKeyboard(int key, int x, int y);

GLfloat angle_1, angle_2, angle_3, angle_4, angle_5, angle_6 = 0.0;
GLfloat characterX = 0.0, characterY = 0.0, characterZ = -20.0;
GLfloat Cambient[10][4];
float ro[] = { 0.3, 0.4, 0.24, 0.33, 0.21, 0.38, 0.15, 0.22, 0.38, 0.29 };
int count = 0;
unsigned int ids[1];
AUX_RGBImageRec *tex[1];

struct cookie{
	GLfloat x, y, z;
	int happy;
};

struct cookie cookie[10];

void main(int argc, char** argv){
	glutInit(&argc, argv); 
	glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
	glutInitWindowSize(1200, 800);
	glutCreateWindow("201302389_hyungyeon_term");
	glClearColor(0, 0, 0, 1);

	tex[0] = auxDIBImageLoad("flower.bmp");
	glGenTextures(0, &ids[0]);//texture id를 생성
	glBindTexture(GL_TEXTURE_2D, ids[0]);
	//texture 이름(id)을 texture 데이터(2d texture사용)와 연결한다.

	/*texture의 filtering방식 설정*/
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	//2D texture,확대필터,양방향 선형 필터링 사용 
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	//2D texture,축소필터,양방향 선형 필터링 사용
	//양방향 선형 필터링이란 텍셀에서 인접한 2*2점을 샘플링하여 가중치 평균값을 구함
	glTexImage2D(GL_TEXTURE_2D, 0, 3, tex[0]->sizeX, tex[0]->sizeY, 0, GL_RGB,
		GL_UNSIGNED_BYTE, tex[0]->data);//2D 이미지를 texture으로 메모리에 load
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
	//텍스쳐가 입혀질때 텍스쳐의 색상과 기존픽셀색상과의 관계를 설정
	//최종 color는 glColor, texture가 영향을 준다
	
	init();
	
	glutIdleFunc(display);
	glutDisplayFunc(display);//display 함수 호출
	glutKeyboardFunc(keyboard);//키보드에서 문자를 눌렀을 때 실행할 함수
	glutSpecialFunc(doKeyboard);//키보드에서 special key(화살표 키)를 눌렀을 때 실행할 함수
	glutReshapeFunc(reshape);
	glutMainLoop();
}

void doKeyboard(int key, int x, int y){
	switch (key) {
	case GLUT_KEY_UP:			//키보드 방향키 위쪽 누를시
		characterZ += 1.0;		//캐릭터의 위치를 Z축방향으로 +1.0만큼 이동
		break;
	case GLUT_KEY_LEFT:			//키보드 방향키 왼쪽 누를시
		characterX += 1.0;		//캐릭터의 위치를 X축방향으로 +1.0만큼 이동
		break;
	case GLUT_KEY_RIGHT:		//키보드 방향키 오른쪽 누를시
		characterX -= 1.0;		//캐릭터의 위치를 X축방향으로 -1.0만큼 이동
		break;
	case GLUT_KEY_DOWN:			//키보드 방향키 아래쪽 누를시
		characterZ -= 1.0;		//캐릭터의 위치를 Z축방향으로 +1.0만큼 이동
		break;
	}
	glutPostRedisplay();  // 다음 디스플레이 콜백이 실행될 때 바뀐 변수 위치로 물체가 보임
}

void keyboard(unsigned char key, int x, int y){
	switch (key) {
	case 'n':				//n를 누르면 카메라를 Y축 방향으로 이동시킨다.
		characterY += 0.5;	//물체가 가까이 오는 것 처럼 보이도록 한다.
		break;
	case 'b':				//b를 누르면 카메라를 -Y축 방향으로 이동시킨다.
		characterY -= 0.5;	//물체가 멀리 떨어지는 것 처럼 보이도록 한다.
		break;
	}
	glutPostRedisplay();
}

void init(){//구 초기화
	for (int i = 0; i < 10; i++){//각 구의 초기 위치 설정
		cookie[i].x = rand() % 60 - 30;
		//cookie[i].y = 0;
		cookie[i].y = rand() % 15 - 7;
		cookie[i].z = rand() % 30 - 15;
		cookie[i].happy = 1;
	}
	for (int i = 0; i < 10; i++){//각 구의 색상 값 설정
		for (int j = 0; j < 4; j++){
			Cambient[i][j] = rand() / (double)RAND_MAX + 0.1;
		}
	}
}

void drawChar(){//캐릭터의 속성
	GLfloat ambient[] = { 0.5, 0.5, 0.5, 0 };
	GLfloat plane_coef_s[] = { 1.0, 0.0, 0.0, 1.0 };
	GLfloat plane_coef_t[] = { 0.0, 1.0, 0.0, 1.0 };
	glEnable(GL_TEXTURE_2D);
	
	glPushMatrix();
	glBindTexture(GL_TEXTURE_2D, ids[0]);
	//ids 배열 0번째에 저장되어 있는 texture을 사용하여 바인딩
	glEnable(GL_TEXTURE_GEN_S);
	/* glTexGen : texture 좌표 생성을 제어
	glTexGeni(GLenum coord, GLenum pname, GLint param)
	coord : texture 좌표를 지정한다.
	pname : texture 좌표계 함수의 이름을 지정한다.
	param : texture 새성 파라미터 값 하나를 지정한다.
	param이 GL_OBJECT_LINEAR인 경우 물체를 이동함에 따라
	물체면의 texture가 바뀐다 */
	/* glTexGen : texture 좌표 생성을 제어
	glTexGenfv(GLenum coord, GLenum pname, const GLfloat params)
	coord : texture 좌표를 지정한다.
	pname : texture 좌표계 함수의 이름이나 함수의 파라미터를 지정한다.
	params : texture 생성 파라미터들의 배열의 포인터를 지정한다. */
	glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
	glTexGenfv(GL_S, GL_OBJECT_PLANE, plane_coef_s);
	glEnable(GL_TEXTURE_GEN_T);//자동으로 texture generate
	glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
	glTexGenfv(GL_T, GL_OBJECT_PLANE, plane_coef_t);
	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambient);
	glTranslatef(characterX, characterY, characterZ);
	glutSolidSphere(1.5, 50, 50);
	glDisable(GL_TEXTURE_GEN_S);
	glDisable(GL_TEXTURE_GEN_T);
	glPopMatrix();
}

void drawSphere(){
	for (int i = 0; i < 10; i++){
		if (sqrt(pow(characterX - cookie[i].x*cos(PI*ro[i]), 2) + pow(characterY - cookie[i].y, 2) + pow(characterZ - cookie[i].z*sin(PI*ro[i]), 2)) < 3){
			//캐릭터가 구와 충돌했을때
			//구가 사라지고 score + 1
			cookie[i].happy = 0;
		}
	}
	for (int i = 0; i < 10; i++){//구 10개 그리기
		if (cookie[i].happy == 1){
			glPushMatrix();
			glTranslatef(cookie[i].x * cos(PI*ro[i]), cookie[i].y, cookie[i].z * sin(PI*ro[i]));
			glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, Cambient[i]);
			glutSolidSphere(1.5, 50, 50);
			glPopMatrix();
		}
	}

	for (int i = 0; i < 10; i++){//구 회전 삼각함수의 세타 값
		ro[i] += 0.001;
	}

	count = 0;
	for (int i = 0; i < 10; i++){//구를 먹었을 때 먹은 구의 개수
		if (cookie[i].happy == 0){
			count++;
		}
	}
	if (count == 10){//모두 먹었을 때 : 게임 성공
		glutIdleFunc(false);
		/*text 출력*/
		glMatrixMode(GL_PROJECTION);
		glPushMatrix();
		glLoadIdentity();
		gluOrtho2D(0, 500, 0, 500);
		glMatrixMode(GL_MODELVIEW);
		glPushMatrix();
		glLoadIdentity();
		GLfloat ambientSuccess[] = { 1.0, 0.0, 0.0, 0.0 };
		glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambientSuccess);
		glColor3f(0.0f, 1.0f, 0.0f);//needs to be called before RasterPos
		glRasterPos2i(230, 250);//위치
		std::string s = "SUCCESS";
		void * font = GLUT_BITMAP_TIMES_ROMAN_24;//폰트

		for (std::string::iterator i = s.begin(); i != s.end(); ++i)
		{
			char c = *i;
			glutBitmapCharacter(font, c);
		}
		glMatrixMode(GL_MODELVIEW);
		glPopMatrix();
		glMatrixMode(GL_PROJECTION);
		glPopMatrix();
		glEnable(GL_TEXTURE_2D);
	}
}


void display(){
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);//프레임 버퍼를 초기화
	glMatrixMode(GL_MODELVIEW);//모델뷰 행렬
	glLoadIdentity();//행렬 초기화

	gluLookAt(0, 60, 0, 0, 0, 0, 0, 0, 1);//관측변환 지정

	glEnable(GL_LIGHTING);//조명 기능 ON
	glEnable(GL_LIGHT0);//첫번째 조명 사용
	glEnable(GL_LIGHT1);
	glEnable(GL_LIGHT2);
	glEnable(GL_LIGHT3);

	glEnable(GL_NORMALIZE);//자동으로 unit normal vector 구함

	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LESS);

	GLfloat ambient0[] = { 1.0, 0.0, 0.0, 1.0 };//주변광의 세기(r,g,b,a)
	GLfloat diffuse0[] = { 1.0, 0.0, 0.0, 1.0 };//분산광의 세기(난반사)
	GLfloat specular0[] = { 1.0, 0.0, 0.0, 1.0 };//반사광의 세기
	GLfloat light_pos0[] = { 0, 0, -30, 1.0 };//조명(x,y,z,w)의 위치S

	glLightfv(GL_LIGHT0, GL_POSITION, light_pos0);
	glLightfv(GL_LIGHT0, GL_AMBIENT, ambient0);
	glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse0);
	glLightfv(GL_LIGHT0, GL_SPECULAR, specular0);


	GLfloat ambient1[] = { 0.0, 1.0, 0.0, 1.0 };//주변광의 세기(r,g,b,a)
	GLfloat diffuse1[] = { 0.0, 1.0, 0.0, 1.0 };//분산광의 세기(난반사)
	GLfloat specular1[] = { 0.0, 1.0, 0.0, 1.0 };//반사광의 세기
	GLfloat light_pos1[] = { 0, 0, 20, 1.0 };//조명(x,y,z,w)의 위치S

	glLightfv(GL_LIGHT1, GL_POSITION, light_pos1);
	glLightfv(GL_LIGHT1, GL_AMBIENT, ambient1);
	glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse1);
	glLightfv(GL_LIGHT1, GL_SPECULAR, specular1);

	GLfloat ambient2[] = { 0.0, 0.0, 1.0, 1.0 };//주변광의 세기(r,g,b,a)
	GLfloat diffuse2[] = { 0.0, 0.0, 1.0, 1.0 };//분산광의 세기(난반사)
	GLfloat specular2[] = { 0.0, 0.0, 1.0, 1.0 };//반사광의 세기
	GLfloat light_pos2[] = { -30, 0, 0, 1.0 };//조명(x,y,z,w)의 위치S

	glLightfv(GL_LIGHT2, GL_POSITION, light_pos2);
	glLightfv(GL_LIGHT2, GL_AMBIENT, ambient2);
	glLightfv(GL_LIGHT2, GL_DIFFUSE, diffuse2);
	glLightfv(GL_LIGHT2, GL_SPECULAR, specular2);

	GLfloat ambient3[] = { 0.0, 0.0, 1.0, 1.0 };//주변광의 세기(r,g,b,a)
	GLfloat diffuse3[] = { 0.0, 0.0, 1.0, 1.0 };//분산광의 세기(난반사)
	GLfloat specular3[] = { 0.0, 0.0, 1.0, 1.0 };//반사광의 세기
	GLfloat light_pos3[] = { 30, 0, 0, 1.0 };//조명(x,y,z,w)의 위치S

	glLightfv(GL_LIGHT3, GL_POSITION, light_pos3);
	glLightfv(GL_LIGHT3, GL_AMBIENT, ambient3);
	glLightfv(GL_LIGHT3, GL_DIFFUSE, diffuse3);
	glLightfv(GL_LIGHT3, GL_SPECULAR, specular3);

	drawChar();
	drawSphere();

	/*if (count == 9){
		GLfloat ambientSuccess[] = { 0.1, 0.8, 0.2, 0.0 };
		glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambientSuccess);
		glBegin(GL_POLYGON);
		glVertex3f(-10, 0, 10);
		glVertex3f(10, 0, 10);
		glVertex3f(10, 0, 0);
		glVertex3f(-10, 0, 0);
		glEnd();
	}*/
	glFlush();
}

void reshape(int w, int h){
	float ratio = w / (float)h;

	glViewport(0, 0, w, h);
	//창의 크기를 변경시켜도 display 함수에서 그린 것의 모양이 변하지 않음 
	glMatrixMode(GL_PROJECTION);//투영 행렬
	glLoadIdentity();//행렬 초기화
	gluPerspective(45, ratio, 10, 100);//원근 투영
}

 

이슬기