Flash/Flex学习笔记(23):运动学原理
先写一个公用的小球类Ball:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 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坐标
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | 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中将速度增加固定值即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | 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 ; } |
自由落体运动:
其实就是匀加速直线运动的特例,把上面的代码稍作修改即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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 ; } } |
反弹:只要将上面的例子稍候修改即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | 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 ; } |
往返直线运动:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | 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中的示例)
飞船类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 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 ); } } } } |
主动画
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | 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 ; } } } } |
带摩擦力的加速旋转:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | 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 ; } |
作者:菩提树下的杨过
出处:http://yjmyzz.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
出处:http://yjmyzz.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 现代计算机视觉入门之:什么是图片特征编码
· .NET 9 new features-C#13新的锁类型和语义
· Sdcb Chats 技术博客:数据库 ID 选型的曲折之路 - 从 Guid 到自增 ID,再到
· 语音处理 开源项目 EchoSharp
· 《HelloGitHub》第 106 期
· Spring AI + Ollama 实现 deepseek-r1 的API服务和调用
· 使用 Dify + LLM 构建精确任务处理应用
2008-04-03 [转自scott]ASP.NET MVC框架 (第二部分): URL路径选择