銀月の符号

Python 使い見習いの日記・雑記

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()