bound
2010522
ボールを跳ね返らせたい。って時の
物理的な考察をしていきます。
ActionSCript3.0です。
※下記のサンプルはball,btnという2つのクラスに関しては省略して記載してあります。
(ライブラリに用意しているだけ。)
01.ボールを落とす。
物理運動に習ったものなので、とりあえず、ボールを落とす運動を書いてみます。
– script –
package { import flash.display.MovieClip; import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; public class bound1 extends Sprite { var _ball:MovieClip var _ballVelocityY:Number; public function bound1() { init(); } private function init():void { makeball(); } private function makeball():void { var _btn:MovieClip = new btn(); addChild(_btn) _btn.x = 10; _btn.y = 10; _btn.addEventListener(MouseEvent.CLICK,function(){ _ball= new ball(); addChild(_ball); _ball.x = stage.stageWidth / 2; _ball.y = stage.stageHeight / 4; _ballVelocityY = 0; putVelocity(); }); } private function putVelocity():void { _ballVelocityY = 0; addEventListener(Event.ENTER_FRAME,moving); } private function moving(e:Event):void { _ballVelocityY += 9.8 / 60; _ball.y += _ballVelocityY; } } }
では、落ちた時に、
つまり、ボールがステージの外に出た瞬間に、
ボールの速度を反対方向にしてあげれば
ボールがぶつかった速度で跳ね返ります。
02.ボールを跳ね返す。
– script –
package { import flash.display.MovieClip; import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; public class bound2 extends Sprite { var _ball:MovieClip var _ballVelocityY:Number; public function bound2() { init(); } private function init():void { makeball(); } private function makeball():void { var _btn:MovieClip = new btn(); addChild(_btn) _btn.x = 10; _btn.y = 10; _btn.addEventListener(MouseEvent.CLICK,function(){ _ballVelocityY = 0; _ball= new ball(); addChild(_ball); _ball.x = stage.stageWidth / 2; _ball.y = stage.stageHeight / 4; putVelocity() }); } private function putVelocity():void { _ballVelocityY = 0; addEventListener(Event.ENTER_FRAME,moving); } private function moving(e:Event):void { _ballVelocityY += 9.8 / 60; _ball.y += _ballVelocityY; if (_ball.y+_ball.height/2 > stage.stageHeight) { _ballVelocityY = -_ballVelocityY; } } } }
上の記述は一見ただしそうですが、
ぶつかった瞬間にボールが壁に埋もれている。
_ball.y+_ball.height/2 > stage.stageHeight
埋まってた分だけこの瞬間に跳ね返してしまいます。
– script –
package { import flash.display.MovieClip; import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; public class bound3 extends Sprite { var _ball:MovieClip var _ballVelocityY:Number = 0; public function bound3() { init(); } private function init():void { makeball(); } private function makeball():void { var _btn:MovieClip = new btn(); addChild(_btn) _btn.x = 10;_btn.y = 10; _btn.addEventListener(MouseEvent.CLICK,function(){ _ballVelocityY = 0; _ball= new ball(); addChild(_ball); _ball.x = stage.stageWidth / 2; _ball.y = stage.stageHeight / 4; putVelocity() }); } private function putVelocity():void { _ballVelocityY = 0; addEventListener(Event.ENTER_FRAME,moving); } private function moving(e:Event):void { _ballVelocityY += 9.8 / 60; _ball.y += _ballVelocityY; if (_ball.y + _ball.height / 2 > stage.stageHeight) { //めりこまない _ball.y -= (_ball.y + _ball.height / 2 - stage.stageHeight); _ballVelocityY = -_ballVelocityY; } } } }
上のだとずっと同じ繰り返しです。
frictionっていう名前で
跳ね返りの瞬間に速度を削ってあげると以下になります。
– script –
package { import flash.display.MovieClip; import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; public class bound4 extends Sprite { var _ball:MovieClip var _ballVelocityY:Number = 0; static var _friction:Number = 0.9 public function bound4() { init(); } private function init():void { makeball(); } private function makeball():void { var _btn:MovieClip = new btn(); addChild(_btn) _btn.x = 10;_btn.y = 10; _btn.addEventListener(MouseEvent.CLICK,function(){ _ball= new ball(); _ballVelocityY = 0 addChild(_ball); _ball.x = stage.stageWidth / 2; _ball.y = stage.stageHeight / 4; putVelocity() }); } private function putVelocity():void { _ballVelocityY = 0; addEventListener(Event.ENTER_FRAME,moving); } private function moving(e:Event):void { _ballVelocityY += 9.8 / 60; _ball.y += _ballVelocityY; if (_ball.y + _ball.height / 2 > stage.stageHeight) { _ball.y -= (_ball.y + _ball.height / 2 - stage.stageHeight) * _friction; _ballVelocityY = -_ballVelocityY*_friction; } } } }
固い感じがします。
あたった瞬間に「ぐにゅ」って縮めてあげればいいのではないかな。
しかも速度に応じての必要があるよね。
下記の式は
_ball.scaleX = 1/_ball.scaleY
常に玉の面積(2次なので)が一定になるようにする事で、
縦に短くすると同時に横も伸びるようにしています。
– script –
package { import flash.display.MovieClip; import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; public class bound5 extends Sprite { var _ball:MovieClip var _ballVelocityY:Number = 0; static var _friction:Number = 0.6 public function bound5() { init(); } private function init():void { makeball(); } private function makeball():void { var _btn:MovieClip = new btn(); addChild(_btn) _btn.x = 10; _btn.y = 10; _btn.addEventListener(MouseEvent.CLICK,function(){ _ball= new ball(); addChild(_ball); _ball.x = stage.stageWidth / 2; _ball.y = stage.stageHeight / 4; putVelocity() _ballVelocityY = 0; }); } private function putVelocity():void { _ballVelocityY = 0; addEventListener(Event.ENTER_FRAME,moving); } private function moving(e:Event):void { _ballVelocityY += 9.8 / 60; _ball.y += _ballVelocityY; _ball.scaleY += (1 - _ball.scaleY)/5 if (_ball.y + _ball.height / 2 > stage.stageHeight) { _ball.scaleY = 1/(_ballVelocityY/30+1); _ball.y -= (_ball.y + _ball.height / 2 - stage.stageHeight) * _friction; _ballVelocityY = -_ballVelocityY*_friction; } _ball.scaleX = 1/_ball.scaleY } } }
大きさが戻る時に妙な違和感がありますよね。
大きさが元に戻るんだけど、
ぽにょぽにょするものって、
横長のものが丸に戻った後に縦長になって。
っていうみたいな動きが必要なので。
伸縮にバネの公式を当てはめてあげます。
– script –
package { import flash.display.MovieClip; import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; public class bound6 extends Sprite { var _ball:MovieClip var _ballVelocityY:Number = 0; var _ballVelocityIN:Number = 0 static var _friction:Number = 0.6; public function bound6() { init(); } private function init():void { makeball(); } private function makeball():void { var _btn:MovieClip = new btn(); addChild(_btn) _btn.x = 10;_btn.y = 10; _btn.addEventListener(MouseEvent.CLICK,function(){ _ball= new ball(); addChild(_ball); _ball.x = stage.stageWidth / 2; _ball.y = stage.stageHeight / 4; putVelocity() _ballVelocityY = 0; _ballVelocityIN = 0; }); } private function putVelocity():void { _ballVelocityY = 0; addEventListener(Event.ENTER_FRAME,moving); } private function moving(e:Event):void { _ballVelocityY += 9.8 / 60; _ball.y += _ballVelocityY; _ballVelocityIN += (1 - _ball.scaleY) * Math.abs(1 - _ball.scaleY) * 0.9 _ballVelocityIN *= 0.90 _ball.scaleY += _ballVelocityIN if (_ball.y + _ball.height / 2 > stage.stageHeight) { _ball.y -= (_ball.y + _ball.height / 2 - stage.stageHeight) * _friction; _ball.scaleY = 1/(_ballVelocityY/30+1); _ballVelocityY = -_ballVelocityY*_friction; } _ball.scaleX = 1/_ball.scaleY } } }
既に気持ちは完成ですが、縦だけじゃつまらないので、
横にも移動する形にします。
大きさに関しては若干見苦しいかと思いますが、
体積が変わらず、ってとこを中心に
調整をしてみました。
– script –
package { import flash.display.MovieClip; import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; public class bound7 extends Sprite { var _ball:MovieClip var _ballVelocityY:Number = 0; var _ballVelocityX:Number = 0; var _ballweight:Number = 1; var _ballVelocityINX:Number = 0; var _ballVelocityINY:Number = 0; var _friction:Number = 0.9; var _ballScaleY:Number = 1; var _ballScaleX:Number = 1 public function bound7() { init(); } private function init():void { makeball(); } private function makeball():void { var _btn:MovieClip = new btn(); addChild(_btn) _btn.x = 10;_btn.y = 10; _btn.addEventListener(MouseEvent.CLICK,function(){ _ball= new ball(); addChild(_ball); _ball.x = stage.stageWidth / 2; _ball.y = stage.stageHeight / 4; putVelocity() }); } private function putVelocity():void { _ballVelocityY = 0; _ballVelocityX = 0; addEventListener(Event.ENTER_FRAME, movingY); addEventListener(Event.ENTER_FRAME, movingX); addEventListener(Event.ENTER_FRAME,movingScale); } private function movingY(e:Event):void { _ballVelocityY += 9.8 / 60*_ballweight; _ball.y += _ballVelocityY; _ballVelocityINY += (1 - _ballScaleY) * Math.abs(1 - _ballScaleY) _ballVelocityINY *= 0.9 _ballScaleY += _ballVelocityINY if (_ball.y + _ball.height/2 > stage.stageHeight) { _ball.y -= (_ball.y + _ball.height/2 - stage.stageHeight) * _friction; _ballScaleY /= (_ballVelocityY/30+1); _ballVelocityY = -_ballVelocityY*_friction; } //_ball.scaleX = 1/_ball.scaleY } private function movingX(e:Event):void { _ballVelocityX += 9.8 / 60*_ballweight; _ball.x += _ballVelocityX; _ballVelocityINX += (1 - _ballScaleX) * Math.abs(1 - _ballScaleX) _ballVelocityINX *= 0.9 _ballScaleX += _ballVelocityINX if (_ball.x + _ball.width/2 > stage.stageWidth) { _ball.x -= (_ball.x + _ball.width/2 - stage.stageWidth) * _friction; _ballScaleX /= (_ballVelocityY/30+1); _ballVelocityX = -_ballVelocityX*_friction; } //_ball.scaleY = 1/_ball.scaleX } private function movingScale(e:Event):void { var _rate:Number = _ballScaleX*_ballScaleY _ball.scaleX = _ballScaleX / Math.sqrt(_rate); _ball.scaleY = _ballScaleY / Math.sqrt(_rate); } } }