javascriptによる人間工学シミュレーション

なぞと大層なタイトルをつけてみましたが、やったことはコレです。



prototype.jsによってjavascriptでクラスを実現し、道を歩く人の簡単なAIを作成しました。prototype.jsを用いてクラスを作成するには、
var Human = Class.create();
このように記述します。クラスの定義については、
Human.prototype = {
 initialize: function(obj,x,y,vx,vy) {

 },
 move: function() {

 }
};
こんな感じです。initializeがコンストラクタで、この中にフィールドを入れます。メソッドはprototypeの中に放り込んでやればおkです。他にも記述の仕方はありますが、僕の場合は面倒くさいんでこれで統一しています。ちなみにプログラム自体は、場合分け処理が適当なので見ての通りうまく避けてくれませんw。誰かうまい処理考えてくれないかなー...。以下全ソースです。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html;">
<meta http-equiv="content-script-type" content="text/JavaScript">
<title>人間工学シミュレーション</title>
<meta http-equiv="Content-Type" content="text/html; charset=Shift-JIS">
<style type="text/css"><!--
* {
 margin: 0;
 padding: 0;
}
.street {
 background-color: #ccc;
 position: absolute;
}
.human {
 position: absolute;
 font-size: 16px;
 line-height: 16px;
 margin-left: -8px;
 margin-top: -8px;
}
.human2 {
 color: #f00;
}
#area{
background-color: #000;
}
--></style>
<script type="text/javascript" src="pt.js"></script>
<script type="text/javascript">
// ---------- 初期設定 ----------
// ウインドウサイズと道幅
var WinSizeW = 360, WinSizeH = 360;
var StreetW = WinSizeH/2;
var StreetL = (WinSizeW - StreetW)/2;
var StreetR = StreetL + StreetW;

// 描画間隔(ms)
var t = 10;

// 速度幅
var vy = 5;
var vx = 0;

// 人
var num = 8; // 人数
var size = 8;
var human = Array(num);
var human2 = Array(num);

// ---------- 初期化 ----------
// 初期化関数
function init() {
 createStreet(); // 道の描画
 for(i=0; i<num; i++) {
  var left = StreetL + Math.floor(StreetW * Math.random());
  var vx0 = Math.floor(vx * Math.random());
  var vy0 = Math.floor(1 + vy * Math.random());
  human[i] = new Human($('human_p' + i), left, 0, vx0, vy0);
  human[i].move();

  left = StreetL + Math.floor(StreetW * Math.random());
  vx0 = Math.floor(vx * Math.random());
  vy0 = Math.floor(1 + vy * Math.random());
  human2[i] = new Human($('human_m' + i), left, WinSizeH, vx0, -vy0);
  human2[i].move();
 }

 // タイマーの実行
 Timer();
}

// 道の生成
function createStreet() {
 var vertical = $('vertical');
 Element.setStyle(vertical,
 {
  'left' : StreetL+ "px",
  'top' : 0 + "px",
  'width' : StreetW + "px",
  'height': WinSizeH + "px"
 });
}

// humanクラス
var Human = Class.create();

// クラスの中身
Human.prototype = {
 initialize: function(obj,x,y,vx,vy) { // コンストラクタ(ここでメンバ変数も指定)
  this.obj = obj;
  this.x = x;
  this.y = y;
  this.vx = vx;
  this.vy = vy;
  Element.setStyle(this.obj, // 実際の移動 / 体裁整え
  {
   'left': x + "px",
   'top' : y + "px",
   'font-size': size + "px",
   'line-height': size + "px"
  });
 },
 move: function() { // 移動の記述
  if(this.y > WinSizeH || this.y < 0) { // 下から出たら
   var left = StreetL + Math.floor(StreetW * Math.random()); // 開始位置指定
   var tb = this.vy / Math.abs(this.vy); // 進んでた向き
   var vx0 = Math.floor(vx * Math.random()); // 初速度
   var vy0 = tb * Math.floor(1 + vy * Math.random()); // 初速度
   if(tb>0) this.y = 0; // 上に戻す
   else this.y = WinSizeH; // 下に戻す
   this.x = left; // 初期位置に持っていく
   this.vx = vx0; // 初速度指定
   this.vy = vy0; // 初速度指定
  }
  if(this.x < StreetL) { // 道の外に出たら
   this.vx = -this.vx; // 速度逆
   this.x += size;
  } else if(this.x > StreetR) {
   this.vx = -this.vx;
   this.x -= size;
  }
  this.x += this.vx; // 進む
  this.y += this.vy; // 進む
  this.vx = 0;  // 速度初期化
  Element.setStyle(this.obj, // 実際の移動
  {
   'left': this.x + "px",
   'top' : this.y + "px"
  });
 },
 // --------- ここが衝突判定 ---------
 // this: 自分   obj: 相手
 conflict: function( obj ) {
 // --------- ここから判断の記述 ---------
  var tb = this.vy / Math.abs(this.vy);
  var lx = (obj.x - this.x); // x方向距離
  var ly = tb*(obj.y - this.y); // y方向距離
  var lf = tb*((obj.y + 10*obj.vy) - (this.y + 10*this.vy)); // 10時間後の距離

  if(
   ly > 0 &&   // 後ろにいて
   Math.abs(lx) < 3*size && // かつ3人分の幅の中に入っていて
   lf < 0    // 10時間後抜かしてるとき時
  ) {
   var lr = this.x - obj.x;  // 右か左かの符号用
   if(!lr) lr = 0.5 - Math.random() // 真ん中だったらどっちか
   lr = lr / Math.abs(lr);   // 1か-1にする
   var to = obj.x + lr*3*size;  // 抜かす際の移動幅
   this.vx += Math.floor((to - this.x)/3 + 0.5); // 3時間後に抜かす速度
  }
 // ------------- ここまで -------------
 }
};

// 画面更新関数
function winDraw() {
 for(i=0; i<num; i++) {
  for(j=0; j<num; j++) {
   if(i!=j) human[i].conflict(human[j]);
   if(i!=j) human[i].conflict(human2[j]);
   if(i!=j) human2[i].conflict(human[j]);
   if(i!=j) human2[i].conflict(human2[j]);
  }
 }
 for(i=0; i<num; i++) {
  human[i].move();
  human2[i].move();
 }
}

// タイマー
function Timer() {
 winDraw();
 setTimeout("Timer()", t);
}
--></script>
</head>
<body>
<div id="area">
<div id="vertical" class="street"></div>
<script type="text/javascript">
for(i=0; i<num; i++) {
 document.write('<div id="human_p' + i + '" class="human">●</div>');
 document.write('<div id="human_m' + i + '" class="human human2">●</div>');
}
</script>
</div>
</body>
<script type="text/javascript">init();</script>
</html>

トラックバック(0)

このブログ記事を参照しているブログ一覧: javascriptによる人間工学シミュレーション

このブログ記事に対するトラックバックURL: http://www.hecomi.com/mt/mt-tb.cgi/75