Fujillin さん謹製のウロチョロを勉強させて頂きました。

move の中のベクトルの考え方が参考になりました。もし今度書くのなら Math.abs を使うかもしれない。領域外なのか?の判定は、いわゆるクロージャーにした function を作成して行うか?それなら画面のリサイズで再設定もあるべきか・・・

gtlt さんに教えていただいた、方式に変えました。
ところで、この無名関数の中に、オブジェクト指向のようなプログラムを詰め込む方式の名称(方式名)とかあるのでしょうか?もし、無いのなら隠語での名称を付けたい。なので公募!!

    • 「ごった煮式」とか・・・(センスねぇなぁ〜〜)
    • 「ハイブリット梱包式」とか・・・(やっぱセンスねぇ〜)
<!DOCTYPE html>
<title></title>
<style type="text/css">
#target0 {
  font-size : 60px;
  color     : blue;
}

#target1 {
  font-size : 60px;
  color     : red;
}
</style>

<body>
<div id="target0">☆</div>
<div id="target1">☆</div>

<script type="text/javascript">

(function () { //@cc_on

  function Wanderer (target, personality, interval) {
    var doc = target.ownerDocument;
    
    this.style        = target.style;
    this.size         = [ target.clientWidth, target.clientHeight ];
    this.position     = [ ];
    this.speed        = [ 2, 0];
    this.acceleration = [ ];
    this.interval     = interval;
    this.max          = getPersonality (personality);
    this.view         = doc /*@if (1) [doc.compatMode == 'CSS1Compat'
                          ? 'documentElement': 'body'] /*@else@*/ .defaultView /*@end@*/;
  }
  
  
  function start () {
    var that = this;
    
    if (this.id) return;
    if (! this.position.length)
      this.position = [ 0, randomInt( getScreenSize (this.view)[1] )]; // height

    this.acceleration = getAccel (this.max);
    this.id = setInterval (function () { move.call (that) }, this.interval);
  }
  
  
  function stop () {
    if (this.id) {
      clearInterval (this.id)
      this.id = null;
    }
  }

//_____
  
  function move () {
    var p = this.position,
        a = this.acceleration,
        s = this.speed,
        max = this.max.speed,
        ss = getScreenSize (this.view),
        tmp, i;

    for (i = 0; i < 2; i++) {  // 0=x, 1=y
      tmp = s[i] + a[i];       // speedに加速をプラス
      s[i] = tmp > max         // スピードが上限になったら
        ? max                  // 設定最高速度にする
        : tmp < -max           // マイナス側の上限なら
          ? -max               // マイナス側の上限にする
          : tmp;
      p[i] = tmp = p[i] + s[i]; // 現在地から移動する
      
      if (tmp < 0 || tmp > ss[i] - this.size[i]) { // 領域をはみ出たら
        p[i] = tmp < 0          // マイナス側にはみ出たら
          ? -tmp                // はみ出た分戻す。普通0からだよね。仮に-200ならいきなり200px?
          : (ss[i] - this.size[i]) * 2 - tmp; //ここも?
        s[i] = -s[i];           // 戻るようにするため反転 -1 * x の時は、省略できるものがある
        a[i] = -a[i];           // 加速も反転
      }
    } // tmp を使いまわし、しやがって・・・・。

    this.style.left = Math.floor (p[0]) + 'px';
    this.style.top  = Math.floor (p[1]) + 'px';

    if (--a[2] < 0) //a[2] == getAccel()::count 方向転換の時期が来たら
      this.acceleration = getAccel (this.max); // 方向を変える
  }

  
  function getAccel (m) {
    return [(randomInt (2) - 1) * m.accel, (randomInt (2) - 1) * m.accel, randomInt (m.count)];
  }


  function getScreenSize (v) {
    return [
      /*@if (1) v.clientWidth  @else@*/ v.innerWidth  /*@end@*/,
      /*@if (1) v.clientHeight @else@*/ v.innerHeight /*@end@*/
    ];
  };


  function randomInt (max) {
    return Math.floor (Math.random () * max);
  }


  function getPersonality (no) {
    var result;

    switch (no) {
    case 1 :
      result = { speed: 18, accel: 1.5, count: 24 }; break;
    case 0 : default :
      result = { speed: 18, accel: 5, count: 8 }; break;
    }
    return result;
  }

//_____

  function init (target, personality, interval) {
    var style, obj;
    
    if (1 > arguments.length)
      return null;
    
    style = target.style;
    style.position = 'absolute';

    obj = new Wanderer (target, personality, interval || 30);
    obj.start ();
    return obj;
  }

//_____

  Wanderer.prototype.start = start;
  Wanderer.prototype.stop = stop;

//_____
  
  this.Wanderer = Wanderer;
  this.createWanderer = init;
})();

createWanderer (document.getElementById ('target0'), 0);
createWanderer (document.getElementById ('target1'), 1);

</script>