Newer
Older
SproutServerMicro / src / main / java / org / ntlab / SproutServerMicro / battles / Battle.java
package org.ntlab.SproutServerMicro.battles;

import framework.model3D.Placeable;
import framework.model3D.Position3D;
import framework.model3D.Universe;
import framework.physics.Ground;
import org.ntlab.SproutServerMicro.rooms.Room;
import org.ntlab.SproutServerMicro.rooms.Rooms;

import javax.vecmath.Vector3d;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.HashMap;

/**
 * バトル
 *
 * @author matsumoto_k
 */
public class Battle {
    private HashMap<Integer, Team> teamMap = new HashMap<>(); // チームの情報を保持
    private double time = BattlesConst.BATTLE_INIT_TIME; // タイム
    private Universe universe = null;
    private Ground ground = null;

    private int teamId1 = -1; // チームを判別するID
    private int teamId2 = -1; // チームを判別するID
    /**
     * バトルの状態に関する変数
     * battle:対戦中, end:終了
     */
    private String state = "battle";

    public Battle(Room room1, Room room2) {
        universe = new Universe();
        teamId1 = room1.getRoomId();
        teamId2 = room2.getRoomId();
        teamMap.put(room1.getRoomId(), new Team(room1));
        teamMap.put(room2.getRoomId(), new Team(room2));

        ground = createStage();
        placeStage(ground);
    }

    public Team getTeam(int roomId) {
        return teamMap.get(roomId);
    }

    public HashMap<Integer, Team> getTeamMap() {
        return teamMap;
    }

    public void setTeamMap(HashMap<Integer, Team> teamMap) {
        this.teamMap = teamMap;
    }

    public double getTime() {
        return time;
    }

    public void setTime(double time) {
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }

    /**
     * ステージを作成
     *
     * @return ステージオブジェクト
     */
    private Ground createStage() {
        String path = "";
        try {
            path = URLDecoder.decode(Battles.getInstance().getClass().getResource("standardStage.obj").getPath(), "utf-8");
        } catch (Exception e) {
            System.out.println("error path");
        }
        return new StandardStage(path);
    }

    /**
     * ステージを配置
     *
     * @param ground 配置するステージオブジェクト
     */
    private void placeStage(Ground ground) {
        universe.place(ground);
    }

    /**
     * idによってチームを取得する
     *
     * @param teamId 取得したいチームのID
     * @return チーム
     */
    private Team findTeamByID(int teamId) {
        return teamMap.get(teamId);
    }

    /**
     * 対戦相手のチームを取得
     *
     * @param teamId 自身のteamId
     * @return 対戦相手のチーム
     */
    private Team getOppositeTeam(int teamId) {
        if (teamId != teamId1)
            return findTeamByID(teamId1);
        return findTeamByID(teamId2);
    }

    /**
     * クライアントからのアップデート
     *
     * @param userId
     * @param teamId
     * @param playerData 更新するプレイヤーデータ
     */
    public void update(int userId, int teamId, PlayerData playerData) {
        Player player = findTeamByID(teamId).findPlayerById(userId);

        Position3D position3D = player.getPlayerPosition3d(); // 更新する前のプレイヤーの位置を記録
        Vector3d vector3d = player.getPlayerVector3d(); // 更新する前のプレイヤーの向きを状態を記録

		/* プレイヤーのアップデート  */
        player.update(playerData.getUserPosition(), playerData.getUserVector());

		/* プレイヤー同士の衝突判定  */
        boolean collision = checkPlayerCollision(player, userId);
        player.setPlayerCollision(collision);

		/* プレイヤー同士が衝突していた時は前の状態に戻す  */
        if (player.isPlayerCollision()) {
            player.update(position3D, vector3d);
        }

		/* playerと相手チームの弾の衝突判定  */
        checkCollisionWithWeapons(player, teamId);

		/* playerDataに弾の情報が含まれている ∧ プレイヤーが生きている 場合実行  */
        if (playerData.isWeaponShoot() && player.isAlive()) {
           // switch (Role.getRole(Rooms.getInstance().roomList.get(teamId).getMemberList().get(userId).getRole())){
                //case Gunman:
                    Bullet bullet = findTeamByID(teamId).createBullet(playerData.getWeaponPosition(), playerData.getWeaponVector(), playerData.getWeaponVelocity());
                    universe.place(bullet.getActor());
                   // break;
                //case Witch:
                   //Magic magic = findTeamByID(teamId).createMagic(playerData.getWeaponPosition(), playerData.getWeaponVector(), playerData.getWeaponVelocity());
                    //universe.place(magic.getActor());
                   // break;
            //}
        }

		/* 生存者による勝利のチェック  */
        updateResultByAllDead();
    }

    /**
     * プレイヤーの衝突判定
     *
     * @param player プレイヤーインスタンス
     * @param userId userId
     * @return 衝突している時はtrue, していない時はfalse
     */
    public boolean checkPlayerCollision(Player player, int userId) {
        return findTeamByID(teamId1).checkCollision(player, userId) || findTeamByID(teamId2).checkCollision(player, userId);
    }

    private void playerUpdate(Player player, Position3D userPosition, Vector3d userVector) {
        player.update(userPosition, userVector);
    }

    /**
     * プレイヤーと相手チームの武器の衝突判定
     *
     * @param player
     * @param teamId
     */
    public void checkCollisionWithWeapons(Player player, int teamId) {
        ArrayList<Placeable> colliedObjects = getOppositeTeam(teamId).getColliedObjects(player); // 取り除くオブジェクトを取得に変更する
        for (Placeable obj : colliedObjects) {
            universe.displace(obj);
        }
    }

    /**
     * バトルをアップデートする
     */
    public void update() {
        if (getTime() > 0) {
            this.time -= BattlesConst.UPDATE_INTERVAL;
        } else {
            updateResultByTimeOut();
            return;
        }
        /* universeに配置している全ての武器を動かす */
        universe.update(BattlesConst.UPDATE_INTERVAL);
        checkAllWeaponCollision(findTeamByID(teamId1), findTeamByID(teamId2));
        updateResultByAllDead();
    }

    /**
     * 両チームのプレイヤーと弾の当たり判定
     */
    public void checkAllWeaponCollision(Team team1, Team team2) {
        ArrayList<Placeable> displaceObj = team1.getColliedObjects(team2);
        for (Placeable obj : displaceObj) {
            universe.displace(obj);
        }
        displaceObj = team2.getColliedObjects(team1);
        for (Placeable obj : displaceObj) {
            universe.displace(obj);
        }
    }

    /**
     * 生存者の数によって勝敗をチェックする
     */
    private void updateResultByTimeOut() {
        if (findTeamByID(teamId1).getAliveCount() > findTeamByID(teamId2).getAliveCount())
            findTeamByID(teamId1).setResult(true);
        else
            findTeamByID(teamId2).setResult(true);
        finish();
    }

    /**
     * 生存者による勝敗のチェック
     */
    private void updateResultByAllDead() {
        Team team1 = findTeamByID(teamId1);
        Team team2 = findTeamByID(teamId2);

        if (team1.isAllPlayerDead() || team2.isAllPlayerDead()) {
            team1.setResult(!team1.isAllPlayerDead());
            team2.setResult(!team2.isAllPlayerDead());
            finish();
        }
    }

    /**
     * バトルを終了させる
     */
    public void finish() {
        state = "end";
        Rooms.getInstance().getRoomList().get(teamId1).roomInitialize();
        Rooms.getInstance().getRoomList().get(teamId2).roomInitialize();
    }
}