シューティングゲーム

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include "display.h"
 
void displayMain(){
    glClear(GL_COLOR_BUFFER_BIT);
 
    float test1 = 1.0f;
    int test2 = 23;
 
    // font test
    fontBegin();
    fontSetPosition(0.0, 100.0);
    fontSetSize(FONT_DEFAULT_SIZE * 0.25);
    fontSetWeight(1.0);
    fontSetColor(0, 0, 255);
    fontDraw("float:%f, int:%d", test1, test2);
    fontEnd();
 
    glutSwapBuffers();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#ifndef __HEADER_FONT
#define __HEADER_FONT
 
#define FONT_DEFAULT_SIZE (100.0f)
 
void fontBegin();
void fontEnd();
 
void fontSetPosition(float _x, float _y);
void fontSetSize(float _size);
void fontSetWeight(float _weight);
void fontSetColor(unsigined char _red, unsigned char _green, unsigned char _blue);
void fontDraw(const char *format, ...);
 
#endif
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include "font.h"
 
#include <GL/glut.h>
#include <stdio.h>
#include <stdarg.h> // 可変長引数の関数を実装
 
static float positionX;  // staticは静的記憶クラス
static float positionY;
static float size = FONT_DEFAULT_SIZE;
static float weight = 1.0;
 
void fontBegin(){
    glPushMatrix();
    glPushAttrib(GL_ALL_ATTRIB_BITS);
 
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
 
    GLint viewport[4];
    glGetIntegerv(GL_VIEWPORT, viewport);
    gluOrtho2D(0, viewport[2], viewport[3], 0);
 
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}
 
void fontEnd(){
    glPopMatrix();
    glPopAttrib();
}
 
void fontSetPosition(float _x, float _y){
    positionX = _x;
    positionY = _y;
}
 
void fontSetSize(float _size){
    size = _size;
}
 
void fontSetWeight(float _weight){
    weight = _weight;
}
 
void fontSetColor(unsigned char _red, unsigned char _green, unsigned char _blue){
    color[0] = red;
    color[1] = green;
    color[2] = blue;
}
 
void fontDraw(const char *format, ...){
    va_list argList;
    va_start(argList, format);
    char str[256];
    vsprintf(str, format, argList);
    va_end(argList);
 
    glLineWidth(weight);
    glColor3ub(color[0], color[1], color[2]);
    glPushMatrix();
 
    glTranslatef(positionX, positionY + size, 0.0);
    float s = size / FONT_DEFAULT_SIZE;
    glScalef(s, -s, s);
    for(char *p = str; *p != '\0'; p++)
        glutStrokeCharacter(CLUT_STROKE_ROMAN, *p);
 
    glPopMatrix();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
main: main.c game.o display.o font.o
    gcc main.c game.o display.o font.o -o main -lglut -lGLU -lGL
 
game.o: game.c game.h define.h display.h
    gcc -c game.c -o game.o -lglut -lGLU -lGL
 
display.o: display.c display.h
    gcc -c display.c -o display.o -lglut -lGLU -lGL
 
font.o: font.c font.h
    gcc -c font.c -o font.o -lglut -lGLU -lGL
 
clean:
    rm -rf main *.o

$ make
gcc -c display.c -o display.o -lglut -lGLU -lGL
display.c: In function ‘displayMain’:
display.c:4:2: warning: implicit declaration of function ‘glClear’ [-Wimplicit-function-declaration]
glClear(GL_COLOR_BUFFER_BIT);
^~~~~~~
display.c:4:10: error: ‘GL_COLOR_BUFFER_BIT’ undeclared (first use in this function)
glClear(GL_COLOR_BUFFER_BIT);
^~~~~~~~~~~~~~~~~~~
display.c:4:10: note: each undeclared identifier is reported only once for each function it appears in
display.c:10:2: warning: implicit declaration of function ‘fontBegin’ [-Wimplicit-function-declaration]
fontBegin();
^~~~~~~~~
display.c:11:2: warning: implicit declaration of function ‘fontSetPosition’ [-Wimplicit-function-declaration]
fontSetPosition(0.0, 100.0);
^~~~~~~~~~~~~~~
display.c:12:2: warning: implicit declaration of function ‘fontSetSize’ [-Wimplicit-function-declaration]
fontSetSize(FONT_DEFAULT_SIZE * 0.25);
^~~~~~~~~~~
display.c:12:14: error: ‘FONT_DEFAULT_SIZE’ undeclared (first use in this function)
fontSetSize(FONT_DEFAULT_SIZE * 0.25);
^~~~~~~~~~~~~~~~~
display.c:13:2: warning: implicit declaration of function ‘fontSetWeight’ [-Wimplicit-function-declaration]
fontSetWeight(1.0);
^~~~~~~~~~~~~
display.c:14:2: warning: implicit declaration of function ‘fontSetColor’ [-Wimplicit-function-declaration]
fontSetColor(0, 0, 255);
^~~~~~~~~~~~
display.c:15:2: warning: implicit declaration of function ‘fontDraw’ [-Wimplicit-function-declaration]
fontDraw(“float:%f, int:%d”, test1, test2);
^~~~~~~~
display.c:16:2: warning: implicit declaration of function ‘fontEnd’ [-Wimplicit-function-declaration]
fontEnd();
^~~~~~~
display.c:18:2: warning: implicit declaration of function ‘glutSwapBuffers’ [-Wimplicit-function-declaration]
glutSwapBuffers();
^~~~~~~~~~~~~~~
GNUmakefile:8: recipe for target ‘display.o’ failed
make: *** [display.o] Error 1

何故だーーーーーー

[C言語]Makefile2

main.c // 初期化、ゲーム実行処理

1
2
3
4
5
6
7
8
9
#include "game.h"
 
int main(int argc, char *argv[]){ // コマンドライン引数 int argcは引数の個数、char *argvは引数の文字列
    gameInit(&argc, argv);
 
    gameRun();
 
    return 0;
}

game.h

1
2
3
4
5
6
7
8
#ifndef __HEADER_GAME
 
#define __HEADER_GAME
 
void gameInit(int *argc, char **argv);
void gameRun();
 
#endif

game.c  // glut初期化 ※glInit

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include "game.h"
 
#include <GL/glut.h>
#include "define.h"
#include "display.h"
 
void glInit(int *argc, char **argv);
 
void gameInit(int *argc, char **argv){
    glInit(argc, argv);
}
 
void gameRun(){
    glutMainLoop();
}
 
void glInit(int *argc, char **argv){
    glutInit(argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE);
    glutInitWindowPosition(100, 100);
    glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT);
    glutCreateWindow("myGame");
    glutDisplayFunc(displayMain);
}

define.h

1
2
3
4
5
6
7
8
#ifndef __HEADER_DEFINE
 
#define __HEADER_DEFINE
 
#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480
 
#endif

display.h

1
2
3
4
5
6
7
#ifndef __HEADER_DISPLAY
 
#define __HEADER_DISPLAY
 
void displayMain();
 
#endif

display.c  // ゲーム処理

1
2
3
4
5
#include "display.h"
 
void displayMain(){
     
}

GNUmakefile // コンパイル

1
2
3
4
5
6
7
8
9
10
11
main: main.c game.o display.o
    gcc main.c game.o display.o -o main -lglut -lGLU -lGL
 
game.o: game.c game.h define.h display.h
    gcc -c game.c -o game.o -lglut -lGLU -lGL
 
display.o: display.c display.h
    gcc -c display.c -o display.o -lglut -lGLU -lGL
 
clean:
    rm -rf main *.o

$ make
gcc -c game.c -o game.o -lglut -lGLU -lGL
gcc -c display.c -o display.o -lglut -lGLU -lGL
gcc main.c game.o display.o -o main -lglut -lGLU -lGL

[C言語]Makefile

各ファイルとコンパイルに必要なコマンド、ファイル間の依存関係を書く

makeの種類
– Microsoft nmake (Windows)
– Borland make (Windows)
– GNU make (windows, UNIX 系)
– Solaris make (Solaris)

hello.c

1
2
3
4
5
6
#include <stdio.h>
 
int main(int argc, char *argv[]){
    printf("Hello C\n");
    return 0;
}

GNUmakefile

1
2
hello: hello.c
    gcc -Wall -O2 -o hello hello.c

依存関係行

1
2
3
4
5
6
7
8
9
10
11
hello: hello.c
    gcc -Wall -O2 -o hello hello.c print.o
 
hello.o: hello.c
    gcc -c hello.c
 
print.o: print.c
    gcc -c print.c
 
clean:
    rm -f hello hello.o print.o

make cleanで不要なファイルを削除する

#ifndefと#endif

機能 :識別子が定義されていないかどうかの判定
書式 :
#ifndef <識別子名>
<処理>
詳細 :<識別子名>が未定義なら<処理>を実行。<処理>が複数行にわたる場合は、処理ブロックの最後を示すために#endifを記述。

1
2
#ifndef ARRAY_H // 二重でincludeされることを防ぐ
#define ARRAY_H

複数のソースから array.hがインクルードされていたとしても、 確実に1度だけ array.hの中身を有効にすることができる

array.hをARRAY_Hと書くのはコンベンションか?
特殊な書き方のような印象

[C言語]ヘッダファイルの使い方

### main.c
ヘッダファイルはダブルクオテーションで囲む

#include 
#include "array.h"


int main(){

	int size = 5;
	
	int a[size]; range(a, size, 1, 1);
	int b[size]; range(b, size, 1, -1);
	int c[size]; init(c, size, 0);

	printf("a = ");print(a, size);
	printf("b = ");print(b, size);
	printf("c = ");print(c, size);


	// void init(int *a, int size, int num){
	// 	for(int i = 0; i < size; i++){
	// 		a[i] = num;
	// 	}
	// }

	// for(int i = 0; i < size; i++){
	// 	a[i] = 1 + i * 1;
	// 	b[i] = 1 + i * (-1);
	// }

	// int a[size] = {1, 2, 3, 4, 5};
	// int b[size] = {1, 0, -1, -2, -3};

	for(int i = 0; i < size; i++){
		c[i] = a[i] + b[i];
	}
	printf("\n");
	printf("c = ");print(c, size);

	return 0;
}

array.c

#include 
#include "array.h"

void range(int *a, int size, int start, int step){
		for(int i = 0; i < size; i++){
			a[i] = start + i*step;
		}
	}

void init(int *a, int size, int num){
	for(int i = 0; i < size; i++){
		a[i] = num;
	}
}

void zeros(int *a, int size){
	for(int i = 0; i < size; i++){
		a[i] = 0;
	}
}

void print(int *a, int size){
	printf("[");
	for(int i = 0; i < size; i++){
		printf("%d,", a[i]);
	}
	printf("\b]\n");
}

### ヘッダ
array.h

#ifndef ARRAY_H // 二重でincludeされることを防ぐ
#define ARRAY_H

void range(int *a, int size, int start, int step);
void init(int *a, int size, int num);
void zeros(int *a, int size);
void print(int *a, int size);

#endif

### コンパイル&実行
$ gcc -O2 -o main main.c array.c
$ ./main
a = [1,2,3,4,5]
b = [1,0,-1,-2,-3]
c = [0,0,0,0,0]

c = [2,2,2,2,2]

[C言語]GLUTの隠面消去処理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#include <stdlib.h>
#include <GL/glut.h>
 
GLdouble vertex[][3] = {
    {0.0, 0.0, 0.0},
    {1.0, 0.0, 0.0},
    {1.0, 1.0, 0.0},
    {0.0, 1.0, 0.0},
    {0.0, 0.0, 1.0},
    {1.0, 0.0, 1.0},
    {1.0, 1.0, 1.0},
    {0.0, 1.0, 1.0}
};
 
int face[][4] = {
    {0, 1, 2, 3},
    {1, 5, 6, 2},
    {5, 4, 7, 6},
    {4, 0, 3, 7},
    {4, 5, 1, 0},
    {3, 2, 6, 7},
};
 
GLdouble color[][3] = {
    {1.0, 0.0, 0.0},
    {0.0, 1.0, 0.0},
    {0.0, 0.0, 1.0},
    {1.0, 1.0, 0.0},
    {1.0, 0.0, 1.0},
    {0.0, 1.0, 1.0},
};
 
void idle(void){
    glutPostRedisplay();
}
 
void display(void){
    int i;
    int j;
    static int r = 0; /* 回転角 */
 
    glClear(GL_COLOR_BUFFER_BIT);
     
    glLoadIdentity();
 
    /* 視点位置と視点方向 */
    gluLookAt(3.0, 4.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
 
    /* 図形の回転 */
    glRotated((double)r, 0.0, 1.0, 0.0);
 
    /* 図形の描画 */
    glBegin(GL_QUADS);
    for(j = 0; j < 6; ++j){
        glColor3dv(color&#91;j&#93;);
        for(i = 0; i < 4; ++i){
            glVertex3dv(vertex&#91;face&#91;j&#93;&#91;i&#93;&#93;);
        }
    }
    glEnd();
     
    glutSwapBuffers();
 
    /* 一周回ったら回転角を0に戻す */
    if(++r >= 360) r = 0;
}
 
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 mouse(int button, int state, int x, int y){
    switch(button){
        case GLUT_LEFT_BUTTON:
            if(state == GLUT_DOWN){
                glutIdleFunc(idle);
            } else {
                glutIdleFunc(0);
            }
            break;
        case GLUT_RIGHT_BUTTON:
            if (state == GLUT_DOWN){
                glutPostRedisplay();
            }
            break;
        default:
            break;
    }
}
 
void keyboard(unsigned char key, int x, int y){
    switch(key){
        case 'q':
        case 'Q':
        case '\033':
            exit(0);
        default:
            break;
    }
}
 
void init(void){
    glClearColor(1.0, 1.0, 1.0, 1.0);
}
 
int main(int argc, char *argv[]){
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGBA);
    glutCreateWindow(argv[0]);
    glutDisplayFunc(display);
    glutReshapeFunc(resize);
    glutMouseFunc(mouse);
    glutKeyboardFunc(keyboard);
    init();
    glutMainLoop();
    return 0;
}

[C言語]GLUTでアニメーション

– プログラム中でウィンドウの再描画イベントを発生させるには, glutPostRedisplay() 関数を用いる
– 繰り返し描画を行うには, 描画の度に座標変換の行列を設定する必要がある
– 座標変換のプロセス
 L 図形の空間中での位置を決める「モデリング変換」
 L その空間を視点から見た空間に直す「ビューイング (視野) 変換」
 L その空間をコンピュータ内の空間にあるスクリーンに投影する「透視変換」
 L スクリーン上の図形をディスプレイ上の表示領域に切り出す「ビューポート変換」

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#include <stdlib.h>
#include <GL/glut.h>
 
GLdouble vertex[][3] = {
    {0.0, 0.0, 0.0},
    {1.0, 0.0, 0.0},
    {1.0, 1.0, 0.0},
    {0.0, 1.0, 0.0},
    {0.0, 0.0, 1.0},
    {1.0, 0.0, 1.0},
    {1.0, 1.0, 1.0},
    {0.0, 1.0, 1.0}
};
 
int edge[][2] = {
    {0, 1},
    {1, 2},
    {2, 3},
    {3, 0},
    {4, 5},
    {5, 6},
    {6, 7},
    {7, 4},
    {0, 4},
    {1, 5},
    {2, 6},
    {3, 7}
};
 
void idle(void){
    glutPostRedisplay();
}
 
void display(void){
    int i;
    static int r = 0; /* 回転角 */
 
    glClear(GL_COLOR_BUFFER_BIT);
     
    glLoadIdentity();
 
    /* 視点位置と視点方向 */
    gluLookAt(3.0, 4.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
 
    /* 図形の回転 */
    glRotated((double)r, 0.0, 1.0, 0.0);
 
    /* 図形の描画 */
    glColor3d(0.0, 0.0, 0.0);
    glBegin(GL_LINES);
    for(i = 0; i < 12; ++i){
        glVertex3dv(vertex&#91;edge&#91;i&#93;&#91;0&#93;&#93;);
        glVertex3dv(vertex&#91;edge&#91;i&#93;&#91;1&#93;&#93;);
    }
    glEnd();
    glFlush();
 
    /* 一周回ったら回転角を0に戻す */
    if(++r >= 360) r = 0;
}
 
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 mouse(int button, int state, int x, int y){
    switch(button){
        case GLUT_LEFT_BUTTON:
            if(state == GLUT_DOWN){
                glutIdleFunc(idle);
            } else {
                glutIdleFunc(0);
            }
            break;
        case GLUT_RIGHT_BUTTON:
            if (state == GLUT_DOWN){
                glutPostRedisplay();
            }
            break;
        default:
            break;
    }
}
 
void keyboard(unsigned char key, int x, int y){
    switch(key){
        case 'q':
        case 'Q':
        case '\033':
            exit(0);
        default:
            break;
    }
}
 
void init(void){
    glClearColor(1.0, 1.0, 1.0, 1.0);
}
 
int main(int argc, char *argv[]){
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGBA);
    glutCreateWindow(argv[0]);
    glutDisplayFunc(display);
    glutReshapeFunc(resize);
    glutMouseFunc(mouse);
    glutKeyboardFunc(keyboard);
    init();
    glutMainLoop();
    return 0;
}

[C言語]GLUTで三次元図形

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <GL/glut.h>
 
void display(void){
    glClear(GL_COLOR_BUFFER_BIT);
    glRotated(25.0, 0.0, 1.0, 0.0);
    glBegin(GL_POLYGON);
    glColor3d(1.0, 0.0, 0.0);
    glVertex2d(-0.9, -0.9);
    glColor3d(0.0, 1.0, 0.0);
    glVertex2d(0.9, -0.9);
    glColor3d(0.0, 0.0, 1.0);
    glVertex2d(0.9, 0.9);
    glColor3d(1.0, 1.0, 0.0);
    glVertex2d(-0.9, 0.9);
    glEnd();
    glFlush();
}
 
void init(void){
    glClearColor(1.0, 1.0, 1.0, 1.0);
}
 
int main(int argc, char *argv[]){
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGBA);
    glutCreateWindow(argv[0]);
    glutDisplayFunc(display);
    init();
    glutMainLoop();
    return 0;
}


glRotated() による回転の行列が積算されている

### 線画を表示する

#include 

GLdouble vertex[][3] = {
	{0.0, 0.0, 0.0},
	{1.0, 0.0, 0.0},
	{1.0, 1.0, 0.0},
	{0.0, 1.0, 0.0},
	{0.0, 0.0, 1.0},
	{1.0, 0.0, 1.0},
	{1.0, 1.0, 1.0},
	{0.0, 1.0, 1.0}
};

int edge[][2] = {
	{0, 1},
	{1, 2},
	{2, 3},
	{3, 0},
	{4, 5},
	{5, 6},
	{6, 7},
	{7, 4},
	{0, 4},
	{1, 5},
	{2, 6},
	{3, 7}
};

void display(void){
	int i;

	glClear(GL_COLOR_BUFFER_BIT);
	
	/* 図形の描画 */
	glColor3d(0.0, 0.0, 0.0);
	glBegin(GL_LINES);
	for(i = 0; i < 12; ++i){
		glVertex3dv(vertex[edge[i][0]]);
		glVertex3dv(vertex[edge[i][1]]);
	}
	glEnd();
	glFlush(); 
}

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

	glLoadIdentity();
	gluPerspective(30.0, (double)w / (double)h, 1.0, 100.0);
	glTranslated(0.0, 0.0, -5.0);
}

void init(void){
	glClearColor(1.0, 1.0, 1.0, 1.0); 
}

int main(int argc, char *argv[]){
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGBA); 
	glutCreateWindow(argv[0]); 
	glutDisplayFunc(display);
	glutReshapeFunc(resize);
	init();
	glutMainLoop(); 
	return 0;
}

### 視点の位置を変更する
(3,4,5) の位置から原点 (0,0,0) を眺める

1
2
3
4
5
6
7
void resize(int w, int h){
    glViewport(0, 0, w, h);
 
    glLoadIdentity();
    gluPerspective(30.0, (double)w / (double)h, 1.0, 100.0);
    gluLookAt(3.0, 4.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
}

凄い。

[C言語]GLUTでキーボードの入力を読み取る

キーボード入力にはglutKeyboardFunc()を使う

#include 
#include 
#include 

#define MAXPOINTS 100 /* 記憶する点の数 */
GLint point[MAXPOINTS][2]; /* 座標を記憶する配列 */
int pointnum = 0; /* 記憶した座標の数 */
int rubberband = 0;  /* ラバーバンドの消去 */

void display(void){
	int i;

	glClear(GL_COLOR_BUFFER_BIT);

	if(pointnum > 1){
		glColor3d(0.0, 0.0, 0.0);
		glBegin(GL_LINES);
		for (i = 0; i < pointnum; ++i){
			glVertex2iv(point[i]);
		}
		glEnd();
	}
	glFlush(); 
}

void resize(int w, int h){
	glViewport(0, 0, w, h);
	glLoadIdentity();
	glOrtho(-0.5, (GLdouble)w - 0.5, (GLdouble)h - 0.5, -0.5, -1.0, 1.0);
}

void mouse(int button, int state, int x, int y){

	switch(button){
		case GLUT_LEFT_BUTTON:
			point[pointnum][0] = x;
			point[pointnum][1] = y;
			if(state == GLUT_UP){
				glColor3d(0.0, 0.0, 0.0);
				glBegin(GL_LINES);
				glVertex2iv(point[pointnum - 1]);
				glVertex2iv(point[pointnum]);
				glEnd();
				glFlush();

				rubberband = 0;
			} else {
			}
			if(pointnum < MAXPOINTS - 1) ++pointnum;
			break;
		case GLUT_MIDDLE_BUTTON:
			break;
		case GLUT_RIGHT_BUTTON:
			break;
		default:
			break;
	}
}

void motion(int x, int y){
	static GLint savepoint[2];

	/* 論理演算機能 ON */
	glEnable(GL_COLOR_LOGIC_OP); // 引数capに指定した機能を使用可能にする。
	glLogicOp(GL_INVERT); // 論理演算のタイプを指定

	glBegin(GL_LINES);
	if(rubberband){
		glVertex2iv(point[pointnum - 1]);
		glVertex2iv(savepoint);
	}
	/* 新しいラバーバンドを描く */
	glVertex2iv(point[pointnum - 1]);
	glVertex2i(x, y);
	glEnd();

	glFlush();

	/* 論理演算機能 OFF */
	glLogicOp(GL_COPY);
	glDisable(GL_COLOR_LOGIC_OP);

	/* 今描いたラバーバンドの端点を保存 */
	savepoint[0] = x;
	savepoint[1] = y;

	/* 今描いたラバーバンドは次のタイミングで消す*/
	rubberband = 1;
}

void keyboard(unsigned char key, int x, int y){
	switch(key){
		case 'q':
		case 'Q':
		case '\033':   /* '\033'はESCのASCIIコード */
			exit(0);
		default:
			break;
	}
}

void init(void){
	glClearColor(1.0, 1.0, 1.0, 1.0); 
}

int main(int argc, char *argv[]){
	glutInitWindowPosition(100, 100);
	glutInitWindowSize(320, 240);
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGBA); 
	glutCreateWindow(argv[0]); 
	glutDisplayFunc(display); 
	glutReshapeFunc(resize);
	glutMouseFunc(mouse);
	glutMotionFunc(motion); // マウスを動かした時に実行する引数を与える
	glutKeyboardFunc(keyboard);
	init();
	glutMainLoop(); 
	return 0;
}

exit(0)で終了する。
なるほど、viなどもq, Q, \033でexit(0)の処理を入れているのか。

[C言語]GLUTのマウスをドラッグ

#include 
#include 

#define MAXPOINTS 100 /* 記憶する点の数 */
GLint point[MAXPOINTS][2]; /* 座標を記憶する配列 */
int pointnum = 0; /* 記憶した座標の数 */
int rubberband = 0;  /* ラバーバンドの消去 */

void display(void){
	int i;

	glClear(GL_COLOR_BUFFER_BIT);

	if(pointnum > 1){
		glColor3d(0.0, 0.0, 0.0);
		glBegin(GL_LINES);
		for (i = 0; i < pointnum; ++i){
			glVertex2iv(point[i]);
		}
		glEnd();
	}
	glFlush(); 
}

void resize(int w, int h){
	glViewport(0, 0, w, h);
	glLoadIdentity();
	glOrtho(-0.5, (GLdouble)w - 0.5, (GLdouble)h - 0.5, -0.5, -1.0, 1.0);
}

void mouse(int button, int state, int x, int y){

	switch(button){
		case GLUT_LEFT_BUTTON:
			point[pointnum][0] = x;
			point[pointnum][1] = y;
			if(state == GLUT_UP){
				glColor3d(0.0, 0.0, 0.0);
				glBegin(GL_LINES);
				glVertex2iv(point[pointnum - 1]);
				glVertex2iv(point[pointnum]);
				glEnd();
				glFlush();

				rubberband = 0;
			} else {
			}
			if(pointnum < MAXPOINTS - 1) ++pointnum;
			break;
		case GLUT_MIDDLE_BUTTON:
			break;
		case GLUT_RIGHT_BUTTON:
			break;
		default:
			break;
	}
}

void motion(int x, int y){
	static GLint savepoint[2];

	/* 論理演算機能 ON */
	glEnable(GL_COLOR_LOGIC_OP); // 引数capに指定した機能を使用可能にする。
	glLogicOp(GL_INVERT); // 論理演算のタイプを指定

	glBegin(GL_LINES);
	if(rubberband){
		glVertex2iv(point[pointnum - 1]);
		glVertex2iv(savepoint);
	}
	/* 新しいラバーバンドを描く */
	glVertex2iv(point[pointnum - 1]);
	glVertex2i(x, y);
	glEnd();

	glFlush();

	/* 論理演算機能 OFF */
	glLogicOp(GL_COPY);
	glDisable(GL_COLOR_LOGIC_OP);

	/* 今描いたラバーバンドの端点を保存 */
	savepoint[0] = x;
	savepoint[1] = y;

	/* 今描いたラバーバンドは次のタイミングで消す*/
	rubberband = 1;
}

void init(void){
	glClearColor(1.0, 1.0, 1.0, 1.0); 
}

int main(int argc, char *argv[]){
	glutInitWindowPosition(100, 100);
	glutInitWindowSize(320, 240);
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGBA); 
	glutCreateWindow(argv[0]); 
	glutDisplayFunc(display); 
	glutReshapeFunc(resize);
	glutMouseFunc(mouse);
	glutMotionFunc(motion); // マウスを動かした時に実行する引数を与える
	init();
	glutMainLoop(); 
	return 0;
}

キャプチャ

ラバーバンド:ゴムのひものように伸び縮み

何を論理演算してるのかよくわからんな。