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