オブジェクト化し(いわゆる)クロージャーにして・・・「ボールを左から右へ」
yyr446 さんの、指示のもと作ってみた。
単純に左から右への移動だとつまらないので、
2次元の運動もできるように考えた。
そうしたら、3次元でも出来るようにと、あれこれ考えていたら・・・
思考手順
ボールとは、HTMLでいう要素、空間座標、運動エネルギー(運動を計算する関数)から成り立っている。
運動エネルギーは、自分が動ける空間を認知していなければならない。
空間を認知するためには、エリアの中なのか外なのかを理解できなければならない。
ボールの回転を含めないと、嘘っぽい。しかも重力の向きが逆! 残念。
<!DOCTYPE html> <title></title> <div style="position:relative"> <img id="ball" onclick="" src="data:image/gif;base64, R0lGODlhGwAaALMAAO/v8I2Njry9wM7P0cXGyLK0tqmrrZ6foOTl5tjZ2np7ewoKCfv7+2Fh YTMzM////yH5BAEAAA8ALAAAAAAbABoAAAT/8MlJ30AoDVG7VwMjAgCGbF53FAUijiQiaEUq FUnikvxQKA4FgFDz4C6wkqFgCDQcAVmRoiAQAK8s6+B0LA4JwfQhGOiyWQNX8VwsDEQKljFH MwyNp3fhOBjUEgJ0JHZYBntuXz4/Egk8LnYnAgdtCmEFAk4zj2gAGgQXJQVWLAUHDgQ6CJ6j jgyfZho0Yn8CC6A6AEwHbA0JuDkDVga0BgMNZQMAA34BbAuxwVYES38FA8QDF1zObS0awgQC AktM49SYh3l6CwHL4eNiCsmjD5gDCnwOew0IVuOYBOhRMIqAvXEJGiTiMy8ewF5eFCCYwGKG QihlaPmhlGePmQl/UIgRCABKTKklevbxYVCBSTWXIf8QyIdIXId0fmKW25DIAbEUAhCYAiVO AChhDUAwGGDjQQM1CkhmMBlUhIKmE/K4QZaDRIIAWDvoA1HAiY0IADs=" > </div> <script> // (配列数)次元の範囲に存在すか調べる関数を返す function isInsideSpace (start/*Array*/, end/*Array*/, offset/*Array*/) { //配列は次元の数だけ if (2 > arguments.length) return null; var min = []; var max = []; var len = start.length; var i; var o; for (i = 0; i < len; i++) { o = offset ? offset[i]: 0; min[i] = start[i] + o; max[i] = end[i] + o; } return function (d, position) { // d 次の座標を評価する。戻り値は配列で[評価値, 適正値] return (position < min[d]) ? [ -2, min[d] ] // エリアの外側(マイナス) : (position == min[d]) ? [ -1, min[d] ] // エリアの線上 : (position == max[d]) ? [ 1, max[d] ] // エリアの線上 : (position > max[d]) ? [ 2, max[d] ] // エリアの外側(プラス) : [ 0, position ]; // エリア内 }; } function createMover (motionList, area) { if (2 > arguments.length) return null; var counter = 0; return function (position) { var i; var motion; var p; var a = null; var result = []; for (i = 0; i < this.len; i++) { p = position[i]; if (motion = motionList[i]) { p = motion.call (counter, p); a = area (i, p); if (a[0]) p = motion.call (counter, p, a[0], a[1]) } result.push (p); } counter += 1; return result; } } function Locator (p) { this.top = p[1] + 'px'; this.left = p[0] + 'px'; } function Stopper () { crearInterval (this.timerId); this.timerId = null; } function Loop () { Locator.call (this.target.style, this.position = this.mover (this.position)); } //_________ function Ball (target, position, mover, interval) { this.target = target; this.position = position; this.mover = mover; this.interval = interval; this.timerId = null; this.len = position.length; } Ball.prototype.start = function () { var that = this; var cbFunc = function () { Loop.call (that); }; if (! this.timerId) this.timerId = setInterval (cbFunc, this.interval); }; Ball.prototype.stop = function () { if (this.timerId) Stopper.call (this); }; Ball.create = function (ballId, position, mover, interval) { var target = document.getElementById (ballId); var obj = null; if (target) { target.style.position = 'absolute'; target.style.top = position[1] + 'px'; target.style.left = position[0] + 'px'; obj = new Ball (target, position, mover, interval || 500); obj.start (); } return obj; } //_________ var bound = function (height, speed, gravity) { speed = speed || 0; gravity = gravity || 0.980665; return function (y, f, v) { if (f < 0) { speed = -speed; y = v; } else { speed = speed + gravity; y -= speed; } return Math.floor (y); }; }; var area = isInsideSpace ([0, 0], [700, 200]); // 2次元の動ける範囲 var motionList = [ (function (v) { return function (x, f) { if (f) v = -v; v *=0.995; return (x + v) |0; };})(5), // x 座標の動き bound (400, 0) // y 座標の動き ]; var mover = createMover (motionList, area); //_________ var BALL = Ball.create ('ball', [0, 100], mover, 10); </script>