public EnemyManager(ContentManager content, StageSelect.SelectEnemy selectEnemy, StageSelect.SelectStage selectStage, Maze maze, Player player) { this.content = content; this.maze = maze; this.player = player; int chaseEnemyNum; int randomWalkEnemyNum; // 敵数を決める switch (selectEnemy) { case StageSelect.SelectEnemy.Few: chaseEnemyNum = 10; break; case StageSelect.SelectEnemy.Regular: chaseEnemyNum = 15; break; case StageSelect.SelectEnemy.Much: chaseEnemyNum = 20; break; default: throw new ArgumentException(); } randomWalkEnemyNum = chaseEnemyNum; switch (selectStage) { case StageSelect.SelectStage.Small: randomWalkEnemyNum *= 1; break; case StageSelect.SelectStage.Regular: randomWalkEnemyNum *= 2; break; case StageSelect.SelectStage.Big: randomWalkEnemyNum *= 3; break; default: throw new ArgumentException(); } // リストにChaseEnemyを突っ込む for (int i = 0; i < chaseEnemyNum; i++) { Point enemyPosition = GetEnemyInitialPosition(maze, player); enemies.Add(new ChaseEnemy(content, enemyPosition, Collidable.Orientation.North, maze, player)); } // リストにRandomWalkEnemyNumを突っ込む for (int i = 0; i < randomWalkEnemyNum; i++) { Point enemyPosition = GetEnemyInitialPosition(maze, player); enemies.Add(new RandomWalkEnemy(content, enemyPosition, Collidable.Orientation.North, maze, player, rand.Next())); } }
/// <summary> /// 更新処理 /// </summary> /// <param name="maze"></param> public override void Update(GameTime gameTime, Maze maze) { // アニメーションの更新 AnimationUpdate(gameTime); // 動作中ならなにもしないで終了 if (currentMoveState != MoveState.Stop) { Move(currentMoveState, maze); return; } // たまっている動作があればそれを実行して終了 if (moveStateQ.Count > 0) { Move(moveStateQ.Dequeue(), maze); return; } // 動ける方角を探す Orientation orientation; int tries = 0; while (true) { orientation = (Orientation)rand.Next(4); // 後ろ向きなら前向きに変更 if (orientation == DirecState.Back()) { orientation = DirecState; } // 壁じゃないならbreak if (CanMove(orientation, maze)) { break; } // 20回以上リトライしても決まらなかったらUターン(無限ループ対策) if (tries > 20) { orientation = DirecState.Back(); break; } tries++; } // そこに動くために必要な動きを得る StoreMovenents(orientation); // 動く Move(moveStateQ.Dequeue(), maze); // アニメーションの開始 AnimationStart("walk"); }
/// <summary> /// /// </summary> /// <param name="content"></param> /// <param name="startPosition"></param> /// <param name="orient"></param> public Player(ContentManager content, Point startPosition, Orientation orient, Maze maze) : base(content, @"Objects\Chick\chick", startPosition, orient, new Vector3(0.8f, 0.8f, 0.8f), maze) { //モデルの移動速度 speed = 0.05; //モデルの回転速度 degreespeed = 2.0f; Radius = 1.0f; JumpFlag = false; }
/// <summary> /// コンストラクタ /// </summary> /// <param name="content"></param> /// <param name="startPosition"></param> /// <param name="orient"></param> /// <param name="maze"></param> /// <param name="player"></param> public Enemy(ContentManager content, string assetName, Point startPosition, Orientation orient, Maze maze, Player player) : base(content, assetName, startPosition, orient, new Vector3(0.35f, 0.35f, 0.35f), maze) { //モデルの移動速度 speed = 0.03; //モデルの回転速度 degreespeed = 1.5f; //モデルの半径 Radius = 1.2f; // プレイヤー this.player = player; // 迷路 this.maze = maze; }
/// <summary> /// 更新処理 /// </summary> /// <param name="maze"></param> public override void Update(GameTime gameTime, Maze maze) { // アニメーションの更新 AnimationUpdate(gameTime); // 動作中ならなにもしないで終了 if (currentMoveState != MoveState.Stop) { Move(currentMoveState, maze); return; } // たまっている動作があればそれを実行して終了 if (moveStateQ.Count > 0) { Move(moveStateQ.Dequeue(), maze); return; } // 動ける方角を探す Orientation? orientation = null; while (true) { orientation = (Orientation)rand.Next(4); // 壁じゃない&後ろじゃないならbreak if (CanMove(orientation.Value, maze) && orientation.Value != DirecState.Back()) { break; } } // そこに動くために必要な動きを得る MoveState[] movement = RequireMovement(orientation.Value, maze); // 動きをキューに入れる foreach (MoveState m in movement) { moveStateQ.Enqueue(m); } // 動く Move(moveStateQ.Dequeue(), maze); // アニメーションの開始 AnimationStart("walk"); }
/// <summary> /// コンストラクタ /// </summary> /// <param name="contentManager"></param> /// <param name="assetName"></param> /// <param name="startPosition"></param> /// <param name="orient"></param> /// <param name="scale"></param> /// <param name="maze"></param> public AnimationModel(ContentManager contentManager, string assetName,Point startPosition, Orientation orient, Vector3 scale, Maze maze) : base(contentManager, null, startPosition, orient,scale, maze) { // モデルの読み込み model = contentManager.Load<Model>(assetName); // スキニングデータ SkinningData skinningData = model.Tag as SkinningData; if (skinningData == null) throw new InvalidOperationException("This model does not contain a SkinningData tag."); // アニメーションプレイヤーの初期化 animationPlayer = new AnimationPlayer(skinningData); // クリップ集の取得 clips = skinningData.AnimationClips; //ダメージカウンターの初期化 DamegedFlag = false; damegeCounter = 0; dColor = 0.8f; }
private static Point GetEnemyInitialPosition(Maze maze, Player player) { // プレイヤーから6ます以上離す Point enemyPosition; while (true) { enemyPosition = maze.RandomPoint(); if (Math.Sqrt((player.Position2.X - enemyPosition.X) * (player.Position2.X - enemyPosition.X) + (player.Position2.Y - enemyPosition.Y) * (player.Position2.Y - enemyPosition.Y)) > 6) { return enemyPosition; } } }
public RandomWalkEnemy(ContentManager content, Point startPosition, Orientation orient, Maze maze, Player player, int seed) : base(content, @"Objects\Enemy1\enemy1", startPosition, orient, maze, player) { rand = new Random(seed); }
/// <summary> /// 指定した方角に動けるかどうか /// </summary> /// <param name="orientation"></param> /// <param name="maze"></param> /// <returns></returns> protected bool CanMove(Orientation orientation, Maze maze) { return CanMove(orientation, maze, position2); }
/// <summary> /// 2次元座標を3次元座標に変換するメソッド /// </summary> /// <param name="maze"></param> protected Vector3 PointToVecto3(Point pos2, Maze maze) { Vector3 pos3 = new Vector3(); //モデル座標の更新(2D->3D) pos3.X = (float)(0.5 * maze.WallWidth + (pos2.X / 2) * maze.WallWidth + ((pos2.X / 2) + 0.5) * maze.WallDepth); pos3.Z = (float)(0.5 * maze.WallWidth + (pos2.Y / 2) * maze.WallWidth + ((pos2.Y / 2) + 0.5) * maze.WallDepth); pos3.Y = position3.Y; return pos3; }
/// <summary> /// 更新処理 /// </summary> /// <param name="maze"></param> public override void Update(GameTime gameTime, Maze maze) { // ダメージを受けた瞬間か justDamaged = damegeCounter == 1; if (justDamaged) SoundManager.Instance.SoundBank.PlayCue("damage"); #region ジャンプ処理 if (Input.Instance.PushKey(Microsoft.Xna.Framework.Input.Keys.Space)) StartJump(); Jumping(); #endregion //停止状態でのみキー入力を可能にする if (currentMoveState == MoveState.Stop) { //左向きに回転 if (Input.Instance.DownKey(Microsoft.Xna.Framework.Input.Keys.Left)) Move(MoveState.TurnLeft, maze); //右向きに回転 if (Input.Instance.DownKey(Microsoft.Xna.Framework.Input.Keys.Right)) Move(MoveState.TurnRight, maze); //前進 if (Input.Instance.DownKey(Microsoft.Xna.Framework.Input.Keys.Up)) { Move(MoveState.Advance, maze); // アニメーションの開始 AnimationStart("walk"); } //後退 if (Input.Instance.DownKey(Microsoft.Xna.Framework.Input.Keys.Down)) { Move(MoveState.Back, maze); // アニメーションの開始 AnimationStart("walk"); } } else { //移動更新 Move(currentMoveState, maze); } // アニメーションの更新 AnimationUpdate(gameTime); }
/// <summary> /// 後退開始 /// </summary> protected void StartBack(Maze maze) { // 後ろに動けないなら何もしないで終わる if (!CanMove(DirecState.Back(), maze)) { return; } //モデルの方向によって移動判定を行う switch (DirecState) { case Orientation.North: currentMoveState = MoveState.Back; nextposition2.Y += 2; nextposition3 = PointToVecto3(nextposition2, maze); break; case Orientation.West: currentMoveState = MoveState.Back; nextposition2.X += 2; nextposition3 = PointToVecto3(nextposition2, maze); break; case Orientation.East: currentMoveState = MoveState.Back; nextposition2.X -= 2; nextposition3 = PointToVecto3(nextposition2, maze); break; case Orientation.South: currentMoveState = MoveState.Back; nextposition2.Y -= 2; nextposition3 = PointToVecto3(nextposition2, maze); break; } }
/// <summary> /// 移動更新 /// </summary> /// <param name="moveState"></param> /// <param name="maze"></param> protected override void Move(Collidable.MoveState moveState, Maze maze) { //停止状態のとき対応する初期動作を行う if (currentMoveState == MoveState.Stop) { switch (moveState) { case MoveState.Advance: StartAdvance(maze); break; case MoveState.Back: StartBack(maze); break; case MoveState.Stop: break; case MoveState.TurnLeft: StartTurnLeft(); break; case MoveState.TurnRight: StartTurnRight(); break; } } //状態に対応する動作を行う,動作終了後Stop状態に遷移 else { //switch (moveState) switch (currentMoveState) { case MoveState.Advance: Advancing(); break; case MoveState.Back: Backing(); break; case MoveState.Stop: break; case MoveState.TurnLeft: TurningLeft(); break; case MoveState.TurnRight: TurningRight(); break; } } }
/// <summary> /// 指定した方角に動けるかどうか /// </summary> /// <param name="orientation"></param> /// <param name="maze"></param> /// <returns></returns> protected bool CanMove(Orientation orientation, Maze maze, Point position) { //モデルの方向によって移動判定を行う switch (orientation) { case Orientation.North: return maze[position.Y - 1, position.X]; case Orientation.West: return maze[position.Y, position.X - 1]; case Orientation.East: return maze[position.Y, position.X + 1]; case Orientation.South: return maze[position.Y + 1, position.X]; } throw new ArgumentOutOfRangeException("orientation"); }
/// <summary> /// コンストラクタ /// </summary> /// <param name="content"></param> /// <param name="assetname"></param> /// <param name="startPosition"></param> /// <param name="orient"></param> /// <param name="scale"></param> /// <param name="maze"></param> public Collidable(ContentManager content, string assetname, Point startPosition, Orientation orient, Vector3 scale, Maze maze) { // nullの場合はAnimationModelなどでロードしておく if (assetname != null) model = content.Load<Model>(assetname); position2 = startPosition; nextposition2 = startPosition; //2DPos -> 3DPos position3 = PointToVecto3(position2, maze); nextposition3 = position3; //方向設定 DirecState = orient; this.scale = scale; //停止状態 currentMoveState = MoveState.Stop; //オリエントからrotate,degreeを計算 rotate = OrientationToRotate(DirecState); degree = OrientationToDegree(DirecState); }
/// <summary> /// 何も移動しない /// </summary> /// <param name="maze"></param> public override void Update(GameTime gameTime, Maze maze) { }
public GoalObject(ContentManager content, Point startPosition, Orientation orient, Maze maze) : base(content, @"Objects\Goal\flag", startPosition, orient, new Vector3(1.0f, 1.0f, 1.0f), maze) { }
/// <summary> /// メインゲームシーン /// </summary> /// <param name="content"></param> /// <param name="graphicsDevice"></param> /// <param name="input"></param> public GameIn(ContentManager content, GraphicsDevice graphicsDevice, GameTime gameTime, StageSelect.SelectStage selectStage, StageSelect.SelectEnemy selectEnemy) { this.content = content; this.graphicsDevice = graphicsDevice; this.selectStage = selectStage; // 乱数の初期化 rand = new Random(); // 迷路初期化。難易度によって大きさを変える maze = new Maze(content, selectStage); Point playerPosition; Point goalPosition; while (true) { playerPosition = maze.RandomPoint(); goalPosition = maze.RandomPoint(); // 迷路の斜辺の長さを求める。三平方の定理 c^2 = sqrt(a^2 + b^2) double hypotenuse = Math.Sqrt(maze.Width * maze.Width + maze.Height * maze.Height); // 0.5斜辺 < 距離 < 0.6斜辺ならOK double distance = Math.Sqrt((playerPosition.X - goalPosition.X) * (playerPosition.X - goalPosition.X) + (playerPosition.Y - goalPosition.Y) * (playerPosition.Y - goalPosition.Y)); if (hypotenuse * 0.5 < distance && distance < hypotenuse * 0.6) { break; } } //プレイヤー初期化 player = new Player(content, playerPosition, Collidable.Collidable.Orientation.East, maze); //ゴール初期化 goalobj = new GoalObject(content, goalPosition, Collidable.Collidable.Orientation.East, maze); // Enemyマネージャ初期化 enemyManager = new EnemyManager(content, selectEnemy, selectStage, maze, player); //背景モデルの宣言 backmodel = new BackGround(content); //カメラの初期設定 camera = new Camera(player); // ミニマップの初期化 miniMap = new MiniMap(content, graphicsDevice); // スコアの初期化 score = new Score(content, graphicsDevice, gameTime, selectStage); //フェードアウト処理 fadeout = new FadeOut(content, graphicsDevice, FadeOut.SceneType.InGame); // カウントダウン countdown = new CountDown(content, graphicsDevice, gameTime); // BGMの再生 cueBGM = SoundManager.Instance.SoundBank.GetCue("game"); }
/// <summary> /// 更新 /// </summary> /// <param name="maze"></param> /// <param name="playerPosition3"></param> /// <param name="playerPosition2"></param> /// <param name="playerRotate"></param> /// <param name="goalPosition"></param> public void Update(Maze maze, Vector3 playerPosition3, Point playerPosition2, float playerRotate, Vector3 goalPosition) { // ミニマップを全て透明に初期化 for (int i = 0; i < miniMapColor.Length; i++) miniMapColor[i] = Color.Transparent; // 離散値 Vector2 discrete = new Vector2( (float)((maze.WallWidth + maze.WallDepth) / 2 + (maze.WallWidth + maze.WallDepth) * (playerPosition2.X / 2)), (float)((maze.WallWidth + maze.WallDepth) / 2 + (maze.WallWidth + maze.WallDepth) * (playerPosition2.Y / 2)) ); // 連続値で本来いる位置と離散値でいる位置の差 Vector2 difference = discrete - new Vector2(playerPosition3.X, playerPosition3.Z); // 2次元の連続値と離散値を同時に変化させる for (int i = (int)(miniMap.Height / 2.0f - bigWall.Width / 2.0f) - (bigWall.Width + bigWall.Height) * wallNumber + (int)(difference.Y * bigWall.Height / maze.WallDepth) , y = playerPosition2.Y - wallNumber * 2; y <= playerPosition2.Y + wallNumber * 2; i += y % 2 == 0 ? bigWall.Height : bigWall.Width, y++) for (int j = (int)(miniMap.Width / 2.0f - bigWall.Width / 2.0f) - (bigWall.Width + bigWall.Height) * wallNumber + (int)(difference.X * bigWall.Height / maze.WallDepth) , x = playerPosition2.X - wallNumber * 2; x <= playerPosition2.X + wallNumber * 2; j += x % 2 == 0 ? bigWall.Height : bigWall.Width, x++) if (x >= 0 && x < maze.Width && y >= 0 && y < maze.Height && !maze[y, x]) if (x % 2 == 0 && y % 2 == 0) DrawWall(i, j, bigWall.Height, bigWall.Height); // 細い壁 else if (x % 2 == 0) DrawWall(i, j, bigWall.Height, bigWall.Width); // 縦長 else DrawWall(i, j, bigWall.Width, bigWall.Height); // 横長 // ミニマップを円形にする(円外を透明にする) Color[] data = new Color[miniMapBack.Height * miniMapBack.Width]; miniMapBack.GetData<Color>(data); for (int i = 0; i < miniMapBack.Height; i++) for (int j = 0; j < miniMapBack.Width; j++) if (data[i * miniMapBack.Width + j] == Color.Transparent) miniMapColor[i * miniMapBack.Width + j] = Color.Transparent; // プレイヤーの回転 this.playerRotate = playerRotate; // ゴールの回転 flagRotate = (float)Math.Atan2(goalPosition.Z - playerPosition3.Z, goalPosition.X - playerPosition3.X); flagRotate += playerRotate; }
/// <summary> /// 更新処理 /// </summary> /// <param name="maze"></param> public virtual void Update(GameTime gameTime, Maze maze) { }