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);
}
}
}