powered by hsp3dish.js / OpenHSP
ボイドを作ってみました。最初の長さ定義を変えてみたり、最後の3行(BIDAddVXVY~
)をコメントアウトしたり、ラジバンダリして動作を楽しみたまえ。
何故かX+Y+方向に収束してしまう。
#include "hsp3dish.as" #const global WD 640 ; 画面サイズ横 #const global HE 480 ; 画面サイズ縦 #const BOID_NUM 64 ; ボイドの数 #const LEN_SEPARATION 10.0 ; (分離)近すぎるとき分離する距離 #const LEN_ALIGNMENT 50.0 ; (整列)仲間と同じ方向、速度に合わせる距離 #const LEN_COHESION 100.0 ; (結合)群れの中心に向かう距離 //************************************************************** // ボイド #module BOIDS m_x, m_y, m_vx, m_vy //============================== // モジュール初期化処理 #modinit m_x = 1.0 * rnd( WD ) m_y = 1.0 * rnd( HE ) r = deg2rad( rnd( 360 ) ) m_vx = cos( r ) m_vy = sin( r ) return //============================== // モジュール開放処理 #modterm return //============================== // getter #modfunc BIDGetXY var _x, var _y _x = m_x _y = m_y return //============================== // getter #modfunc BIDGetVXVY var _vx, var _vy _vx = m_vx _vy = m_vy return //============================== // setter #modfunc BIDSetVXVY double _vx, double _vy m_vx = _vx m_vy = _vy return //============================== // #modfunc BIDAddVXVY double _vx, double _vy m_vx += _vx m_vy += _vy return //============================== // #modfunc BIDSubVXVY double _vx, double _vy m_vx -= _vx m_vy -= _vy return //============================== // ボイド表示処理 #modfunc BIDDraw #const rad120 M_PI * 3 / 4 pset m_x, m_y #if 0 // 蟻っぽいど px = m_x - m_vx py = m_y - m_vy circle m_x - 2, m_y - 2, m_x + 2, m_y + 2, 1 circle px - 2, py - 2, px + 2, py + 2, 1 #else // ▲っぽいど m_dir = atan( m_vy, m_vx ) x1 = cos( m_dir ) * 10 + m_x y1 = sin( m_dir ) * 10 + m_y x2 = cos( m_dir + rad120 ) * 5 + m_x y2 = sin( m_dir + rad120 ) * 5 + m_y x3 = cos( m_dir - rad120 ) * 5 + m_x y3 = sin( m_dir - rad120 ) * 5 + m_y line x1, y1, x2, y2 line x1, y1, x3, y3 line x2, y2, x3, y3 #endif return //============================== // ボイド更新処理 #modfunc BIDUpdate // 速さの上限設定 len = GetLength( m_vx, m_vy ) if ( len > 5.0 ) { mag = 5.0 / len m_vx *= mag m_vy *= mag } // 歩行 m_x += m_vx m_y += m_vy // 壁際処理 #if 0 // 跳ね返る if ( m_x < 0 ) : m_x = 0 : m_vx = -m_vx if ( m_x > WD ) : m_x = WD : m_vx = -m_vx if ( m_y < 0 ) : m_y = 0 : m_vy = -m_vy if ( m_y > HE ) : m_y = HE : m_vy = -m_vy #else // トーラス座標 m_x = ( m_x + WD ) \ WD m_y = ( m_y + HE ) \ HE #endif return //============================== // 対象座標距離取得 #modcfunc BIDGetLength int _x, int _y return GetLength( m_x - _x, m_y - _y ) #modcfunc BIDGetLengthSq int _x, int _y return GetLengthSq( m_x - _x, m_y - _y ) //============================== // vx, vy の長さ取得 #modcfunc BIDGetVLength return GetLength( m_vx, m_vy ) #modcfunc BIDGetVLengthSq return GetLengthSq( m_vx, m_vy ) //============================== // 正規化 #deffunc Normalize double _i, double _x, double _y, var _ox, var _oy mag = _i / GetLength( _x, _y ) _ox = _x * mag _oy = _y * mag return #defcfunc GetLength double _x, double _y return sqrt( GetLengthSq( _x, _y ) ) #defcfunc GetLengthSq double _x, double _y return _x * _x + _y * _y #global //============================== *game_init // 初期化 screen 0, WD, HE randomize // ボイド作成 repeat BOID_NUM newmod boid, BOIDS loop //============================== *game_loop //============================== // 入力処理 stick key, 128, 1 if key & 128 : goto *game_term if key & 16 : flgPause = 1 - flgPause //============================== // 描画 if flgPause : else { // 画面の書き換えを止める redraw 0 // クリア color 96, 96, 96 : boxf // ボイド関係の処理 repeat BOID_NUM i = cnt // 位置取得 BIDGetXY boid( i ), x, y // rule1 中心に寄る // rule2 少し離れる // rule3 速度を合わせる gosub *boids_rules // 更新 BIDUpdate boid( cnt ) // 描画 r = limit( r3_sum * 15, 0, 255 ) g = limit( r2_sum * 64, 0, 255 ) b = limit( r1_sum * 20, 0, 255 ) color r, g, b BIDDraw boid( cnt ) loop // 画面の書き換えを反映 redraw 1 } // 16ミリ秒待つ await 16 // *mainまで戻る goto *game_loop //============================== *game_term // ボイド破棄 repeat BOID_NUM delmod boid( cnt ) loop end //============================== // ボイドルール // 1.中心に寄る // 2.少し離れる // 3.速度を合わせる *boids_rules // r1_vx = 0.0 : r1_vy = 0.0 r2_vx = 0.0 : r2_vy = 0.0 r3_vx = 0.0 : r3_vy = 0.0 sum_x = 0.0 : sum_y = 0.0 r1_sum = 0 r2_sum = 0 r3_sum = 0 repeat BOID_NUM if ( cnt != i ) { // boid( i )とboid( cnt )の距離を取得 len = BIDGetLength( boid( cnt ), x, y ) // 結合距離に入った仲間の合計位置を取得 if len < LEN_COHESION { BIDGetXY boid( cnt ), x2, y2 sum_x += x2 sum_y += y2 r1_sum ++ } // 分離距離に入った場合、相手( boid(cnt) )の反対に行くようにする if ( len < LEN_SEPARATION ){ BIDGetXY boid( cnt ), x2, y2 r2_vx -= ( x2 - x ) r2_vy -= ( y2 - y ) r2_sum ++ } // 整列距離に入った仲間の合計速度を取得 if ( len < LEN_ALIGNMENT ) { BIDGetVXVY boid( cnt ), vx2, vy2 r3_vx += vx2 r3_vy += vy2 r3_sum ++ } } loop // 合計位置が求められる場合、追加速度を計算する if r1_sum > 0 { r1_vx = sum_x / r1_sum r1_vy = sum_y / r1_sum r1_vx = ( r1_vx - x ) / 100 r1_vy = ( r1_vy - y ) / 100 } // 合計速度が求められる場合、追加速度を計算する if r3_sum > 0 { r3_vx /= r3_sum r3_vy /= r3_sum r3_vx /= 8 r3_vy /= 8 } // 速度値に追加 BIDAddVXVY boid( i ), r1_vx, r1_vy BIDAddVXVY boid( i ), r2_vx, r2_vy BIDAddVXVY boid( i ), r3_vx, r3_vy return