PyOpenGL と Pygame 2日目(何も理解していない)
(9/23 オリジナル似コードを追加しました。)チラシの裏レベル。唐突に 3D でゲームもどき作ってみたくなってから2日経過。トライフォース回してみた。
PyOpenGL + Pygame で 描くのと Pygame で 2D 描くのとの違いは
- pygame.display.set_mode の第2引数に OPENGL フラグを入れる。
- 視点位置などの OpenGL 設定を要する。
- screen.blit による描画の代わりに glBegin 〜 glEnd 。
よくわかっていない状況でコード晒すのはいつもはしないところだけど、今回あえて挑戦。自重はダークサイド。
# coding: utf-8 u""" Pythonでゲーム作りますが何か? 神々のトライフォース http://pygame.skr.jp/index.php?%E7%A5%9E%E3%80%85%E3%81%AE%E3%83%88% E3%83%A9%E3%82%A4%E3%83%95%E3%82%A9%E3%83%BC%E3%82%B9 を GLUT 用から Pygame 用へ書き換えてみた """ import pygame import numpy from pygame.locals import * from OpenGL.GL import * from OpenGL.GLU import * #from OpenGL.GLUT import * class Triforce(object): orig_triangles = ( ((0.0, 0.8), (-0.4, 0.0), (0.4, 0.0)), ((-0.4, 0.0), (-0.8, -0.8), (0.0, -0.8)), ((0.4, 0.0), (0.0, -0.8), (0.8, -0.8)), ) def __init__(self, position=(0.0, 0.0), color=(1.0, 1.0, 0.0)): self.triangles = [numpy.array(L) + position for L in self.orig_triangles] self.color = color def draw(self): glColor3dv(self.color) glBegin(GL_TRIANGLES) for triangle in self.triangles: for point in triangle: glVertex2dv(point) glEnd() def move(self, x, y): for triangle in self.triangles: triangle += (x, y) def init(window_size): w, h = window_size glClearColor(0.0, 0.0, 0.0, 0.0) glEnable(GL_DEPTH_TEST) glViewport(0, 0, w, h) glMatrixMode(GL_PROJECTION) glLoadIdentity() gluPerspective(60.0, float(w) / float(h), 1.0, 100.0) glMatrixMode(GL_MODELVIEW) def draw(): glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glLoadIdentity() gluLookAt(0.0, 0.0, 3.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) glRotated(angle, 0.0, 1.0, 0.0) for o in objects: o.draw() glFlush() def exit_check(event, inkey=None): u""" 終了チェック """ if event.type == QUIT: return True if inkey is not None: if event.type == KEYDOWN and event.key == inkey: return True return False objects = [] angle = 0.0 def main(): global objects global angle window_size = (800, 600) screen = pygame.display.set_mode( window_size, OPENGL | DOUBLEBUF, ) pygame.display.set_caption(u'神々のトライフォース'.encode('utf-8')) init(window_size) clock = pygame.time.Clock() triforce = Triforce() objects.append(triforce) while True: clock.tick(30) angle += 4.0 angle %= 360 draw() pygame.display.flip() for event in pygame.event.get(): if exit_check(event, K_ESCAPE): return if __name__ == '__main__': pygame.init() main() pygame.quit()
参考
9/23追記
なるべくオリジナルの要素を残したものもアップ。オリジナルと見比べるとき用。
# coding: utf-8 u""" Pythonでゲーム作りますが何か? 神々のトライフォース http://pygame.skr.jp/index.php?%E7%A5%9E%E3%80%85%E3%81%AE%E3%83%88% E3%83%A9%E3%82%A4%E3%83%95%E3%82%A9%E3%83%BC%E3%82%B9 を GLUT 用から Pygame 用へ """ import pygame from pygame.locals import * from OpenGL.GL import * from OpenGL.GLU import * #from OpenGL.GLUT import * angle = 0.0 def main(): global angle window_size = (800, 600) screen = pygame.display.set_mode( window_size, OPENGL | DOUBLEBUF, ) pygame.display.set_caption(u'神々のトライフォース'.encode('utf-8')) w, h = window_size init() # 元 reshape の設定 # 画面サイズの切り替えはないので最初に一度だけ実行 glViewport(0, 0, w, h) glMatrixMode(GL_PROJECTION) glLoadIdentity() gluPerspective(60.0, float(w) / float(h), 1.0, 100.0) glMatrixMode(GL_MODELVIEW) clock = pygame.time.Clock() # ループ while True: clock.tick(30) # TODO: 長時間回すことによる、オーバーフローに注意 angle += 4.0 # ディスプレイ描画関数を明示的に呼ぶ # TODO: GLUT のような関数登録、ループ内で自動実行の # 機構をつくるのがよいかもしれない。 display() pygame.display.flip() for event in pygame.event.get(): if exit_check(event, K_ESCAPE): return def init(): glClearColor(0.0, 0.0, 0.0, 0.0) glEnable(GL_DEPTH_TEST) def display(): glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glColor3f(1.0, 1.0, 1.0) glLoadIdentity() gluLookAt(0.0, 0.0, 3.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) glRotatef(angle, 0.0, 1.0, 0.0) draw_triforce() glFlush() def draw_triforce(): u"""トライフォースを描画""" glColor3f(1.0, 1.0, 0.0) glBegin(GL_TRIANGLES) # 上の三角形 glVertex2f(0, 0.8) glVertex2f(-0.4, 0.0) glVertex2f(0.4, 0.0) # 左下の三角形 glVertex2f(-0.4, 0.0) glVertex2f(-0.8, -0.8) glVertex2f(0.0, -0.8) # 右下の三角形 glVertex2f(0.4, 0.0) glVertex2f(0.0, -0.8) glVertex2f(0.8, -0.8) glEnd() def exit_check(event, inkey=None): u""" 終了チェック """ if event.type == QUIT: return True if inkey is not None: if event.type == KEYDOWN and event.key == inkey: return True return False if __name__ == '__main__': pygame.init() main() pygame.quit()