読者です 読者をやめる 読者になる 読者になる

個人的自由ノート

ふと自分が気になった事を書いてます

OpenGLでテストゲーム用に視点移動を作った

結構苦戦しました…。こんな感じです。gluLookAt関数にsinやらcosやらの数式を使ってみるとあっさりと出来ました。我ながら良い!

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

int flag_up = 0;
int flag_down = 0;
int flag_left = 0;
int flag_right = 0;
const double PI = 3.141592;

void scene(void){
  static GLfloat red[] = { 0.8, 0.2, 0.2, 1.0 };
  static GLfloat green[] = { 0.2, 0.8, 0.2, 1.0 };
  static GLfloat blue[] = { 0.2, 0.2, 0.8, 1.0 };
  static GLfloat yellow[] = { 0.8, 0.8, 0.2, 1.0 };
  static GLfloat ground[][4] = {
    { 0.6, 0.6, 0.6, 1.0 },
    { 0.3, 0.3, 0.3, 1.0 }
  };

  int i, j;

  glPushMatrix();
  glTranslated(0.0, 0.0, -3.0);
  glMaterialfv(GL_FRONT, GL_DIFFUSE, red);
  glutSolidCube(1.0);
  glPopMatrix();

  glPushMatrix();
  glTranslated(0.0, 0.0, 3.0);
  glMaterialfv(GL_FRONT, GL_DIFFUSE, green);
  glutSolidCube(1.0);
  glPopMatrix();

  glPushMatrix();
  glTranslated(-3.0, 0.0, 0.0);
  glMaterialfv(GL_FRONT, GL_DIFFUSE, blue);
  glutSolidCube(1.0);
  glPopMatrix();

  glPushMatrix();
  glTranslated(3.0, 0.0, 0.0);
  glMaterialfv(GL_FRONT, GL_DIFFUSE, yellow);
  glutSolidCube(1.0);
  glPopMatrix();

  glBegin(GL_QUADS);
  glNormal3d(0.0, 1.0, 0.0);
  for(j = -5; j < 5; ++j){
    for(i = -5; i < 5; ++i){
      glMaterialfv(GL_FRONT, GL_DIFFUSE, ground[(i + j) & 1]);
      glVertex3d((GLdouble)i, -0.5, (GLdouble)j);
      glVertex3d((GLdouble)i, -0.5, (GLdouble)(j + 1));
      glVertex3d((GLdouble)(i + 1), -0.5, (GLdouble)(j + 1));
      glVertex3d((GLdouble)(i + 1), -0.5, (GLdouble)j);
    }
  }
  glEnd();
}

void idle(void){
  glutPostRedisplay();
}

void display(void){
  static GLfloat lightpos[] = { 3.0, 4.0, 5.0, 1.0 };
  static double ex = 0.0, ez = -1.0;
  static double r = 0.0;

  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  glLoadIdentity();

  gluLookAt(ex, 0.0, ez, ex + sin(r / 180.0 * PI), 0.0, ez + cos(r / 180.0 * PI), 0.0, 1.0, 0.0);

  glLightfv(GL_LIGHT0, GL_POSITION, lightpos);

  scene();

  glutSwapBuffers();

  if(flag_up){
    ex = ex + 0.1 * sin(r / 180.0 * PI);
    ez = ez + 0.1 * cos(r / 180.0 * PI);
  }
  if(flag_down){
    ex = ex - 0.1 * sin(r / 180.0 * PI);
    ez = ez - 0.1 * cos(r / 180.0 * PI);
  }
  if(flag_left) r += 1;
  if(flag_right) r -= 1;
}

void resize(int w, int h){
  glViewport(0, 0, w, h);
  glMatrixMode(GL_PROJECTION);

  glLoadIdentity();
  gluPerspective(30.0, (double)w / (double)h, 1.0, 100.0);

  glMatrixMode(GL_MODELVIEW);
}

void specialkeyup(int key, int x, int y){
  switch(key){
    case GLUT_KEY_UP:
      flag_up = 0;
      glutIdleFunc(0);
      break;
    case GLUT_KEY_DOWN:
      flag_down = 0;
      glutIdleFunc(0);
      break;
    case GLUT_KEY_LEFT:
      flag_left = 0;
      glutIdleFunc(0);
      break;
    case GLUT_KEY_RIGHT:
      flag_right = 0;
      glutIdleFunc(0);
      break;
  }
}

void specialkeydown(int key, int x, int y){
  switch(key){
    case GLUT_KEY_UP:
      flag_up = 1;
      glutIdleFunc(idle);
      break;
    case GLUT_KEY_DOWN:
      flag_down = 1;
      glutIdleFunc(idle);
      break;
    case GLUT_KEY_LEFT:
      flag_left = 1;
      glutIdleFunc(idle);
      break;
    case GLUT_KEY_RIGHT:
      flag_right = 1;
      glutIdleFunc(idle);
      break;
  }
}

void keyboard(unsigned char key, int x, int y){
  switch(key){
    case '\033':
    case 'q':
      exit(0);
      break;
  }
}

void init(void){
  glClearColor(1.0, 1.0, 1.0, 0.0);
  glEnable(GL_DEPTH_TEST);
  glEnable(GL_CULL_FACE);
  glEnable(GL_LIGHTING);
  glEnable(GL_LIGHT0);
}

int main(int argc, char** argv){
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
  glutCreateWindow(argv[0]);
  glutDisplayFunc(display);
  glutReshapeFunc(resize);
  glutKeyboardFunc(keyboard);
  glutSpecialFunc(specialkeydown);
  glutSpecialUpFunc(specialkeyup);
  init();
  glutMainLoop();
  return 0;
}
# gcc core.c -o game -framework GLUT -framework OpenGL -mmacosx-version-min=10.8

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-11-28-16-07-18