//python #!/usr/bin/env python # -*- coding: utf-8 -*- u""" PyGame + OpenGLのテストサンプル - Pキー : 平行投影/透視投影の切り替え - Wキー : ワイヤーフレーム/ソリッド表示の切り替え - Lキー : 照明のon/off - Tキー : テクスチャ設定の切り替え(3種類) - Sキー : ポイントスプライトの切り替え - Fキー : ウインドウ/フルスクリーン切り替え - カーソルキー : ティーポットの回転 - Bキー : Pause - ESCキー,Qキー : 終了 - マウスカーソルの位置に合わせて図形の表示位置を変える。 参考ページ: pygameに移行 — メモ庫 v1.0 documentation http://gunload.web.fc2.com/opengl/tutorial/skinning/pygame/ PyOpenGL + PIL でテクスチャ貼り - 銀月の符号 http://d.hatena.ne.jp/fgshun/20080922/1222095288 Wiki - pygame - python game development http://www.pygame.org/wiki/SimpleOpenGL2dClasses """ import pygame from OpenGL.GL import * from OpenGL.GLU import * from OpenGL.GLUT import * from OpenGL.extensions import alternate from OpenGL.GL.ARB.point_parameters import * from OpenGL.GL.EXT.point_parameters import * import Image import math # 照明 light_ambient = [1.0, 1.0, 1.0, 1.0] # 環境光(白色) light_diffuse = [1.0, 1.0, 1.0, 1.0] # 拡散光(白色) light_specular = [1.0, 1.0, 1.0, 1.0] # 鏡面光(白色) light_position = [2.0, 2.0, 1.0, 1.0] # 照明の位置 # マテリアル no_mat = [0.0, 0.0, 0.0, 1.0] # 反射しない mat_ambient = [0.0, 0.0, 0.3, 1.0] # 環境光の青成分だけ少し反射 mat_diffuse = [0.0, 1.0, 0.0, 1.0] # 拡散光の緑成分を全反射 mat_specular = [1.0, 1.0, 1.0, 1.0] # 鏡面光の全成分を全反射 mat_emission = [0.3, 0.3, 0.2, 0.0] # 放射の色 no_shininess = [0.0] # 鏡面反射しない low_shininess = [5.0] # 弱い鏡面反射 high_shininess = [100.0] # 強い鏡面反射 glPointParameterf = alternate( glPointParameterf, glPointParameterfARB, glPointParameterfEXT ) glPointParameterfv = alternate( glPointParameterfv, glPointParameterfvARB, glPointParameterfEXT ) RESET_ATTENUATION = [1.0, 1.0, 1.0] class PyGame: def __init__(self): """コンストラクタ""" self._running = True self._screen = None self.frame = 0 # フレームカウンタ self.mx = 0 self.my = 0 self.tex = [] self.cap = "" self.pausefg = False # キー操作で変更するフラグ群 self.flag2d = True # 平行/透視投影 self.wireframe = False # ワイヤーフレーム/ソリッド表示 self.light_enable = True # 照明 on/off self.tex_mode = 0 # テクスチャモード self.point_spr = False # ポイントスプライト on/ff self.fullscr = False # フルスクリーン/ウインドウ表示 self.filter_type = 0 # テクスチャのフィルタ種類(0 or 1) self.tex_repeat = False # テクスチャをリピートさせるか否か self.line_width = 1.0 # ワイヤーフレーム表示時の線の太さ # 画面の縦横幅記録用 self.view_wh = 1.0 self.view_hh = 1.0 # テクスチャ付きポリゴンの色指定用 self.texcol = 0.0 self.texcol_spd = 0.01 self.angle = 0.0 # 回転角度 self.scale = 0.0 # 拡大縮小 self.xrot = 0.0 # 回転角度 self.yrot = 0.0 self.xspeed = 0.0 # 回転速度 self.yspeed = 0.0 self.mvfrm = 0 # eventの分岐をディクショナリに変更 self._eventMap = { pygame.QUIT: self.onQuit, pygame.MOUSEBUTTONDOWN: self.onMouseDown, pygame.MOUSEBUTTONUP: self.onMouseUp, pygame.MOUSEMOTION: self.onMouseMotion, pygame.KEYDOWN: self.onKeyDown, pygame.KEYUP: self.onKeyUp, } def initialize(self, w, h): """初期化処理""" pygame.init() # PyGame初期化 self.scrw = float(w) self.scrh = float(h) return self.init_gl() def init_gl(self): """OpenGL関係の初期化""" w = int(self.scrw) h = int(self.scrh) # OPENGL向けに初期化する modev = pygame.OPENGL | pygame.DOUBLEBUF if self.fullscr: modev |= pygame.FULLSCREEN self._screen = pygame.display.set_mode((w, h), modev) if not self._screen: return False glViewport(0, 0, int(self.scrw), int(self.scrh)) glClearColor(0.0, 0.0, 0.5, 1.0) # クリア色の設定 # 隠面消去、カリングを設定 glEnable(GL_DEPTH_TEST) glEnable(GL_CULL_FACE) glCullFace(GL_BACK) # 裏面をカリング # 照明の設定 glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient) glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse) glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular) glLightfv(GL_LIGHT0, GL_POSITION, light_position) glEnable(GL_LIGHTING) # 照明を有効化 glEnable(GL_LIGHT0) # 0番目の照明を有効化 # テクスチャの読み込み glEnable(GL_TEXTURE_2D) # テクスチャ有効化 t = self.loadImage('res/tex1.png') self.tex.append(t[0]) t = self.loadImage('res/tex2.png') self.tex.append(t[0]) t = self.loadImage('res/tex4.png') self.tex.append(t[0]) # ウインドウ内の座標値を計算して記録 # (-w ~ 0.0 ~ +w, +h ~ 0.0 ~ -h) s = 8.0 self.view_wh = s * (self.scrw / self.scrh) self.view_hh = s if self.flag2d: self.set_view2d() else: self.set_view3d() return True def loadImage(self, image_fila_path): """テクスチャ画像をロード""" # PyGameを使って画像ロード textureSurface = pygame.image.load(image_fila_path) # 画像読み込み width = textureSurface.get_width() # 横幅取得 height = textureSurface.get_height() # 縦幅取得 # OpenGLに渡すために文字列化 textureData = pygame.image.tostring(textureSurface, "RGBA", False) texture = glGenTextures(1) # テクスチャを1枚生成 glBindTexture(GL_TEXTURE_2D, texture) # テクスチャとして登録 # _S は横方向、_T は縦方向 # テクスチャをリピートさせるかしないか if self.tex_repeat: glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT) else: glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP) # _MAG_FILTER は拡大時のフィルタ種類, _MIN_ は縮小? if self.filter_type == 0: glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST) else: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) # glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL) # glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE) glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE) # ポイントスプライトにも使えるように設定 glTexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE) # テクスチャを設定 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureData) # アルファテストの判別関数 # コレを入れないとポイントスプライトを透過できない glAlphaFunc(GL_GREATER, 0.5) return texture, width, height def set_view2d(self): """2D描画用に設定""" # 座標系の設定 glMatrixMode(GL_PROJECTION) # 射影変換 glLoadIdentity() # 単位行列 # 以後、平行投影で描画するよう指定 glOrtho(-self.view_wh, self.view_wh, - self.view_hh, self.view_hh, 0.1, 100.0) # 以下のように書けば、2Dっぽい座標系になる # gluOrtho2D(0, 640, 480, 0) def set_view3d(self): """3D描画用に設定""" glMatrixMode(GL_PROJECTION) glLoadIdentity() # 以後、透視投影で描画するよう指定 gluPerspective(60.0, self.scrw / self.scrh, 0.1, 100.0) def set_tex_mode(self): """テクスチャモードの切り替え""" md = [ GL_REPLACE, GL_MODULATE, GL_DECAL ] glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, md[self.tex_mode]) def update(self): """毎フレーム呼ばれる処理""" if not self.pausefg: # マウス座標を表示系の座標値に変換して記録 wh = self.scrw / 2.0 hh = self.scrh / 2.0 self.tx = (self.mx - wh) / wh self.ty = (self.scrh - self.my - hh) / hh self.tx *= self.view_wh self.ty *= self.view_hh self.angle += 1.5 # 角度を更新 self.scale = 2.0 * math.cos(math.radians(self.mvfrm)) + 2.5 self.xrot += self.xspeed self.yrot += self.yspeed # オブジェクトの色指定用変数を変更 self.texcol += self.texcol_spd if self.texcol >= 1.0 or self.texcol <= 0.0: self.texcol_spd *= -1 self.mvfrm += 1 def draw(self): """描画処理""" # OpenGLバッファのクリア glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) # 視野変換:カメラの位置と方向のセット # gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) # glShadeModel(GL_FLAT) # フラットシェーディングを有効化 glShadeModel(GL_SMOOTH) # スムースシェーディングを有効化 glEnable(GL_NORMALIZE) # 法線の自動正規化を有効化 # 平行投影/透視投影を設定 if self.flag2d: self.set_view2d() else: self.set_view3d() # 照明の有効/無効化 if self.light_enable: glEnable(GL_LIGHTING) else: glDisable(GL_LIGHTING) glMatrixMode(GL_MODELVIEW) glLoadIdentity() self.draw_teapot() # ティーポットを描画 self.draw_ball() # 球を描画 self.draw_cube() # 箱を描画 glDisable(GL_LIGHTING) # 照明無効化 self.draw_point(-self.angle / 4.0, self.view_hh * 0.5) # 点を描画 x = self.tx y = self.ty w = self.view_wh h = self.view_hh # テクスチャ付きポリゴンを描画(テクスチャ1) tx = 0.0 ty = 0.0 tz = -60.0 texid = 0 self.draw_polygon_tex(tx, ty, tz, 1.0, 1.0, h, h, texid) # テクスチャ付きポリゴンを描画(テクスチャ2) tx = self.view_wh / 3 tz = -40.0 texid = 1 self.draw_polygon_tex(tx, ty, tz, 1.0, 1.0, h, h, texid) self.set_view2d() # 平行投影にするよう設定 glDisable(GL_DEPTH_TEST) # 隠面消去を無効 glDisable(GL_CULL_FACE) # カリング無効化 glClear(GL_DEPTH_BUFFER_BIT) # デプスバッファクリア glMatrixMode(GL_MODELVIEW) glLoadIdentity() self.draw_box(x, y, w, h) # 赤いグラデの四角形を描画 self.draw_tri(x, y, w, h) # 緑のグラデの三角形を描画 self.draw_line(x, y, w, h) # 線を描画 # テキストを描画 self.draw_info() # バッファ切り替え (ダブルバッファ時) # glutSwapBuffers() # OpenGL描画実行 (シングルバッファ時?) # glFlush() # pygameダブルバッファ交換 pygame.display.flip() def draw_text(self, x, y, st): """文字列をビットマップフォントで描画""" glColor3f(1.0, 1.0, 1.0) glRasterPos3f(x, y, -3.0) for s in st: glutBitmapCharacter(GLUT_BITMAP_HELVETICA_10, ord(s)) def draw_info(self): """現在の状態をテキスト描画する""" lyadd = -(self.view_hh / 12.0) lx = -(self.view_wh * 0.95) ly = self.view_hh + lyadd strlist = [] strlist.append(self.cap) strlist.append("P: " + ("Pers" if not self.flag2d else "Ortho")) strlist.append("W: " + ("Wireframe" if self.wireframe else "Solid")) strlist.append("L: Light " + ("On" if self.light_enable else "Off")) strlist.append("T: " + (["GL_REPLACE", "GL_MODULATE", "GL_DECAL"][self.tex_mode])) strlist.append("S: PointSprite " + ("On" if self.point_spr else "Off")) strlist.append("F: " + ("Full" if self.fullscr else "Wdw")) strlist.append("B: Pause") strlist.append("ESC,Q : EXIT") for s in strlist: self.draw_text(lx, ly, s) ly += lyadd def draw_polygon_tex(self, x, y, z, tx, ty, vx, vy, texid): """テクスチャ付きポリゴンを描画""" col = self.texcol glFrontFace(GL_CCW) # 頂点反時計回りを表として扱う # 頂点配列を作成 vertices = [-1.0, -1.0, 0.0, # 左下 1.0, -1.0, 0.0, # 右下 1.0, 1.0, -25.0, # 右上 - 1.0, 1.0, -25.0 # 左上 ] # テクスチャ座標配列を作成 texcoords = [0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0 ] # カラー配列を作成 colors = [col, col, 0.5, 1.0, col, col, 0.5, 1.0, col, col, 0.0, 1.0, col, col, 0.0, 1.0 ] # 使うテクスチャを選択 glBindTexture(GL_TEXTURE_2D, self.tex[texid]) # テクスチャを透過にする glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); glLoadIdentity() glTranslatef(x, y, z) # 平行移動 glRotatef(self.angle / 2.0, 0.0, 0.0, 1.0) # 回転 glScale(vx, vy, 1.0) # 拡大縮小 # 頂点配列、テクスチャ座標配列、カラー配列有効化 glEnableClientState(GL_VERTEX_ARRAY) glEnableClientState(GL_TEXTURE_COORD_ARRAY) glEnableClientState(GL_COLOR_ARRAY) # 頂点配列、テクスチャ座標配列、カラー配列を指定 glVertexPointer(3, GL_FLOAT, 0, vertices) glTexCoordPointer(2, GL_FLOAT, 0, texcoords) glColorPointer(4, GL_FLOAT, 0, colors) glEnable(GL_TEXTURE_2D) # テクスチャを有効に # ポリゴンとして描画 glDrawElements(GL_QUADS, 4, GL_UNSIGNED_BYTE, [0, 1, 2, 3]) # glDrawArrays(GL_POLYGON, 0, 4) glDisable(GL_TEXTURE_2D) # テクスチャを無効に # 頂点配列、テクスチャ座標配列、カラー配列無効化 glDisableClientState(GL_VERTEX_ARRAY) glDisableClientState(GL_TEXTURE_COORD_ARRAY) glDisableClientState(GL_COLOR_ARRAY) def draw_box(self, x, y, w, h): """赤いグラデの四角形を描く""" glFrontFace(GL_CCW) # 頂点反時計回りを表とする h /= 10.0 w = h z = -40.0 glLoadIdentity() glBegin(GL_QUADS) # 描画開始 glColor3f(0.5, 0.0, 0.0) # 色を指定 glVertex3f(x - w, y - h, z) # 左下 glColor3f(0.5, 0.0, 0.0) glVertex3f(x + w, y - h, z) # 右下 glColor3f(1.0, 0.0, 0.0) glVertex3f(x + w, y + h, z) # 右上 glColor3f(1.0, 0.0, 0.0) glVertex3f(x - w, y + h, z) # 左上 glEnd() # 描画終了 def draw_tri(self, x, y, w, h): """緑のグラデの三角形を描く""" glFrontFace(GL_CCW) # 頂点反時計回りを表とする z = -50.0 glBegin(GL_TRIANGLES) # 三角形描画開始 glColor4f(0.0, 1.0, 0.0, 1.0) # 色を指定 glVertex3f(-w, -h, z) # 左下 glVertex3f(w, -h, z) # 右下 glColor4f(0.0, 0.2, 0.0, 0.2) glVertex3f(x, y, z) # 上 glEnd() def draw_line(self, x, y, w, h): """線を描く""" z = -5.0 glColor3f(0.0, 1.0, 1.0) # 水色 glLineWidth(self.line_width) # 線のサイズ glBegin(GL_LINES) glVertex3f(-w, y, z) # 始点 glVertex3f(w, y, z) # 終点 glVertex3f(x, h, z) # 始点 glVertex3f(x, -h, z) # 終点 glEnd() def draw_point(self, startang, r): """点を描く""" glLoadIdentity() z_d = 10 zadd = (float(self.mvfrm) / 5.0) % float(z_d) # アルファブレンディングを有効化 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) glEnable(GL_BLEND) if self.point_spr: # ポイントスプライト有効時 glEnable(GL_POINT_SPRITE) # ポイントスプライトを有効化 glDisable(GL_POINT_SMOOTH) # 点のAAを無効化 glEnable(GL_TEXTURE_2D) # テクスチャを有効化 # テクスチャに色指定を反映させるよう指定 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE) # 使うテクスチャを選択 glBindTexture(GL_TEXTURE_2D, self.tex[2]) glEnable(GL_ALPHA_TEST) # アルファテストを有効化 glPointSize(64.0) # 点のサイズを指定 # 距離に応じて点の大きさを変える glPointParameterfv(GL_POINT_DISTANCE_ATTENUATION, [0.0, 0.0, 0.02]) glBegin(GL_POINTS) # 点の描画開始を指定 lang = math.radians(startang) langadd = math.radians(20) for z in range(-40, -5, z_d): # 奥行を変えて描画 zz = z + zadd v = (30.0 + zz + 10.0) / 30.0 if v > 1.0: v = 1.0 for i in range(0, 360, 20): # 円を描くように描画 x = r * math.cos(lang) y = r * math.sin(lang) glColor3f(v, v, 0.5) # 色を指定 glVertex3f(x, y, zz) # 点座標を指定 lang += langadd glEnd() # 距離に応じて点のサイズを変えるソレに初期値を入れてリセット glPointParameterfv(GL_POINT_DISTANCE_ATTENUATION, [1.0, 0.0, 0.0]) glDisable(GL_ALPHA_TEST) # アルファテストを無効化 glDisable(GL_POINT_SPRITE) # ポイントスプライトを無効化 self.set_tex_mode() else: # ポイントスプライト無効時 glDisable(GL_TEXTURE_2D) # テクスチャを無効化 glDisable(GL_POINT_SPRITE) # point_sprite を無効化 glEnable(GL_POINT_SMOOTH) # 点のAAを有効化 glHint(GL_POINT_SMOOTH_HINT, GL_NICEST) # AAの品質を参考に glPointSize(3.0) # 点のサイズ # 距離に応じて点の大きさを変えない glPointParameterfv(GL_POINT_DISTANCE_ATTENUATION, [1.0, 0.0, 0.0]) glBegin(GL_POINTS) lang = math.radians(startang) langadd = math.radians(10) for z in range(-40, -5, z_d): # 奥行を変えて描画 zz = z + zadd v = (30.0 + zz + 10.0) / 30.0 if v > 1.0: v = 1.0 for i in range(0, 360, 10): # 円を描くように描画 x = r * math.cos(lang) y = r * math.sin(lang) glColor3f(v, v, 0.5) # 色を指定 glVertex3f(x, y, zz) # 点座標を指定 lang += langadd glEnd() glDisable(GL_TEXTURE_2D) # テクスチャを無効化 def set_material(self, kind): """マテリアルを設定""" matdata = [ [mat_ambient, mat_diffuse, no_mat, no_shininess, no_mat], [no_mat, mat_diffuse, mat_specular, low_shininess, no_mat], [no_mat, mat_diffuse, mat_specular, high_shininess, no_mat], [no_mat, mat_diffuse, no_mat, no_shininess, mat_emission] ] dt = matdata[kind] glMaterialfv(GL_FRONT, GL_AMBIENT, dt[0]) glMaterialfv(GL_FRONT, GL_DIFFUSE, dt[1]) glMaterialfv(GL_FRONT, GL_SPECULAR, dt[2]) glMaterialfv(GL_FRONT, GL_SHININESS, dt[3]) glMaterialfv(GL_FRONT, GL_EMISSION, dt[4]) def draw_teapot(self): """ティーポットを描く""" glFrontFace(GL_CW) # teapotは頂点時計回りが表。他と逆なので注意。 glEnable(GL_DEPTH_TEST) # 隠面消去を有効化 glDisable(GL_CULL_FACE) # カリング無効化 # teapotだけはテクスチャを反映できるので、テクスチャを無効にしておく。 # cubeやsphere等はテクスチャを反映できない。 glDisable(GL_TEXTURE_2D) self.set_material(1) # マテリアルの設定 # 平行移動、回転、拡大縮小は、 # 下に書いてある変換のほうから先に実行される glLoadIdentity() glTranslatef(-6.0, 0.0, -10.0) # 平行移動 glRotatef(self.xrot, 1.0, 0.0, 0.0) # x軸に沿って回転 glRotatef(self.yrot, 0.0, 1.0, 0.0) # y軸に沿って回転 glScale(1.0, 1.0, 1.0) # 拡大縮小 glColor3f(1.0, 0.0, 0.0) # 色を赤に(照明利用時は無視される) if self.wireframe: # ワイヤーフレームで描画 glLineWidth(self.line_width) # 線のサイズ glutWireTeapot(2.0) else: # ソリッドで描画 glutSolidTeapot(2.0) def draw_cube(self): """立方体を描画""" glFrontFace(GL_CCW) # cubeは頂点反時計回りが表扱い glEnable(GL_CULL_FACE) # カリング有効化 glCullFace(GL_BACK) # 裏面をカリングするように指定 self.set_material(0) # マテリアルの設定 glLoadIdentity() glTranslatef(0.0, 0.0, -15.0) glRotatef(self.angle, 0.0, 1.0, 1.0) # y軸、z軸に沿って回転 glScale(1.0, 1.0, self.scale / 2) glColor3f(0.0, 1.0, 0.0) # 色を緑に if self.wireframe: glLineWidth(self.line_width) glutWireCube(3.0) else: glutSolidCube(3.0) def draw_ball(self): """球を描画""" glFrontFace(GL_CCW) # 球は頂点反時計回りが表扱い glEnable(GL_CULL_FACE) glCullFace(GL_BACK) self.set_material(2) # マテリアルの設定 glLoadIdentity() glTranslatef(6.0, 0.0, -20.0) glRotatef(self.angle, 1.0, 0.0, 0.0) # x軸に沿って回転 glScale(1.0, self.scale, 1.0) glColor3f(1.0, 0.0, 1.0) # 色を紫に if self.wireframe: glLineWidth(self.line_width) glutWireSphere(1.0, 10, 10) else: glutSolidSphere(1.0, 10, 10) def on_event(self, event): """イベント発生時に呼ばれる処理""" if event.type in self._eventMap: self._eventMap[event.type](event) def onQuit(self, event): """メインループを終了させるよう設定""" self._running = False def onKeyDown(self, event): """キーが押された瞬間に呼ばれる処理""" if event.key == pygame.K_ESCAPE or event.unicode == u'q': # ESCキーかqキーが押されたので終了 pygame.event.post(pygame.event.Event(pygame.QUIT)) elif event.key == pygame.K_UP: # 上キーが押された self.xspeed -= 0.1 elif event.key == pygame.K_DOWN: # 下キーが押された self.xspeed += 0.1 elif event.key == pygame.K_LEFT: # 左キーが押された self.yspeed -= 0.1 elif event.key == pygame.K_RIGHT: # 右キーが押された self.yspeed += 0.1 elif event.key == pygame.K_l: # 照明のon/off self.light_enable = not self.light_enable elif event.key == pygame.K_p: # 平行投影/透視投影の切り替え self.flag2d = not self.flag2d elif event.key == pygame.K_w: # ワイヤーフレーム/ソリッド描画の切り替え self.wireframe = not self.wireframe elif event.key == pygame.K_t: # テクスチャモードの切り替え self.tex_mode = (self.tex_mode + 1) % 3 md = [GL_REPLACE, GL_MODULATE, GL_DECAL] glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, md[self.tex_mode]) elif event.key == pygame.K_f: # フルスクリーン/ウインドウの切り替え self.fullscr = not self.fullscr self.init_gl() elif event.key == pygame.K_s: # ポイントスプライトの切り替え self.point_spr = not self.point_spr elif event.key == pygame.K_b: # ポーズ self.pausefg = not self.pausefg else: print("KeyDown", event.unicode, event.key, event.mod) def onKeyUp(self, event): """キーが離された瞬間に呼ばれる処理""" # print("KeyUp", event.key, event.mod) pass def onMouseDown(self, event): """マウスボタンが押された瞬間に呼ばれる処理""" lis = [ 'unknown', # 0 'left', # 1 'middle', # 2 'right', # 3 'wheelup', # 4 'wheeldown' # 5 ] if event.button <= 5: print('onMouseDown', lis[event.button], event.pos) def onMouseUp(self, event): """マウスボタンが離された瞬間に呼ばれる処理""" lis = [ 'unknown', # 0 'left', # 1 'middle', # 2 'right', # 3 'wheelup', # 4 'wheeldown' # 5 ] if event.button <= 5: print('onMouseUp ', lis[event.button], event.pos) def onMouseMotion(self, event): """マウスカーソルが動いた時に呼ばれる処理""" # print('onMouseMotion', event.pos, event.rel, event.buttons) self.mx = event.pos[0] self.my = event.pos[1] def execute(self, w, h): if not self.initialize(w, h): return timer = pygame.time.Clock() # メインループ while self._running: timer.tick(60) # 60FPSを指定 for event in pygame.event.get(): self.on_event(event) self.update() self.draw() self.frame += 1 self.cap = '%5.2f FPS' % (timer.get_fps()) # ウインドウタイトル文字列を指定 pygame.display.set_caption(self.cap) pygame.quit() if __name__ == "__main__" : game = PyGame() game.execute(800, 600)