これは何?
こんなやつです。それとなくメダカっぽい動きをしています。
Tkinterでメダカっぽい動きを表現するの続き。
curses
で動かしてみました。
ソースコード
import math
import random
import time
import numpy as np
# ベクトル正規化
def norm( a):
x = np.linalg.norm(a)
if x == 0.0:
x = 1
return a / x
#
# 魚
#
class Fish(object):
VISCOSITY = 2.2 # 粘性係数[1/sec]
RUSH_ACL = 15.0 # 突進加速度[m/sec^2]
RUSH_TIME= 2 # 突進加速する時間間隔[sec]
MAX_POS = 1 # 空間の広さ[m]
fishes = [] # 魚群
def __init__(self,id=-1,pos_x=0,pos_y=0):
self.id = id
self.pt_vel = np.array([0.0,0.0])
self.pt_pos = np.array([pos_x,pos_y])
self.rush_time = 0 # 次回突進までの残り時間
# 更新
def update(self, delta_t,mode='MODE_RAND'):
# 一定時間がたったら突進加速
self.rush_time -= delta_t
if self.rush_time < 0:
acl,tim = 1,1 # 先頭魚用の係数
# 各自ランダムに泳ぐ
if mode == 'MODE_RAND':
pt_dir = norm( np.array([random.uniform(-1,1),random.uniform(-1,1)]))
# 先頭魚を追う
elif mode == 'MODE_HEAD':
if self.id == 0: # 先頭魚
pt_dir = norm( np.array([random.uniform(-1,1),random.uniform(-1,1)]))
acl,tim = 2,0.1 # 10倍の頻度で2倍の加速
else: # その他の魚
head = Fish.fishes[0]
pt_dir = norm( head.pt_pos - self.pt_pos)
pt_acl = pt_dir * acl * Fish.RUSH_ACL * random.uniform(0.8,1.2)
self.rush_time = tim * Fish.RUSH_TIME * random.uniform(0.5,1.2)
else:
pt_acl = self.pt_vel * -Fish.VISCOSITY
# 速度、位置の計算
self.pt_vel += pt_acl * delta_t
self.pt_pos += self.pt_vel * delta_t
self.limitWall()
return (self.pt_pos,self.pt_vel)
# 壁(境界)処理
def limitWall(self):
bLim = False
if self.pt_pos[0] >= Fish.MAX_POS:self.pt_pos[0] = Fish.MAX_POS; bLim = True
elif self.pt_pos[0] < 0: self.pt_pos[0] = 0; bLim = True
elif self.pt_pos[1] >= Fish.MAX_POS:self.pt_pos[1] = Fish.MAX_POS; bLim = True
elif self.pt_pos[1] < 0: self.pt_pos[1] = 0; bLim = True
if bLim: self.pt_vel *= -1 # 反転
import curses
#
def main(stdscr):
N_FISH = 15
DELTA_T = 0.033
SX,SY = 60,30
curses.curs_set(0) # カーソルを消す
stdscr.nodelay(True) # 非同期でキー入力
# 魚群の生成
Fish.fishes = []
for idx in range(N_FISH):
fish = Fish(idx,random.uniform(0,1),random.uniform(0,1))
Fish.fishes.append( fish)
# イベントループ
mode_time = 0
while True:
# スペースキー入力で終了
try:
key = stdscr.getkey()
if key == ' ':
break
except curses.error:
pass
stdscr.clear()
# 魚が泳ぐ
for idx,fish in enumerate(Fish.fishes):
pt_pos,pt_vel = fish.update(DELTA_T)
pt_vel = norm(pt_vel)
try:
pos_body = [ int(pt_pos[0]*SX), int(pt_pos[1]*SY)]
pos_tail = [ pos_body[0]-int(round(pt_vel[0])), pos_body[1]-int(round(pt_vel[1]))]
stdscr.addstr(pos_tail[1], pos_tail[0], 'o') # しっぽ
stdscr.addstr(pos_body[1], pos_body[0], 'O') # 本体
except curses.error:
pass
stdscr.refresh()
time.sleep(DELTA_T)
if __name__ == '__main__':
curses.wrapper(main)
感想
全然メダカに見えなくて残念。