Flash/Flex学习笔记(20):运动学原理
先写一个公用的小球类Ball:
package
{
import
flash.display.Sprite;
//小球 类
public
class
Ball
extends
Sprite{
private
var
radius:
Number
;
//半径
private
var
color:
uint
;
//颜色
public
function
Ball(r:
Number
=
50
,c:
uint
=
0xff0000
){
this
.radius = r;
this
.color = c;
init();
}
private
function
init():
void
{
graphics.beginFill(color);
graphics.drawCircle(
0
,
0
,radius);
graphics.endFill();
}
?}
}
圆周运行与椭圆运动:
主要依靠三角函数结合椭圆公式计算对象的x,y坐标
var
ball:Ball =
new
Ball(
5
,
0xff0000
);
?var
ball2:Ball =
new
Ball(
8
,
0x0000ff
);
?addChild(ball);
addChild(ball2);
var
_radius:
uint
=
75
;
var
_angle:
Number
=
0
;
var
_centerX = stage.stageWidth/
2
;
var
_centerY = stage.stageHeight/
2
;
var
_radius_X =
100
;
var
_radius_Y =
175
;
addEventListener(Event.ENTER_FRAME,EnterFrameHandler);
graphics.lineStyle(
1
);
?graphics.moveTo(_centerX,_centerY);
function
EnterFrameHandler(event:Event):
void
{
ball.x =? _centerX +? _radius * Math.cos(_angle * Math.PI/
180
);
ball.y = _centerY + _radius * Math.sin(_angle * Math.PI/
180
);
ball2.x =? _centerX +? _radius_X * Math.cos(_angle * Math.PI/
180
);
?ball2.y = _centerY + _radius_Y * Math.sin(_angle * Math.PI/
180
);
_angle +=
1
;
if
(_angle<=
360
){????????
graphics.moveTo(ball.x,ball.y);
graphics.lineStyle(
1
,_angle * Math.pow(
2
,
24
)/
360
,
1
);
?//graphics.lineStyle(1,Math.random() * 0xffffff,1);
?graphics.lineTo(ball2.x,ball2.y);
?}???
?}
匀加速直线运动:
速度公式:v = v0 + at,物理学上的公式虽然是这样,但是到了Flash中思路得稍微换一下,Flash默认为每秒24帧,而EnterFrame事件在每次进入新一帧时触发,所以可粗略的认为每一帧就是一个“单位时间”,匀加速的重要特征就是每单位时间速度增加固定值,所以在Flash中只要在EnterFrame中将速度增加固定值即可
var
ball:Ball;
var
vx:
Number
=
0
;
?var
ax:
Number
=
0
;
var
vy:
Number
=
0
;
var
ay:
Number
=
0
;
?ball =
new
Ball? ;
addChild(ball);
ball.x = stage.stageWidth/
2
;
ball.y = stage.stageHeight/
2
;
?ball.scaleX =
0.1
;
?ball.scaleY =
0.1
;
addEventListener(Event.ENTER_FRAME,EnterFrameHandler);
stage.addEventListener(KeyboardEvent.KEY_DOWN, KeyDownHandler);
?stage.addEventListener(KeyboardEvent.KEY_UP, KeyUpHandler);
graphics.lineStyle(
1
,
0
,
1
);
graphics.moveTo((stage.stageWidth/
2
)-
10
,stage.stageHeight/
2
);
?graphics.lineTo((stage.stageWidth/
2
)+
10
,stage.stageHeight/
2
);
?graphics.moveTo(stage.stageWidth/
2
,(stage.stageHeight/
2
)-
10
);
?graphics.lineTo(stage.stageWidth/
2
,(stage.stageHeight/
2
)+
10
);?
function
EnterFrameHandler(event:Event):
void
{
vx += ax;
//每次进入该帧时,x轴方向的速度增加指定值(即x轴方向匀加速运行)
ball.x += vx;
vy += ay;
//每次进入该帧时,y轴方向的速度增加指定值(即y轴方向匀加速运行)????
ball.y += vy;
if
(ball.x>=stage.stageWidth-ball.width/
2
) {
?ball.x=stage.stageWidth-ball.width/
2
;???????
vx =
0
;
}
else
if
(ball.x <= ball.width/
2
) {
ball.x = ball.width/
2
;??????
vx =
0
;
}???
if
(ball.y>=stage.stageHeight-ball.height/
2
) {
?ball.y=stage.stageHeight-ball.height/
2
;?????
vy =
0
;
}
else
if
(ball.y <= ball.height/
2
) {
?ball.y = ball.height/
2
;?????
?vy =
0
;
?}
?}
function
KeyDownHandler(event:KeyboardEvent):
void
{
switch
(event.keyCode){
case
Keyboard.RIGHT:
ax =
0.5
;
break
;
case
Keyboard.LEFT:
ax = -
0.5
;
break
;
?case
Keyboard.DOWN:
?ay =
0.5
;
?break
;
case
Keyboard.UP:
ay = -
0.5
;
default
:
?break
;
}
?}
function
KeyUpHandler(event:KeyboardEvent):
void
{
ax=
0
;
?ay=
0
;
}
自由落体运动:
其实就是匀加速直线运动的特例,把上面的代码稍作修改即可。
function
EnterFrameHandler(event:Event):
void
{
?vx += ax;?
ball.x += vx;
?vy += ay;???
vy +=
0.45
;
//这里再强行增加一个值做为重力加速度,所以不做控制的时候,也会自己向下掉
ball.y += vy;
if
(ball.x>=stage.stageWidth-ball.width/
2
) {
ball.x=stage.stageWidth-ball.width/
2
;???????
vx =
0
;
}
else
if
(ball.x <= ball.width/
2
) {
ball.x = ball.width/
2
;??????
vx =
0
;
?}???
if
(ball.y>=stage.stageHeight-ball.height/
2
) {
ball.y=stage.stageHeight-ball.height/
2
;?????
vy *= -
0.7
;
//假设反弹后的反向速度是原来速度的70%
}
else
if
(ball.y <= ball.height/
2
) {
ball.y = ball.height/
2
;?????
vy =
0
;
}
}
反弹:只要将上面的例子稍候修改即可
var
ball:Ball;
?var
vx:
Number
=
0
;
?var
ax:
Number
=
0
;
?var
vy:
Number
=
0
;
var
ay:
Number
=
0
;
ball =
new
Ball? ;
addChild(ball);
ball.x = stage.stageWidth/
2
;
ball.y = stage.stageHeight/
2
;
?ball.scaleX =
0.1
;
ball.scaleY =
0.1
;
addEventListener(Event.ENTER_FRAME,EnterFrameHandler);
stage.addEventListener(KeyboardEvent.KEY_DOWN, KeyDownHandler);
stage.addEventListener(KeyboardEvent.KEY_UP, KeyUpHandler);
graphics.lineStyle(
1
,
0
,
1
);
graphics.moveTo((stage.stageWidth/
2
)-
10
,stage.stageHeight/
2
);
graphics.lineTo((stage.stageWidth/
2
)+
10
,stage.stageHeight/
2
);
graphics.moveTo(stage.stageWidth/
2
,(stage.stageHeight/
2
)-
10
);
graphics.lineTo(stage.stageWidth/
2
,(stage.stageHeight/
2
)+
10
);?
var
_bounce:
Number
= -
0.5
;
//反弹后的速度百分比
function
EnterFrameHandler(event:Event):
void
{
vx += ax;?
ball.x += vx;
vy += ay;???
ball.y += vy;
if
(ball.x>=stage.stageWidth-ball.width/
2
) {
ball.x=stage.stageWidth-ball.width/
2
;???????
vx *= _bounce;
}
else
if
(ball.x <= ball.width/
2
) {
ball.x = ball.width/
2
;??????
?vx *= _bounce;
}???
if
(ball.y>=stage.stageHeight-ball.height/
2
) {
ball.y=stage.stageHeight-ball.height/
2
;?????
?vy *= _bounce;?
}
else
if
(ball.y <= ball.height/
2
) {
ball.y = ball.height/
2
;?????
vy *= _bounce;?
}
}
function
KeyDownHandler(event:KeyboardEvent):
void
{
switch
(event.keyCode){
case
Keyboard.RIGHT:
?ax =
0.5
;
?break
;
case
Keyboard.LEFT:
ax = -
0.5
;
break
;
case
Keyboard.DOWN:
ay =
0.5
;
break
;
case
Keyboard.UP:
ay = -
0.5
;
default
:
break
;
?}???
}
function
KeyUpHandler(event:KeyboardEvent):
void
{
ax=
0
;
ay=
0
;
}
往返直线运动:
?graphics.lineStyle(
1
,
0xff0000
,
0.5
);
graphics.moveTo(
0
,
0
);
graphics.lineTo(stage.stageWidth,stage.stageHeight);
?graphics.lineStyle(
1
,
0x00ff00
,
0.5
);
graphics.moveTo(stage.stageWidth,
0
);
graphics.lineTo(
0
,stage.stageHeight);
var
ball:Ball=
new
Ball(
10
,
0xff0000
);
ball.x=
0
;
ball.y=
0
;
?var
_seedX=-
90
;
?var
_seedY=
0
;
var
angle:
Number
=
45
* Math.PI/
180
;
?addChild(ball);
var
ball2:Ball =
new
Ball(
10
,
0x00ff00
);
ball2.x = stage.stageWidth;
?var
speed =
2
;
var
isDown =
true
;
addChild(ball2);
addEventListener(Event.ENTER_FRAME,EnterFrameHandler);
function
EnterFrameHandler(e:Event):
void
{??
ball.x = Math.cos(_seedX*Math.PI/
180
)*stage.stageWidth;?
ball.y = Math.sin(_seedY*Math.PI/
180
)*stage.stageHeight;
?_seedX+=
1
;
?_seedY+=
1
;
if
(_seedX >
90
){
_seedX = -
90
;
?}
if
(_seedY >
180
){
?_seedY =
0
;
?}???
//向下
if
(isDown){
?ball2.x -= speed;
ball2.y += speed;
if
(ball2.x <
0
){
isDown =
false
;
}
?}
else
{
//向上
ball2.x -= -speed;
ball2.y += -speed;
if
(ball2.x > stage.stageWidth){
isDown =
true
;
}
}
}
注:上面演示了二种方法,对于往返匀速直线运动,最简单的办法就是让x,y轴方向速度增加固定值;如果不要求匀速的话,用sin,cos函数也许更简单
飞船键盘控制演示:(来自ActionScript 3.0 Animation中的示例)
飞船类
package
{
?import
flash.display.Sprite;
public
class
Ship
extends
Sprite {
?public
function
Ship() {
?draw(
false
);
?}
?public
function
draw(showFlame:
Boolean
):
void
{
?graphics.clear();
?graphics.lineStyle(
1
,
0xffffff
);
graphics.moveTo(
10
,
0
);
?graphics.lineTo(-
10
,
10
);
?graphics.lineTo(-
5
,
0
);
?graphics.lineTo(-
10
,-
10
);
?graphics.lineTo(
10
,
0
);
?if
(showFlame) {
?graphics.moveTo(-
7.5
,-
5
);
?graphics.lineTo(-
15
,
0
);
?graphics.lineTo(-
7.5
,
5
);
?}
?}
?}
}
主动画
?package
{
?import
flash.display.Sprite;
?import
flash.events.Event;
import
flash.events.KeyboardEvent;
?import
flash.ui.Keyboard;
?public
class
ShipSim
extends
Sprite {
private
var
ship:Ship;
private
var
vr:
Number
=
0
;
?private
var
thrust:
Number
=
0
;
?private
var
vx:
Number
=
0
;
?private
var
vy:
Number
=
0
;
?public
function
ShipSim() {
init();
?}
private
function
init():
void
{
?ship=
new
Ship? ;
?ship.scaleX = ship.scaleY =
1.5
;
addChild(ship);
ship.x=stage.stageWidth/
2
;
?ship.y=stage.stageHeight/
2
;
?addEventListener(Event.ENTER_FRAME,EnterFrameHandler);
?stage.addEventListener(KeyboardEvent.KEY_DOWN,KeyDownHandler);
?stage.addEventListener(KeyboardEvent.KEY_UP,KeyUpHandler);
?}
private
function
KeyDownHandler(event:KeyboardEvent):
void
{?????????
?switch
(event.keyCode) {
?case
Keyboard.LEFT :
vr=-
5
;
break
;
case
Keyboard.RIGHT :
?vr=
5
;
?break
;
case
Keyboard.UP :
?thrust=
0.2
;
?ship.draw(
true
);
?break
;
?default
:
?break
;
?}
?}
?private
function
KeyUpHandler(event:KeyboardEvent):
void
{
?vr=
0
;
thrust=
0
;
ship.draw(
false
);
?}
private
function
EnterFrameHandler(event:Event):
void
{
ship.rotation+=vr;
var
angle:
Number
=ship.rotation*Math.PI/
180
;
var
ax:
Number
=Math.cos(angle)*thrust;
?var
ay:
Number
=Math.sin(angle)*thrust;???????????
?vx+=ax;
?vy+=ay;
?ship.x+=vx;
?ship.y+=vy;
if
(ship.x < ship.width/
2
){
?ship.x = ship.width/
2
;??????????????
vx =
0
;
}
if
(ship.x>stage.stageWidth -ship.width/
2
){
ship.x = stage.stageWidth -ship.width/
2
;
?vx =
0
;
}
if
(ship.y > stage.stageHeight - ship.height/
2
){
?ship.y = stage.stageHeight - ship.height/
2
;
vy=
0
;
?}
?if
(ship.y < ship.height/
2
){
ship.y = ship.height/
2
;
vy=
0
;
}
?}
?}
?}
带摩擦力的加速旋转:
?addEventListener(Event.ENTER_FRAME,EnterFrameHandler);
stage.addEventListener(KeyboardEvent.KEY_DOWN,KeyDownHandler);
?stage.addEventListener(KeyboardEvent.KEY_UP,KeyUpHandler);
var
ar:
Number
=
0
;
var
vr:
Number
=
0
;
var
_isStart:
Boolean
=
false
;
//是否正在加速(或减速)
?var
_isRight:
Boolean
=
true
;
//是否正在向右顺时针转动
?function
EnterFrameHandler(e:Event):
void
{
?vr+=ar;
?obj.rotation+=vr;
//obj是舞台中的箭头实例
?if
(!_isStart) {
?if
(_isRight) {
if
(vr<=
0
) {
vr=
0
;
ar=
0.0
;
}
}
else
{
if
(vr>=
0
) {
vr=
0
;
ar=
0.0
;
?}
}
?}
?}
?function
KeyDownHandler(e:KeyboardEvent):
void
{
?_isStart=
true
;
?if
(e.keyCode==Keyboard.RIGHT) {
?ar=
0.2
;
?_isRight=
true
;
}
else
if
(e.keyCode == Keyboard.LEFT) {
ar=-
0.2
;
?_isRight=
false
;
}
}
function
KeyUpHandler(e:KeyboardEvent):
void
{
if
(e.keyCode==Keyboard.RIGHT) {
ar=-
0.1
;
}
else
if
(e.keyCode == Keyboard.LEFT) {
ar=
0.1
;
?}
_isStart=
false
;
}
?