エラーが発生しています。

【Boids】HSPでボイド作ってみたwww【人工生命】

by ふんすけ@来年から頑張る, at 2018年1月14日 01:51:11

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

作成者
icon

ふんすけ@来年から頑張る

ここはユーザの紹介文

詳しく...


関連プログラム