前回の第18回
ボールを床で弾ませる
第18回コード2
var floor = 50;
var bounce = -0.6;
function move(ball) {
ball.move(gravity);
var realY = ball.realY;
if (realY > floor) {
ball.velocityY *= bounce;
ball.realY = floor - realY % floor;
}
}
これで、
function animate(eventObject) {
if (newY > stageHeight) {
child.velocityY *= -0.8;
newY = stageHeight - newY % stageHeight;
}
}
つぎに、
もうひとつ、
![第16回図6 z軸における焦点距離と視野角(再掲) 第16回図6 z軸における焦点距離と視野角(再掲)](/assets/images/design/serial/01/createjs/0016/thumb/TH800_006.png)
ステージから消すオブジェクトは、
EaselJS 0.
indexOf(配列, エレメント)
function move(ball) {
ball.move(gravity);
var x = ball.x;
if (ball.realZ < -focalLength || x < 0 || stageWidth < x) {
var index = createjs.indexOf(balls, ball);
stage.removeChild(ball);
balls.splice(index, 1);
} else {
}
}
これで、
function Ball3D(radius, color) {
this.initialize();
this.radius = radius;
this.color = color;
this.realX = 0;
this.realY = 0;
this.realZ = 0;
this.velocityX = 0;
this.velocityY = 0;
this.velocityZ = 0;
this.drawBall(radius, color);
}
Ball3D.prototype = new createjs.Shape();
Ball3D.prototype.move = function(gravity) {
this.realX += this.velocityX;
this.realY += this.velocityY;
this.realZ += this.velocityZ;
this.velocityY += gravity;
};
Ball3D.prototype.getProjectedData = function(focalLength) {
var scale = focalLength / (focalLength + this.realZ);
var x = this.realX * scale;
var y = this.realY * scale;
return {x:x, y:y, scale:scale};
};
Ball3D.prototype.drawBall = function(radius, color) {
this.graphics.beginFill(color)
.drawCircle(0, 0, radius);
};
var stage;
var balls = [];
var numBalls = 100;
var stageWidth;
var centerX;
var centerY;
var gravity = 0.2;
var focalLength = 200;
var floor = 50;
var bounce = -0.6;
function initialize() {
var canvasElement = document.getElementById("myCanvas");
stage = new createjs.Stage(canvasElement);
stageWidth = canvasElement.width;
centerX = stageWidth / 2;
centerY = canvasElement.height / 2;
for (var i = 0; i < numBalls; i++) {
var color = createjs.Graphics.getRGB(getRandom(0, 0xFFFFFF));
var ball = new Ball3D(3, color);
balls.push(ball);
ball.realY = -50;
ball.velocityX = getRandom(-3, 3);
ball.velocityY = getRandom(-6, 0);
ball.velocityZ = getRandom(-3, 3);
stage.addChild(ball);
}
createjs.Ticker.addEventListener("tick", animate);
}
function animate(eventObject) {
for (var i = balls.length - 1; i > -1; i--) {
var ball = balls[i];
move(ball);
}
stage.update();
}
function move(ball) {
ball.move(gravity);
var x = ball.x;
var realY = ball.realY;
if (realY > floor) {
ball.velocityY *= bounce;
ball.realY = floor - realY % floor;
}
if (ball.realZ < -focalLength || x < 0 || stageWidth < x) {
var index = createjs.indexOf(balls, ball);
stage.removeChild(ball);
balls.splice(index, 1);
} else {
var data = ball.getProjectedData(focalLength);
ball.scaleX = ball.scaleY = data.scale;
ball.x = centerX + data.x;
ball.y = centerY + data.y;
}
}
function getRandom(min, max) {
var randomNumber = Math.random() * (max - min) + min;
return randomNumber;
}
残るは、
![図1 透視投影で手前に見えるべきボールの前に小さいボールが重なる 図1 透視投影で手前に見えるべきボールの前に小さいボールが重なる](/assets/images/design/serial/01/createjs/0019/thumb/TH800_001.png)
オブジェクトの重なりをz座標値の順に並べ替える
CreateJSでは、
親オブジェクト.setChildIndex(子オブジェクト, インデックス)
すると、
配列.sort(比較関数)
Array.
function 比較関数(a, b) {
if (aがbより大きい) {
return 1;
} else if (aがbより小さい) {
return -1;
} else { // aとbは等しい
return 0;
}
}
オブジェクトの重なりをz座標値
function sortZ() {
balls.sort(compare);
}
function compare(a, b) {
if (a.realZ > b.realZ) {
return 1;
} else if (a.realZ < b.realZ) {
return -1;
} else {
return 0;
}
}
そのうえで、
function animate(eventObject) {
sortZ();
stage.update();
}
function sortZ() {
var count = balls.length;
balls.sort(compare);
for (var i = 0; i < count; i++) {
var ball = balls[i];
stage.setChildIndex(ball, 0);
}
}
これで、
![図1 ボールにアウトラインを加えて遠近感も強めたアニメーション 図1 ボールにアウトラインを加えて遠近感も強めたアニメーション](/assets/images/design/serial/01/createjs/0019/thumb/TH800_002.png)
function Ball3D(radius, color) {
this.initialize();
this.radius = radius;
this.color = color;
this.realX = 0;
this.realY = 0;
this.realZ = 0;
this.velocityX = 0;
this.velocityY = 0;
this.velocityZ = 0;
this.drawBall(radius, color);
}
Ball3D.prototype = new createjs.Shape();
Ball3D.prototype.move = function(gravity) {
this.realX += this.velocityX;
this.realY += this.velocityY;
this.realZ += this.velocityZ;
this.velocityY += gravity;
};
Ball3D.prototype.getProjectedData = function(focalLength) {
var scale = focalLength / (focalLength + this.realZ);
var x = this.realX * scale;
var y = this.realY * scale;
return {x:x, y:y, scale:scale};
};
Ball3D.prototype.drawBall = function(radius, color) {
this.graphics.beginFill(color)
.drawCircle(0, 0, radius);
};
var stage;
var balls = [];
var numBalls = 100;
var stageWidth;
var centerX;
var centerY;
var gravity = 0.2;
var focalLength = 200;
var floor = 50;
var bounce = -0.6;
function initialize() {
var canvasElement = document.getElementById("myCanvas");
stage = new createjs.Stage(canvasElement);
stageWidth = canvasElement.width;
centerX = stageWidth / 2;
centerY = canvasElement.height / 2;
for (var i = 0; i < numBalls; i++) {
var color = createjs.Graphics.getRGB(getRandom(0, 0xFFFFFF));
var ball = new Ball3D(3, color);
balls.push(ball);
ball.realY = -50;
ball.velocityX = getRandom(-3, 3);
ball.velocityY = getRandom(-6, 0);
ball.velocityZ = getRandom(-3, 3);
stage.addChild(ball);
}
createjs.Ticker.addEventListener("tick", animate);
}
function animate(eventObject) {
for (var i = balls.length - 1; i > -1; i--) {
var ball = balls[i];
move(ball);
}
sortZ();
stage.update();
}
function move(ball) {
ball.move(gravity);
var x = ball.x;
var realY = ball.realY;
if (realY > floor) {
ball.velocityY *= bounce;
ball.realY = floor - realY % floor;
}
if (ball.realZ < -focalLength || x < 0 || stageWidth < x) {
var index = createjs.indexOf(balls, ball);
stage.removeChild(ball);
balls.splice(index, 1);
console.log([stage.getNumChildren(), balls.length]);
} else {
var data = ball.getProjectedData(focalLength);
ball.scaleX = ball.scaleY = data.scale;
ball.x = centerX + data.x;
ball.y = centerY + data.y;
}
}
function sortZ() {
var count = balls.length;
balls.sort(compare);
for (var i = 0; i < count; i++) {
var ball = balls[i];
stage.setChildIndex(ball, 0);
}
}
function compare(a, b) {
if (a.realZ > b.realZ) {
return 1;
} else if (a.realZ < b.realZ) {
return -1;
} else {
return 0;
}
}
function getRandom(min, max) {
var randomNumber = Math.random() * (max - min) + min;
return randomNumber;
}
jsdo.