diff --git a/app/src/main/java/org/ntlab/radishforandroidstudio/framework/gameMain/Actor.java b/app/src/main/java/org/ntlab/radishforandroidstudio/framework/gameMain/Actor.java index eb1666d..c8bac3e 100644 --- a/app/src/main/java/org/ntlab/radishforandroidstudio/framework/gameMain/Actor.java +++ b/app/src/main/java/org/ntlab/radishforandroidstudio/framework/gameMain/Actor.java @@ -22,347 +22,356 @@ /** * ゲーム内の登場物全般 - * @author 新田直也 * + * @author 新田直也 */ public abstract class Actor extends BaseActor { -// public abstract class Actor extends Animatable implements Movable { - protected Vector3d direction = new Vector3d(1.0, 0.0, 0.0); - protected Mode mode; - // 以下省メモリ化のため予めインスタンスを生成 - protected Mode modeFreeFall = new ModeFreeFall(); - protected Mode modeOnGround = new ModeOnGround(); - - public Actor(Object3D body, Animation3D animation) { - super(new Solid3D(body), animation); - mode = modeOnGround; - } + // public abstract class Actor extends Animatable implements Movable { + protected Vector3d direction = new Vector3d(1.0, 0.0, 0.0); + protected Mode mode; + // 以下省メモリ化のため予めインスタンスを生成 + protected Mode modeFreeFall = new ModeFreeFall(); + protected Mode modeOnGround = new ModeOnGround(); - public Actor(Solid3D body, Animation3D animation) { - super(body, animation); - mode = modeOnGround; - } + public Actor(Object3D body, Animation3D animation) { + super(new Solid3D(body), animation); + mode = modeOnGround; + } + + public Actor(Solid3D body, Animation3D animation) { + super(body, animation); + mode = modeOnGround; + } // public Actor(ActorModel model) { // super(model.createBody(), model.getAnimation()); // mode = modeOnGround; // } - - /** - * 単位時間ごとの動作(衝突判定処理は行わない) - * @param interval --- 前回呼び出されたときからの経過時間(ミリ秒単位) - */ - public void motion(long interval){ - // 1. 位置を動かす - ((Solid3D)body).move(interval, getGravity(), getGravityCenter());//地面とあたり判定してない - super.motion(interval); - } - /** - * 単位時間ごとの動作(衝突判定処理も行う) - * @param interval --- 前回呼び出されたときからの経過時間(ミリ秒単位) - * @param ground --- 地面(構造物) - */ - public void motion(long interval, Ground ground) {//k.地面とあたり判定 + /** + * 単位時間ごとの動作(衝突判定処理は行わない) + * + * @param interval --- 前回呼び出されたときからの経過時間(ミリ秒単位) + */ + public void motion(long interval) { + // 1. 位置を動かす + ((Solid3D) body).move(interval, getGravity(), getGravityCenter());//地面とあたり判定してない + super.motion(interval); + } - // 1. 位置を動かす - ((Solid3D)body).move(interval, getGravity(), getGravityCenter()); + /** + * 単位時間ごとの動作(衝突判定処理も行う) + * + * @param interval --- 前回呼び出されたときからの経過時間(ミリ秒単位) + * @param ground --- 地面(構造物) + */ + public void motion(long interval, Ground ground) {//k.地面とあたり判定 - if (animation != null) { - // 2. アニメーションを実行 - if (animation.progress(interval) == false) { - onEndAnimation(); - } - - // 3. 姿勢を変える - body.apply(animation.getPose(), false);//k.実際に適応する - } + // 1. 位置を動かす + ((Solid3D) body).move(interval, getGravity(), getGravityCenter()); - // 4. 衝突判定 - CollisionResult cr = PhysicsUtility.doesIntersect((Solid3D)body, ground);//k.crに情報が入っている + if (animation != null) { + // 2. アニメーションを実行 + if (animation.progress(interval) == false) { + onEndAnimation(); + } - // 5. 衝突応答 - if (cr != null) { - // 構造物にぶつかった、または接触している時 - if (cr.normal.dot(PhysicsUtility.vertical) > GeometryUtility.TOLERANCE) { - // 上向きの面(=地面)にぶつかった、または接触している時 - if (cr.length <= GeometryUtility.TOLERANCE) { - // 地面に乗っている - if (!(mode instanceof ModeOnGround)) { - // 落ちてきて丁度乗った - mode = modeOnGround; - ((ModeOnGround)mode).setNormal(cr.normal); - onEndFall(); - } - } else { - // 地面にめり込んだ - // 5.1. 押し戻す - onIntersect(cr, interval); - if (!(mode instanceof ModeOnGround)) { - // 落ちてきてめり込んだ - // 6. 地面モードにする - mode = modeOnGround; - ((ModeOnGround)mode).setNormal(cr.normal); - onEndFall(); - } else { - // 歩いている途中で、アニメーションの関係で一瞬だけめり込んだ - // または、歩いている途中で斜面に差し掛かった - ((ModeOnGround)mode).setNormal(cr.normal); - } - } - } else if (cr.normal.dot(PhysicsUtility.vertical) >= -GeometryUtility.TOLERANCE) { - // 垂直壁にめり込んだ - // 5.1. 押し戻す - onIntersect(cr, interval); - } else { - // 下からぶつかった、または接触した(頭をぶつけた) - if (cr.length > GeometryUtility.TOLERANCE) { - // 5.1. 押し戻す - onIntersect(cr, interval); - } - } - cr = null; - } else { - // 地面とぶつかっても接触してもいない時 - // 6. 落下モードにする - mode = modeFreeFall; - } + // 3. 姿勢を変える + body.apply(animation.getPose(), false);//k.実際に適応する + } + + // 4. 衝突判定 + CollisionResult cr = PhysicsUtility.doesIntersect((Solid3D) body, ground);//k.crに情報が入っている + + // 5. 衝突応答 + if (cr != null) { + // 構造物にぶつかった、または接触している時 + if (cr.normal.dot(PhysicsUtility.vertical) > GeometryUtility.TOLERANCE) { + // 上向きの面(=地面)にぶつかった、または接触している時 + if (cr.length <= GeometryUtility.TOLERANCE) { + // 地面に乗っている + if (!(mode instanceof ModeOnGround)) { + // 落ちてきて丁度乗った + mode = modeOnGround; + ((ModeOnGround) mode).setNormal(cr.normal); + onEndFall(); + } + } else { + // 地面にめり込んだ + // 5.1. 押し戻す + onIntersect(cr, interval); + if (!(mode instanceof ModeOnGround)) { + // 落ちてきてめり込んだ + // 6. 地面モードにする + mode = modeOnGround; + ((ModeOnGround) mode).setNormal(cr.normal); + onEndFall(); + } else { + // 歩いている途中で、アニメーションの関係で一瞬だけめり込んだ + // または、歩いている途中で斜面に差し掛かった + ((ModeOnGround) mode).setNormal(cr.normal); + } + } + } else if (cr.normal.dot(PhysicsUtility.vertical) >= -GeometryUtility.TOLERANCE) { + // 垂直壁にめり込んだ + // 5.1. 押し戻す + onIntersect(cr, interval); + } else { + // 下からぶつかった、または接触した(頭をぶつけた) + if (cr.length > GeometryUtility.TOLERANCE) { + // 5.1. 押し戻す + onIntersect(cr, interval); + } + } + cr = null; + } else { + // 地面とぶつかっても接触してもいない時 + // 6. 落下モードにする + mode = modeFreeFall; + } // TODO: 2018/06/11 物体と人のあたり判定の記述 - for (ArrayList collidableList: collidableListList) { - for (Placeable anothor: collidableList) { - //自分と物体のあたり判定 - CollisionResult cr2 = PhysicsUtility.checkCollision(body,null,(Solid3D)(anothor.getBody()),null); + for (ArrayList collidableList : collidableListList) { + for (Placeable anothor : collidableList) { + //自分と物体のあたり判定 + CollisionResult cr2 = PhysicsUtility.checkCollision(body, null, (Solid3D) (anothor.getBody()), null); - if(cr2 !=null){ - boolean flag = false; - onCollisionStay(anothor);//k.呼び出される - if(body != null){ - flag = true; - return; - } - } - } - } - } + if (cr2 != null) { + onCollisionStay(anothor);//k.呼び出される + } + } + } + } - //k.完全な物理演算するためのMotion - public void motion(long interval, Ground ground,ArrayList forces, - ArrayList appPoints) { + //k.完全な物理演算するためのMotion + public void motion(long interval, Ground ground, ArrayList forces, + ArrayList appPoints) { - forces.add(getGravity()); - appPoints.add(getGravityCenter()); + forces.add(getGravity()); + appPoints.add(getGravityCenter()); - // 1. 位置を動かす - ((Solid3D) body).move(interval, forces, appPoints); + // 1. 位置を動かす + ((Solid3D) body).move(interval, forces, appPoints); - if (animation != null) { - // 2. アニメーションを実行 - if (animation.progress(interval) == false) { - onEndAnimation(); - } + if (animation != null) { + // 2. アニメーションを実行 + if (animation.progress(interval) == false) { + onEndAnimation(); + } - // 3. 姿勢を変える - body.apply(animation.getPose(), false); - } + // 3. 姿勢を変える + body.apply(animation.getPose(), false); + } - // 4. 衝突判定 - CollisionResult cr = PhysicsUtility.doesIntersect((Solid3D) body, ground);//k.←ここ地面とのあたり判定 + // 4. 衝突判定 + CollisionResult cr = PhysicsUtility.doesIntersect((Solid3D) body, ground);//k.←ここ地面とのあたり判定 - // 5. 衝突応答 - if (cr != null) { - // 構造物にぶつかった、または接触している時 - if (cr.normal.dot(PhysicsUtility.vertical) > GeometryUtility.TOLERANCE) { - // 上向きの面(=地面)にぶつかった、または接触している時 - if (cr.length <= GeometryUtility.TOLERANCE) {//k.押し戻しの処理を - // 地面に乗っている - if (!(mode instanceof ModeOnGround)) { - // 落ちてきて丁度乗った - mode = modeOnGround; - ((ModeOnGround) mode).setNormal(cr.normal); - onEndFall();//k.地面に着地 - } - } else { - // 地面にめり込んだ - // 5.1. 押し戻す - onIntersect(cr, interval);//k.めり込んだとき地面以外のあたり判定 - if (!(mode instanceof ModeOnGround)) { - // 落ちてきてめり込んだ - // 6. 地面モードにする - mode = modeOnGround; - ((ModeOnGround) mode).setNormal(cr.normal); - onEndFall(); - } else { - // 歩いている途中で、アニメーションの関係で一瞬だけめり込んだ - // または、歩いている途中で斜面に差し掛かった - ((ModeOnGround) mode).setNormal(cr.normal); - } - } - } else if (cr.normal.dot(PhysicsUtility.vertical) >= -GeometryUtility.TOLERANCE) { - // 垂直壁にめり込んだ - // 5.1. 押し戻す - onIntersect(cr, interval); - } else { - // 下からぶつかった、または接触した(頭をぶつけた) - if (cr.length > GeometryUtility.TOLERANCE) { - // 5.1. 押し戻す - onIntersect(cr, interval); - } - } - cr = null; - } else { - // 地面とぶつかっても接触してもいない時 - // 6. 落下モードにする - mode = modeFreeFall; - } - } + // 5. 衝突応答 + if (cr != null) { + // 構造物にぶつかった、または接触している時 + if (cr.normal.dot(PhysicsUtility.vertical) > GeometryUtility.TOLERANCE) { + // 上向きの面(=地面)にぶつかった、または接触している時 + if (cr.length <= GeometryUtility.TOLERANCE) {//k.押し戻しの処理を + // 地面に乗っている + if (!(mode instanceof ModeOnGround)) { + // 落ちてきて丁度乗った + mode = modeOnGround; + ((ModeOnGround) mode).setNormal(cr.normal); + onEndFall();//k.地面に着地 + } + } else { + // 地面にめり込んだ + // 5.1. 押し戻す + onIntersect(cr, interval);//k.めり込んだとき地面以外のあたり判定 + if (!(mode instanceof ModeOnGround)) { + // 落ちてきてめり込んだ + // 6. 地面モードにする + mode = modeOnGround; + ((ModeOnGround) mode).setNormal(cr.normal); + onEndFall(); + } else { + // 歩いている途中で、アニメーションの関係で一瞬だけめり込んだ + // または、歩いている途中で斜面に差し掛かった + ((ModeOnGround) mode).setNormal(cr.normal); + } + } + } else if (cr.normal.dot(PhysicsUtility.vertical) >= -GeometryUtility.TOLERANCE) { + // 垂直壁にめり込んだ + // 5.1. 押し戻す + onIntersect(cr, interval); + } else { + // 下からぶつかった、または接触した(頭をぶつけた) + if (cr.length > GeometryUtility.TOLERANCE) { + // 5.1. 押し戻す + onIntersect(cr, interval); + } + } + cr = null; + } else { + // 地面とぶつかっても接触してもいない時 + // 6. 落下モードにする + mode = modeFreeFall; + } + } - public void setInitialDirection(Vector3d dir) { - direction = dir; - } - - public Vector3d getInitialDirection() { - return direction; - } + public void setInitialDirection(Vector3d dir) { + direction = dir; + } - /** - * 指定した方向に向かせる - * @param vec 新しい向き - */ - public void setDirection(Vector3d vec) { - Vector3d v1 = new Vector3d(); - Vector3d v2 = new Vector3d(); - v1.cross(direction, GeometryUtility.Y_AXIS); - v2.cross(vec, GeometryUtility.Y_AXIS); - if (v2.length() < GeometryUtility.TOLERANCE) return; - v1.normalize(); - v2.normalize(); - double cos = v1.dot(v2); - v1.cross(v1, v2); - double sin = v1.dot(GeometryUtility.Y_AXIS); - double angle = Math.atan2(sin, cos); - AxisAngle4d axisAngle = new AxisAngle4d(GeometryUtility.Y_AXIS, angle); - Quaternion3D quat = new Quaternion3D(axisAngle); - ((Solid3D)body).apply(quat, false); - } - - /** - * 指定した方向に向かせる - * @param vec 新しい向き - */ - public void setDirection3D(Vector3d vec) { - Vector3d v1 = new Vector3d(); - Vector3d v2 = new Vector3d(); - v1.cross(direction, GeometryUtility.Y_AXIS); - double angle = Math.PI / 2.0 - Math.acos(vec.dot(GeometryUtility.Y_AXIS)); - AxisAngle4d axisAngle2 = new AxisAngle4d(v1, angle); - v2.cross(vec, GeometryUtility.Y_AXIS); - if (v2.length() < GeometryUtility.TOLERANCE) return; - v1.normalize(); - v2.normalize(); - double cos = v1.dot(v2); - v1.cross(v1, v2); - double sin = v1.dot(GeometryUtility.Y_AXIS); - angle = Math.atan2(sin, cos); - AxisAngle4d axisAngle = new AxisAngle4d(GeometryUtility.Y_AXIS, angle); - Quaternion3D quat = new Quaternion3D(axisAngle); - Quaternion3D quat2 = new Quaternion3D(axisAngle2); - quat.mul(quat2); - ((Solid3D)body).apply(quat, false); - } - - /** - * 現在向いている方向を取得する - * @return 現在の向き - */ - public Vector3d getDirection() { - Vector3d dir = new Vector3d(direction); - Transform3D trans = new Transform3D(); - trans.set(((Solid3D)body).getQuaternion().getAxisAngle()); - trans.transform(dir); - return dir; - } - - /** - * 移動速度ベクトルを設定する - * @param vel 新しい移動速度ベクトル - */ - public void setVelocity(Velocity3D vel) { - ((Solid3D)body).apply(vel, false); - } - - /** - * 移動速度ベクトルを取得する - * @return 現在の移動速度ベクトル - */ - public Velocity3D getVelocity() { - return ((Solid3D)body).getVelocity(); - } - - /** - * X軸を中心に回転する - * @param angle 回転角(反時計回り, 単位:ラジアン) - */ - public void rotX(double angle) { - Quaternion3D curQuat = body.getQuaternion(); - curQuat.add(new AxisAngle4d(GeometryUtility.X_AXIS, angle)); - body.apply(curQuat, false); - } - - /** - * Y軸を中心に回転する - * @param angle 回転角(反時計回り, 単位:ラジアン) - */ - public void rotY(double angle) { - Quaternion3D curQuat = body.getQuaternion(); - curQuat.add(new AxisAngle4d(GeometryUtility.Y_AXIS, angle)); - body.apply(curQuat, false); - } - - /** - * Z軸を中心に回転する - * @param angle 回転角(反時計回り, 単位:ラジアン) - */ - public void rotZ(double angle) { - Quaternion3D curQuat = body.getQuaternion(); - curQuat.add(new AxisAngle4d(GeometryUtility.Z_AXIS, angle)); - body.apply(curQuat, false); - } + public Vector3d getInitialDirection() { + return direction; + } - /** - * 加わっている重力を取得する - * @return 重力 - */ - public Force3D getGravity() { - return mode.getForce((Solid3D)body); - } + /** + * 指定した方向に向かせる + * + * @param vec 新しい向き + */ + public void setDirection(Vector3d vec) { + Vector3d v1 = new Vector3d(); + Vector3d v2 = new Vector3d(); + v1.cross(direction, GeometryUtility.Y_AXIS); + v2.cross(vec, GeometryUtility.Y_AXIS); + if (v2.length() < GeometryUtility.TOLERANCE) return; + v1.normalize(); + v2.normalize(); + double cos = v1.dot(v2); + v1.cross(v1, v2); + double sin = v1.dot(GeometryUtility.Y_AXIS); + double angle = Math.atan2(sin, cos); + AxisAngle4d axisAngle = new AxisAngle4d(GeometryUtility.Y_AXIS, angle); + Quaternion3D quat = new Quaternion3D(axisAngle); + ((Solid3D) body).apply(quat, false); + } - /** - * 重心を取得する - * @return 重心位置 - */ - public Position3D getGravityCenter() { - return ((Solid3D)body).getGravityCenter(); - } + /** + * 指定した方向に向かせる + * + * @param vec 新しい向き + */ + public void setDirection3D(Vector3d vec) { + Vector3d v1 = new Vector3d(); + Vector3d v2 = new Vector3d(); + v1.cross(direction, GeometryUtility.Y_AXIS); + double angle = Math.PI / 2.0 - Math.acos(vec.dot(GeometryUtility.Y_AXIS)); + AxisAngle4d axisAngle2 = new AxisAngle4d(v1, angle); + v2.cross(vec, GeometryUtility.Y_AXIS); + if (v2.length() < GeometryUtility.TOLERANCE) return; + v1.normalize(); + v2.normalize(); + double cos = v1.dot(v2); + v1.cross(v1, v2); + double sin = v1.dot(GeometryUtility.Y_AXIS); + angle = Math.atan2(sin, cos); + AxisAngle4d axisAngle = new AxisAngle4d(GeometryUtility.Y_AXIS, angle); + Quaternion3D quat = new Quaternion3D(axisAngle); + Quaternion3D quat2 = new Quaternion3D(axisAngle2); + quat.mul(quat2); + ((Solid3D) body).apply(quat, false); + } - /** - * 地面に乗っている状態か否かを取得する - * @return true --- 地面に乗っている, false --- 地面に乗っていない(空中にいる) - */ - public boolean isOnGround() { - return (mode instanceof ModeOnGround); - } + /** + * 現在向いている方向を取得する + * + * @return 現在の向き + */ + public Vector3d getDirection() { + Vector3d dir = new Vector3d(direction); + Transform3D trans = new Transform3D(); + trans.set(((Solid3D) body).getQuaternion().getAxisAngle()); + trans.transform(dir); + return dir; + } - /** - * 地面(構造物)に落下した瞬間に呼び出される - */ - public abstract void onEndFall(); + /** + * 移動速度ベクトルを設定する + * + * @param vel 新しい移動速度ベクトル + */ + public void setVelocity(Velocity3D vel) { + ((Solid3D) body).apply(vel, false); + } - /** - * 地面(構造物)に衝突した瞬間に呼び出される - * @param normal --- 地面の法線方向ベクトル - * @param interval --- 前回の動作からの経過時間(ミリ秒単位) - */ - public abstract void onIntersect(CollisionResult normal, long interval); + /** + * 移動速度ベクトルを取得する + * + * @return 現在の移動速度ベクトル + */ + public Velocity3D getVelocity() { + return ((Solid3D) body).getVelocity(); + } + + /** + * X軸を中心に回転する + * + * @param angle 回転角(反時計回り, 単位:ラジアン) + */ + public void rotX(double angle) { + Quaternion3D curQuat = body.getQuaternion(); + curQuat.add(new AxisAngle4d(GeometryUtility.X_AXIS, angle)); + body.apply(curQuat, false); + } + + /** + * Y軸を中心に回転する + * + * @param angle 回転角(反時計回り, 単位:ラジアン) + */ + public void rotY(double angle) { + Quaternion3D curQuat = body.getQuaternion(); + curQuat.add(new AxisAngle4d(GeometryUtility.Y_AXIS, angle)); + body.apply(curQuat, false); + } + + /** + * Z軸を中心に回転する + * + * @param angle 回転角(反時計回り, 単位:ラジアン) + */ + public void rotZ(double angle) { + Quaternion3D curQuat = body.getQuaternion(); + curQuat.add(new AxisAngle4d(GeometryUtility.Z_AXIS, angle)); + body.apply(curQuat, false); + } + + /** + * 加わっている重力を取得する + * + * @return 重力 + */ + public Force3D getGravity() { + return mode.getForce((Solid3D) body); + } + + /** + * 重心を取得する + * + * @return 重心位置 + */ + public Position3D getGravityCenter() { + return ((Solid3D) body).getGravityCenter(); + } + + /** + * 地面に乗っている状態か否かを取得する + * + * @return true --- 地面に乗っている, false --- 地面に乗っていない(空中にいる) + */ + public boolean isOnGround() { + return (mode instanceof ModeOnGround); + } + + /** + * 地面(構造物)に落下した瞬間に呼び出される + */ + public abstract void onEndFall(); + + /** + * 地面(構造物)に衝突した瞬間に呼び出される + * + * @param normal --- 地面の法線方向ベクトル + * @param interval --- 前回の動作からの経過時間(ミリ秒単位) + */ + public abstract void onIntersect(CollisionResult normal, long interval); }