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