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>