HSPコンテスト2007にて株式会社秀和システム章を受賞しました。
おにたまさんから「ある意味ではモジュールの達人」と言っていただけまして、とても嬉しいです。モジュール(変数)は1時期とっても勉強した部分なので……。
モジュール変数の扱いをもっと勉強していきたいですね。
というわけで受賞記念に、得意(?)のモジュールを利用したスクリプトを。
「遠い時はくっつきたがるけど、近い時は離れたがる」という特殊な粒子の運動のシミュレートです。現実では原子がこれにあたります。3次元ですが。
ひとつのモジュール変数でひとつの粒子を表しています。決まった距離を保つために、距離の2乗に従って速度を算出しています。力学のポテンシャルの考え方に近いでしょうか。
粒子数が同じなら、最初の条件が違っても大抵は同じ陣形に収束するのが面白いです。#module member id, x, y, vx, vy
#include "hspmath.as"
// id ... 個別認識用ID(int)
// x, y ... 位置(double)
// vx, vy ... 速度(double)
#const PARTY_DIST 120 // 仲間と保とうとする距離
#const MAX_SPEED 4 // 最大スピード
#const RADIUS 5 // 描画時の半径
#modinit int _x, int _y
x = _x : y = _y
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 = (dist - PARTY_DIST) * (dist - PARTY_DIST) * sgn(dist - PARTY_DIST) / 150
ax += cos(theta) * s
ay += sin(theta) * s
loop
// 速度の変更
vx += ax : vy -= ay
// 速度が大きすぎる場合は調節する
velo = sqrt(vx * vx + vy * vy)
if absf(velo) > MAX_SPEED {
velo = limitf(velo, -MAX_SPEED, MAX_SPEED)
theta = atan(vy, vx)
vx = cos(theta) * velo
vy = sin(theta) * velo
}
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
#global
next_id@member = 0 // IDの初期化
// -----------------------------
// モジュールここまで
#const NUM_MEMBERS 12 // 群れを構成するメンバーの数
// 群れのメンバーをランダムな位置に発生
randomize
repeat NUM_MEMBERS
make_member rnd(ginfo_winx), rnd(ginfo_winy)
loop
*main
calc_all_speed // 全員の速度を計算
move_all // 全員を移動
redraw 0
color : boxf : color ,,255
draw_all // 全員を描画
redraw 1
wait 3
goto *main
2007年12月1日土曜日
相互作用が働く粒子の運動
登録:
コメントの投稿 (Atom)
2 件のコメント:
コンテスト受賞おめでとうございます
最近、気付いたんですけど
応募作品に比して受賞者の数が
けっこう多いみたいですね
僕は完成でえきなかったけど
来年もきっとあると想定して
スクリプト下書きを
コツコツ続けていきたいですね
ellerさんは作成に何時間くらいかかったんですか?
僕はというと、20時間くらいしかやってなかった気がします
ゲームじゃないんだから、20時間じゃショボショボですね
ありがとうございます。
主催者の方々が受賞者数を多くするために配慮してくださっているのではないかと思います。
次回はぜひりすとさんもご参加をー。
作成にかかった時間はちょっとわからないです。もともとは2次元ではねる輪を作って、きれいだったので3次元にしたのですが。
私としてはゲームをつくる方が時間がかかるし難しい気がしていますけどね。
コメントを投稿