package template.shooting;
import java.awt.Container;
import java.util.ArrayList;
import javax.media.j3d.AmbientLight;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.Light;
import javax.media.j3d.Node;
import javax.vecmath.Tuple3f;
import javax.vecmath.Vector3d;
import framework.AI.GeometryGraph;
import framework.AI.IState;
import framework.AI.Location;
import framework.model3D.BaseObject3D;
import framework.model3D.CollisionResult;
import framework.model3D.GeometryCollector;
import framework.model3D.Object3D;
import framework.model3D.Placeable;
import framework.model3D.Position3D;
import framework.model3D.Universe;
import framework.physics.Ground;
import framework.physics.PhysicsUtility;
import framework.physics.Velocity3D;
/**
* プレイヤーと敵が闘う戦場
* @author 新田直也
*
*/
public class BattleField {
private Universe universe;
private Ground stage;
private Player player;
private ArrayList<Enemy> enemies = new ArrayList<Enemy>();
private ArrayList<PlayersBullet> playersBullets = new ArrayList<PlayersBullet>();
private ArrayList<EnemiesBullet> enemiesBullets = new ArrayList<EnemiesBullet>();
private GeometryGraph geometryGraph = null;
private PlayersBulletModel playersBulletModel;
private EnemyModel enemyModel;
private EnemiesBulletModel enemiesBulletModel;
private boolean bPlayerHit = false;
private int hitEnemyCount = 0;
// 定数
public static final int MAX_ENEMIES = 4; // 敵の最大数
public BattleField(Universe universe) {
this.universe = universe;
// 自分の弾のモデルを作成
playersBulletModel = new PlayersBulletModel("data\\models\\bullet.3ds", null);
// 敵のモデルを作成
enemyModel = new EnemyModel("data\\Head4.wrl", "data\\pocha\\walk.wrl");
// 敵の弾のモデルを作成
enemiesBulletModel = new EnemiesBulletModel("data\\pocha\\bubble.wrl", null);
}
/**
* オブジェクトを配置する
* @param obj 配置するオブジェクト
*/
public void place(Node obj) {
universe.place(obj);
}
/**
* オブジェクトを配置する
* @param obj 配置するオブジェクト
*/
public void place(Placeable obj) {
if (obj instanceof Player) {
player = (Player)obj;
} else if (obj instanceof Ground) {
stage = (Ground)obj;
GeometryCollector v = new GeometryCollector();
BaseObject3D baseObj = stage.getBody();
if (baseObj instanceof Object3D) {
if (obj instanceof Stage) {
baseObj = ((Object3D)baseObj).getPart(((Stage)obj).getTerrainPart());
}
((Object3D)baseObj).accept(v);
geometryGraph = new GeometryGraph(v.getGeometry());
}
}
universe.place(obj);
}
/**
* 後で取り除けるようにオブジェクトを配置する
* @param obj 配置するオブジェクト
*/
public void placeDisplacable(Node obj) {
universe.placeDisplacable(obj);
}
/**
* 後で取り除けるようにオブジェクトを配置する
* @param obj 配置するオブジェクト
*/
public void placeDisplacable(Placeable obj) {
universe.placeDisplacable(obj);
}
/**
* 光源の追加
* @param light 追加する光源
*/
public void placeLight(Light light) {
universe.place(light);
}
/**
* すべての構成要素を一斉に動かす
* @param interval 前回呼び出されたときからの経過時間(ミリ秒)
*/
public void motion(long interval) {
// プレイヤーを動かす
player.motion(interval, stage);
// すべての敵を動かすと同時に、プレイヤーと衝突判定し、更に敵の弾を発射する
for (int n = 0; n < enemies.size(); n++) {
Enemy enemy = enemies.get(n); // 敵を一体取り出す
enemy.motion(interval, stage, player, geometryGraph); // 敵を動かす
// 敵とプレイヤーの衝突判定
CollisionResult collisionResult = PhysicsUtility.checkCollision(
enemy.body, null,
player.body, null);
if (collisionResult != null) {
// プレイヤーに当たった
bPlayerHit = true;
}
}
// すべてのプレイヤーの弾を動かすと同時に、敵と衝突判定
for (int n = 0; n < playersBullets.size(); n++) {
PlayersBullet bullet = playersBullets.get(n); // プレイヤーの弾を一つ取り出す
if (bullet.isAlive()) {
bullet.motion(interval, stage); // プレイヤーの弾を動かす
for (int m = 0; m < enemies.size(); m++) {
Enemy enemy = enemies.get(m); // 敵を一体取り出す
// プレイヤーの弾と敵の衝突判定
CollisionResult collisionResult = PhysicsUtility.checkCollision(
bullet.body, null,
enemy.body, null);
if (collisionResult != null) {
// 敵に当たった
removeEnemy(enemy); // 敵を消す
removePlayersBullet(bullet); // 当たった弾も消す
n--;
hitEnemyCount++;
break;
}
}
} else {
removePlayersBullet(bullet); // 弾を消す
n--;
}
}
// すべての敵の弾を動かすと同時に、プレイヤーと衝突判定
for (int n = 0; n < enemiesBullets.size(); n++) {
EnemiesBullet bullet = enemiesBullets.get(n); // 敵の弾を一つ取り出す
if (bullet.isAlive()) {
bullet.motion(interval, stage); // 敵の弾を動かす
// 敵の弾とプレイヤーの衝突判定
CollisionResult collisionResult = PhysicsUtility.checkCollision(
bullet.body, null,
player.body, null);
if (collisionResult != null) {
// プレイヤーに当たった
removeEnemiesBullet(bullet); // 当たった弾を消す
n--;
bPlayerHit = true;
break;
}
} else {
// 弾が壁に当たったりして消えた場合
removeEnemiesBullet(bullet);
n--;
}
}
}
/**
* プレイヤーの位置を取得する
* @return プレイヤーの位置ベクトル
*/
public Position3D getPlayerPosition() {
return player.getPosition();
}
/**
* プレイヤーの位置を設定する
* @param pos プレイヤーの位置ベクトル
*/
public void setPlayerPosition(Position3D pos) {
player.setPosition(pos);
}
/**
* プレイヤーを左右に回転させる
* @param ang 回転角度(ラジアン、正が左方向)
*/
public void playerTurn(double ang) {
player.rotY(ang);
}
/**
* プレイヤーを現在向いている方向に歩かせる
* @param vel 歩く速度
*/
public void playerWalk(double vel) {
Velocity3D curV = player.getVelocity();
curV.setX(player.getDirection().getX() * vel);
curV.setZ(player.getDirection().getZ() * vel);
player.setVelocity(curV);
}
/**
* プレイヤーを静止させる
*/
public void playerStop() {
playerWalk(0.0);
}
/**
* プレイヤーをジャンプさせる
* @param vel ジャンプする際の初速度
*/
public void playerJump(double vel) {
Velocity3D curV = player.getVelocity();
curV.setY(vel);
player.setVelocity(curV);
}
/**
* プレイヤが向いている方向を取得する
* @return プレイヤーが向いている方向ベクトル
*/
public Vector3d getPlayerDirection() {
return player.getDirection();
}
/**
* プレイヤーを指定した方向に向かせる
* @param dir プレイヤーを向かせる方向ベクトル
*/
public void setPlayerDirection(Vector3d dir) {
player.setDirection(dir);
}
/**
* プレイヤーの現在の移動速度を取得する
* @return プレイヤーの移動速度ベクトル
*/
public Velocity3D getPlayerVelocity() {
return player.getVelocity();
}
/**
* プレイヤーの移動速度を設定する
* @param vel プレイヤーに設定する移動速度ベクトル
*/
public void setPlayerVelocity(Velocity3D vel) {
player.setVelocity(vel);
}
/**
* プレイヤーが地面の上に乗っているかどうかを判定する
* @return true --- 地面の上に乗っている, false --- 宙に浮いている
*/
public boolean isPlayerOnGround() {
return player.isOnGround();
}
/**
* プレイヤーに弾を撃たせる
*/
public void playerShoots() {
PlayersBullet bullet = playersBulletModel.createPlayersBullet();
Vector3d bulletVelocity = (Vector3d)player.getDirection().clone();
bulletVelocity.normalize();
bulletVelocity.scale(10.0);
bullet.setVelocity(new Velocity3D(bulletVelocity));
bullet.setPosition(player.getPosition().add(0.0, 1.0, 0.0));
addPlayersBullet(bullet);
}
/**
* プレイヤーが攻撃を受けたか?
* @return true --- 攻撃を受けた, false --- 攻撃を受けていない
*/
public boolean isPlayerHit() {
boolean hit = bPlayerHit;
bPlayerHit = false;
return hit;
}
/**
* 敵を発生させる
* @return 発生した敵のオブジェクト
*/
public Enemy createEnemy() {
if (getEnemyCount() < MAX_ENEMIES) {
Enemy newEnemy = enemyModel.createEnemy();
ArrayList<IState> locations = geometryGraph.getStates();
Location startLoc;
for (;;) {
startLoc = (Location)locations.get((int)(Math.random() * locations.size()));
if (startLoc.getNormal().dot(new Vector3d(0.0, 1.0, 0.0)) >= 0.95) break;
}
newEnemy.setPosition(new Position3D(new Vector3d(startLoc.getCenter())).add(0.0, 2.0, 0.0));
addEnemy(newEnemy);
return newEnemy;
}
return null;
}
/**
* 敵の総数を取得する
* @return 敵の総数
*/
public int getEnemyCount() {
return enemies.size();
}
/**
* 指定した番号の敵を取得する
* @param n 敵の番号(0〜)
* @return 敵のオブジェクト
*/
public Enemy getEnemy(int n) {
return enemies.get(n);
}
/**
* 敵を消す
* @param enemy 消す敵
*/
public void removeEnemy(Enemy enemy) {
enemies.remove(enemy);
universe.displace(enemy);
}
/**
* 乱数で選んだ敵に弾を撃たせる
*/
public void enemyShoots() {
if (enemies.size() > 0) {
Enemy enemy = enemies.get((int)(Math.random() * (double)enemies.size()));
EnemiesBullet enemiesBullet = enemy.shoot(player, enemiesBulletModel);
addEnemiesBullet(enemiesBullet);
}
}
/**
* 倒した敵の数を取得する
* @return 新たに倒した敵の数
*/
public int getHitEnemyCount() {
int hit = hitEnemyCount;
hitEnemyCount = 0;
return hit;
}
/**
* 敵を登場させる
* @param enemy 登場する敵
*/
private void addEnemy(Enemy enemy) {
enemies.add(enemy);
universe.placeDisplacable(enemy);
}
/**
* プレイヤーの弾を発射する
* @param playersBullet 発射するプレイヤーの弾
*/
private void addPlayersBullet(PlayersBullet playersBullet) {
playersBullets.add(playersBullet);
universe.placeDisplacable(playersBullet);
}
/**
* 敵の弾を発射する
* @param enemy 発射する敵
*/
private void addEnemiesBullet(EnemiesBullet enemiesBullet) {
enemiesBullets.add(enemiesBullet);
universe.placeDisplacable(enemiesBullet);
}
/**
* プレイヤーの弾を消す
* @param playersBullet 消す弾
*/
private void removePlayersBullet(PlayersBullet playersBullet) {
playersBullets.remove(playersBullet);
universe.displace(playersBullet);
}
/**
* 敵の弾を消す
* @param enemiesBullet 消す弾
*/
private void removeEnemiesBullet(EnemiesBullet enemiesBullet) {
enemiesBullets.remove(enemiesBullet);
universe.displace(enemiesBullet);
}
}