Flash/Flex学习笔记(25):摩擦力与屏幕环绕
摩擦力:
假如一个物体在某个方向上沿直线运行,摩擦力会使该方向上的速度越来越小,直到停止。 
上图示意了该过程,物体以moveAngle角度正向运动,最终的速度speed矢量为vx矢量与vy矢量的矢量和,在每个单位时间内的位移即Speed矢量的大小,分解到x,y轴后,即为vx与vy;加入摩擦力后,speed矢量每单位时间将减少Friction值,也就是视觉上的越来越慢。
01 var ball:Ball = new Ball(10);
02 ball.x = stage.stageWidth/2;
03 ball.y = stage.stageHeight/2;
04 addChild(ball);
05 Mouse.cursor = MouseCursor.BUTTON;
06 var Velocity:Number = 10;//速度最大值
07 var friction = 0.4;//摩擦力因子
08 stage.addEventListener(MouseEvent.MOUSE_DOWN,MouseDownHandler);
09 stage.addEventListener(MouseEvent.MOUSE_UP,MouseUpHandler);
10
11 function MouseDownHandler(e:MouseEvent):void{
12 graphics.clear();
13 //初始化小球位置以速度
14 ball.x = stage.stageWidth/2;
15 ball.y = stage.stageHeight/2;
16 ball.vx = (Math.random()*2-1) * Velocity;
17 ball.vy = (Math.random()*2-1) * Velocity;
18 graphics.moveTo(ball.x,ball.y);
19 graphics.lineStyle(1,0xcccccc,1);
20 }
21
22 function MouseUpHandler(e:MouseEvent):void{
23 addEventListener(Event.ENTER_FRAME,EnterFrameHandler);
24 }
25
26 function EnterFrameHandler(e:Event):void{
27 ball.x += ball.vx;
28 ball.y += ball.vy;
29
30 var speed:Number = Math.sqrt(ball.vx*ball.vx + ball.vy*ball.vy);
31 var moveAngle = Math.atan2(ball.vy,ball.vx);
32
33 speed -= friction;
34
35 //减速后的新速度
36 ball.vx = speed*Math.cos(moveAngle);
37 ball.vy = speed*Math.sin(moveAngle);
38
39 //防止减速过度,就成反向运动
40 if (speed<=friction){
41 ball.vx = 0;
42 ball.vy = 0;
43 removeEventListener(Event.ENTER_FRAME,EnterFrameHandler);
44 }
45 graphics.lineTo(ball.x,ball.y);
46
47 }
上面这种方法从物理意义上讲最接近现实情况,不过有些复杂,在实际开发中还有一种更简单的办法,虽然不怎么严密,但从视觉效果上很难看出问题
01 var ball:Ball = new Ball(10);
02 ball.x = stage.stageWidth/2;
03 ball.y = stage.stageHeight/2;
04 addChild(ball);
05 Mouse.cursor = MouseCursor.BUTTON;
06 var Velocity:Number = 10;
07 var friction = 0.9;//摩擦力因子(小于1大于0即可)
08 stage.addEventListener(MouseEvent.MOUSE_DOWN,MouseDownHandler);
09 stage.addEventListener(MouseEvent.MOUSE_UP,MouseUpHandler);
10
11 function MouseDownHandler(e:MouseEvent):void{
12 graphics.clear();
13 ball.x = stage.stageWidth/2;
14 ball.y = stage.stageHeight/2;
15 ball.vx = (Math.random()*2-1) * Velocity;
16 ball.vy = (Math.random()*2-1) * Velocity;
17 graphics.moveTo(ball.x,ball.y);
18 graphics.lineStyle(1,0xcccccc,1);
19 }
20
21 function MouseUpHandler(e:MouseEvent):void{
22 addEventListener(Event.ENTER_FRAME,EnterFrameHandler);
23 }
24
25 function EnterFrameHandler(e:Event):void{
26 ball.x += ball.vx;
27 ball.y += ball.vy;
28
29 ball.vx = ball.vx * friction;//直接让x轴速度不断衰减
30 ball.vy = ball.vy * friction;//直接让y轴速度不断衰减
31
32 if (Math.abs(ball.vx)<=0.0001 || Math.abs(ball.vy)<=0.0001){
33 ball.vx = 0;
34 ball.vy = 0;
35 removeEventListener(Event.ENTER_FRAME,EnterFrameHandler);
36 }
37
38 //trace(ball.vx);
39 //trace(ball.vy);
40 graphics.lineTo(ball.x,ball.y);
41
42 }
屏幕环绕:
这个叫法也许从字面上不太直观,说得更白一点就是:一个物体如果在运动过程中跑出了舞台边界,开发人员就要想办法让其从舞台的另一端出现,并继续运动,以保持连贯。前面的一篇文章 Flash/Flex学习笔记(23):运动学原理 中有一个飞船的示例,加入屏幕环绕处理后,代码如下:
01 package {
02 import flash.display.Sprite;
03 import flash.events.Event;
04 import flash.events.KeyboardEvent;
05 import flash.ui.Keyboard;
06 import flash.display.StageAlign;
07 import flash.display.StageScaleMode;
08 import fl.controls.Label;
09
10 public class ShipSim2 extends Sprite {
11
12 private var ship:Ship;
13 private var vr:Number=0;
14 private var thrust:Number=0;
15 private var vx:Number=0;
16 private var vy:Number=0;
17
18 public function ShipSim2() {
19 init();
20 }
21
22 private function init():void {
23 stage.scaleMode=StageScaleMode.NO_SCALE;
24 stage.align=StageAlign.TOP_LEFT;
25
26 ship = new Ship();
27 addChild(ship);
28 ship.x=stage.stageWidth/2;
29 ship.y=stage.stageHeight/2;
30 addEventListener(Event.ENTER_FRAME, EnterFrameHandler);
31 stage.addEventListener(KeyboardEvent.KEY_DOWN, KeyDownHandler);
32 stage.addEventListener(KeyboardEvent.KEY_UP, KeyUpHandler);
33 }
34
35 private function KeyDownHandler(event:KeyboardEvent):void {
36 switch (event.keyCode) {
37 case Keyboard.LEFT :
38 vr=-5;
39 break;
40 case Keyboard.RIGHT :
41 vr=5;
42 break;
43 case Keyboard.UP :
44 thrust=0.2;
45 ship.draw(true);
46 break;
47 default :
48 break;
49 }
50 }
51
52 private function KeyUpHandler(event:KeyboardEvent):void {
53 vr=0;
54 thrust=0;
55 ship.draw(false);
56 }
57
58 private function EnterFrameHandler(event:Event):void {
59 ship.rotation+=vr;
60 var angle:Number=ship.rotation*Math.PI/180;
61 var ax:Number=Math.cos(angle)*thrust;
62 var ay:Number=Math.sin(angle)*thrust;
63 vx+=ax;
64 vy+=ay;
65 ship.x+=vx;
66 ship.y+=vy;
67 var left:Number=0;
68 var right:Number=stage.stageWidth;
69 var top:Number=0;
70 var bottom:Number=stage.stageHeight;
71 //屏幕环绕处理
72 if (ship.x>right + ship.width/2) {
73 ship.x=left-ship.width/2;
74 } else if (ship.x < left - ship.width/2) {
75 ship.x=right+ship.width/2;
76 }
77 if (ship.y-ship.height/2>bottom) {
78 ship.y=top-ship.height/2;
79 } else if (ship.y < top - ship.height / 2) {
80 ship.y=bottom+ship.height/2;
81 }
82 }
83 }
84 }
最后把这二者结合起来,看下效果:
浙公网安备 33010602011771号