2008年10月16日星期四

《making things move》笔记(第十章)

第十章 坐标旋转及角度反弹

简单的坐标旋转
角度应用弧度制来表示。
代码的结构如下所示:
vr = 0.1;
angle = 0;
radius = 100;
centerX = 250;
centerY = 200;
// 在 enterFrame 处理函数中:
sprite.x = centerX + cos(angle) * radius;
sprite.y = centerY + sin(angle) * radius;
angle += vr;

高级坐标旋转
如果物体要绕着某一点旋转,并且以物体本身的位置作为旋转的起点

x1 = cos(angle) * x - sin(angle) * y;
y1 = cos(angle) * y + sin(angle) * x;


坐标旋转:
x1 = Math.cos(angle) * x - Math.sin(angle) * y;
y1 = Math.cos(angle) * y + Math.sin(angle) * x;

反坐标旋转:
x1 = Math.cos(angle) * x + Math.sin(angle) * y;
y1 = Math.cos(angle) * y - Math.sin(angle) * x;

《making things move》笔记(第九章)

--竟然十天没有看这本书了

hitTest 总结
hitTest 的基本设置:
■ 对于矩形影片,使用 hitTestObject(displayObject)。
■ 对于非常小的影片,使用 hitTestPoint(x, y, true)(注意将 shapeFlag 设置为 true)。
■ 对于非常不规则的影片图形,如果不要求非常精确或自定义一些解决方法的话,那么也可以使用 hitTestPoint(x, y, true)。

距离碰撞检测
处理圆形时效果最好
两个物体间距离的方法,
var dx:Number = sprite2.x - sprite1.x;
var dy:Number = sprite2.y - sprite1.y;
var dist:Number = Math.sqrt(dx * dx + dy * dy);


例:
private function onEnterFrame(event:Event):void {

var dx:Number = ball2.x - ball1.x;
var dy:Number = ball2.y - ball1.y;
var dist:Number = Math.sqrt(dx * dx + dy * dy);
if (dist < ball1.radius + ball2.radius) {
trace("hit");
}
}


基本的多物体碰撞检测
numSprites = 6;
for (i = 0; i < numSprites - 1; i++) {
spriteA = sprites[i];
for (j = i + 1; j < numSprites; j++) {
spriteB = sprites[j];
if (spriteA.hitTestObject(spriteB)) {
// do whatever
}
}
}

Math.cos 和 Math.sin 求出目标点:
var angle:Number = Math.atan2(dy, dx);
var tx:Number = ball0.x + Math.cos(angle) * minDist;
var ty:Number = ball0.y + Math.sin(angle) * minDist;
但是大家不要忘记,正弦是对边与斜边之比,而余弦是邻边与斜边之比。
请注意,该角的对边就是 dy,邻边就是 dx,而斜边就是 dist。
所以,我们实际上可以将这三行代码缩短为两行:
var tx:Number = ball0.x + dx / dist * minDist;
var ty:Number = ball0.y + dy / dist * minDist;

距离碰撞检测: // 从 spriteA 和 spriteB 开始 // 如果使用一个空白影片,或影片没有半径(radius)属性 166
// 可以用宽度与高度除以 2。 var dx:Number = spriteB.x - spriteA.x; var dy:Number = spriteB.y - spriteA.y; var dist:Number = Math.sqrt(dx * dx + dy * dy); if (dist < spriteA.radius + spriteB.radius) { // 处理碰撞 }
多物体碰撞检测: var numObjects:uint = 10; for (var i:uint = 0; i < numObjects - 1; i++) { // 使用变量 i 提取引用 var objectA = objects[i]; for (var j:uint = i+1; j //使用变量 j 提取引用 var objectB = objects[j]; // 在 objectA 与 objectB 之间进行碰撞检测 } }

2008年10月7日星期二

《making things move》笔记(第八章)

简单缓动,长形:
var dx:Number = targetX - sprite.x;
var dy:Number = targetY - sprite.y;
vx = dx * easing; vy = dy * easing;
sprite.x += vx;
sprite.y += vy;


简单缓动,中形:
vx = (targetX - sprite.x) * easing;
vy = (targetY - sprite.y) * easing;
sprite.x += vx;
sprite.y += vy;


简单缓动,短形:
sprite.x += (targetX - sprite.x) * easing;
sprite.y += (targetY - sprite.y) * easing;


简单弹性,长形:
var ax:Number = (targetX - sprite.x) * spring;
var ay:Number = (targetY - sprite.y) * spring;
vx += ax;
vy += ay;
vx *= friction;
vy *= friction;
sprite.x += vx;
sprite.y += vy;



简单弹性,中形:
vx += (targetX - sprite.x) * spring;
vy += (targetY - sprite.y) * spring;
vx *= friction;
vy *= friction;
sprite.x += vx;
sprite.y += vy;


简单弹性,短形:
vx += (targetX - sprite.x) * spring;
vy += (targetY - sprite.y) * spring;
sprite.x += (vx *= friction);
sprite.y += (vy *= friction);



偏移弹性运动:
var dx:Number = sprite.x - fixedX;
var dy:Number = sprite.y - fixedY;
var angle:Number = Math.atan2(dy, dx);
var targetX:Number = fixedX + Math.cos(angle) * springLength;
var targetY:Number = fixedX + Math.sin(angle) * springLength;

2008年10月5日星期日

《making things move》笔记(第六章)

设置边界
播放器窗口改变大小后希望舞台的尺寸与播放器尺寸相匹配
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;

影片的左上边界将为零,而右下边界将为 stage.stageWidth 和 stage.stageHeight。
如下:
private var left:Number = 0;
private var top:Number = 0;
private var right:Number = stage.stageWidth;
private var bottom:Number = stage.stageHeight;

看它们是否仍在这个空间内,这里可以使用 if 语句
if(ball.x > stage.stageWidth) {
// do something
}
else if(ball.x < 0) {
// do something
}
if(ball.y > stage.stageHeight) {
// do something
}
else if(ball.y < 0)
{ // do something
}
移除对象
1. removeChild(对象名),删除影片或显示对象,会将对象实例从舞台上移除。请注意,被移除的显示对象仍然存在,只是看不到而已。如果要将该对象彻底删除,还应该调用 delete 对象名 将其完全删除。
2. removeEventListener(Event.ENTER_FRAME, onEnterFrame);

因为注册点在中心,所以,可以将宽度的一半保存为 radius 属性。
代码如下:
if(ball.x - ball.radius > stage.stageWidth || ball.x + ball.radius < 0 || ball.y - ball.radius > stage.stageHeight || ball.y + ball.radius < 0) {
removeChild(ball);
}


var ball:Ball=Ball(balls[i]);????????????????????????????????
移除对象
for (var i:Number=balls.length - 1; i > 0; i--) { var ball:Ball=Ball(balls[i]); 97
ball.x+= ball.vx; ball.y+= ball.vy; if (ball.x - ball.radius > stage.stageWidth || ball.x + ball.radius < 0 || ball.y - ball.radius > stage.stageHeight || ball.y + ball.radius < 0) { removeChild(ball); balls.splice(i,1);

重置对象
if (ball.x - ball.radius > stage.stageWidth || ball.x + ball.radius < 0 || ball.y - ball.radius > stage.stageHeight || ball.y + ball.radius < 0) { ball.x = stage.stageWidth / 2; ball.y = stage.stageHeight; ball.vx = Math.random() * 2 - 1; ball.vy = Math.random() * -10 - 10; }

屏幕环绕
var left:Number = 0; var right:Number = stage.stageWidth; var top:Number = 0; var bottom:Number = stage.stageHeight; if (ship.x - ship.width / 2 > right) { ship.x = left - ship.width / 2; } else if (ship.x + ship.width / 2 < left) { ship.x = right + ship.width / 2; } if (ship.y - ship.height / 2 > bottom) { ship.y = top - ship.height / 2; } else if (ship.y < top - ship.height / 2) { ship.y = bottom + ship.height / 2; }

反弹
如果物体超出了左、右边界,只需要使它的 x 速度向量取反。如果超出了上、下边界,只需要让 y 速度向量取反
:vx *= -1 或 vy *= -1。

摩擦力,正确的方法
摩擦力是与速度向量相反的力
var speed:Number = Math.sqrt(vx * vx + vy * vy);
var angle:Number = Math.atan2(vy, vx);
然后就可以从速度向量中减去速度。如果摩擦力大于速度,速度就变为零,计算代码如下: if (speed > friction) {
speed -= friction;
} else {
speed = 0;
}
正弦和余弦将角速度转换回 vx 和 vy,如下:
vx = Math.cos(angle) * speed;
vy = Math.sin(angle) * speed;

摩擦力,简便的方法
vx *= friction; 106
vy *= friction;

本章重要公式

移除出界对象:
if(sprite.x - sprite.width / 2 > right || sprite.x + sprite.width / 2 < left || sprite.y – sprite.height / 2 > bottom || sprite.y + sprite.height / 2 < top) { // 移除影片的代码
}

重置出界对象:
if(sprite.x - sprite.width / 2 > right || sprite.x + sprite.width / 2 < left || sprite.y – sprite.height / 2 > bottom || sprite.y + sprite.height / 2 < top) {
// 重置影片的位置和速度
}

屏幕环绕出界对象:
if (sprite.x - sprite.width / 2 > right) {
sprite.x = left - sprite.width / 2;
} else if (sprite.x + sprite.width / 2 < left) {
sprite.x = right + sprite.width / 2;
} if (sprite.y – sprite.height / 2 > bottom) {
sprite.y = top – sprite.height / 2;
} else if (sprite.y + sprite.height / 2 < top) {
sprite.y = bottom + sprite.height / 2;
}

摩擦力应用(正确方法):
speed = Math.sqrt(vx * vx + vy * vy);
angle = Math.atan2(vy, vx);
if (speed > friction) {
speed -= friction;
} else {
speed = 0;
}
vx = Math.cos(angle) * speed;
vy = Math.sin(angle) * speed;

摩擦力应用(简便方法):
vx *= friction;
vy *= friction;

《making things move》笔记(第五章)

本章重要公式

角速度转换为 x,y 速度向量:
vx = speed * Math.cos(angle);
vy = speed * Math.sin(angle);

角加速度(作用于物体上的 force )转换为 x,y 加速度:
ax = force * Math.cos(angle);
ay = force * Math.sin(angle);

将加速度加入速度向量:
vx += ax;
vy += ay;

将速度向量加入坐标:
movieclip._x += vx;
sprite.y += vy;