HOME | 10. キャンバスにドラッグできるオブジェクトを描こう | Python | 12. Tk.Text の使い方 | download | 書き込む |
class Hotaru を定義し、縦横の速度と加速度およびキャンバス上の ID 番号を内部変数に持ちます。 加速度はランダムに変化しますが、進行方向に対してブレーキがかかるようにしています。 そうしないと蛍がすぐいなくなってしまいます。ブレーキがかかると蛍がふらふらと漂います。
ソースコードを [code 1] に示します。簡単なプログラムですので、コードも短くてすみます。
[code 1] (hotaru.py)
01: #! /usr/bin/env python 02: # -*- coding: shift_jis -*- 03: """ 04: hotaru.py 05: 06: July 08, 2005 07: """ 08: import Tkinter as Tk 09: import random as R 10: 11: HOTARU_SIZE = 3 12: HOTARU_COLOR = 'yellow' 13: NIGHT_COLOR = 'midnightblue' 14: 15: class Hotaru: 16: canvas = None 17: 18: def __init__(self, x, y): 19: self.id = Hotaru.canvas.create_oval(x-HOTARU_SIZE, y-HOTARU_SIZE, x+HOTARU_SIZE, y+HOTARU_SIZE, 20: fill=HOTARU_COLOR, width=0) 21: self.vx=0 22: self.vy=0 23: self.ax = R.randint(-10,10) 24: self.ay = R.randint(-10,10) 25: 26: 27: 28: def moving(self): 29: vx1=self.ax+self.vx 30: vy1=self.ay+self.vy 31: dx = (self.vx+vx1)/2 32: dy = (self.vy+vy1)/2 33: Hotaru.canvas.move(self.id, dx, dy) 34: self.vx=vx1 35: self.vy=vy1 36: self.ax = R.randint(-10,10) - self.vx/2 37: self.ay = R.randint(-10,10) - self.vy/2 38: 39: 40: class Frame (Tk.Frame): 41: 42: def __init__(self, master=None): 43: Tk.Frame.__init__(self, master) 44: self.master.title("Hotaru") 45: self.master.geometry("+20+20") 46: self.cvs = Tk.Canvas(self, width=500, height=500, relief=Tk.SUNKEN, borderwidth=2, bg=NIGHT_COLOR) 47: self.cvs.pack(fill=Tk.BOTH, expand=1) 48: 49: # assign a Hotaru class parameter 50: Hotaru.canvas=self.cvs 51: 52: self.counter=0 53: self.hotaru_list = [] 54: self.create_hotaru(30) 55: self.move_hotaru() 56: 57: def move_hotaru(self): 58: for p in self.hotaru_list: 59: p.moving() 60: self.counter += 1 61: self.counter%10 or self.create_hotaru(1) # make new hotal every one second 62: self.cvs.after(100, self.move_hotaru) 63: 64: 65: def create_hotaru(self, n): 66: for i in range(n): 67: x=R.randint(50, 450) 68: y=R.randint(50, 450) 69: self.hotaru_list.append(Hotaru(x,y)) 70: 71: 72: ##----------------------------------------------------- 73: if __name__ == '__main__': 74: f = Frame() 75: f.pack(fill=Tk.BOTH, expand=1) 76: f.mainloop()
hotaru.py と同様に、Hanabi というオブジェクトを作り、位置、初速度、寿命、色を指定します。 花火は初速度と重力加速度に従って動き、寿命が来ると消えます。 また、花火のサブクラス Mother を作り、打ち上げる弾を表します。 ソースコードを [code 2]に示します。
[code 2] (hanabi.py)
01: #! /usr/bin/env python 02: # -*- coding: shift_jis -*- 03: """ 04: hanabi.py 05: 06: July 08, 2005 07: """ 08: import Tkinter as Tk 09: import random as R 10: import math as M 11: 12: 13: 14: HANABI_COLORS = ['red', 'lightcyan', '#FF33FF', '#FF99FF', '#FFFFCC', '#FFCC00', 15: 'magenta', 'blueviolet', 'white', '#FF99FF'] 16: NIGHT_COLOR = '#000033' 17: G = 1 18: HR = 1 19: NHANA = 20 20: N_COLORS = len(HANABI_COLORS)-1 21: 22: 23: def rand_angle(n): 24: """ +- x degree, where x is degree of radius of children """ 25: return M.pi * R.randint(-10,10)/(float(n)*10.0) 26: 27: class Hanabi: 28: canvas = None 29: list = None 30: 31: 32: def __init__(self, **p): 33: x = p['x'] 34: y = p['y'] 35: self.vx = p['vx'] 36: self.vy = p['vy'] 37: self.lifetime = p['lifetime'] 38: self.id = Hanabi.canvas.create_oval(x-HR, y-HR, x+HR, y+HR, fill=p['color'], width=0) 39: self.counter=0 40: 41: 42: def moving(self): 43: if(self.counter<self.lifetime): 44: Hanabi.canvas.move(self.id, self.vx, self.vy) 45: self.counter += 1 46: self.vy += G 47: else: 48: self.disappear() 49: 50: 51: def disappear(self): 52: Hanabi.canvas.delete(self.id) 53: self.id = None 54: 55: 56: 57: class Mother(Hanabi): 58: 59: def disappear(self): 60: r0 = R.randint(13,17) 61: v0 = R.randint(18, 22) 62: nc0 = R.randint(0,N_COLORS) 63: nc1 = R.randint(1, N_COLORS-1) 64: x1,y1,x2,y2 = Hanabi.canvas.coords(self.id) 65: x, y = (x1+x2)/2, (y1+y2)/2 66: self.make_sphere(NHANA, x, y, r0, v0, HANABI_COLORS[nc0], self.vx, self.vy) 67: self.make_sphere(NHANA/2, x, y, r0/3, v0/3, HANABI_COLORS[(nc0+nc1)%(N_COLORS+1)], self.vx, self.vy) 68: Hanabi.disappear(self) 69: 70: 71: def make_sphere(self, nh, x, y, r, v, c, vx0, vy0): 72: d_eta = 2.0 * M.pi / float(NHANA) 73: eta = rand_angle(NHANA) 74: for i in range(NHANA/2): 75: dxy = M.sin(eta) 76: n = M.floor(dxy * nh) 77: d_theta = n and 2 * M.pi/n or 2* M.pi 78: theta = rand_angle(NHANA) 79: 80: if i%2: 81: theta += d_theta*0.5 82: 83: for j in range(int(n)): 84: dx = M.cos(theta) * dxy 85: dy = M.sin(theta) * dxy 86: Hanabi.list.append(Hanabi(x=r*dx+x, y=r*dy+y, color=c, 87: vx=v*dx+vx0, vy=v*dy+vy0, lifetime=R.randint(8,15))) 88: theta += d_theta 89: eta +=d_eta 90: 91: 92: 93: 94: class Frame (Tk.Frame): 95: 96: def __init__(self, master=None): 97: Tk.Frame.__init__(self, master) 98: self.master.title("Hanabi") 99: self.master.geometry("+20+20") 100: Hanabi.canvas = Tk.Canvas(self, width=500, height=700, 101: relief=Tk.SUNKEN, borderwidth=2, bg=NIGHT_COLOR) 102: 103: Hanabi.canvas.pack(fill=Tk.BOTH, expand=1) 104: 105: Hanabi.list = [] 106: self.rep() 107: 108: def rep(self): 109: # delete disappeared items 110: n = len(Hanabi.list) 111: i=0 112: while(i<n): 113: if(Hanabi.list[i].id): 114: i += 1 115: else: 116: del Hanabi.list[i] 117: n -= 1 118: 119: # move items 120: for p in Hanabi.list: 121: p.moving() 122: 123: # launch another hanabi, one every second in average 124: if R.randint(0,100)>90: 125: self.create_hanabi() 126: 127: # repeat 128: self.after(100, self.rep) 129: 130: 131: def create_hanabi(self): 132: vy0 = R.randint(-33,-31) 133: Hanabi.list.append(Mother(x=R.randint(150, 350), y=695, vx=R.randint(-1,1), vy=vy0, 134: color='#CC6600', lifetime=vy0*(-1)-R.randint(3,5))) 135: 136: 137: ##----------------------------------------------------- 138: if __name__ == '__main__': 139: f = Frame() 140: f.pack(fill=Tk.BOTH, expand=1) 141: f.mainloop()
初期化するとき (32--39) は、キーワードパラメターをとります。キーワードは以下の通りです。
Hanabi には moving (39--45) と disappear (51--53) の2つのメソッドがあります。
__init__, moving は Hanabi と同じです。
Mother は消えるときたくさんの子を作るので、disappear が Hanabi と異なります。
self.make_sphere を2回使って2重の輪を持つ花火を作ります。内側と外側の花火の色は違う色にします。
make_sphere(self, nh, x, y, r, v, c, vx0, vy0) は親玉が破裂したとき、小玉が球面上に飛び散るようにする
メソッドです。(70--84)
以下の説明は図を用いていないのでちょっとわかりにくいのですが、要するに、
典型的な花火である割物(わりもの)
をシミュレートしています。
今回で Tk.Canvas の解説はおしまいです。 次回は Tk.Text について説明します。
HOME | 10. キャンバスにドラッグできるオブジェクトを描こう | Python | 12. Tk.Text の使い方 | download | 書き込む |