0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

cursesでメダカっぽい動きを表現する

Posted at

これは何?

fish.gif

こんなやつです。それとなくメダカっぽい動きをしています。
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)

感想

全然メダカに見えなくて残念。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?