package fight3D; import javax.media.j3d.Appearance; import javax.media.j3d.Material; import javax.media.j3d.Transform3D; import javax.media.j3d.TransformGroup; import javax.media.j3d.TransparencyAttributes; import javax.vecmath.Vector3d; import com.sun.j3d.utils.geometry.Sphere; import framework.animation.Animation3D; import framework.audio.Sound3D; import framework.gameMain.OvergroundActor; import framework.model3D.Position3D; import framework.model3D.Quaternion3D; import framework.model3D.Universe; import framework.physics.Velocity3D; /** * ゲームに登場するプレイヤー * @author 新田直也 * */ public class Player extends OvergroundActor { public Character character; private int hp; private int tp; private int gp; private Attackable normalAttack; private Attackable upperAttack; private Attackable jumpAttack; private int defeat = 0; private int defeated = 0; private int gpCounter; private TransformGroup guardPos; private TransformGroup guardScale; private Sphere guardSphere; private State stateAttack = new StateAttack(); private State stateUpperAttack = new StateUpperAttack(); private State stateJumpAttack = new StateJumpAttack(); private State stateJump = new StateJump(); private State stateRightMove = new StateRightMove(); private State stateLeftMove = new StateLeftMove(); private State stateGuard = new StateGuard(); private State stateBend = new StateBend(); private State stateFlinch = new StateFlinch(); private State stateNormalRight = new StateNormalRight(); private State stateNormalLeft = new StateNormalLeft(); private State stateDamaged = new StateDamaged(); public State state = stateNormalRight; private State lastMoveState = stateRightMove; public Player(Character m) { super(m); character = m; // 移動速度を設定する ((StateRightMove)stateRightMove).setSpeed(character.getRunSpeed()); ((StateLeftMove)stateLeftMove).setSpeed(character.getRunSpeed()); // ジャンプ力(上方向への初速度)を設定する ((StateJump)stateJump).setSpeed(character.getJumpPower()); // 攻撃方法を設定しておく(通常攻撃、対空攻撃、ジャンプ攻撃) if (character.hasAttackingPart()) { // キャラクターが攻撃に使用するのは、体の一部。 normalAttack = new AttackingPart(character.getAttackingPartName(), this, character.getAttackTimeLag()); } else { // キャラクターが攻撃に使用するのは、飛び道具。 normalAttack = new Weapon(character.getWeaponModel(), this, character.getAttackTimeLag()); } if (character.hasUpperAttackingPart()) { // キャラクターが攻撃に使用するのは、体の一部。 upperAttack = new AttackingPart(character.getUpperAttackingPartName(), this, character.getUpperAttackTimeLag()); } else { // キャラクターが攻撃に使用するのは、飛び道具。 upperAttack = new Weapon(character.getUpperWeaponModel(), this, character.getUpperAttackTimeLag()); } if (character.hasJumpAttackingPart()) { // キャラクターが攻撃に使用するのは、体の一部。 jumpAttack = new AttackingPart(character.getJumpAttackingPartName(), this, character.getJumpAttackTimeLag()); } else { // キャラクターが攻撃に使用するのは、飛び道具。 jumpAttack = new Weapon(character.getJumpWeaponModel(), this, character.getJumpAttackTimeLag()); } } // SceneGraphにぶら下げる public void placeTo(Universe universe) { universe.placeAsAnOcculuder(this); // 弾の表示の準備 if (!character.hasAttackingPart()) { universe.place((Weapon) normalAttack); } if (!character.hasUpperAttackingPart()) { universe.place((Weapon) upperAttack); } if (!character.hasJumpAttackingPart()) { universe.place((Weapon) jumpAttack); } // ガード表示の準備 guardSphere = new Sphere(); Appearance ap = new Appearance(); Material ma = new Material(); ap.setMaterial(ma); TransparencyAttributes ta = new TransparencyAttributes( TransparencyAttributes.FASTEST, 0.5f); ap.setTransparencyAttributes(ta); guardSphere.setAppearance(ap); guardPos = new TransformGroup(); guardPos.setCapability(TransformGroup.ALLOW_TRANSFORM_READ); guardPos.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE); guardScale = new TransformGroup(); guardScale.setCapability(TransformGroup.ALLOW_TRANSFORM_READ); guardScale.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE); guardPos.addChild(guardScale); guardScale.addChild(guardSphere); universe.place(guardPos); setGuardInvisible(); } public void onEndAnimation() { if (!state.isRepeatable()) { normal(true); } } public void onEndFall() { // 落ちている時は左右に歩くアニメーションをしないが、 // 地面についた瞬間歩くアニメーションが始まる Animation3D a = character.getAnimation(mode, state); if (!animation.equals(a)) { // たとえば歩いている途中で、アニメーションの関係で一瞬だけ落下する場合がある。 // そのような場合、着地するたびに歩くアニメーションをリセットしないように、アニメーションの種類が変わったときだけ // アニメーションを設定しなおすようにする。 animation = a; } } /** * 次の状態に変える * @param nextState --- 次の状態 * @param forced --- 強制的に変更するかどうか * @return */ boolean changeState(State nextState, boolean forced) { if (state.getClass() == nextState.getClass()) { // 状態の継続 state.countUp(); // 速度の変更 Velocity3D nextVelocity = state.getVelocity(getVelocity(), mode); if (nextVelocity != null) body.apply(nextVelocity, false); return false; } boolean flag = state.canChange(nextState, mode); if (forced || flag) { // System.out.println("状態:" + s.getClass().getName() + this); // 状態の変更と初期化 State prevState = state; state = nextState; state.init(); // 速度の変更 Velocity3D nextVelocity = state.getVelocity(getVelocity(), mode); if (nextVelocity != null) body.apply(nextVelocity, false); // アニメーションの設定 animation = character.getAnimation(mode, state); // 効果音を鳴らす Sound3D sound = character.getSoundEffect(mode, state); if (sound != null) { sound.play(); } if (prevState instanceof StateAttack || prevState instanceof StateUpperAttack || prevState instanceof StateJumpAttack) { endAttack(); } if ((nextState instanceof StateRightMove) || (nextState instanceof StateLeftMove)) { // 現在の向いてる方向と、これから向く方向が違うならキャラクタを回転させる if (nextState.getClass() != lastMoveState.getClass()) { if (nextState instanceof StateRightMove) { Quaternion3D q = new Quaternion3D(0.0, 1.0, 0.0, 0); body.apply(q, false); } else if (nextState instanceof StateLeftMove) { Quaternion3D q = new Quaternion3D(0.0, 1.0, 0.0, Math.PI); body.apply(q, false); } } lastMoveState = nextState; } } return flag; } /** * 通常状態に戻す * @param forced true --- 強制的に戻す, false --- 戻せる場合だけ戻す */ void normal(boolean forced) { if (lastMoveState instanceof StateRightMove) { State s = stateNormalRight; changeState(s, forced); } else if (lastMoveState instanceof StateLeftMove) { State s = stateNormalLeft; changeState(s, forced); } setGuardInvisible(); } /** * 通常攻撃を開始する * @return 攻撃に使う攻撃物 */ public Attackable startNormalAttack() { Velocity3D weaponSpeed = new Velocity3D(); // 通常攻撃 State s = stateAttack; Attackable a = normalAttack; if (a.isMovable()) weaponSpeed = character.getWeaponSpeed(); return startAttackSub(s, a, weaponSpeed); } /** * 対空攻撃を開始する * @return 攻撃に使う攻撃物 */ public Attackable startUpperAttack() { Velocity3D weaponSpeed = new Velocity3D(); State s = stateUpperAttack; Attackable a = upperAttack; if (a.isMovable()) weaponSpeed = character.getUpperWeaponSpeed(); return startAttackSub(s, a, weaponSpeed); } /** * ジャンプ攻撃を開始する * @return 攻撃に使う攻撃物 */ public Attackable startJumpAttack() { Velocity3D weaponSpeed = new Velocity3D(); State s = stateJumpAttack; Attackable a = jumpAttack; if (a.isMovable()) weaponSpeed = character.getJumpWeaponSpeed(); return startAttackSub(s, a, weaponSpeed); } private Attackable startAttackSub(State s, Attackable a, Velocity3D weaponSpeed) { State prevState = state; if (changeState(s, false)) { if (a instanceof Weapon) { ((Weapon) a).body.apply(body.getPosition3D(), false); if (prevState instanceof StateNormalRight || prevState instanceof StateRightMove) { // 右向きに弾を発射 ((Weapon) a).body.apply(weaponSpeed, false); ((Weapon) a).body.apply(new Quaternion3D(0.0, 1.0, 0.0, 0), false); } if (prevState instanceof StateNormalLeft || prevState instanceof StateLeftMove) { // 左向きに弾を発射 Velocity3D weponSpeed2 = (Velocity3D)weaponSpeed.clone(); weponSpeed2.setX(-weponSpeed2.getX()); ((Weapon) a).body.apply(weponSpeed2, false); ((Weapon) a).body.apply(new Quaternion3D(0.0, 1.0, 0.0, Math.PI), false); } else if (lastMoveState instanceof StateNormalRight || lastMoveState instanceof StateRightMove) { // 右向きに弾を発射 ((Weapon) a).body.apply(weaponSpeed, false); ((Weapon) a).body.apply(new Quaternion3D(0.0, 1.0, 0.0, 0), false); } else { // 左向きに弾を発射 Velocity3D weponSpeed2 = (Velocity3D)weaponSpeed.clone(); weponSpeed2.setX(-weponSpeed2.getX()); ((Weapon) a).body.apply(weponSpeed2, false); ((Weapon) a).body.apply(new Quaternion3D(0.0, 1.0, 0.0, Math.PI), false); } } a.appear(); return a; } else { return null; } } private void endAttack() { normalAttack.disappear(); upperAttack.disappear(); jumpAttack.disappear(); } void startJump() { State s = stateJump; changeState(s, false); mode = modeFreeFall; } void rightMove() { State s = stateRightMove; changeState(s, false); } void leftMove() { State s = stateLeftMove; changeState(s, false); } void guard() { State s = stateGuard; changeState(s, false); if (state instanceof StateGuard) { // StateGuard に状態が変わったときだけではなくて、StateGuard 状態のまま攻撃を受けたときも以下の処理を行う Position3D p = body.getPosition3D().clone(); Transform3D t = new Transform3D(); Vector3d v = new Vector3d(p.getX(), p.getY(), p.getZ()); t.set(v); guardPos.setTransform(t); setGuardScale(this.gp); } } void bend() { State s = stateBend; changeState(s, false); } void flinch() { State s = stateFlinch; changeState(s, true); } void damaged(Position3D attackerPosition) { // 攻撃を受けたら敵の方向を向く if (attackerPosition.getX() > getPosition().getX()) { body.apply(new Quaternion3D(0.0, 1.0, 0.0, 0), false); lastMoveState = stateRightMove; } else { body.apply(new Quaternion3D(0.0, 1.0, 0.0, Math.PI), false); lastMoveState = stateLeftMove; } State s = stateDamaged; changeState(s, false); } void setHp(int hp) { this.hp = hp; } int getHp() { return hp; } void setTp(int tp) { this.tp = tp; } int getTp() { return tp; } void setGp(int gp) { this.gp = gp; } int getGp() { return gp; } void recoverGp() { if (state.getClass() == StateGuard.class) { gpCounter = 0; return; } gpCounter++; if (gpCounter < 20) { return; } gpCounter = 0; if (FightCalculation.MIN_GP < gp && gp < FightCalculation.MAX_GP) { this.gp += 1; } else if (gp >= FightCalculation.MAX_GP) { gp = FightCalculation.MAX_GP; } } void setDefeat(int defeat) { this.defeat = defeat; } int getDefeat() { return defeat; } void setDefeated(int defeated) { this.defeated = defeated; } int getDefeated() { return defeated; } /** * ジャンプを開始してからの経過時間(ループ回数)を返す、 * ジャンプ状態にないときは -1 を返す * @return 経過時間 */ public long getElapsedTimeInJumping() { if (state instanceof StateJump) { // System.out.println(state.getCounter()); return state.getCounter(); } // System.out.println(-1); return -1L; } private void setGuardVisible(double j) { // TODO Auto-generated method stub Transform3D t = new Transform3D(); t.setScale(j); guardScale.setTransform(t); } private void setGuardInvisible() { // TODO Auto-generated method stub Transform3D t = new Transform3D(); t.setScale(0.01); guardScale.setTransform(t); } private void setGuardScale(int i) { double j = 0; if (i > 0) { j = 1.5 * (i / 100.0); setGuardVisible(j); } else { setGuardInvisible(); } } }