パソコン日記

気づいたこと まとめてみる

ライフゲームをPythonで作ってみる(OpenGLでグラフィカルに実行する)

ライフゲームPythonOpenGL

これまでにライフゲームOpenGLPythonでのプログラムをご紹介いたしました。

1-compinfo.hatenablog.com 1-compinfo.hatenablog.com 1-compinfo.hatenablog.com

今回はOpenGLライフゲームをグラフィカルに描画してみました。 コードは次の通りに書いてみました。 モジュールはライフゲームを動かすlifegame.pyと OpenGLで描画するlifegameOpenGL.pyに分かれています。

lifegame.py

 #-*-coding:utf-8-*-
import random

class Lifegame():
    def __init__(self,xsize=10,ysize=10,initialField=[]):
        self.xsize = xsize
        self.ysize = ysize
        self.initialField = initialField
        self.generations = [self.initialField]

    def nextGeneration(self,field):
        xmax = self.xsize -1
        ymax = self.ysize -1
        newField = [[0 for i in range(self.xsize)] for j in range(self.ysize)] #新しい格子
        for y in range(self.ysize):
            for x in range(self.xsize):
                #注目するセルの周りで生きているセルを数える
                aliveCell = 0
                #左上
                if x != 0 and y != 0:
                    if field[y-1][x-1] == 1:
                        aliveCell += 1
                #左
                if x != 0:
                    if field[y][x-1] == 1:
                        aliveCell += 1
                #左下
                if x != 0 and y != ymax:
                    if field[y+1][x-1] == 1:
                        aliveCell += 1
                #上
                if y != 0:
                    if field[y-1][x] == 1:
                        aliveCell += 1
                #下
                if y != ymax:
                    if field[y+1][x] == 1:
                       aliveCell += 1
                #右上
                if x != xmax and y != 0:
                    if field[y-1][x+1] == 1:
                        aliveCell += 1
                #右
                if x != xmax:
                    if field[y][x+1] == 1:
                        aliveCell += 1
                #右下
                if x != xmax and y != ymax:
                    if field[y+1][x+1] == 1:
                        aliveCell += 1

                #注目するセルが死んでいる
                if field[y][x] == 0:
                    #誕生
                    if aliveCell == 3:
                        newField[y][x] = 1
                #注目するセルが生きている
                elif field[y][x] == 1:
                    #生存1
                    if aliveCell == 2:
                        newField[y][x] = 1
                    #生存2
                    elif field[y][x] == 1 and aliveCell == 3:
                        newField[y][x] = 1
                    #過疎
                    elif field[y][x] == 1 and aliveCell <= 1:
                        newField[y][x] = 0
                    #過密
                    elif field[y][x] == 1 and aliveCell >= 4:
                        newField[y][x] = 0
        return newField

    def loopGeneration(self,maxstep=10):
        num = 0
        while num < maxstep:
            self.generations.append(self.nextGeneration(self.generations[-1]))
            num += 1

    def randomInit(self):
        self.initialField = [[0 for i in range(self.xsize)] for j in range(self.ysize)] #新しい格子
        for y in range(self.ysize):
            for x in range(self.xsize):
                self.initialField[y][x] = random.choice([0,1])
        self.generations = [self.initialField]


    def printResult(self):
        num = 0
        for field in self.generations:
            print "============ Generation " + str(num) + " ============"
            for line in field:
                for n in line:
                    if n == 1:
                        print '■' + ' ',
                    else:
                        print ' ' + ' ',
                print ''
            num += 1
lifegameOpenGL.py
 #-*-coding:utf-8-*-
from OpenGL.GL import *
from OpenGL.GLUT import *
import lifegame
import sys

numberOfGeneration = 0
maxstep = 1000
lifegame = lifegame.Lifegame(xsize=50,ysize=50)
lifegame.randomInit()
lifegame.loopGeneration(maxstep)

def display():
    width  = glutGet(GLUT_WINDOW_WIDTH)  #ウィンドウの横の長さを取得
    height = glutGet(GLUT_WINDOW_HEIGHT) #ウィンドウの縦の長さを取得
    xsize = lifegame.xsize #横のセルの数
    ysize = lifegame.ysize #縦のセルの数

    glClear(GL_COLOR_BUFFER_BIT) #ウィンドウの塗りつぶし
    glColor3d(0.0,0.5,0.0) #線の色
    glLineWidth(1.0) #線の太さ
    glBegin(GL_LINES) #描画する図形タイプの指定
    #縦の線
    for i in range(1,xsize+2):
        x = -1.0 + 2.0/(xsize+2) * i #横の長さは-1.0~1.0で2.0
        glVertex2d(x,1.0-2.0/(ysize+2))
        glVertex2d(x,-1.0+2.0/(ysize+2))
    #横の線
    for i in range(1,ysize+2):
        y = -1.0 + 2.0/(ysize+2) * i #縦の長さは-1.0~1.0で2.0
        glVertex2d(-1.0+2.0/(xsize+2),y)
        glVertex2d(1.0-2.0/(xsize+2),y)
    glEnd()
    #生存しているセルを塗りつぶす
    glColor3d(1.0,1.0,1.0) #セルの色
    glBegin(GL_QUADS)
    for y in range(ysize):
        for x in range(xsize):
            if lifegame.generations[numberOfGeneration][y][x] == 1:
               glVertex2d(-1.0+2.0/(xsize+2)*(x+1),1.0-2.0/(ysize+2)*(y+1))
               glVertex2d(-1.0+2.0/(xsize+2)*(x+1),1.0-2.0/(ysize+2)*(y+2))
               glVertex2d(-1.0+2.0/(xsize+2)*(x+2),1.0-2.0/(ysize+2)*(y+2))
               glVertex2d(-1.0+2.0/(xsize+2)*(x+2),1.0-2.0/(ysize+2)*(y+1))
    glEnd()


    glFlush() #まだ実行されていないOpenGLの命令を実行

def init():
    glClearColor(0.0, 0.0, 0.0, 1.0) #glClear(GL_COLOR_BUFFER_BIT)でウィンドウを塗りつぶす際の色を指定

def timer(value):
    global numberOfGeneration,maxstep
    if numberOfGeneration < maxstep:
        numberOfGeneration += 1
    glutPostRedisplay()
    glutTimerFunc(200,timer,0)

def main():
    glutInit(sys.argv) #GLUTおよびOpenGL環境の初期化
    glutInitDisplayMode(GLUT_RGBA) #ディスプレイの表示モード(RGBAモード)
    glutInitWindowSize(800,800)
    glutCreateWindow("test") #ウィンドウを開く
    glutDisplayFunc(display) #引数の関数を再描画のときに実行
    init()
    glutTimerFunc(50,timer,0)
    glutMainLoop() #プログラムのループ
    return 0

if __name__ == "__main__":
    main()

▼▼▼実行するとこんな感じです▼▼▼ f:id:lxxv:20170723232804p:plain