適当のごった煮

Pythonと境界標とQGISを中心にいろいろと

Python TkinterのCanvasを使って簡易アニメーションを作る

スポンサードリンク

Python TkinterのCanvasを使ってファミコンのスカイデストロイヤーのような背景アニメーションを作成しました。


Python Tkinter Canvasを使った簡易アニメーション

画面設計

  • 画面は600×400、上から160ピクセルが空、それより下が海を表す
  • 海は10個の四角形で表し、2色(濃い青と薄い青)を交互に一定時間ごとに塗りつぶして動いて見えるようにする
  • 太陽を円で表す
  • 太陽が水平線に接したら夕方、水平線より下がったら夜とする
  • 昼、夕、夜で空の色を変える。空の色はCanvasの背景(bg)を変化させる

Canvasの機能

Canvasウィジットには様々な機能があり、大元になるCanvasを作成した後、そのCanvasに対して線や円、多角形やテキスト、画像などを載せていくことができます。

重要なのは、それらの線や円などのオブジェクトに整数のID番号が自動的に付与されることです。そのID番号を指定して色を変えたり動かしたり削除することが可能です。

ID番号の他にタグを自分でつけることもできます。タグは複数のオブジェクトに同じモノをつけられるので、同時に扱いたいオブジェクトに付けておくとグループのように操作できます。

ソース

import tkinter as tk
import time

yoko = 600 # Canvasの幅
tate = 400 # Canvasの高さ
umi = 160  # 水平線の高さ
bai = 3    # 波表現高さ調整用倍率
rect = []  # 波表現長方形のID保存用
sun_r = 30 # 太陽の半径

# 空と海の色と波の高さ
iro_sora = ['#6ff4fb', '#fed8aa', '#1105ae']
iro_umi = ['#43b4ff', '#5e92fb']
nami = [1, 3, 2, 5, 3, 8, 6, 18, 14, 20] # 波を表す四角形の高さの割合

animation = tk.Tk()
cvs = tk.Canvas(animation, width=yoko, height=tate, bg=iro_sora[0])
cvs.pack()

# 太陽と波表現と初期メッセージ作成
sun_id = cvs.create_oval(yoko/2-sun_r, -sun_r*2, yoko/2+sun_r, 0, \
                           fill='RED')
takasa = 0 # 長方形高さ調整用
for i in nami:
    rect.append(cvs.create_rectangle(0, umi+takasa, yoko, \
                                     umi+takasa+i*bai, fill=iro_umi[0]))
    iro_umi.reverse()
    takasa += i * bai
text_id = cvs.create_text(yoko/2, 100, font=('32'), \
                          text='Enterを押すとアニメーションを開始')

def anime(event):
    cvs.itemconfigure(text_id, text='')
    counter = 0
    while counter < 80:
        # 波の表現
        for x in rect:
            cvs.itemconfigure(x, fill=iro_umi[0])
            iro_umi.reverse()
        iro_umi.reverse()

        # 太陽の動き
        cvs.move(sun_id, 0, 4)

        # 空の色変化と時間経過
        if cvs.bbox(sun_id)[3] > umi and cvs.bbox(sun_id)[3] < sun_r*2+umi:
            cvs.configure(bg=iro_sora[1])
        elif cvs.bbox(sun_id)[3] > sun_r*2+umi:
            cvs.configure(bg=iro_sora[2])
        counter += 1
        time.sleep(0.1)
        animation.update()
    # 終了
    cvs.itemconfigure(text_id, text='終了', font=('32'))
    cvs.configure(bg=iro_sora[0])
    animation.update()

cvs.bind_all('', anime)
animation.mainloop()

参考