前回のスクリプトの改良版。
速度に上限をつけるのではなく、抵抗力による減速を導入することでより物理らしくなっています。ガタガタと動かずにきれいに収束するのも特徴です。
また、粒子の追加および初期化の機能をつけました。
Java移植版#module member id, x, y, vx, vy
#include "hspmath.as"
// id ... 個別認識用ID(int)
// x, y ... 位置(double)
// vx, vy ... 速度(double)
#const PARTY_DIST 120 // 仲間と保とうとする距離
#const RADIUS 5 // 描画時の半径
#modinit double _x, double _y
x = _x : y = _y : vx = 0.0 : vy = 0.0
id = next_id : next_id++
return
#deffunc make_member double new_x, double new_y
newmod members, member, new_x, new_y
return
// -----------------------------
// ここから各メンバーごとに用いる命令
// IDを返す
#modfunc get_id
return id
// 位置を返す
#modfunc get_position array v
v = x, y
return
// 自分自身の速度の計算
#modfunc calc_speed
ax = 0.0 : ay = 0.0
// 仲間との相互作用(一定の距離を保とうとする)
foreach members
// 自分自身とは判定を行わない
get_id members(cnt)
if id == stat : continue
// 仲間との距離を計算
this_member_pos = x, y
get_position members(cnt), target_member_pos
dist = distance2(this_member_pos, target_member_pos) // 対象の仲間との距離(double)
// 仲間との角度を計算
theta = atan(y - target_member_pos(1), target_member_pos(0) - x)
// 距離に応じて加速
s = absf(dist - PARTY_DIST) * (dist - PARTY_DIST) / 5000
ax += cos(theta) * s
ay += sin(theta) * s
loop
// 速度の変更(加速・減速)
vx = 0.9 * (vx + ax)
vy = 0.9 * (vy - ay)
return
// 自分自身の移動
#modfunc move
x = limitf(x + vx, 0, ginfo_winx)
y = limitf(y + vy, 0, ginfo_winy)
return
// 自分自身を描画
#modfunc draw
circle x - RADIUS, y - RADIUS, x + RADIUS, y + RADIUS
return
// -----------------------------
// ここから外部から呼び出す群れ全体を扱う命令
// 全員の速度を計算
#deffunc calc_all_speed
foreach members
calc_speed members(cnt)
loop
return
// 全員の移動
#deffunc move_all
foreach members
move members(cnt)
loop
return
// 全員の描画
#deffunc draw_all
foreach members
draw members(cnt)
loop
return
// 全員消去
#deffunc kill_all
if vartype(members) != 5 : return
foreach members
delmod members(cnt)
loop
return
#global
next_id@member = 0 // IDの初期化
// -----------------------------
// モジュールここまで
#const NUM_MEMBERS 12 // 群れを構成するメンバーの数(初期値)
randomize
onclick goto *flag_onclick
title "左クリック:粒子の追加 / 右クリック:やりなおし"
*restart
// すべてのメンバーを削除
kill_all
// 群れのメンバーをランダムな位置に発生
repeat NUM_MEMBERS
make_member rnd(ginfo_winx), rnd(ginfo_winy)
loop
// 色を決定
color_h = rnd(192)
*main
calc_all_speed // 全員の速度を計算
move_all // 全員を移動
redraw 0
color : boxf : hsvcolor color_h, 255, 255
draw_all // 全員を描画
redraw 1
wait 3
goto *main
*flag_onclick
if iparam == 0 {
// 左クリックなら、粒子を追加
make_member mousex, mousey
goto *main
} else {
// それ以外は初期化
goto *restart
}
2007年12月2日日曜日
相互作用が働く粒子の運動2
登録:
コメントの投稿 (Atom)
0 件のコメント:
コメントを投稿