package fight3D;
import com.sun.j3d.utils.universe.SimpleUniverse;
import framework.RWT.RWTCanvas3D;
import framework.RWT.RWTVirtualController;
import framework.gameMain.Actor;
import framework.model3D.CollisionResult;
import framework.model3D.Model3D;
import framework.model3D.Object3D;
import framework.model3D.Position3D;
import framework.model3D.Universe;
import framework.physics.Ground;
import framework.physics.PhysicsUtility;
import framework.view3D.Camera3D;
import java.awt.Dimension;
import java.util.ArrayList;
import javax.media.j3d.AmbientLight;
import javax.media.j3d.BoundingSphere;
import javax.media.j3d.DirectionalLight;
import javax.vecmath.Color3f;
import javax.vecmath.Point3d;
import javax.vecmath.Vector3f;
/**
* @author 新田直也
*
*/
public class Fight { // 操作ボタン
// static long speed[] = new long[2000];
// static int count = 0;
static final long INTERVAL = 17L;
static final long ENDTIME = 60L * 1000L;
static final double DEFAULT_STAGE_WIDTH = 10.0;
static final double DEFAULT_AREA_RIGHT = 20.0;
static final double DEFAULT_AREA_LEFT = -20.0;
static final double DEFAULT_AREA_BOTTOM = -30.0;
private ArrayList<Player> playerList = new ArrayList<Player>();
ArrayList<Actor> actorList = new ArrayList<Actor>();
ArrayList<Attackable> attackableList = new ArrayList<Attackable>();
FightCalculation fightCalculation = new FightCalculation();
Universe universe;
Camera3D camera;
Ground stageGround = null;
FightListener fightListener;
private boolean isEnd = false;
int rank[];
int defeated[];
int defeat[];
private int tp[];
private long startTime = 0;
private long leftTime;
public Fight(RWTCanvas3D canvas, int stagenum, int[] selectedCharacterArray,
FightListener fightListener) {
this.universe = new Universe();
this.fightListener = fightListener;
// カメラの設定
camera = new Camera3D(universe);
camera.setSideView();
canvas.attachCamera(camera);
// 光源の設定
createLight(universe);
// ステージの読み込み
Stage s = StageManager.getInstance().getStage(stagenum);
Model3D model = s.getModel();
Object3D stageObj = model.createObject();
stageGround = new Ground(stageObj);
universe.placeAsAReceiver(stageGround);
RWTCanvas3D c = (RWTCanvas3D) fightListener;
s.setBackgroundSize(new Dimension(c.getWidth(), c.getHeight()));
universe.place(s.getBackground());
// キャラクタの追加、武器の追加
for (int i = 0; i < selectedCharacterArray.length; i++) {
Player player = createPlayer(selectedCharacterArray[i]);
player.setPosition(getPlayersPosition(i, selectedCharacterArray.length));
player.placeTo(universe);
getPlayerList().add(player);
actorList.add(player);
camera.addTarget(player.body);
player.setHp(fightCalculation.initialiseHP());
player.setGp(fightCalculation.initialiseGP());
player.setTp(fightCalculation.initialiseTP());
}
universe.compile();
leftTime = ENDTIME;
rank = new int[2];
}
void createLight(Universe universe){
//環境光
AmbientLight amblight = new AmbientLight(new Color3f(0.5f, 0.5f, 0.5f));
amblight.setInfluencingBounds(new BoundingSphere(new Point3d(), 10000.0));
universe.placeLight(amblight);
//平行光源
DirectionalLight dirlight = new DirectionalLight(
true, //光のON/OFF
new Color3f(1.0f, 1.0f, 1.0f), //光の色
new Vector3f(0.0f, -1.0f, -0.5f) //光の方向ベクトル
);
dirlight.setInfluencingBounds(new BoundingSphere(new Point3d(), 10000.0));
universe.placeLight(dirlight);
}
public Player createPlayer(int id) {
Player player;
Character c = CharacterManager.getInstance().getCharacter(id);
player = new Player(c);
return player;
}
public void progress(RWTVirtualController controller, long interval) {
long curTime = System.currentTimeMillis();
if (startTime == 0) {
startTime = curTime;
}
// 経過時間の計算
// if (count < 2000) speed[count++] = interval;
if (interval > INTERVAL * 3) interval = INTERVAL * 3;
leftTime = (ENDTIME - (curTime - startTime));
fightListener.update(this);
// 5分経過したか
if (leftTime < 0) {
isEnd = true;
calculateRank();
calculateDefeated();
calculateDefeat();
calculateTP();
fightListener.update(this);
// for (int i = 0; i < count; i++) {
// System.out.println(speed[i]);
// }
return;
}
// GPの自然回復
for (int i = 0; i < getPlayerList().size(); i++) {
getPlayerList().get(i).recoverGp();
}
// カメラを調節
camera.adjust(interval);
// キー入力があったかどうかを記録する
boolean[] flags = new boolean[playerList.size()];
for (int p = 0; p < flags.length; p++) {
flags[p] = false;
}
for (int playerNum = 0; playerNum < getPlayerList().size(); playerNum++) {
// keysのi番目の中身(キー入力)がキャラクタのどの動作に当てはまるか
if (controller.isKeyDown(playerNum, RWTVirtualController.UP)) {
flags[playerNum] = true;
// 攻撃ボタンを同時に押していない場合ジャンプする
if (!controller.isKeyDown(playerNum, RWTVirtualController.BUTTON_A)) getPlayerList().get(playerNum).startJump();
}
if (controller.isKeyDown(playerNum, RWTVirtualController.RIGHT)) {
flags[playerNum] = true;
// 攻撃ボタンを同時に押していない場合右に動く
if (!controller.isKeyDown(playerNum, RWTVirtualController.BUTTON_A)) getPlayerList().get(playerNum).rightMove();
}
if (controller.isKeyDown(playerNum, RWTVirtualController.LEFT)) {
flags[playerNum] = true;
// 攻撃ボタンを同時に押していない場合左に動く
if (!controller.isKeyDown(playerNum, RWTVirtualController.BUTTON_A)) getPlayerList().get(playerNum).leftMove();
}
if (controller.isKeyDown(playerNum, RWTVirtualController.BUTTON_B)) {
flags[playerNum] = true;
// 攻撃ボタンを押していない場合ガードのメソッドを呼ぶ
if (!controller.isKeyDown(playerNum, RWTVirtualController.BUTTON_A)) getPlayerList().get(playerNum).guard();
}
if (controller.isKeyDown(playerNum, RWTVirtualController.BUTTON_A)) {
flags[playerNum] = true;
// 攻撃のメソッドを呼ぶ
Attackable a;
Player player = getPlayerList().get(playerNum);
if (!player.isOnGround()) {
if (player.getElapsedTimeInJumping() > 2L || player.getElapsedTimeInJumping() < 0L) {
// 空中にいるときは基本的にジャンプ攻撃
a = player.startJumpAttack();
} else {
// ジャンプしてすぐは対空攻撃をするようにする
// (そうしないと対空攻撃を出す操作が難しくなるため)
a = player.startUpperAttack();
}
} else {
// 地面にいるとき
if (controller.isKeyDown(playerNum, RWTVirtualController.UP)) {
// 対空攻撃
a = player.startUpperAttack();
} else {
// 通常攻撃
a = player.startNormalAttack();
}
}
if (a != null) {
attackableList.add(a);
if (a instanceof Weapon) {
if (a.isMovable()) {
actorList.add((Weapon) a);
}
}
}
}
}
for (int i = 0; i < flags.length; i++) {
if (!flags[i]) {
getPlayerList().get(i).normal(false);
}
}
// 全登場物を動かす
for (int i = 0; i < actorList.size(); i++) {
Actor p = actorList.get(i);
// 移動
p.motion(interval, stageGround);
// 範囲外に出たかどうかの判定
Position3D pos = p.getPosition();
if (pos.getY() < DEFAULT_AREA_BOTTOM
|| pos.getX() > DEFAULT_AREA_RIGHT
|| pos.getX() < DEFAULT_AREA_LEFT) {
// 範囲外に出たときの処理
outOfArea(i);
}
}
// 攻撃の当たり判定
hitJudg();
}
/**
* 範囲外に出たときの処理
* @param p 対象物
*/
private void outOfArea(int index) {
Actor p = actorList.get(index);
if (p instanceof Player) {
playerDefeated(index);
} else if (p instanceof Weapon) {
((Weapon)p).disappear();
}
}
/**
* 攻撃の当たり判定と、当たったときの処理
*/
private void hitJudg() {
// 当たり判定
for (int i = attackableList.size() - 1; i >= 0; i--) {
Attackable attack = attackableList.get(i);
if (attack.isAlive() && attack.isActivate()) {
// 攻撃物が有効だった場合
for (int j = 0; j < getPlayerList().size(); j++) {
CollisionResult collisionResult = null;
Player attacker = attack.getOwner();
Player damagedCandidate = getPlayerList().get(j);
if (attacker != damagedCandidate) {
collisionResult = PhysicsUtility.checkCollision(attack.getBody(),
attack.getPartName(),
(Object3D) damagedCandidate.body,
null);
}
// 衝突があった場合
if (collisionResult != null) {
// if (attacker != damagedCandidate) {
if (damagedCandidate.state.getClass() != StateGuard.class) {
// ダメージを受ける。
if (damagedCandidate.state.getClass() == StateFlinch.class) {
damagedCandidate.normal(true);
damagedCandidate.setGp(100);
}
damagedCandidate.damaged(attacker.getPosition());
int afterHP = (int) fightCalculation.decreaseHP(attack
.getAP(), damagedCandidate.getHp(),
damagedCandidate.character.getDefense());
// 攻撃によってキャラが死んでいない場合
if (fightCalculation.isDead(afterHP) != true) {
damagedCandidate.setHp(afterHP);
// damagedCandidate.changeState(new StateFlinch(),
// false);
}
// 死んだ場合
else {
// キャラを殺したキャラクタの「倒した回数」を1増やす
attacker.setDefeat(attacker.getDefeat() + 1);
// キャラが倒されたときの処理
playerDefeated(j);
}
// 攻撃によるTPの上昇
int attackerAfterTP = fightCalculation.increaseTP(
attack.getAP(), damagedCandidate.getHp(),
damagedCandidate.character.getDefense(), attacker.getTp());
attacker.setTp(attackerAfterTP);
} else {
// ダメージを受けない。
int afterGP = (int) fightCalculation.decreaseGP(attack
.getAP(), damagedCandidate.character.getDefense(), damagedCandidate.getGp());
if (!fightCalculation.isOver(afterGP)) {
// 攻撃によってGPが0にならなかった場合
damagedCandidate.setGp(afterGP);
} else {
// 攻撃によってGPが0になった場合
damagedCandidate.flinch();
damagedCandidate.setGp(0);
}
}
// 攻撃物を無効にする
attack.disappear();
}
}
}
if (!attack.isAlive()) {
// 攻撃物が無効になっていた場合、攻撃物リストから削除
attackableList.remove(i);
for (int j = 0; j < actorList.size(); j++) {
if (actorList.get(j) == attack) {
actorList.remove(j);
break;
}
}
continue;
}
}
}
/**
* プレイヤーが倒されたときの処理
* @param index 倒されたプレイヤーの番号
*/
private void playerDefeated(int index) {
Player damagedCandidate = getPlayerList().get(index);
// TPを減らす
int damagedAfterTP = fightCalculation
.decreaseTP(damagedCandidate.getTp());
damagedCandidate.setTp(damagedAfterTP);
// 死んだキャラクタの「死亡回数」を1増やす
damagedCandidate.setDefeated(damagedCandidate
.getDefeated() + 1);
// HPとGPを初期値に戻す
damagedCandidate.setHp(fightCalculation
.initialiseHP());
damagedCandidate.setGp(fightCalculation
.initialiseGP());
// 出現位置に再登場させる
damagedCandidate.setPosition(getPlayersPosition(index, getPlayerList().size()));
}
/**
*
* プレイヤーの登場(再登場)位置を返す
* @param index プレイヤーの番号
* @param numPlayer 全プレイヤーの数
* @return
*/
private Position3D getPlayersPosition(int index, int numPlayer) {
return new Position3D((((double)index / (double)(numPlayer - 1)) - 0.5) * DEFAULT_STAGE_WIDTH, 0.0, 0.0);
}
private void calculateTP() {
// TODO Auto-generated method stub
tp = new int[playerList.size()];
for (int i = 0; i < playerList.size(); i++) {
tp[i] = playerList.get(i).getTp();
}
}
private void calculateDefeated() {
// TODO Auto-generated method stub
defeated = new int[playerList.size()];
for (int i = 0; i < playerList.size(); i++) {
defeated[i] = playerList.get(i).getDefeated();
}
}
private void calculateDefeat() {
// TODO Auto-generated method stub
defeat = new int[playerList.size()];
for (int i = 0; i < playerList.size(); i++) {
defeat[i] = playerList.get(i).getDefeat();
}
}
private void calculateRank() {
// TODO Auto-generated method stub
for (int i = 0; i < rank.length; i++) {
int max = 0;
int maxNum = 0;
int playerTp;
for (int j = 0; j < rank.length; j++) {
if (rank[j] == 0
&& max <= (playerTp = getPlayerList().get(j).getTp())) {
max = playerTp;
maxNum = j;
}
}
rank[maxNum] = i + 1;
}
}
int getRemnantMinute() {
int time = (int) (leftTime / 1000) / 60;
if(time > 0) {
return time;
}
return 0;
}
int getRemnantSecond() {
int time = (int) (leftTime / 1000) % 60;
if (time > 0) {
return time;
}
return 0;
}
boolean checkEnd() {
return isEnd;
}
int[] getRank() {
return rank;
}
ArrayList<Player> getPlayerList() {
return playerList;
}
int[] getTp() {
return tp;
}
int[] getDefeated() {
return defeated;
}
int[] getDefeat() {
return defeat;
}
}