レトロゲームエンジン Pyxel でプログラミングを始めよう! を見て何か作りたいなという気分になっていたので、ライフゲームをシミュレーションできるやつを作ってみました。
ライフゲームとは
名前の通り生き物をシミュレーションしたようなもので、Wikipediaの記事を見てもらうのが早いです。
実は今年のアドベントカレンダーでも、既に(今これを書いている12/7時点で)
と2つもライフゲームに関する記事を観測していて、早くもネタ被りが怖い。
できたもの
コード
こんな感じで書いてます。gist: https://gist.github.com/HelloRusk/09e255522b6827fe3f4abb3df377d4f4
import pyxel
class App:
def __init__(self):
pyxel.init(100, 110, caption="Pyxel Life Game")
self.is_alive = [[False] * 50 for i in range(50)]
self.is_alive_next = [[False] * 50 for i in range(50)]
self.is_moving = False
pyxel.mouse(True)
pyxel.run(self.update, self.draw)
def update(self):
if pyxel.btnp(pyxel.KEY_Q):
pyxel.quit()
if pyxel.btnp(pyxel.MOUSE_LEFT_BUTTON):
x_n, y_n = pyxel.mouse_x, pyxel.mouse_y
if 101 <= y_n <= 110:
if 59 <= x_n <= 78:
self.is_moving = False
elif 79 <= x_n <= 100:
self.is_moving = True
if 0 <= x_n <= 99 and 0 <= y_n <= 99:
self.is_alive[x_n // 2][y_n // 2] = not self.is_alive[x_n // 2][y_n // 2]
self.is_alive_next[x_n // 2][y_n // 2] = not self.is_alive_next[x_n // 2][y_n // 2]
if self.is_moving:
x = [1, 1, 0, -1, -1, -1, 0, 1]
y = [0, 1, 1, 1, 0, -1, -1, -1]
for i in range(1, 49):
for j in range(1, 49):
alive_num = 0
for k in range(8):
if self.is_alive[i + x[k]][j + y[k]]:
alive_num += 1
if self.is_alive[i][j]:
if alive_num <= 1: # 過疎による死滅
self.is_alive_next[i][j] = False
elif alive_num >= 4: # 過密による死滅
self.is_alive_next[i][j] = False
else:
if alive_num == 3: # 誕生
self.is_alive_next[i][j] = True
for i in range(1, 49):
for j in range(1, 49):
self.is_alive[i][j] = self.is_alive_next[i][j]
def draw(self):
pyxel.cls(0)
for i in range(50):
for j in range(50):
if self.is_alive[i][j]:
pyxel.pset(2*i, 2*j, 8)
pyxel.pset(2*i, 2*j+1, 8)
pyxel.pset(2*i+1, 2*j, 8)
pyxel.pset(2*i+1, 2*j+1, 8)
pyxel.text(1, 102, "Time: {:0>6}".format(pyxel.frame_count), 10)
pyxel.text(60, 102, "STOP", 6 if self.is_moving else 3)
pyxel.text(80, 102, "START", 3 if self.is_moving else 6)
App()
今回は、分かりやすさのために、100ピクセル * 100ピクセルに対して2ピクセル * 2ピクセルを1単位としてプログラムを書いています。なので、動けるのは50マス * 50マスという狭い範囲になってしまっています。
Pyxelでは256ピクセル * 256ピクセルが最大でサポートされているので、より広範囲で繁殖する物体を観察する場合はpyxel.init()
のプロパティやself.is_alive
の配列の大きさを適宜変えてみましょう。
さまざまなライフゲームの物体
ここからはもうプログラミングの記事ではないです。Wikipediaの記事を見ながら面白そうなものをいくつか試してみました。
パルサー
周期3の振動子
ペンタデカスロン
周期15の振動子
スイッチ機関車
長寿型の物体
シャトル
特にこれは女王蜂とも言われる
宇宙船の衝突
軽量級宇宙船の衝突により2つのグライダーが発生
中量級宇宙船の衝突によりパルサーが発生
グライダー銃
グライダーを永遠に打ち出し続ける