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