from machine import SoftI2C, Pin
from ssd1306 import SSD1306_I2C
from utime import sleep
from math import floor
# 定数
DISPLAY_WIDTH = 128 # 画面全体のサイズ(横)
DISPLAY_HEIGHT = 64 # 画面全体のサイズ(縦)
i2c = SoftI2C(scl=Pin(1), sda=Pin(0))
display = SSD1306_I2C(DISPLAY_WIDTH, DISPLAY_HEIGHT, i2c)
anim_file = open("anim.txt", encoding="utf8")
fps = int(anim_file.readline()) # 1行目からFPSを読取
sleep_interval = 1 / fps # 各フレーム後のsleep時間を計算
draw_width = int(anim_file.readline()) # 2行目からアニメーションの解像度(横)を取得
draw_height = int(anim_file.readline()) # 3行目からアニメーションの解像度(縦)を取得
local_corner_x = floor((DISPLAY_WIDTH - draw_width) / 2) # 画面内での左端の座標を計算
local_corner_y = floor((DISPLAY_HEIGHT - draw_height) / 2) # 画面内での上端の座標を計算
point_index = 0
numarg_buf = ""
anim_start_pos = anim_file.tell()
# 指定した数だけピクセルを追加し、現在のインデックスを進める関数
def add_points(char, amount):
global point_index
if char == "+": # 可能な場合はhlineを使って一度に描画
if amount == 1:
display.pixel(local_corner_x + point_index % draw_width, local_corner_y + floor(point_index / draw_width))
else:
cur = point_index
to = point_index + amount
x_to = to % draw_width
y_to = floor(to / draw_width)
while cur < to:
x_cur = cur % draw_width
y_cur = floor(cur / draw_width)
if y_cur >= draw_height:
break
if y_cur == y_to:
rem_width = x_to
else:
rem_width = draw_width
linew = rem_width - x_cur
if linew == 1:
display.pixel(local_corner_x + x_cur, local_corner_y + y_cur)
else:
display.hline(local_corner_x + x_cur, local_corner_y + y_cur, linew)
cur += linew
point_index += amount
print("### Animation Data ###")
print("FPS: " + str(fps))
print("Resolution: " + str(draw_width) + "x" + str(draw_height))
while True:
line = anim_file.readline()
if not line: # ファイルの終わりに到達したら、アニメーションの開始地点まで巻き戻し
anim_file.seek(anim_start_pos)
continue
for char in line:
if char == "#": # コメント
break
elif char == "x": # X座標を指定
point_index = int(numarg_buf) + floor(point_index / draw_width) * draw_width
numarg_buf = ""
elif char == "y": # Y座標を指定
point_index = int(numarg_buf) * draw_width + floor(point_index % draw_width)
numarg_buf = ""
elif char == "v": # 次の行へ移動
point_index = (floor(point_index / draw_width) + 1) * draw_width
numarg_buf = ""
elif char == "+" or char == "-": # + → ピクセル追加, - → 何もしない
if not numarg_buf:
amount = 1
else:
amount = int(numarg_buf)
add_points(char, amount)
numarg_buf = ""
elif char == ";": # 画面を描画し、次のフレームへ
display.show()
display.fill_rect(local_corner_x, local_corner_y, draw_width, draw_height, 0)
point_index = 0
numarg_buf = ""
sleep(sleep_interval)
elif char != "\n" and char != "\r": # その他、改行以外の文字は引数として扱う
numarg_buf += char