2014年2月6日木曜日

新作Androidアプリ開発 ボールを投げてみる編

新作アプリはバスケシュートゲームなんで何はともあれボールを投げてみましょう
ボールを投げるということでまずBall.classの作成
public class Ball {
    final public static int G = 9800;    //重力加速度(mm/s)
    final public static float k = 0.01f; //空気抵抗係数
    final public static int R = 122;     //半径(mm)
    public Plot position = new Plot();   //位置
    public int xSpeed; //X方向の速度(mm/s)
    public int ySpeed; //Y方向の速度(mm/s)
    public int zSpeed; //Z方向の速度(mm/s)

    public Ball() {}

}

必要となる主要メンバはボールの速度、位置ですね
ここで位置を表すpositionのクラスPlotはxyz座標を持った自作クラスです
これに初速度と垂直・水平方向の投射角を与えてやります
public void shot(double speed, double vangle, double hangle) {
    //speed  初速(mm/s)
    //vangle 垂直方向の角度
    //hangle 水平方向の角度
    zSpeed = (int)(speed * Math.sin(vangle));
    speed = speed * Math.cos(vangle);
    xSpeed = (int)(speed * Math.cos(hangle));
    ySpeed = (int)(speed * Math.sin(hangle));
    position = new Plot(6423, 8682, 1800);
}

まず与えた初速度をMath.sin(垂直角度)cos(垂直角度)で水平方向と垂直方向の速度に分解
分解した水平方向の速度をまたMath.sin,cos(水平角度)でXY方向の速度に分解してやります
XYZに分解してやれば、それぞれに経過時間をかけるだけで移動距離が出ます

public void move(long interval) {
    //重力加速度による加速
    zSpeed -= ((G * interval) / 1000);
    //位置変更
    position.x += ((xSpeed * interval) / 1000);
    position.y += ((ySpeed * interval) / 1000);
    position.z += ((zSpeed * interval) / 1000);
}

経過時間intervalはミリ秒、物理で習ったように重力加速度をZ方向速度に加算します
移動距離は速度×時間ですからXYZ方向の各速度に(interval/1000ミリ秒)かけた分を加算すれば移動後の位置が取得できます
計算式としては

となりますが、そのままコードにして
int x = x + (vx * (interval / 1000));
などとしてしまうと式に使われている変数はintとlongしかありませんので(interval / 1000)の部分は整数に丸められてしまいます
こういった最終的にint型が必要だとしても、途中計算までもintで行うことはお勧めしません
このように必ず分子に比率をかけてから除算しなければなりません
int x = x + ((vx * interval) / 1000);

こんな感じ
投げた感じがよくわからないので、横からの様子を描画

よさそうですが、なんか飛びすぎな感じがします
学校の物理では省略されましたが、ボールの投射の実際には空気抵抗による影響があります
そこで空気抵抗の計算方法を調べてみますとこのような式が出てきました

参考:ホームランの打球について
http://www.nasekouki.co.jp/~shig/homerun.html


Cd:抗力係数
p:空気密度
v:速度
A:ボールの見付け面積

速度によって変わるようですね、回転速度なども影響するようです
計算がめんどくさい大変なのでやめます
本格的なシミュレータを目指してるわけではないので、簡易式を作ります


k:空気抵抗簡易係数

これを取り入れてmove関数を修正

final public static float k = 0.01f; //空気抵抗係数
public void move(long interval) {
    //空気抵抗による減速
    xSpeed -= ((xSpeed * k * interval) / 1000);
    ySpeed -= ((ySpeed * k * interval) / 1000);
    zSpeed -= ((zSpeed * k * interval) / 1000);
    //重力加速度による加速
    zSpeed -= ((G * interval) / 1000);
    //位置変更
    position.x += ((xSpeed * interval) / 1000);
    position.y += ((ySpeed * interval) / 1000);
    position.z += ((zSpeed * interval) / 1000);
}

これを実行してみます
それらしくなったので良しとします

0 件のコメント:

コメントを投稿