1、欧拉积分
1 package { 2 import flash.display.Sprite; 3 import flash.display.StageAlign; 4 import flash.display.StageScaleMode; 5 import flash.events.Event; 6 import flash.geom.Point; 7 import flash.utils.getTimer; 8 public class Euler extends Sprite 9 { 10 private var _ball:Sprite; 11 private var _position:Point; 12 private var _velocity:Point; 13 private var _gravity:Number = 32; 14 private var _bounce:Number = -0.6; 15 private var _oldTime:int; 16 private var _pixelsPerFoot:Number = 10; 17 18 public function Euler() 19 { 20 stage.align = StageAlign.TOP_LEFT; 21 stage.scaleMode = StageScaleMode.NO_SCALE; 22 _ball = new Sprite(); 23 _ball.graphics.beginFill(0xff0000); 24 _ball.graphics.drawCircle(0, 0, 20); 25 _ball.graphics.endFill(); 26 _ball.x = 50; 27 _ball.y = 50; 28 addChild(_ball); 179 29 _velocity = new Point(10, 0); 30 _position = new Point( _ball.x / _pixelsPerFoot, _ball.y / _pixelsPerFoot ); 31 _oldTime = getTimer(); 32 addEventListener(Event.ENTER_FRAME, onEnterFrame); 33 } 34 private function onEnterFrame(event:Event):void 35 { 36 var time:int = getTimer(); 37 var elapsed:Number = (time - _oldTime) / 1000; 38 _oldTime = time; 39 var accel:Point = acceleration(_position, _velocity); 40 _position.x += _velocity.x * elapsed; 41 _position.y += _velocity.y * elapsed; 42 _velocity.x += accel.x * elapsed; 43 _velocity.y += accel.y * elapsed; 44 // 检测如果对象超过边缘就弹回 45 if(_position.y > ( stage.stageHeight - 20 ) / _pixelsPerFoot ) 46 { 47 _position.y = ( stage.stageHeight - 20 ) / _pixelsPerFoot; 48 _velocity.y *= _bounce; 49 } 50 if(_position.x > ( stage.stageWidth - 20 ) / _pixelsPerFoot ) 51 { 52 _position.x = ( stage.stageWidth - 20 ) / _pixelsPerFoot; 53 _velocity.x *= _bounce 54 } 55 else if(_position.x < 20 / _pixelsPerFoot) 56 { 57 _position.x = 20 / _pixelsPerFoot; 58 _velocity.x *= _bounce; 59 } 60 _ball.x = _position.x * _pixelsPerFoot; 61 _ball.y = _position.y * _pixelsPerFoot; 62 } 63 private function acceleration(p:Point, v:Point):Point 64 { 65 return new Point(0, _gravity); 66 } 67 } 68 }
2、Runge-Kutta积分
RK2:计算出每段开始时和结束时的加速度和速度,然后取平均值。
首先,计算开始时的加速度,然后是位置和速度,这些和欧拉法是完全一致的。不过我们用新的变量来保存这些信息。
// position1是对象的当前位置
// velocity1是对象的当前速度
acceleration1 = acceleration(position1, velocity1)
position2 = position1 + velocity1 * time
velocity2 = velocity1 + acceleration1 * time
position2和velocity2就是结束时对象的位置和速度。接下来求结束时的加速度:
acceleration2 = acceleration(position2, velocity2)
然后是RK2的关键一步,求两个状态下的平均速度和加速度:
position1 += (velocity1 + velocity2) / 2 * time
velocity1 += (acceleration1 + acceleration2) / 2 * time
开始时和结束时的平均速度乘以时间,得到改变的位移,加于当前位置,就是改变后的位置。同理加速度,就是改变后的速度。
1 package { 2 import flash.display.Sprite; 3 import flash.display.StageAlign; 4 import flash.display.StageScaleMode; 5 import flash.events.Event; 6 import flash.geom.Point; 7 import flash.utils.getTimer; 8 public class RK2 extends Sprite 9 { 10 private var _ball:Sprite; 11 private var _position:Point; 12 private var _velocity:Point; 13 private var _gravity:Number = 32; 14 private var _bounce:Number = -0.6; 15 private var _oldTime:int; 16 private var _pixelsPerFoot:Number = 10; 17 public function RK2() 18 { 19 stage.align = StageAlign.TOP_LEFT; 20 stage.scaleMode = StageScaleMode.NO_SCALE; 21 _ball = new Sprite(); 22 _ball.graphics.beginFill(0xff0000); 23 _ball.graphics.drawCircle(0, 0, 20); 24 _ball.graphics.endFill(); 25 _ball.x = 50; 26 _ball.y = 50; 27 addChild(_ball); 28 _velocity = new Point(10, 0); 29 _position = new Point(_ball.x / _pixelsPerFoot, _ball.y / _pixelsPerFoot); 30 _oldTime = getTimer(); 31 addEventListener(Event.ENTER_FRAME, onEnterFrame); 32 } 33 private function onEnterFrame(event:Event):void 34 { 35 var time:int = getTimer(); 36 var elapsed:Number = (time - _oldTime) / 1000; 37 _oldTime = time; 38 var accel1:Point = acceleration(_position, _velocity); 39 var position2:Point = new Point(); 40 position2.x = _position.x + _velocity.x * elapsed; 41 position2.y = _position.y + _velocity.y * elapsed; 42 var velocity2:Point = new Point(); 43 velocity2.x = _velocity.x + accel1.x * elapsed; 183 44 velocity2.y = _velocity.y + accel1.x * elapsed; 45 var accel2:Point = acceleration(position2, velocity2); 46 _position.x += (_velocity.x + velocity2.x) / 2 * elapsed; 47 _position.y += (_velocity.y + velocity2.y) / 2 * elapsed; 48 _velocity.x += (accel1.x + accel2.x) / 2 * elapsed; 49 _velocity.y += (accel1.y + accel2.y) / 2 * elapsed; 50 if(_position.y > (stage.stageHeight - 20) / _pixelsPerFoot) 51 { 52 _position.y = (stage.stageHeight - 20) / _pixelsPerFoot; 53 _velocity.y *= _bounce; 54 } 55 if(_position.x > (stage.stageWidth - 20) / _pixelsPerFoot) 56 { 57 _position.x = (stage.stageWidth - 20) / _pixelsPerFoot; 58 _velocity.x *= _bounce 59 } 60 else if(_position.x < 20 / _pixelsPerFoot) 61 { 62 _position.x = 20 / _pixelsPerFoot; 63 _velocity.x *= _bounce; 64 } 65 _ball.x = _position.x * _pixelsPerFoot; 66 _ball.y = _position.y * _pixelsPerFoot; 67 } 68 private function acceleration(p:Point, v:Point):Point 69 { 70 return new Point(0, _gravity); 71 } 72 } 73 }
3、RK4:。如果人们提及“Runge-Kutta”,几乎总是讨论RK4。
和RK2比,我们要做差不多类似的事情,只是不再采用开始和结束端的信息,而是要用4处的信息。
在RK4中,求平均值的方式有点不同。先让我们看看伪码,很长,所以名词我都用了简称。
// pos1是对象的当前位置
// vel1是对象的当前速度
acc1 = acceleration(pos1, vel1)
pos2 = pos1 + vel1 / 2 * time
vel2 = vel1 + acc1 / 2 * time
acc2 = acceleration(pos2, vel2)
pos3 = pos1 + vel2 / 2 * time
vel3 = vel1 + acc2 / 2 * time
acc3 = acceleration(pos3, vel3)
pos4 = pos1 + vel3 * time
vel4 = vel1 + acc3 * time
acc4 = acceleration(pos4, vel4)
pos1 += (vel1 + vel2 * 2 + vel3 * 2 + vel4) / 6 * time
vel1 += (acc1 + acc2 * 2 + acc3 * 2 + acc4) / 6 * time
注意,第一、第四步的求解和第二、第三步不同,在第二、第三步时候先除以了2,在最后求平均时又乘以了2。
1 package { 2 import flash.display.Sprite; 3 import flash.display.StageAlign; 4 import flash.display.StageScaleMode; 5 import flash.events.Event; 6 import flash.geom.Point; 7 import flash.utils.getTimer; 8 public class RK4 extends Sprite 9 { 10 private var _ball:Sprite; 11 private var _position:Point; 12 private var _velocity:Point; 13 private var _gravity:Number = 32; 14 private var _bounce:Number = -0.6; 15 private var _oldTime:int; 16 private var _pixelsPerFoot:Number = 10; 17 public function RK4() 18 { 19 stage.align = StageAlign.TOP_LEFT; 20 stage.scaleMode = StageScaleMode.NO_SCALE; 21 _ball = new Sprite(); 22 _ball.graphics.beginFill(0xff0000); 23 _ball.graphics.drawCircle(0, 0, 20); 24 _ball.graphics.endFill(); 25 _ball.x = 50; 26 _ball.y = 50; 27 addChild(_ball); 28 _velocity = new Point(10, 0); 29 185 30 _position = new Point(_ball.x / _pixelsPerFoot, _ball.y / _pixelsPerFoot); 31 _oldTime = getTimer(); 32 addEventListener(Event.ENTER_FRAME, onEnterFrame); 33 } 34 private function onEnterFrame(event:Event):void 35 { 36 var time:int = getTimer(); 37 var elapsed:Number = (time - _oldTime) / 1000; 38 _oldTime = time; 39 var accel1:Point = acceleration(_position, _velocity); 40 var position2:Point = new Point(); 41 position2.x = _position.x + _velocity.x / 2 * elapsed; 42 position2.y = _position.y + _velocity.y / 2 * elapsed; 43 var velocity2:Point = new Point(); 44 velocity2.x = _velocity.x + accel1.x / 2 * elapsed; 45 velocity2.y = _velocity.y + accel1.x / 2 * elapsed; 46 var accel2:Point = acceleration(position2, velocity2); 47 var position3:Point = new Point(); 48 position3.x = _position.x + velocity2.x / 2 * elapsed; 49 position3.y = _position.y + velocity2.y / 2 * elapsed; 50 var velocity3:Point = new Point(); 51 velocity3.x = _velocity.x + accel2.x / 2 * elapsed; 52 velocity3.y = _velocity.y + accel2.y / 2 * elapsed; 53 var accel3:Point = acceleration(position3, velocity3); 54 var position4:Point = new Point(); 55 position4.x = _position.x + velocity3.x * elapsed; 56 position4.y = _position.y + velocity3.y * elapsed; 57 var velocity4:Point = new Point(); 58 velocity4.x = _velocity.x + accel3.x * elapsed; 59 velocity4.y = _velocity.y + accel3.y * elapsed; 60 var accel4:Point = acceleration(position4, velocity4); 61 _position.x += (_velocity.x + 2 * velocity2.x + 2 * velocity3.x + velocity4.x) / 6 * elapsed; 62 _position.y += (_velocity.y + 2 * velocity2.y + 2 * velocity3.y + velocity4.y) / 6 * elapsed; 63 _velocity.x += (accel1.x + 2 * accel2.x + 2 * accel3.x + accel4.x) / 6 * elapsed; 64 _velocity.y += (accel1.y + 2 * accel2.y + 2 * accel3.y + accel4.y) / 6 * elapsed; 65 if(_position.y > (stage.stageHeight - 20) / _pixelsPerFoot) 66 { 67 _position.y = (stage.stageHeight - 20) / _pixelsPerFoot; 68 186 69 _velocity.y *= _bounce; 70 } 71 if(_position.x > (stage.stageWidth - 20) / _pixelsPerFoot) 72 { 73 _position.x = (stage.stageWidth - 20) / _pixelsPerFoot; 74 _velocity.x *= _bounce 75 } 76 else if(_position.x < 20 / _pixelsPerFoot) 77 { 78 _position.x = 20 / _pixelsPerFoot; 79 _velocity.x *= _bounce; 80 } 81 _ball.x = _position.x * _pixelsPerFoot; 82 _ball.y = _position.y * _pixelsPerFoot; 83 } 84 private function acceleration(p:Point, v:Point):Point 85 { 86 return new Point(0, _gravity); 87 } 88 } 89 }
原文:http://www.cnblogs.com/actionkong/p/3525462.html