Last active
April 8, 2025 12:56
-
-
Save kujirahand/3f1acb7d148f4f9b4ac998f92b048a79 to your computer and use it in GitHub Desktop.
lifegame using PyScript
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="ja"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width,initial-scale=1" /> | |
<!-- PyScriptのライブラリを取り込み --> | |
<link rel="stylesheet" href="https://pyscript.net/releases/2025.3.1/core.css"> | |
<script type="module" src="https://pyscript.net/releases/2025.3.1/core.js"></script> | |
<title>PyScriptでライフゲーム</title> | |
</head> | |
<body> | |
<h1>ライフゲーム</h1> | |
<canvas id="game" width="400" height="400" style="border: 1px solid black"> | |
</canvas><br /> | |
<button id="start-btn">▶️ 開始する</button> | |
<button id="reset-btn">🔄 初期化</button> | |
<script type="py"> | |
# 必要なライブラリをインポートする --- (*1) | |
from js import document, window | |
from pyodide.ffi import create_proxy | |
import random, math | |
# 描画用のコンテキストを取得する --- (*2) | |
canvas = document.getElementById("game") | |
ctx = canvas.getContext("2d") | |
# キャンバスのサイズを計算 | |
cell_size = 10 | |
rows = canvas.height // cell_size | |
cols = canvas.width // cell_size | |
interval_id = None | |
# グリッドを初期化 --- (*3) | |
def create_grid(): | |
global grid | |
grid = [[random.choice([0, 0, 1]) for _ in range(cols)] for _ in range(rows)] | |
# グリッドを描画する --- (*4) | |
def draw_grid(): | |
ctx.clearRect(0, 0, canvas.width, canvas.height) | |
for y in range(rows): | |
for x in range(cols): | |
# 値が1の時生物を描画する ---- (*5) | |
if grid[y][x] == 1: | |
ctx.beginPath() | |
ctx.arc( | |
x * cell_size + cell_size / 2, | |
y * cell_size + cell_size / 2, | |
cell_size / 2, | |
0, | |
2 * math.pi | |
) | |
ctx.fillStyle = "red" | |
ctx.fill() | |
ctx.closePath() | |
# グリッドの世代を進める --- (*6) | |
def update_grid(): | |
global grid | |
new_grid = [[0 for _ in range(cols)] for _ in range(rows)] | |
for y in range(rows): | |
for x in range(cols): | |
neighbors = sum( | |
grid[(y + dy) % rows][(x + dx) % cols] | |
for dy in [-1, 0, 1] | |
for dx in [-1, 0, 1] | |
if not (dy == 0 and dx == 0) | |
) | |
if grid[y][x] == 1 and neighbors in [2, 3]: | |
new_grid[y][x] = 1 | |
elif grid[y][x] == 0 and neighbors == 3: | |
new_grid[y][x] = 1 | |
grid = new_grid | |
draw_grid() | |
# 開始・停止・リセット --- (*7) | |
def start(event): | |
global interval_id | |
if interval_id is None: | |
# タイマーイベントを設定 --- (*8) | |
interval_id = window.setInterval( | |
create_proxy(update_grid), 300) | |
def stop(event): | |
global interval_id | |
if interval_id is not None: | |
window.clearInterval(interval_id) | |
interval_id = None | |
def reset(event): | |
stop(None) | |
create_grid() | |
draw_grid() | |
# ボタン操作を指定 --- (*9) | |
document.getElementById("start-btn").onclick = create_proxy(start) | |
document.getElementById("reset-btn").onclick = create_proxy(reset) | |
reset(None) | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment