Example #1
0
        private void Edit()
        {
            this.Map.Load();             // ゲーム中にマップを書き換える場合があるので、再ロードする。

            DDEngine.FreezeInput();
            DDUtils.SetMouseDispMode(true);
            LevelEditor.ShowDialog();

            int lastMouseX = DDMouse.X;
            int lastMouseY = DDMouse.Y;

            for (; ;)
            {
                if (LevelEditor.Dlg.XPressed)
                {
                    break;
                }

                // 廃止
                //if (DDKey.GetInput(DX.KEY_INPUT_E) == 1)
                //    break;

                I2Point cellPos = GameCommon.ToTablePoint(
                    DDGround.Camera.X + DDMouse.X,
                    DDGround.Camera.Y + DDMouse.Y
                    );

                MapCell cell = Game.I.Map.GetCell(cellPos);

                if (cell.IsDefault)
                {
                    // noop
                }
                else if (1 <= DDKey.GetInput(DX.KEY_INPUT_LSHIFT) && 1 <= DDKey.GetInput(DX.KEY_INPUT_LCONTROL)) // 左シフト・コントロール押下 -> 塗り潰し_L / 塗り潰し_R
                {
                    if (DDMouse.L.GetInput() == -1)                                                              // クリックを検出
                    {
                        this.Map.Save();                                                                         // 失敗を想定して、セーブしておく

                        switch (LevelEditor.Dlg.GetMode())
                        {
                        case LevelEditor.Mode_e.TILE:
                        {
                            string tileName = LevelEditor.Dlg.GetTile_L();

                            if (tileName != cell.TileName)
                            {
                                string targetTileName = cell.TileName;                                                 // cell.TileName は this.EditFill で変更される。

                                this.EditFill(
                                    cellPos,
                                    v => v.TileName == targetTileName,
                                    v =>
                                    {
                                        v.TileName = tileName;
                                        v.Tile     = TileCatalog.Create(tileName);
                                    }
                                    );
                            }
                        }
                        break;

                        case LevelEditor.Mode_e.ENEMY:
                        {
                            string enemyName = LevelEditor.Dlg.GetEnemy();

                            if (enemyName != cell.EnemyName)
                            {
                                string targetEnemyName = cell.EnemyName;                                                 // cell.EnemyName は this.EditFill で変更される。

                                this.EditFill(
                                    cellPos,
                                    v => v.EnemyName == targetEnemyName,
                                    v => v.EnemyName = enemyName
                                    );
                            }
                        }
                        break;

                        default:
                            throw null;                                     // never
                        }
                    }
                    else if (DDMouse.R.GetInput() == -1)         // クリックを検出
                    {
                        this.Map.Save();                         // 失敗を想定して、セーブしておく

                        switch (LevelEditor.Dlg.GetMode())
                        {
                        case LevelEditor.Mode_e.TILE:
                        {
                            string tileName = LevelEditor.Dlg.GetTile_R();

                            if (tileName != cell.TileName)
                            {
                                string targetTileName = cell.TileName;                                                 // cell.TileName は this.EditFill で変更される。

                                this.EditFill(
                                    cellPos,
                                    v => v.TileName == targetTileName,
                                    v =>
                                    {
                                        v.TileName = tileName;
                                        v.Tile     = TileCatalog.Create(tileName);
                                    }
                                    );
                            }
                        }
                        break;

                        case LevelEditor.Mode_e.ENEMY:
                            // none
                            break;

                        default:
                            throw null;                                     // never
                        }
                    }
                }
                else if (1 <= DDKey.GetInput(DX.KEY_INPUT_LSHIFT))                 // 左シフト押下 -> 移動 / none
                {
                    if (1 <= DDMouse.L.GetInput())
                    {
                        DDGround.Camera.X -= DDMouse.X - lastMouseX;
                        DDGround.Camera.Y -= DDMouse.Y - lastMouseY;

                        DDUtils.ToRange(ref DDGround.Camera.X, 0.0, this.Map.W * GameConsts.TILE_W - DDConsts.Screen_W);
                        DDUtils.ToRange(ref DDGround.Camera.Y, 0.0, this.Map.H * GameConsts.TILE_H - DDConsts.Screen_H);

                        DDGround.ICamera.X = SCommon.ToInt(DDGround.Camera.X);
                        DDGround.ICamera.Y = SCommon.ToInt(DDGround.Camera.Y);
                    }
                    else if (1 <= DDMouse.R.GetInput())
                    {
                        // none
                    }
                }
                else if (1 <= DDKey.GetInput(DX.KEY_INPUT_LCONTROL))                 // 左コントロール押下 -> スポイト_L / スポイト_R
                {
                    if (1 <= DDMouse.L.GetInput())
                    {
                        switch (LevelEditor.Dlg.GetMode())
                        {
                        case LevelEditor.Mode_e.TILE:
                            LevelEditor.Dlg.SetTile_L(cell.TileName);
                            break;

                        case LevelEditor.Mode_e.ENEMY:
                            LevelEditor.Dlg.SetEnemy(cell.EnemyName);
                            break;

                        default:
                            throw null;                                     // never
                        }
                    }
                    else if (1 <= DDMouse.R.GetInput())
                    {
                        switch (LevelEditor.Dlg.GetMode())
                        {
                        case LevelEditor.Mode_e.TILE:
                            LevelEditor.Dlg.SetTile_R(cell.TileName);
                            break;

                        case LevelEditor.Mode_e.ENEMY:
                            // none
                            break;

                        default:
                            throw null;                                     // never
                        }
                    }
                }
                else if (1 <= DDKey.GetInput(DX.KEY_INPUT_LALT))        // 左 ALT 押下 -> 自機ワープ / none
                {
                    if (DDMouse.L.GetInput() == -1)                     // クリックを検出
                    {
                        this.Player.X = cellPos.X * GameConsts.TILE_W + GameConsts.TILE_W / 2;
                        this.Player.Y = cellPos.Y * GameConsts.TILE_H + GameConsts.TILE_H / 2;

                        DDGround.EL.Add(SCommon.Supplier(Effects.中爆発(this.Player.X, this.Player.Y)));                         // アクションが分かるように
                    }
                    else if (1 <= DDMouse.R.GetInput())
                    {
                        // none
                    }
                }
                else                 // シフト系押下無し -> セット_L / セット_R (敵はクリア)
                {
                    if (1 <= DDMouse.L.GetInput())
                    {
                        switch (LevelEditor.Dlg.GetMode())
                        {
                        case LevelEditor.Mode_e.TILE:
                        {
                            string tileName = LevelEditor.Dlg.GetTile_L();

                            cell.TileName = tileName;
                            cell.Tile     = TileCatalog.Create(tileName);
                        }
                        break;

                        case LevelEditor.Mode_e.ENEMY:
                        {
                            string enemyName = LevelEditor.Dlg.GetEnemy();

                            cell.EnemyName = enemyName;
                        }
                        break;

                        default:
                            throw null;                                     // never
                        }
                    }
                    else if (1 <= DDMouse.R.GetInput())
                    {
                        switch (LevelEditor.Dlg.GetMode())
                        {
                        case LevelEditor.Mode_e.TILE:
                        {
                            string tileName = LevelEditor.Dlg.GetTile_R();

                            cell.TileName = tileName;
                            cell.Tile     = TileCatalog.Create(tileName);
                        }
                        break;

                        case LevelEditor.Mode_e.ENEMY:
                            cell.EnemyName = GameConsts.ENEMY_NONE;
                            break;

                        default:
                            throw null;                                     // never
                        }
                    }
                }

                if (DDKey.GetInput(DX.KEY_INPUT_S) == 1)                 // S キー --> Save
                {
                    this.Map.Save();

                    // 表示
                    {
                        int endFrame = DDEngine.ProcFrame + 60;

                        DDGround.EL.Add(() =>
                        {
                            DDPrint.SetDebug(0, 16);
                            DDPrint.SetBorder(new I3Color(0, 0, 0));
                            DDPrint.Print("セーブしました...");
                            DDPrint.Reset();

                            return(DDEngine.ProcFrame < endFrame);
                        });
                    }
                }
                if (DDKey.GetInput(DX.KEY_INPUT_L) == 1)                 // L キー --> Load
                {
                    this.Map.Load();

                    // 表示
                    {
                        int endFrame = DDEngine.ProcFrame + 60;

                        DDGround.EL.Add(() =>
                        {
                            DDPrint.SetDebug(0, 16);
                            DDPrint.SetBorder(new I3Color(0, 0, 0));
                            DDPrint.Print("ロードしました...");
                            DDPrint.Reset();

                            return(DDEngine.ProcFrame < endFrame);
                        });
                    }
                }

                DDCurtain.DrawCurtain();

                if (LevelEditor.Dlg.IsShowTile())
                {
                    this.DrawMap();
                }

                if (LevelEditor.Dlg.IsShowEnemy())
                {
                    LevelEditor.DrawEnemy();
                }

                lastMouseX = DDMouse.X;
                lastMouseY = DDMouse.Y;

                DDEngine.EachFrame();
            }
            DDEngine.FreezeInput();
            DDUtils.SetMouseDispMode(false);
            LevelEditor.CloseDialog();

            this.Map.Save();             // ★★★ マップをセーブする ★★★
        }
Example #2
0
        public void Perform()
        {
            this.Player.X = DDConsts.Screen_W / 4;
            this.Player.Y = DDConsts.Screen_H / 2;

            this.Player.BornScene.Fire();

            DDCurtain.SetCurtain(10);

            for (; ; this.Frame++)
            {
                // プレイヤー行動
                {
                    bool   bornOrDead = this.Player.BornScene.IsFlaming() || this.Player.DeadScene.IsFlaming();
                    bool   dead       = this.Player.DeadScene.IsFlaming();
                    double xa         = 0.0;
                    double ya         = 0.0;

                    if (!dead && 1 <= DDInput.DIR_4.GetInput())                     // 左移動
                    {
                        xa = -1.0;
                    }
                    if (!dead && 1 <= DDInput.DIR_6.GetInput())                     // 右移動
                    {
                        xa = 1.0;
                    }
                    if (!dead && 1 <= DDInput.DIR_8.GetInput())                     // 上移動
                    {
                        ya = -1.0;
                    }
                    if (!dead && 1 <= DDInput.DIR_2.GetInput())                     // 下移動
                    {
                        ya = 1.0;
                    }

                    double speed;

                    if (1 <= DDInput.A.GetInput())                     // 低速ボタン押下中
                    {
                        speed = (double)this.Player.SpeedLevel;
                    }
                    else
                    {
                        speed = (double)(this.Player.SpeedLevel * 2);
                    }

                    this.Player.X += xa * speed;
                    this.Player.Y += ya * speed;

                    DDUtils.ToRange(ref this.Player.X, 0.0, DDConsts.Screen_W);
                    DDUtils.ToRange(ref this.Player.Y, 0.0, DDConsts.Screen_H);

                    if (!bornOrDead && 1 <= DDInput.B.GetInput())                     // 攻撃ボタン押下中
                    {
                        this.Player.Shoot();
                    }

                    if (DDInput.L.GetInput() == 1)
                    {
                        this.Player.SpeedLevel--;
                    }
                    if (DDInput.R.GetInput() == 1)
                    {
                        this.Player.SpeedLevel++;
                    }
                    DDUtils.ToRange(ref this.Player.SpeedLevel, Player.SPEED_LEVEL_MIN, Player.SPEED_LEVEL_MAX);
                }

                {
                    DDScene scene = this.Player.BornScene.GetScene();

                    if (scene.Numer != -1)
                    {
                        if (scene.Remaining == 0)
                        {
                            this.Player.MutekiScene.FireDelay();
                        }
                    }
                }

                {
                    DDScene scene = this.Player.DeadScene.GetScene();

                    if (scene.Numer != -1)
                    {
                        if (scene.Remaining == 0)
                        {
                            if (this.Status.RemainingLiveCount <= 0)
                            {
                                break;
                            }

                            this.Status.RemainingLiveCount--;
                            this.Player.BornScene.FireDelay();
                        }
                    }
                }

                {
                    DDScene scene = this.Player.MutekiScene.GetScene();

                    if (scene.Numer != -1)
                    {
                        // noop
                    }
                }

                if (this.Scenario.EachFrame() == false)
                {
                    break;
                }

                this.EnemyEachFrame();
                this.WeaponEachFrame();

                DDCrashView cv = DDKey.GetInput(DX.KEY_INPUT_LSHIFT) == 0 ? null : new DDCrashView();

                // Crash
                {
                    DDCrash playerCrash = DDCrashUtils.Point(new D2Point(this.Player.X, this.Player.Y));

                    foreach (WeaponBox weapon in this.Weapons.Iterate())
                    {
                        weapon.Crash = weapon.Value.GetCrash();
                    }

                    foreach (EnemyBox enemy in this.Enemies.Iterate())
                    {
                        DDCrash enemyCrash = enemy.Value.GetCrash();

                        if (cv != null)
                        {
                            cv.Draw(enemyCrash);
                        }

                        foreach (WeaponBox weapon in this.Weapons.Iterate())
                        {
                            if (enemyCrash.IsCrashed(weapon.Crash))
                            {
                                if (enemy.Value.Crashed(weapon.Value) == false)                                 // ? 消滅
                                {
                                    enemy.Dead = true;
                                }

                                if (weapon.Value.Crashed(enemy.Value) == false)                                 // ? 消滅
                                {
                                    weapon.Dead = true;
                                }
                            }
                        }
                        this.Weapons.RemoveAll(weapon => weapon.Dead);

                        if (this.Player.BornScene.IsFlaming() == false &&
                            this.Player.DeadScene.IsFlaming() == false &&
                            this.Player.MutekiScene.IsFlaming() == false && enemyCrash.IsCrashed(playerCrash))
                        {
                            foreach (DDScene scene in DDSceneUtils.Create(30))                             // プレイヤ死亡効果
                            {
                                this.DrawWall();
                                this.Player.Draw();
                                this.DrawEnemies();

                                DDDraw.SetAlpha(0.3);
                                DDDraw.SetBright(1.0, 0.0, 0.0);
                                DDDraw.DrawRect(DDGround.GeneralResource.WhiteBox, 0, 0, DDConsts.Screen_W, DDConsts.Screen_H);
                                DDDraw.Reset();

                                {
                                    int ix = DoubleTools.ToInt(this.Player.X);
                                    int iy = DoubleTools.ToInt(this.Player.Y);

                                    DDDraw.SetBright(1.0, 1.0, 0.0);
                                    DDDraw.SetAlpha(scene.Rate);
                                    DDDraw.DrawRect_LTRB(DDGround.GeneralResource.WhiteBox, ix - 1, 0, ix + 1, DDConsts.Screen_H);
                                    DDDraw.SetAlpha(scene.RemainingRate);
                                    DDDraw.DrawRect_LTRB(DDGround.GeneralResource.WhiteBox, 0, iy - 1, DDConsts.Screen_W, iy + 1);
                                    DDDraw.Reset();
                                }

                                DDEngine.EachFrame();
                            }

                            this.Player.DeadScene.Fire();
                        }
                    }
                    this.Enemies.RemoveAll(enemy => enemy.Dead);
                }

                // ここから描画

                this.DrawWall();
                this.Player.Draw();
                this.DrawEnemies();
                this.DrawWeapons();

                if (cv != null)
                {
                    cv.DrawToScreen(0.8);
                    cv.Dispose();
                    cv = null;
                }

                DDPrint.SetPrint();
                DDPrint.Print(DDEngine.FrameProcessingMillis_Worst + " " + this.Enemies.Count + " SPEED=" + this.Player.SpeedLevel);

                DDEngine.EachFrame();
            }
        }
Example #3
0
        public void Perform()
        {
            Func <bool> f_ゴミ回収 = SCommon.Supplier(this.E_ゴミ回収());

            this.Map = new Map(GameCommon.GetMapFile(this.World.GetCurrMapName()));
            this.ReloadEnemies();

            // デフォルトの「プレイヤーのスタート地点」
            // -- マップの中央
            this.Player.X = this.Map.W * GameConsts.TILE_W / 2.0;
            this.Player.Y = this.Map.H * GameConsts.TILE_H / 2.0;

            {
                Enemy enemy = this.Enemies.Iterate().FirstOrDefault(v => v is Enemy_スタート地点 && ((Enemy_スタート地点)v).Direction == this.Status.StartPointDirection);

                if (enemy != null)
                {
                    this.Player.X = enemy.X;
                    this.Player.Y = enemy.Y;
                }
            }

            // ★★★★★
            // プレイヤー・ステータス反映(マップ入場時)
            // その他の反映箇所:
            // -- マップ退場時
            // -- セーブ時
            {
                this.Player.HP            = this.Status.StartHP;
                this.Player.FaceDirection = this.Status.StartFaceDirection;
                this.Player.選択武器          = this.Status.Start選択武器;
            }

            this.Wall = WallCreator.Create(this.Map.WallName);

            MusicCollection.Get(this.Map.MusicName).Play();

            DDGround.Camera.X = this.Player.X - DDConsts.Screen_W / 2.0;
            DDGround.Camera.Y = this.Player.Y - DDConsts.Screen_H / 2.0;

            DDCurtain.SetCurtain(0, -1.0);
            DDCurtain.SetCurtain(10);

            DDEngine.FreezeInput();

            // TODO: 音楽

            for (this.Frame = 0; ; this.Frame++)
            {
                if (!this.UserInputDisabled && DDInput.PAUSE.GetInput() == 1)
                {
                    this.Pause();

                    if (this.Pause_ReturnToTitleMenu)
                    {
                        this.Status.ExitDirection = 5;
                        break;
                    }
                }
                if (this.RequestReturnToTitleMenu)
                {
                    this.Status.ExitDirection = 5;
                    break;
                }
                if (DDConfig.LOG_ENABLED && DDKey.GetInput(DX.KEY_INPUT_RETURN) == 1)
                {
                    this.DebugPause();
                }

                // 死亡時にカメラ移動を止める。
                //if (this.Player.DeadFrame == 0)
                //    this.カメラ位置調整(false);

                this.カメラ位置調整(false);

                if (DDConfig.LOG_ENABLED && DDKey.GetInput(DX.KEY_INPUT_E) == 1)                 // エディットモード(デバッグ用)
                {
                    this.Edit();
                    this.ReloadEnemies();
                    this.Frame = 0;
                }

                // プレイヤー入力・移動
                {
                    bool deadOrUID = 1 <= this.Player.DeadFrame || this.UserInputDisabled;
                    bool dir2      = !deadOrUID && 1 <= DDInput.DIR_2.GetInput() || this.PlayerHacker.DIR_2;
                    bool dir4      = !deadOrUID && 1 <= DDInput.DIR_4.GetInput() || this.PlayerHacker.DIR_4;
                    bool dir6      = !deadOrUID && 1 <= DDInput.DIR_6.GetInput() || this.PlayerHacker.DIR_6;
                    bool dir8      = !deadOrUID && 1 <= DDInput.DIR_8.GetInput() || this.PlayerHacker.DIR_8;
                    int  dir;                    // 1~9 == { 左下, 下, 右下, 左, 動かない, 右, 左上, 上, 右上 }

                    if (dir2 && dir4)
                    {
                        dir = 1;
                    }
                    else if (dir2 && dir6)
                    {
                        dir = 3;
                    }
                    else if (dir4 && dir8)
                    {
                        dir = 7;
                    }
                    else if (dir6 && dir8)
                    {
                        dir = 9;
                    }
                    else if (dir2)
                    {
                        dir = 2;
                    }
                    else if (dir4)
                    {
                        dir = 4;
                    }
                    else if (dir6)
                    {
                        dir = 6;
                    }
                    else if (dir8)
                    {
                        dir = 8;
                    }
                    else
                    {
                        dir = 5;
                    }

                    if (1 <= this.Player.DamageFrame)                     // ? プレイヤー・ダメージ中
                    {
                        dir = 5;
                    }

                    bool camSlide = !deadOrUID && 1 <= DDInput.L.GetInput();

                    if (camSlide)
                    {
                        dir = 5;
                    }

                    bool slow = !deadOrUID && 1 <= DDInput.A.GetInput() || this.PlayerHacker.Slow;
                    bool fast = !deadOrUID && 1 <= DDInput.R.GetInput() || this.PlayerHacker.Fast;

                    if (Ground.I.FastReverseMode)
                    {
                        fast = !fast;
                    }

                    double speed = 3.0;

                    if (slow)
                    {
                        speed -= 1.0;
                    }

                    if (fast)
                    {
                        speed += 2.0;
                    }

                    double nanameSpeed = speed / Consts.ROOT_OF_2;

                    switch (dir)
                    {
                    case 2:
                        this.Player.Y += speed;
                        break;

                    case 4:
                        this.Player.X -= speed;
                        break;

                    case 6:
                        this.Player.X += speed;
                        break;

                    case 8:
                        this.Player.Y -= speed;
                        break;

                    case 1:
                        this.Player.X -= nanameSpeed;
                        this.Player.Y += nanameSpeed;
                        break;

                    case 3:
                        this.Player.X += nanameSpeed;
                        this.Player.Y += nanameSpeed;
                        break;

                    case 7:
                        this.Player.X -= nanameSpeed;
                        this.Player.Y -= nanameSpeed;
                        break;

                    case 9:
                        this.Player.X += nanameSpeed;
                        this.Player.Y -= nanameSpeed;
                        break;

                    case 5:
                        break;

                    default:
                        throw null;                                 // never
                    }
                    if (dir != 5 && !slow)
                    {
                        this.Player.FaceDirection = dir;
                    }

                    if (dir != 5)
                    {
                        this.Player.MoveFrame++;
                    }
                    else
                    {
                        this.Player.MoveFrame = 0;
                    }

                    if (this.Player.MoveFrame == 0)                     // 立ち止まったら座標を整数に矯正
                    {
                        this.Player.X = SCommon.ToInt(this.Player.X);
                        this.Player.Y = SCommon.ToInt(this.Player.Y);
                    }
                    if (camSlide)
                    {
                        if (dir4)
                        {
                            this.CamSlideCount++;
                            this.CamSlideX--;
                        }
                        if (dir6)
                        {
                            this.CamSlideCount++;
                            this.CamSlideX++;
                        }
                        if (dir8)
                        {
                            this.CamSlideCount++;
                            this.CamSlideY--;
                        }
                        if (dir2)
                        {
                            this.CamSlideCount++;
                            this.CamSlideY++;
                        }
                        DDUtils.ToRange(ref this.CamSlideX, -1, 1);
                        DDUtils.ToRange(ref this.CamSlideY, -1, 1);
                    }
                    else
                    {
                        if (this.CamSlideMode && this.CamSlideCount == 0)
                        {
                            this.CamSlideX = 0;
                            this.CamSlideY = 0;
                        }
                        this.CamSlideCount = 0;
                    }
                    this.CamSlideMode = camSlide;

                    bool attack = !deadOrUID && 1 <= DDInput.B.GetInput() || this.PlayerHacker.Attack;

                    if (attack)
                    {
                        this.Player.AttackFrame++;
                    }
                    else
                    {
                        this.Player.AttackFrame = 0;
                    }

                    bool 武器切り替え = !deadOrUID && DDInput.C.GetInput() == 1;

                    if (武器切り替え)
                    {
                        this.Player.選択武器 = (Player.武器_e)(((int)this.Player.選択武器 + 1) % Player.武器_e_Length);
                    }
                }

                //startDead:
                if (1 <= this.Player.DeadFrame)                 // プレイヤー死亡中の処理
                {
                    if (GameConsts.PLAYER_DEAD_FRAME_MAX < ++this.Player.DeadFrame)
                    {
                        this.Player.DeadFrame     = 0;
                        this.Status.ExitDirection = 5;
                        break;
                    }
                    int    frame = this.Player.DeadFrame;                  // 値域 == 2 ~ GameConsts.PLAYER_DEAD_FRAME_MAX
                    double rate  = DDUtils.RateAToB(2, GameConsts.PLAYER_DEAD_FRAME_MAX, frame);

                    // ----

                    const int HIT_BACK_FRAME_MAX = 30;
                    double    hitBackRate        = DDUtils.RateAToB(2, HIT_BACK_FRAME_MAX, frame);

                    if (hitBackRate < 1.0)
                    {
                        double invHitBackRate = 1.0 - hitBackRate;

                        D2Point speed = GameCommon.GetXYSpeed(this.Player.FaceDirection, 10.0 * invHitBackRate);

                        this.Player.X -= speed.X;
                        this.Player.Y -= speed.Y;
                    }
                }
                //endDead:

                //startDamage:
                if (1 <= this.Player.DamageFrame)                 // プレイヤー・ダメージ中の処理
                {
                    if (GameConsts.PLAYER_DAMAGE_FRAME_MAX < ++this.Player.DamageFrame)
                    {
                        this.Player.DamageFrame     = 0;
                        this.Player.InvincibleFrame = 1;
                        goto endDamage;
                    }
                    int    frame = this.Player.DamageFrame;                  // 値域 == 2 ~ GameConsts.PLAYER_DAMAGE_FRAME_MAX
                    double rate  = DDUtils.RateAToB(2, GameConsts.PLAYER_DAMAGE_FRAME_MAX, frame);

                    // ----

                    {
                        D2Point speed = GameCommon.GetXYSpeed(this.Player.FaceDirection, 5.0);

                        for (int c = 0; c < 5; c++)
                        {
                            {
                                int x = SCommon.ToInt(this.Player.X) / GameConsts.TILE_W;
                                int y = SCommon.ToInt(this.Player.Y) / GameConsts.TILE_H;

                                if (this.Map.GetCell(x, y).Tile.GetKind() != Tile.Kind_e.SPACE)                                 // ? 歩行可能な場所ではない -> これ以上ヒットバックさせない。
                                {
                                    break;
                                }
                            }

                            this.Player.X -= speed.X;
                            this.Player.Y -= speed.Y;
                        }
                    }
                }
endDamage:

                //startInvincible:
                if (1 <= this.Player.InvincibleFrame)                 // プレイヤー無敵時間中の処理
                {
                    if (GameConsts.PLAYER_INVINCIBLE_FRAME_MAX < ++this.Player.InvincibleFrame)
                    {
                        this.Player.InvincibleFrame = 0;
                        goto endInvincible;
                    }
                    int    frame = this.Player.InvincibleFrame;                  // 値域 == 2 ~ GameConsts.PLAYER_INVINCIBLE_FRAME_MAX
                    double rate  = DDUtils.RateAToB(2, GameConsts.PLAYER_INVINCIBLE_FRAME_MAX, frame);

                    // ----

                    // noop
                }
endInvincible:

                // プレイヤー位置矯正
                {
                    壁キャラ処理.Perform(ref this.Player.X, ref this.Player.Y, v => v.GetKind() != Tile.Kind_e.SPACE);
                }

                if (this.Player.X < 0.0)                 // ? マップの左側に出た。
                {
                    this.Status.ExitDirection = 4;
                    break;
                }
                if (this.Map.W * GameConsts.TILE_W < this.Player.X)                 // ? マップの右側に出た。
                {
                    this.Status.ExitDirection = 6;
                    break;
                }
                if (this.Player.Y < 0.0)                 // ? マップの上側に出た。
                {
                    this.Status.ExitDirection = 8;
                    break;
                }
                if (this.Map.H * GameConsts.TILE_H < this.Player.Y)                 // ? マップの下側に出た。
                {
                    this.Status.ExitDirection = 2;
                    break;
                }

                // 画面遷移時の微妙なカメラ位置ズレ解消
                // -- 必要無いかもしれないが、念の為実行しておく。
                if (this.Frame == 0)
                {
                    this.カメラ位置調整(true);
                }

                if (1 <= this.Player.AttackFrame)
                {
                    this.Player.Attack();
                }

                DDCrash plCrash = DDCrashUtils.Point(new D2Point(this.Player.X, this.Player.Y));

                // ====
                // 描画ここから
                // ====

                this.DrawWall();
                this.DrawMap();
                this.Player.Draw();

                // memo: DeadFlag をチェックするのは「当たり判定」から

                foreach (Enemy enemy in this.Enemies.Iterate())
                {
                    enemy.Crash = DDCrashUtils.None();                     // reset
                    enemy.Draw();
                }
                foreach (Shot shot in this.Shots.Iterate())
                {
                    shot.Crash = DDCrashUtils.None();                     // reset
                    shot.Draw();
                }

                if (this.当たり判定表示)
                {
                    // 最後に描画されるように DDGround.EL.Add() する。

                    DDGround.EL.Add(() =>
                    {
                        DDCurtain.DrawCurtain(-0.8);

                        const double A = 0.3;

                        DDCrashView.Draw(new DDCrash[] { plCrash }, new I3Color(255, 0, 0), 1.0);
                        DDCrashView.Draw(this.Enemies.Iterate().Select(v => v.Crash), new I3Color(255, 255, 255), A);
                        DDCrashView.Draw(this.Shots.Iterate().Select(v => v.Crash), new I3Color(0, 255, 255), A);

                        return(false);
                    });
                }

                // ====
                // 描画ここまで
                // ====

                // ====
                // 当たり判定ここから
                // ====

                foreach (Enemy enemy in this.Enemies.Iterate())
                {
                    if (1 <= enemy.HP)                     // ? 敵:生存 && 無敵ではない
                    {
                        foreach (Shot shot in this.Shots.Iterate())
                        {
                            // 衝突判定:敵 x 自弾
                            if (
                                !shot.DeadFlag &&                                 // ? 自弾:生存
                                enemy.Crash.IsCrashed(shot.Crash)                 // ? 衝突
                                )
                            {
                                // ★ 敵_被弾ここから

                                if (!shot.敵を貫通する)
                                {
                                    shot.Kill();
                                }

                                enemy.HP -= shot.AttackPoint;

                                if (1 <= enemy.HP)                                 // ? まだ生存している。
                                {
                                    enemy.Damaged(shot);
                                }
                                else                                 // ? 撃破した。
                                {
                                    enemy.Kill(true);
                                    break;                                     // この敵は死亡したので、この敵について以降の当たり判定は不要
                                }

                                // ★ 敵_被弾ここまで
                            }
                        }
                    }

                    // 衝突判定:敵 x 自機
                    if (
                        this.Player.DeadFrame == 0 &&                // ? プレイヤー死亡中ではない。
                        this.Player.DamageFrame == 0 &&              // ? プレイヤー・ダメージ中ではない。
                        this.Player.InvincibleFrame == 0 &&          // ? プレイヤー無敵時間中ではない。
                        !enemy.DeadFlag &&                           // ? 敵:生存
                        DDCrashUtils.IsCrashed(enemy.Crash, plCrash) // ? 衝突
                        )
                    {
                        // ★ 自機_被弾ここから

                        if (enemy.自機に当たると消滅する)
                        {
                            enemy.Kill();
                        }

                        this.Player.HP -= enemy.AttackPoint;

                        if (1 <= this.Player.HP)                         // ? まだ生存している。
                        {
                            this.Player.DamageFrame = 1;
                        }
                        else                         // ? 死亡した。
                        {
                            this.Player.HP        = -1;
                            this.Player.DeadFrame = 1;
                        }

                        // ★ 自機_被弾ここまで
                    }
                }

                foreach (Shot shot in this.Shots.Iterate())
                {
                    // 壁への当たり判定は自弾の「中心座標のみ」であることに注意して下さい。

                    if (
                        !shot.DeadFlag &&                                                                            // ? 自弾:生存
                        !shot.壁をすり抜ける &&                                                                             // ? この自弾は壁に当たる。
                        this.Map.GetCell(GameCommon.ToTablePoint(shot.X, shot.Y)).Tile.GetKind() == Tile.Kind_e.WALL // ? 壁に当たった。
                        )
                    {
                        shot.Kill();
                    }
                }

                // ====
                // 当たり判定ここまで
                // ====

                f_ゴミ回収();

                this.Enemies.RemoveAll(v => v.DeadFlag);
                this.Shots.RemoveAll(v => v.DeadFlag);

                DDEngine.EachFrame();

                // ★★★ ゲームループの終わり ★★★
            }
            DDEngine.FreezeInput();

            if (this.Status.ExitDirection == 5)
            {
                DDMusicUtils.Fade();
                DDCurtain.SetCurtain(30, -1.0);

                foreach (DDScene scene in DDSceneUtils.Create(40))
                {
                    this.DrawWall();
                    this.DrawMap();

                    DDEngine.EachFrame();
                }
            }
            else
            {
                double destSlide_X = 0.0;
                double destSlide_Y = 0.0;

                switch (this.Status.ExitDirection)
                {
                case 4:
                    destSlide_X = DDConsts.Screen_W;
                    break;

                case 6:
                    destSlide_X = -DDConsts.Screen_W;
                    break;

                case 8:
                    destSlide_Y = DDConsts.Screen_H;
                    break;

                case 2:
                    destSlide_Y = -DDConsts.Screen_H;
                    break;

                default:
                    throw null;                             // never
                }
                using (DDSubScreen wallMapScreen = new DDSubScreen(DDConsts.Screen_W, DDConsts.Screen_H))
                {
                    using (wallMapScreen.Section())
                    {
                        this.DrawWall();
                        this.DrawMap();
                    }
                    foreach (DDScene scene in DDSceneUtils.Create(30))
                    {
                        double slide_X = destSlide_X * scene.Rate;
                        double slide_Y = destSlide_Y * scene.Rate;

                        DDCurtain.DrawCurtain();
                        DDDraw.DrawSimple(wallMapScreen.ToPicture(), slide_X, slide_Y);

                        DDEngine.EachFrame();
                    }
                }
                DDCurtain.SetCurtain(0, -1.0);
            }

            // ★★★★★
            // プレイヤー・ステータス反映(マップ退場時)
            // その他の反映箇所:
            // -- マップ入場時
            // -- セーブ時
            {
                this.Status.StartHP            = this.Player.HP;
                this.Status.StartFaceDirection = this.Player.FaceDirection;
                this.Status.Start選択武器          = this.Player.選択武器;
            }

            // ★★★ end of Perform() ★★★
        }
Example #4
0
        public static void EachFrame()
        {
            I2Point pt   = Map.ToTablePoint(DDMouse.X + DDGround.ICamera.X, DDMouse.Y + DDGround.ICamera.Y);
            MapCell cell = Game.I.Map.GetCell(pt, null);

            if (cell == null)
            {
                return;
            }

            if (DDUtils.IsOutOfScreen(new D2Point(DDMouse.X, DDMouse.Y)))
            {
                return;
            }

            HideMenu = 1 <= DDKey.GetInput(DX.KEY_INPUT_LCONTROL) || 1 <= DDKey.GetInput(DX.KEY_INPUT_RCONTROL);

            if (HideMenu || DDUtils.IsOut(new D2Point(DDMouse.X, DDMouse.Y), MenuRect))
            {
                if (1 <= DDMouse.L.GetInput())
                {
                    if (InputWallFlag)
                    {
                        cell.Wall = Wall;
                    }
                    if (InputTileFlag)
                    {
                        cell.Tile = MapTileManager.GetTile(MapTileManager.GetNames()[TileIndex]);
                    }
                    if (InputEnemyFlag)
                    {
                        cell.EnemyLoader = EnemyManager.GetEnemyLoader(EnemyManager.GetNames()[EnemyIndex]);
                    }
                }
                if (1 <= DDMouse.R.GetInput())
                {
                    cell.Wall        = false;
                    cell.Tile        = null;
                    cell.EnemyLoader = null;
                }
            }
            else
            {
                int cursorMenuItemIndex = DDMouse.Y / 16;

                bool l = 1 <= DDMouse.L.GetInput();
                bool r = 1 <= DDMouse.R.GetInput();

                if (l || r)
                {
                    bool flag = l;

                    switch (cursorMenuItemIndex)
                    {
                    case 0: InputWallFlag = flag; break;

                    case 1: InputTileFlag = flag; break;

                    case 2: InputEnemyFlag = flag; break;

                    case 3: DisplayWallFlag = flag; break;

                    case 4: DisplayTileFlag = flag; break;

                    case 5: DisplayEnemyFlag = flag; break;

                    case 6: Wall = flag; break;

                    case 7:
                    case 8:
                        IntoInputTileMode();
                        break;

                    case 9:
                    case 10:
                        IntoInputEnemyMode();
                        break;
                    }
                }

                Rot += DDMouse.Rot;

                if (DDMouse.Rot == 0)
                {
                    NoRotFrame++;
                }
                else
                {
                    NoRotFrame = 0;
                }

                if (90 < NoRotFrame)
                {
                    Rot = 0;
                }

                switch (cursorMenuItemIndex)
                {
                case 7:
                case 8:
                    if (MenuItemRot(ref TileIndex, MapTileManager.GetCount()))
                    {
                        IntoInputTileMode();
                    }
                    break;

                case 9:
                case 10:
                    if (MenuItemRot(ref EnemyIndex, EnemyManager.GetCount()))
                    {
                        IntoInputEnemyMode();
                    }
                    break;
                }
            }

            if (DDKey.GetInput(DX.KEY_INPUT_C) == 1)
            {
                if (InputWallFlag)
                {
                    Wall = cell.Wall;
                }
                if (InputTileFlag)
                {
                    TileIndex = cell.Tile == null ? 0 : MapTileManager.GetNames().IndexOf(cell.Tile.Name);
                }
                if (InputEnemyFlag)
                {
                    EnemyIndex = cell.EnemyLoader == null ? 0 : EnemyManager.GetNames().IndexOf(cell.EnemyLoader.Name);
                }

                if (TileIndex == -1)                 // 2bs
                {
                    TileIndex = 0;
                }

                if (EnemyIndex == -1)                 // 2bs
                {
                    EnemyIndex = 0;
                }
            }
            if (DDKey.GetInput(DX.KEY_INPUT_S) == 1)
            {
                MapLoader.SaveToLastLoadedFile(Game.I.Map);
            }
        }
Example #5
0
        public void Perform()
        {
            Func <bool> f_ゴミ回収 = SCommon.Supplier(this.E_ゴミ回収());

            this.Map = new Map(GameCommon.GetMapFile(this.World.GetCurrMapName()));
            this.ReloadEnemies();

            // デフォルトの「プレイヤーのスタート地点」
            // -- マップの中央
            this.Player.X = this.Map.W * GameConsts.TILE_W / 2.0;
            this.Player.Y = this.Map.H * GameConsts.TILE_H / 2.0;

            {
                Enemy enemy = this.Enemies.Iterate().FirstOrDefault(v => v is Enemy_スタート地点 && ((Enemy_スタート地点)v).Direction == this.Status.StartPointDirection);

                if (enemy != null)
                {
                    this.Player.X = enemy.X;
                    this.Player.Y = enemy.Y;
                }
            }

            // ★★★★★
            // プレイヤー・ステータス反映(マップ入場時)
            // その他の反映箇所:
            // -- マップ退場時
            // -- セーブ時
            {
                this.Player.HP         = this.Status.StartHP;
                this.Player.FacingLeft = this.Status.StartFacingLeft;
                this.Player.武器         = this.Status.Start_武器;
            }

            this.Wall = WallCreator.Create(this.Map.WallName);

            MusicCollection.Get(this.Map.MusicName).Play();

            DDGround.Camera.X = this.Player.X - DDConsts.Screen_W / 2.0;
            DDGround.Camera.Y = this.Player.Y - DDConsts.Screen_H / 2.0;

            DDCurtain.SetCurtain(0, -1.0);
            DDCurtain.SetCurtain(10);

            DDEngine.FreezeInput();

            for (this.Frame = 0; ; this.Frame++)
            {
                if (!this.UserInputDisabled && DDInput.PAUSE.GetInput() == 1)
                {
                    this.Pause();

                    if (this.Pause_ReturnToTitleMenu)
                    {
                        this.Status.ExitDirection = 5;
                        break;
                    }
                }
                if (DDConfig.LOG_ENABLED && DDKey.GetInput(DX.KEY_INPUT_RETURN) == 1)
                {
                    this.DebugPause();
                }

                // 死亡時にカメラ移動を止める。
                //if (this.Player.DeadFrame == 0)
                //    this.カメラ位置調整(false);

                this.カメラ位置調整(false);

                if (DDConfig.LOG_ENABLED && DDKey.GetInput(DX.KEY_INPUT_E) == 1)                 // エディットモード(デバッグ用)
                {
                    this.Edit();
                    this.ReloadEnemies();
                    this.Frame = 0;
                }

                // プレイヤー入力
                {
                    bool deadOrDamageOrUID = 1 <= this.Player.DeadFrame || 1 <= this.Player.DamageFrame || this.UserInputDisabled;
                    bool move     = false;
                    bool slow     = false;
                    bool camSlide = false;
                    int  jump     = 0;
                    bool shagami  = false;
                    bool attack   = false;

                    if (!deadOrDamageOrUID && 1 <= DDInput.DIR_2.GetInput() || this.PlayerHacker.DIR_2)
                    {
                        shagami = true;
                    }

                    // 入力抑止中であるか否かに関わらず左右の入力は受け付ける様にする。
                    int freezeInputFrameBackup = DDEngine.FreezeInputFrame;
                    DDEngine.FreezeInputFrame = 0;

                    if (!deadOrDamageOrUID && 1 <= DDInput.DIR_4.GetInput() || this.PlayerHacker.DIR_4)
                    {
                        this.Player.FacingLeft = true;
                        move = true;
                    }
                    if (!deadOrDamageOrUID && 1 <= DDInput.DIR_6.GetInput() || this.PlayerHacker.DIR_6)
                    {
                        this.Player.FacingLeft = false;
                        move = true;
                    }

                    DDEngine.FreezeInputFrame = freezeInputFrameBackup;                     // restore

                    if (1 <= DDInput.L.GetInput())
                    {
                        move     = false;
                        shagami  = false;
                        camSlide = true;
                    }
                    if (!deadOrDamageOrUID && 1 <= DDInput.R.GetInput() || this.PlayerHacker.Slow)
                    {
                        slow = true;
                    }
                    if (!deadOrDamageOrUID && 1 <= DDInput.A.GetInput())
                    {
                        jump = DDInput.A.GetInput();
                    }
                    if (this.PlayerHacker.Jump != 0)
                    {
                        jump = this.PlayerHacker.Jump;
                    }
                    if (!deadOrDamageOrUID && 1 <= DDInput.B.GetInput() || this.PlayerHacker.Attack)
                    {
                        attack = true;
                    }

                    if (move)
                    {
                        this.Player.MoveFrame++;
                        shagami = false;
                    }
                    else
                    {
                        this.Player.MoveFrame = 0;
                    }

                    this.Player.MoveSlow = move && slow;

                    if (1 <= this.Player.JumpFrame)
                    {
                        const int JUMP_FRAME_MAX = 22;

                        if (1 <= jump && this.Player.JumpFrame < JUMP_FRAME_MAX)
                        {
                            this.Player.JumpFrame++;
                        }
                        else
                        {
                            this.Player.JumpFrame = 0;
                        }
                    }
                    else
                    {
                        // 事前入力 == 着地前の数フレーム間にジャンプボタンを押し始めてもジャンプできるようにする。
                        // 入力猶予 == 落下(地面から離れた)直後の数フレーム間にジャンプボタンを押し始めてもジャンプできるようにする。

                        const int 事前入力時間 = 5;
                        const int 入力猶予時間 = 5;

                        if (1 <= jump && jump < 事前入力時間 && this.Player.AirborneFrame < 入力猶予時間)
                        {
                            this.Player.JumpFrame = 1;
                        }
                    }

                    if (camSlide)
                    {
                        if (DDInput.DIR_4.IsPound())
                        {
                            this.CamSlideCount++;
                            this.CamSlideX--;
                        }
                        if (DDInput.DIR_6.IsPound())
                        {
                            this.CamSlideCount++;
                            this.CamSlideX++;
                        }
                        if (DDInput.DIR_8.IsPound())
                        {
                            this.CamSlideCount++;
                            this.CamSlideY--;
                        }
                        if (DDInput.DIR_2.IsPound())
                        {
                            this.CamSlideCount++;
                            this.CamSlideY++;
                        }
                        DDUtils.ToRange(ref this.CamSlideX, -1, 1);
                        DDUtils.ToRange(ref this.CamSlideY, -1, 1);
                    }
                    else
                    {
                        if (this.CamSlideMode && this.CamSlideCount == 0)
                        {
                            this.CamSlideX = 0;
                            this.CamSlideY = 0;
                        }
                        this.CamSlideCount = 0;
                    }
                    this.CamSlideMode = camSlide;

                    if (1 <= this.Player.AirborneFrame)
                    {
                        shagami = false;
                    }

                    if (shagami)
                    {
                        this.Player.ShagamiFrame++;
                    }
                    else
                    {
                        this.Player.ShagamiFrame = 0;
                    }

                    if (attack)
                    {
                        this.Player.AttackFrame++;
                    }
                    else
                    {
                        this.Player.AttackFrame = 0;
                    }
                }

                //startDead:
                if (1 <= this.Player.DeadFrame)                 // プレイヤー死亡中の処理
                {
                    int frame = this.Player.DeadFrame - 1;

                    if (GameConsts.PLAYER_DEAD_FRAME_MAX < frame)
                    {
                        this.Player.DeadFrame     = 0;
                        this.Status.ExitDirection = 5;
                        break;
                    }
                    this.Player.DeadFrame++;

                    // この時点でとりうる this.Player.DeadFrame の最大値は Consts.PLAYER_DEAD_FRAME_MAX + 2

                    // ----

                    const int HIT_BACK_FRAME_MAX = 30;

                    if (frame < HIT_BACK_FRAME_MAX)
                    {
                        double rate = (double)frame / HIT_BACK_FRAME_MAX;

                        this.Player.X -= 10.0 * (1.0 - rate) * (this.Player.FacingLeft ? -1 : 1);
                    }
                }
                //endDead:

                //startDamage:
                if (1 <= this.Player.DamageFrame)                 // プレイヤー・ダメージ中の処理
                {
                    int frame = this.Player.DamageFrame - 1;

                    if (GameConsts.PLAYER_DAMAGE_FRAME_MAX < frame)
                    {
                        this.Player.DamageFrame     = 0;
                        this.Player.InvincibleFrame = 1;
                        goto endDamage;
                    }
                    this.Player.DamageFrame++;

                    // この時点でとりうる this.Player.DamageFrame の最大値は Consts.PLAYER_DAMAGE_FRAME_MAX + 2

                    // ----

                    {
                        double rate = (double)frame / GameConsts.PLAYER_DAMAGE_FRAME_MAX;

                        this.Player.X -= (9.0 - 6.0 * rate) * (this.Player.FacingLeft ? -1 : 1);
                    }
                }
endDamage:

                //startInvincible:
                if (1 <= this.Player.InvincibleFrame)                 // プレイヤー無敵時間中の処理
                {
                    int frame = this.Player.InvincibleFrame - 1;

                    if (GameConsts.PLAYER_INVINCIBLE_FRAME_MAX < frame)
                    {
                        this.Player.InvincibleFrame = 0;
                        goto endInvincible;
                    }
                    this.Player.InvincibleFrame++;

                    // この時点でとりうる this.Player.InvincibleFrame の最大値は Consts.PLAYER_INVINCIBLE_FRAME_MAX + 2

                    // ----

                    // noop
                }
endInvincible:

                // プレイヤー移動
                {
                    if (1 <= this.Player.MoveFrame)
                    {
                        double speed = 0.0;

                        if (this.Player.MoveSlow)
                        {
                            speed = this.Player.MoveFrame * 0.2;
                            DDUtils.Minim(ref speed, 2.0);
                        }
                        else
                        {
                            speed = 6.0;
                        }

                        speed *= this.Player.FacingLeft ? -1 : 1;

                        this.Player.X += speed;
                    }
                    else
                    {
                        this.Player.X = (double)SCommon.ToInt(this.Player.X);
                    }

                    const double 重力加速度            = 1.0;
                    const double 落下最高速度           = 8.0;
                    const double ジャンプによる上昇_YSpeed = -8.0;

                    if (1 <= this.Player.JumpFrame)
                    {
                        this.Player.YSpeed = ジャンプによる上昇_YSpeed;
                    }
                    else
                    {
                        this.Player.YSpeed += 重力加速度;
                    }

                    DDUtils.Minim(ref this.Player.YSpeed, 落下最高速度);

                    this.Player.Y += this.Player.YSpeed;                     // 自由落下
                }

                // 上昇が速すぎると、脳天判定より先に側面判定に引っ掛かってしまう可能性がある。
                // -- ( -(ジャンプによる上昇_YSpeed) < 脳天判定Pt_Y - 側面判定Pt_Y ) を維持すること。
                // 下降が速すぎると、接地判定より先に側面判定に引っ掛かってしまう可能性がある。
                // -- ( 落下最高速度 < 接地判定Pt_Y - 側面判定Pt_Y ) を維持すること。

                // プレイヤー位置矯正
                {
                    const double 側面判定Pt_X = 10.0;
                    const double 側面判定Pt_Y = GameConsts.TILE_H / 2.0;

                    bool touchSide_L =
                        this.Map.GetCell(GameCommon.ToTablePoint(this.Player.X - 側面判定Pt_X, this.Player.Y - 側面判定Pt_Y)).Tile.IsWall() ||
                        this.Map.GetCell(GameCommon.ToTablePoint(this.Player.X - 側面判定Pt_X, this.Player.Y)).Tile.IsWall() ||
                        this.Map.GetCell(GameCommon.ToTablePoint(this.Player.X - 側面判定Pt_X, this.Player.Y + 側面判定Pt_Y)).Tile.IsWall();

                    bool touchSide_R =
                        this.Map.GetCell(GameCommon.ToTablePoint(this.Player.X + 側面判定Pt_X, this.Player.Y - 側面判定Pt_Y)).Tile.IsWall() ||
                        this.Map.GetCell(GameCommon.ToTablePoint(this.Player.X + 側面判定Pt_X, this.Player.Y)).Tile.IsWall() ||
                        this.Map.GetCell(GameCommon.ToTablePoint(this.Player.X + 側面判定Pt_X, this.Player.Y + 側面判定Pt_Y)).Tile.IsWall();

                    if (touchSide_L && touchSide_R)
                    {
                        // noop
                    }
                    else if (touchSide_L)
                    {
                        this.Player.X = (double)SCommon.ToInt(this.Player.X / GameConsts.TILE_W) * GameConsts.TILE_W + 側面判定Pt_X;
                    }
                    else if (touchSide_R)
                    {
                        this.Player.X = (double)SCommon.ToInt(this.Player.X / GameConsts.TILE_W) * GameConsts.TILE_W - 側面判定Pt_X;
                    }

                    const double 脳天判定Pt_X = 9.0;
                    const double 脳天判定Pt_Y = GameConsts.TILE_H;

                    bool touchCeiling_L =
                        this.Map.GetCell(GameCommon.ToTablePoint(this.Player.X - 脳天判定Pt_X, this.Player.Y - 脳天判定Pt_Y)).Tile.IsWall();

                    bool touchCeiling_R =
                        this.Map.GetCell(GameCommon.ToTablePoint(this.Player.X + 脳天判定Pt_X, this.Player.Y - 脳天判定Pt_Y)).Tile.IsWall();

                    if (touchCeiling_L && touchCeiling_R)
                    {
                        if (this.Player.YSpeed < 0.0)
                        {
                            double plY = ((int)((this.Player.Y - 脳天判定Pt_Y) / GameConsts.TILE_H) + 1) * GameConsts.TILE_H + 脳天判定Pt_Y;

                            this.Player.Y         = plY;
                            this.Player.YSpeed    = 0.0;
                            this.Player.JumpFrame = 0;
                        }
                    }
                    else if (touchCeiling_L)
                    {
                        this.Player.X = (double)SCommon.ToInt(this.Player.X / GameConsts.TILE_W) * GameConsts.TILE_W + 脳天判定Pt_X;
                    }
                    else if (touchCeiling_R)
                    {
                        this.Player.X = (double)SCommon.ToInt(this.Player.X / GameConsts.TILE_W) * GameConsts.TILE_W - 脳天判定Pt_X;
                    }

                    const double 接地判定Pt_X = 9.0;
                    const double 接地判定Pt_Y = GameConsts.TILE_H;

                    bool touchGround =
                        this.Map.GetCell(GameCommon.ToTablePoint(this.Player.X - 接地判定Pt_X, this.Player.Y + 接地判定Pt_Y)).Tile.IsWall() ||
                        this.Map.GetCell(GameCommon.ToTablePoint(this.Player.X + 接地判定Pt_X, this.Player.Y + 接地判定Pt_Y)).Tile.IsWall();

                    if (touchGround)
                    {
                        if (0.0 < this.Player.YSpeed)
                        {
                            double plY = (int)((this.Player.Y + 接地判定Pt_Y) / GameConsts.TILE_H) * GameConsts.TILE_H - 接地判定Pt_Y;

                            this.Player.Y      = plY;
                            this.Player.YSpeed = 0.0;
                        }
                    }

                    if (touchGround)
                    {
                        this.Player.AirborneFrame = 0;
                    }
                    else
                    {
                        this.Player.AirborneFrame++;
                    }
                }
                //endPlayer:

                if (this.Player.X < 0.0)                 // ? マップの左側に出た。
                {
                    this.Status.ExitDirection = 4;
                    break;
                }
                if (this.Map.W * GameConsts.TILE_W < this.Player.X)                 // ? マップの右側に出た。
                {
                    this.Status.ExitDirection = 6;
                    break;
                }
                if (this.Player.Y < 0.0)                 // ? マップの上側に出た。
                {
                    this.Status.ExitDirection = 8;
                    break;
                }
                if (this.Map.H * GameConsts.TILE_H < this.Player.Y)                 // ? マップの下側に出た。
                {
                    this.Status.ExitDirection = 2;
                    break;
                }

                // 画面遷移時の微妙なカメラ位置ズレ解消
                // -- スタート地点(入場地点)が地面と接していると、最初のフレームでプレイヤーは上に押し出されてカメラの初期位置とズレてしまう。
                if (this.Frame == 0 || this.次のカメラ位置調整を一瞬で)
                {
                    this.次のカメラ位置調整を一瞬で = false;
                    this.カメラ位置調整(true);
                }

                if (1 <= this.Player.AttackFrame)
                {
                    this.Player.Attack();
                }

                DDCrash plCrash = DDCrashUtils.Point(new D2Point(this.Player.X, this.Player.Y + (1 <= this.Player.ShagamiFrame ? 16 : 0)));

                // ====
                // 描画ここから
                // ====

                this.DrawWall();
                this.DrawMap();
                this.Player.Draw();

                // memo: DeadFlag をチェックするのは「当たり判定」から

                foreach (Enemy enemy in this.Enemies.Iterate())
                {
                    enemy.Crash = DDCrashUtils.None();                     // reset
                    enemy.Draw();
                }
                foreach (Shot shot in this.Shots.Iterate())
                {
                    shot.Crash = DDCrashUtils.None();                     // reset
                    shot.Draw();
                }

                if (this.当たり判定表示)
                {
                    // 最後に描画されるように DDGround.EL.Add() する。

                    DDGround.EL.Add(() =>
                    {
                        DDCurtain.DrawCurtain(-0.7);

                        const double A = 0.7;

                        DDCrashView.Draw(new DDCrash[] { plCrash }, new I3Color(255, 0, 0), 1.0);
                        DDCrashView.Draw(this.Enemies.Iterate().Select(v => v.Crash), new I3Color(255, 255, 255), A);
                        DDCrashView.Draw(this.Shots.Iterate().Select(v => v.Crash), new I3Color(0, 255, 255), A);

                        return(false);
                    });
                }

                // ====
                // 描画ここまで
                // ====

                // ====
                // 当たり判定ここから
                // ====

                foreach (Enemy enemy in this.Enemies.Iterate())
                {
                    if (1 <= enemy.HP)                     // ? 敵:生存 && 無敵ではない
                    {
                        foreach (Shot shot in this.Shots.Iterate())
                        {
                            // 衝突判定:敵 x 自弾
                            if (
                                !shot.DeadFlag &&                                 // ? 自弾:生存
                                enemy.Crash.IsCrashed(shot.Crash)                 // ? 衝突
                                )
                            {
                                // ★ 敵_被弾ここから

                                if (!shot.敵を貫通する)
                                {
                                    shot.Kill();
                                }

                                enemy.HP -= shot.AttackPoint;

                                if (1 <= enemy.HP)                                 // ? まだ生存している。
                                {
                                    enemy.Damaged(shot);
                                }
                                else                                 // ? 撃破した。
                                {
                                    enemy.Kill(true);
                                    break;                                     // この敵は死亡したので、この敵について以降の当たり判定は不要
                                }

                                // ★ 敵_被弾ここまで
                            }
                        }
                    }

                    // 衝突判定:敵 x 自機
                    if (
                        this.Player.DeadFrame == 0 &&                // ? プレイヤー死亡中ではない。
                        this.Player.DamageFrame == 0 &&              // ? プレイヤー・ダメージ中ではない。
                        this.Player.InvincibleFrame == 0 &&          // ? プレイヤー無敵時間中ではない。
                        !enemy.DeadFlag &&                           // ? 敵:生存
                        DDCrashUtils.IsCrashed(enemy.Crash, plCrash) // ? 衝突
                        )
                    {
                        // ★ 自機_被弾ここから

                        if (enemy.自機に当たると消滅する)
                        {
                            enemy.Kill();
                        }

                        this.Player.HP -= enemy.AttackPoint;

                        if (1 <= this.Player.HP)                         // ? まだ生存している。
                        {
                            this.Player.DamageFrame = 1;
                        }
                        else                         // ? 死亡した。
                        {
                            this.Player.HP        = -1;
                            this.Player.DeadFrame = 1;
                        }

                        // ★ 自機_被弾ここまで
                    }
                }

                foreach (Shot shot in this.Shots.Iterate())
                {
                    // 壁への当たり判定は自弾の「中心座標のみ」であることに注意して下さい。

                    if (
                        !shot.DeadFlag &&                                                       // ? 自弾:生存
                        !shot.壁をすり抜ける &&                                                        // ? この自弾は壁に当たる。
                        this.Map.GetCell(GameCommon.ToTablePoint(shot.X, shot.Y)).Tile.IsWall() // ? 壁に当たった。
                        )
                    {
                        shot.Kill();
                    }
                }

                // ====
                // 当たり判定ここまで
                // ====

                f_ゴミ回収();

                this.Enemies.RemoveAll(v => v.DeadFlag);
                this.Shots.RemoveAll(v => v.DeadFlag);

                DDEngine.EachFrame();

                // ★★★ ゲームループの終わり ★★★
            }
            DDEngine.FreezeInput();

            if (this.Status.ExitDirection == 5)
            {
                DDMusicUtils.Fade();
                DDCurtain.SetCurtain(30, -1.0);

                foreach (DDScene scene in DDSceneUtils.Create(40))
                {
                    this.DrawWall();
                    this.DrawMap();

                    DDEngine.EachFrame();
                }
            }
            else
            {
                double destSlide_X = 0.0;
                double destSlide_Y = 0.0;

                switch (this.Status.ExitDirection)
                {
                case 4:
                    destSlide_X = DDConsts.Screen_W;
                    break;

                case 6:
                    destSlide_X = -DDConsts.Screen_W;
                    break;

                case 8:
                    destSlide_Y = DDConsts.Screen_H;
                    break;

                case 2:
                    destSlide_Y = -DDConsts.Screen_H;
                    break;

                default:
                    throw null;                             // never
                }
                using (DDSubScreen wallMapScreen = new DDSubScreen(DDConsts.Screen_W, DDConsts.Screen_H))
                {
                    using (wallMapScreen.Section())
                    {
                        this.DrawWall();
                        this.DrawMap();
                    }
                    foreach (DDScene scene in DDSceneUtils.Create(30))
                    {
                        double slide_X = destSlide_X * scene.Rate;
                        double slide_Y = destSlide_Y * scene.Rate;

                        DDCurtain.DrawCurtain();
                        DDDraw.DrawSimple(wallMapScreen.ToPicture(), slide_X, slide_Y);

                        DDEngine.EachFrame();
                    }
                }
                DDCurtain.SetCurtain(0, -1.0);
            }

            // ★★★★★
            // プレイヤー・ステータス反映(マップ退場時)
            // その他の反映箇所:
            // -- マップ入場時
            // -- セーブ時
            {
                this.Status.StartHP         = this.Player.HP;
                this.Status.StartFacingLeft = this.Player.FacingLeft;
                this.Status.Start_武器        = this.Player.武器;
            }

            // ★★★ end of Perform() ★★★
        }
Example #6
0
        public void Perform()
        {
            DDCurtain.SetCurtain(0, -1.0);
            DDCurtain.SetCurtain();

            DDEngine.FreezeInput();

            Ground.I.Music.Title.Play();

            this.SimpleMenu = new DDSimpleMenu();

            this.SimpleMenu.BorderColor = new I3Color(0, 96, 192);
            this.SimpleMenu.WallDrawer  = this.DrawWall.Execute;

            for (; ;)
            {
                if (DDInput.DIR_8.IsPound())
                {
                    this.TopMenu.SelectIndex--;
                }

                if (DDInput.DIR_2.IsPound())
                {
                    this.TopMenu.SelectIndex++;
                }

                this.TopMenu.SelectIndex += TopMenuTask.ITEM_NUM;
                this.TopMenu.SelectIndex %= TopMenuTask.ITEM_NUM;

                if (DDConfig.LOG_ENABLED && DDKey.GetInput(DX.KEY_INPUT_Q) == 1)                 // (開発デバッグ用)ロック解除
                {
                    Ground.I.ReachedStageIndex = 10;
                }
                if (DDInput.A.GetInput() == 1)                 // ? 決定ボタン押下
                {
                    switch (this.TopMenu.SelectIndex)
                    {
                    case 0:
                        if (DDConfig.LOG_ENABLED && 1 <= DDInput.DIR_6.GetInput())
                        {
                            this.DrawWall.TopMenuLeaved = true;
                            this.CheatMainMenu();
                            this.DrawWall.TopMenuLeaved = false;
                        }
                        else
                        {
                            this.LeaveTitleMenu();

                            using (new GameProgressMaster())
                            {
                                GameProgressMaster.I.StartStageIndex = 1;
                                GameProgressMaster.I.Perform();
                            }
                            this.ReturnTitleMenu();
                        }
                        break;

                    case 1:
                        this.DrawWall.TopMenuLeaved = true;
                        this.SelectStage();
                        this.DrawWall.TopMenuLeaved = false;
                        break;

                    case 2:
                        this.DrawWall.TopMenuLeaved = true;
                        this.Setting();
                        this.DrawWall.TopMenuLeaved = false;
                        break;

                    case 3:
                        goto endMenu;

                    default:
                        throw new DDError();
                    }
                }
                if (DDInput.B.GetInput() == 1)                 // ? キャンセルボタン押下
                {
                    if (this.TopMenu.SelectIndex == TopMenuTask.ITEM_NUM - 1)
                    {
                        break;
                    }

                    this.TopMenu.SelectIndex = TopMenuTask.ITEM_NUM - 1;
                }

                this.DrawWall.Execute();
                this.TopMenu.Execute();

                DDEngine.EachFrame();
            }
endMenu:
            DDMusicUtils.Fade();
            DDCurtain.SetCurtain(30, -1.0);

            foreach (DDScene scene in DDSceneUtils.Create(40))
            {
                //this.SimpleMenu.DrawWall();
                this.DrawWall.Execute();

                DDEngine.EachFrame();
            }

            DDEngine.FreezeInput();
        }
Example #7
0
		public void Perform()
		{
			Func<bool> f_ゴミ回収 = SCommon.Supplier(this.E_ゴミ回収());

			this.Map = new Map(GameCommon.GetMapFile(this.World.GetCurrMapName()));
			this.ReloadEnemies();

			// デフォルトの「プレイヤーのスタート地点」
			// -- マップの中央
			this.Player.X = this.Map.W * GameConsts.TILE_W / 2.0;
			this.Player.Y = this.Map.H * GameConsts.TILE_H / 2.0;

			{
				Enemy enemy = this.Enemies.Iterate().FirstOrDefault(v => v is Enemy_スタート地点 && ((Enemy_スタート地点)v).Direction == this.Status.StartPointDirection);

				if (enemy != null)
				{
					this.Player.X = enemy.X;
					this.Player.Y = enemy.Y;
				}
			}

			// ★★★★★
			// プレイヤー・ステータス反映(マップ入場時)
			// その他の反映箇所:
			// -- マップ退場時
			// -- セーブ時
			{
				this.Player.Chara = this.Status.StartChara;
				this.Player.HP = this.Status.StartHP;
				this.Player.FacingLeft = this.Status.StartFacingLeft;
			}

			this.Wall = WallCreator.Create(this.Map.WallName);

			MusicCollection.Get(this.Map.MusicName).Play();

			DDGround.Camera.X = this.Player.X - DDConsts.Screen_W / 2.0;
			DDGround.Camera.Y = this.Player.Y - DDConsts.Screen_H / 2.0;

			DDCurtain.SetCurtain(0, -1.0);
			DDCurtain.SetCurtain(10);

			DDEngine.FreezeInput();

			for (this.Frame = 0; ; this.Frame++)
			{
				// Attack_ほむらシールド 終了から Shot_ほむらシールド の PlayerTracer.Start 実行の間に
				// ポーズできるタイミングは無いはずだけど、曲芸的で気持ち悪い。

				if (
					!this.UserInputDisabled &&
					//Game.I.Player.Attack == null && // ? プレイヤーの攻撃モーション中ではない。// モーション中でも良いはず!
					DDInput.PAUSE.GetInput() == 1
					)
				{
					this.Pause();

					if (this.Pause_ReturnToTitleMenu)
					{
						this.Status.ExitDirection = 5;
						break;
					}
				}
				if (this.RequestReturnToTitleMenu)
				{
					this.Status.ExitDirection = 5;
					break;
				}
				if (DDConfig.LOG_ENABLED && DDKey.GetInput(DX.KEY_INPUT_RETURN) == 1)
				{
					this.DebugPause();
				}

				// 死亡時にカメラ移動を止める。
				//if (this.Player.DeadFrame == 0)
				//    this.カメラ位置調整(false);

				this.カメラ位置調整(false);

				if (DDConfig.LOG_ENABLED && DDKey.GetInput(DX.KEY_INPUT_E) == 1) // エディットモード(デバッグ用)
				{
					this.Edit();
					this.ReloadEnemies();
					this.Frame = 0;
				}

				if (this.Player.Attack != null) // プレイヤー攻撃中
				{
					if (this.Player.Attack.EachFrame()) // ? このプレイヤー攻撃を継続する。
						goto endPlayer;

					this.Player.Attack = null; // プレイヤー攻撃_終了
				}

				// プレイヤー入力
				{
					bool deadOrDamageOrUID = 1 <= this.Player.DeadFrame || 1 <= this.Player.DamageFrame || this.UserInputDisabled;
					bool move = false;
					bool slow = false;
					bool camSlide = false;
					int jump = 0;
					bool shagami = false;
					int attack = 0;
					int extendedAttack = 0;

					if (!deadOrDamageOrUID && 1 <= DDInput.DIR_2.GetInput())
					{
						shagami = true;
					}

					// 入力抑止中であるか否かに関わらず左右の入力は受け付ける様にする。
					int freezeInputFrameBackup = DDEngine.FreezeInputFrame;
					DDEngine.FreezeInputFrame = 0;

					if (!deadOrDamageOrUID && 1 <= DDInput.DIR_4.GetInput())
					{
						this.Player.FacingLeft = true;
						move = true;
					}
					if (!deadOrDamageOrUID && 1 <= DDInput.DIR_6.GetInput())
					{
						this.Player.FacingLeft = false;
						move = true;
					}

					DDEngine.FreezeInputFrame = freezeInputFrameBackup; // restore

					if (1 <= DDInput.L.GetInput())
					{
						move = false;
						camSlide = true;
					}
					if (!deadOrDamageOrUID && 1 <= DDInput.R.GetInput())
					{
						slow = true;
					}
					if (!deadOrDamageOrUID && 1 <= DDInput.A.GetInput())
					{
						jump = DDInput.A.GetInput();
					}
					if (!deadOrDamageOrUID && 1 <= DDInput.B.GetInput())
					{
						attack = DDInput.B.GetInput();
					}
					if (!deadOrDamageOrUID && 1 <= DDInput.C.GetInput())
					{
						extendedAttack = DDInput.C.GetInput();
					}

					if (move)
					{
						this.Player.MoveFrame++;
						shagami = false;
					}
					else
						this.Player.MoveFrame = 0;

					this.Player.MoveSlow = move && slow;

					if (1 <= this.Player.JumpFrame)
					{
						if (1 <= jump)
						{
							this.Player.JumpFrame++;
						}
						else
						{
							// ★ ジャンプを中断・終了した。

							this.Player.JumpFrame = 0;

							if (this.Player.YSpeed < 0.0)
								this.Player.YSpeed /= 2.0;
						}
					}
					else
					{
						// 事前入力 == 着地前の数フレーム間にジャンプボタンを押し始めてもジャンプできるようにする。
						// 入力猶予 == 落下(地面から離れた)直後の数フレーム間にジャンプボタンを押し始めてもジャンプできるようにする。

						const int 事前入力時間 = 5;
						const int 入力猶予時間 = 10;

						if (this.Player.AirborneFrame < 入力猶予時間) // ? 接地状態からのジャンプが可能な状態
						{
							if (1 <= jump && jump < 事前入力時間)
							{
								// ★ ジャンプを開始した。

								this.Player.JumpFrame = 1;
								this.Player.JumpCount = 1;

								this.Player.YSpeed = GameConsts.PLAYER_ジャンプ初速度;
							}
							else
							{
								this.Player.JumpCount = 0;
							}
						}
						else // ? 接地状態からのジャンプが「可能ではない」状態
						{
							// 滞空状態に入ったら「通常ジャンプの状態」にする。
							if (this.Player.JumpCount < 1)
								this.Player.JumpCount = 1;

							if (1 <= jump && jump < 事前入力時間 && this.Player.JumpCount < GameConsts.JUMP_MAX)
							{
								// ★ 空中(n-段)ジャンプを開始した。

								this.Player.JumpFrame = 1;
								this.Player.JumpCount++;

								this.Player.YSpeed = GameConsts.PLAYER_ジャンプ初速度;

								DDGround.EL.Add(SCommon.Supplier(Effects.空中ジャンプの足場(this.Player.X, this.Player.Y + 48)));
							}
							else
							{
								// noop
							}
						}
					}

					if (camSlide)
					{
						if (DDInput.DIR_4.IsPound())
						{
							this.CamSlided = true;
							this.CamSlideX--;
						}
						if (DDInput.DIR_6.IsPound())
						{
							this.CamSlided = true;
							this.CamSlideX++;
						}
						if (DDInput.DIR_8.IsPound())
						{
							this.CamSlided = true;
							this.CamSlideY--;
						}
						if (DDInput.DIR_2.IsPound())
						{
							this.CamSlided = true;
							this.CamSlideY++;
						}
						DDUtils.ToRange(ref this.CamSlideX, -1, 1);
						DDUtils.ToRange(ref this.CamSlideY, -1, 1);
					}
					else
					{
						if (this.CamSlideMode && !this.CamSlided)
						{
							this.CamSlideX = 0;
							this.CamSlideY = 0;
						}
						this.CamSlided = false;
					}
					this.CamSlideMode = camSlide;

					if (this.Player.AirborneFrame != 0) // ? 滞空状態
						shagami = false;

					if (shagami)
						this.Player.ShagamiFrame++;
					else
						this.Player.ShagamiFrame = 0;

					{
						const int 事前入力時間 = 2; // 無効
						//const int 事前入力時間 = 5;
						//const int 事前入力時間 = 10; // HACK: ちょっと長すぎるかもしれない。無効でも良いかもしれない。// 暴発があるので事前入力は無効にする。

						if (1 <= attack && attack < 事前入力時間)
						{
							switch (this.Player.Chara)
							{
								case Player.Chara_e.HOMURA:
									{
										if (this.Player.AirborneFrame == 0)
											this.Player.Attack = new Attack_ほむら接地攻撃();
										else
											this.Player.Attack = new Attack_ほむら滞空攻撃();
									}
									break;

								case Player.Chara_e.SAYAKA:
									{
										if (this.Player.AirborneFrame == 0)
											this.Player.Attack = new Attack_さやか接地攻撃();
										else
											this.Player.Attack = new Attack_さやか滞空攻撃();
									}
									break;

								default:
									throw null; // never
							}
						}
						if (1 <= extendedAttack && extendedAttack < 事前入力時間)
						{
							switch (this.Player.Chara)
							{
								case Player.Chara_e.HOMURA:
									{
										if (this.Player.AirborneFrame == 0)
											this.Player.Attack = new Attack_ほむらシールド();
									}
									break;

								case Player.Chara_e.SAYAKA:
									{
										this.Player.Attack = new Attack_さやか突き();
									}
									break;

								default:
									throw null; // never
							}
						}
					}
				}

			startDead:
				if (1 <= this.Player.DeadFrame) // プレイヤー死亡中の処理
				{
					if (GameConsts.PLAYER_DEAD_FRAME_MAX < ++this.Player.DeadFrame)
					{
						this.Player.DeadFrame = 0;
						this.Status.ExitDirection = 5;
						break;
					}
					int frame = this.Player.DeadFrame; // 値域 == 2 ~ GameConsts.PLAYER_DEAD_FRAME_MAX
					double rate = DDUtils.RateAToB(2, GameConsts.PLAYER_DEAD_FRAME_MAX, frame);

					// ---- Dead

					// noop
				}
				//endDead:

				//startDamage:
				if (1 <= this.Player.DamageFrame) // プレイヤー・ダメージ中の処理
				{
					if (GameConsts.PLAYER_DAMAGE_FRAME_MAX < ++this.Player.DamageFrame)
					{
						this.Player.DamageFrame = 0;

						if (1 <= this.Player.HP)
						{
							this.Player.InvincibleFrame = 1;
							goto endDamage;
						}
						else
						{
							this.Player.DeadFrame = 1;
							goto startDead;
						}
					}
					int frame = this.Player.DamageFrame; // 値域 == 2 ~ GameConsts.PLAYER_DAMAGE_FRAME_MAX
					double rate = DDUtils.RateAToB(2, GameConsts.PLAYER_DAMAGE_FRAME_MAX, frame);

					// ---- Damage

					this.Player.X -= (9.0 - 6.0 * rate) * (this.Player.FacingLeft ? -1 : 1);
				}
			endDamage:

				//startInvincible:
				if (1 <= this.Player.InvincibleFrame) // プレイヤー無敵時間中の処理
				{
					if (GameConsts.PLAYER_INVINCIBLE_FRAME_MAX < ++this.Player.InvincibleFrame)
					{
						this.Player.InvincibleFrame = 0;
						goto endInvincible;
					}
					int frame = this.Player.InvincibleFrame; // 値域 == 2 ~ GameConsts.PLAYER_INVINCIBLE_FRAME_MAX
					double rate = DDUtils.RateAToB(2, GameConsts.PLAYER_INVINCIBLE_FRAME_MAX, frame);

					// ---- Invincible

					// noop
				}
			endInvincible:

				// プレイヤー移動
				{
					if (1 <= this.Player.MoveFrame)
					{
						double speed = 0.0;

						if (this.Player.MoveSlow)
						{
							speed = this.Player.MoveFrame / 10.0;
							DDUtils.Minim(ref speed, GameConsts.PLAYER_SLOW_SPEED);
						}
						else
							speed = GameConsts.PLAYER_SPEED;

						speed *= this.Player.FacingLeft ? -1 : 1;

						this.Player.X += speed;
					}
					else
						this.Player.X = (double)SCommon.ToInt(this.Player.X);

					// 重力による加速
					this.Player.YSpeed += GameConsts.PLAYER_GRAVITY;

					// 自由落下の最高速度を超えないように矯正
					DDUtils.Minim(ref this.Player.YSpeed, GameConsts.PLAYER_FALL_SPEED_MAX);

					// 自由落下
					this.Player.Y += this.Player.YSpeed;
				}

				// プレイヤー位置矯正
				{
					bool touchSide_L =
						this.Map.GetCell(GameCommon.ToTablePoint(this.Player.X - GameConsts.PLAYER_側面判定Pt_X, this.Player.Y - GameConsts.PLAYER_側面判定Pt_Y)).Tile.IsWall() ||
						this.Map.GetCell(GameCommon.ToTablePoint(this.Player.X - GameConsts.PLAYER_側面判定Pt_X, this.Player.Y)).Tile.IsWall() ||
						this.Map.GetCell(GameCommon.ToTablePoint(this.Player.X - GameConsts.PLAYER_側面判定Pt_X, this.Player.Y + GameConsts.PLAYER_側面判定Pt_Y)).Tile.IsWall();

					bool touchSide_R =
						this.Map.GetCell(GameCommon.ToTablePoint(this.Player.X + GameConsts.PLAYER_側面判定Pt_X, this.Player.Y - GameConsts.PLAYER_側面判定Pt_Y)).Tile.IsWall() ||
						this.Map.GetCell(GameCommon.ToTablePoint(this.Player.X + GameConsts.PLAYER_側面判定Pt_X, this.Player.Y)).Tile.IsWall() ||
						this.Map.GetCell(GameCommon.ToTablePoint(this.Player.X + GameConsts.PLAYER_側面判定Pt_X, this.Player.Y + GameConsts.PLAYER_側面判定Pt_Y)).Tile.IsWall();

					if (touchSide_L && touchSide_R) // -> 壁抜け防止のため再チェック
					{
						touchSide_L = this.Map.GetCell(GameCommon.ToTablePoint(this.Player.X - GameConsts.PLAYER_側面判定Pt_X, this.Player.Y)).Tile.IsWall();
						touchSide_R = this.Map.GetCell(GameCommon.ToTablePoint(this.Player.X + GameConsts.PLAYER_側面判定Pt_X, this.Player.Y)).Tile.IsWall();
					}

					if (touchSide_L && touchSide_R)
					{
						// noop
					}
					else if (touchSide_L)
					{
						this.Player.X = (double)SCommon.ToInt(this.Player.X / GameConsts.TILE_W) * GameConsts.TILE_W + GameConsts.PLAYER_側面判定Pt_X;
					}
					else if (touchSide_R)
					{
						this.Player.X = (double)SCommon.ToInt(this.Player.X / GameConsts.TILE_W) * GameConsts.TILE_W - GameConsts.PLAYER_側面判定Pt_X;
					}

					bool touchCeiling =
						this.Map.GetCell(GameCommon.ToTablePoint(this.Player.X - GameConsts.PLAYER_脳天判定Pt_X, this.Player.Y - GameConsts.PLAYER_脳天判定Pt_Y)).Tile.IsWall() ||
						this.Map.GetCell(GameCommon.ToTablePoint(this.Player.X + GameConsts.PLAYER_脳天判定Pt_X, this.Player.Y - GameConsts.PLAYER_脳天判定Pt_Y)).Tile.IsWall();

					if (touchCeiling)
					{
						if (this.Player.YSpeed < 0.0)
						{
							double plY = ((int)((this.Player.Y - GameConsts.PLAYER_脳天判定Pt_Y) / GameConsts.TILE_H) + 1) * GameConsts.TILE_H + GameConsts.PLAYER_脳天判定Pt_Y;

							this.Player.Y = plY;
							this.Player.YSpeed = 0.0;
						}
					}

					bool touchGround =
						this.Map.GetCell(GameCommon.ToTablePoint(this.Player.X - GameConsts.PLAYER_接地判定Pt_X, this.Player.Y + GameConsts.PLAYER_接地判定Pt_Y)).Tile.IsWall() ||
						this.Map.GetCell(GameCommon.ToTablePoint(this.Player.X + GameConsts.PLAYER_接地判定Pt_X, this.Player.Y + GameConsts.PLAYER_接地判定Pt_Y)).Tile.IsWall();

					if (touchGround)
					{
						if (0.0 < this.Player.YSpeed)
						{
							double plY = (int)((this.Player.Y + GameConsts.PLAYER_接地判定Pt_Y) / GameConsts.TILE_H) * GameConsts.TILE_H - GameConsts.PLAYER_接地判定Pt_Y;

							this.Player.Y = plY;
							this.Player.YSpeed = 0.0;
						}
					}

					if (touchGround)
						this.Player.AirborneFrame = 0;
					else
						this.Player.AirborneFrame++;
				}
			endPlayer:

				if (this.Player.X < 0.0) // ? マップの左側に出た。
				{
					this.Status.ExitDirection = 4;
					break;
				}
				if (this.Map.W * GameConsts.TILE_W < this.Player.X) // ? マップの右側に出た。
				{
					this.Status.ExitDirection = 6;
					break;
				}
				if (this.Player.Y < 0.0) // ? マップの上側に出た。
				{
					this.Status.ExitDirection = 8;
					break;
				}
				if (this.Map.H * GameConsts.TILE_H < this.Player.Y) // ? マップの下側に出た。
				{
					this.Status.ExitDirection = 2;
					break;
				}

				// 画面遷移時の微妙なカメラ位置ズレ解消
				// -- スタート地点(入場地点)が地面と接していると、最初のフレームでプレイヤーは上に押し出されてカメラの初期位置とズレてしまう。
				if (this.Frame == 0)
				{
					this.カメラ位置調整(true);
				}

				DDCrash plCrash = DDCrashUtils.Point(new D2Point(this.Player.X, this.Player.Y));

				// ====
				// 描画ここから
				// ====

				this.DrawWall();
				this.DrawMap();
				this.Player.Draw();

				// memo: DeadFlag をチェックするのは「当たり判定」から

				foreach (Enemy enemy in this.Enemies.Iterate())
				{
					enemy.Crash = DDCrashUtils.None(); // reset
					enemy.Draw();
				}
				foreach (Shot shot in this.Shots.Iterate())
				{
					shot.Crash = DDCrashUtils.None(); // reset
					shot.Draw();
				}

				if (this.当たり判定表示)
				{
					// 最後に描画されるように DDGround.EL.Add() する。

					DDGround.EL.Add(() =>
					{
						DDCurtain.DrawCurtain(-0.7);

						const double A = 0.7;

						DDCrashView.Draw(new DDCrash[] { plCrash }, new I3Color(255, 0, 0), 1.0);
						DDCrashView.Draw(this.Enemies.Iterate().Select(v => v.Crash), new I3Color(255, 255, 255), A);
						DDCrashView.Draw(this.Shots.Iterate().Select(v => v.Crash), new I3Color(0, 255, 255), A);

						return false;
					});
				}

				// ====
				// 描画ここまで
				// ====

				// ====
				// 当たり判定ここから
				// ====

				// ? 無敵な攻撃中 -> 敵 x 自機 の衝突判定を行わない。
				bool attackInvincibleMode =
					Game.I.Player.Attack != null &&
					Game.I.Player.Attack.IsInvincibleMode();

				foreach (Enemy enemy in this.Enemies.Iterate())
				{
					if (1 <= enemy.HP) // ? 敵:生存 && 無敵ではない
					{
						foreach (Shot shot in this.Shots.Iterate())
						{
							// 衝突判定:敵 x 自弾
							if (
								!shot.DeadFlag && // ? 自弾:生存
								enemy.Crash.IsCrashed(shot.Crash) // ? 衝突
								)
							{
								// ★ 敵_被弾ここから

								if (!shot.敵を貫通する)
									shot.Kill();

								enemy.HP -= shot.AttackPoint;

								if (1 <= enemy.HP) // ? まだ生存している。
								{
									enemy.Damaged(shot);
								}
								else // ? 撃破した。
								{
									enemy.Kill(true);
									break; // この敵は死亡したので、この敵について以降の当たり判定は不要
								}

								// ★ 敵_被弾ここまで
							}
						}
					}

					// 衝突判定:敵 x 自機
					if (
						this.Player.DeadFrame == 0 && // ? プレイヤー死亡中ではない。
						this.Player.DamageFrame == 0 && // ? プレイヤー・ダメージ中ではない。
						this.Player.InvincibleFrame == 0 && // ? プレイヤー無敵時間中ではない。
						!attackInvincibleMode && // 無敵になる攻撃中ではない。
						!enemy.DeadFlag && // ? 敵:生存
						DDCrashUtils.IsCrashed(enemy.Crash, plCrash) // ? 衝突
						)
					{
						// ★ 自機_被弾ここから

						if (enemy.自機に当たると消滅する)
							enemy.Kill();

						this.Player.HP -= enemy.AttackPoint;

						if (1 <= this.Player.HP) // ? まだ生存している。
						{
							this.Player.DamageFrame = 1;
						}
						else // ? 死亡した。
						{
							this.Player.HP = -1;
							//this.Player.DeadFrame = 1; // ヒットバックした後で死亡フレームを上げる。
							this.Player.DamageFrame = 1;
						}

						// ★ 自機_被弾ここまで
					}
				}

				foreach (Shot shot in this.Shots.Iterate())
				{
					// 壁への当たり判定は自弾の「中心座標のみ」であることに注意して下さい。

					if (
						!shot.DeadFlag && // ? 自弾:生存
						!shot.壁をすり抜ける && // ? この自弾は壁に当たる。
						this.Map.GetCell(GameCommon.ToTablePoint(shot.X, shot.Y)).Tile.IsWall() // ? 壁に当たった。
						)
						shot.Kill();
				}

				// ====
				// 当たり判定ここまで
				// ====

				f_ゴミ回収();

				this.Enemies.RemoveAll(v => v.DeadFlag);
				this.Shots.RemoveAll(v => v.DeadFlag);

				DDEngine.EachFrame();

				// ★★★ ゲームループの終わり ★★★
			}

			DDEngine.FreezeInput();

			if (this.Status.ExitDirection == 5)
			{
				DDMusicUtils.Fade();
				DDCurtain.SetCurtain(30, -1.0);

				foreach (DDScene scene in DDSceneUtils.Create(40))
				{
					this.DrawWall();
					this.DrawMap();

					DDEngine.EachFrame();
				}
			}
			else
			{
				double destSlide_X = 0.0;
				double destSlide_Y = 0.0;

				switch (this.Status.ExitDirection)
				{
					case 4:
						destSlide_X = DDConsts.Screen_W;
						break;

					case 6:
						destSlide_X = -DDConsts.Screen_W;
						break;

					case 8:
						destSlide_Y = DDConsts.Screen_H;
						break;

					case 2:
						destSlide_Y = -DDConsts.Screen_H;
						break;

					default:
						throw null; // never
				}
				using (DDSubScreen wallMapScreen = new DDSubScreen(DDConsts.Screen_W, DDConsts.Screen_H))
				{
					using (wallMapScreen.Section())
					{
						this.DrawWall();
						this.DrawMap();
					}
					foreach (DDScene scene in DDSceneUtils.Create(30))
					{
						double slide_X = destSlide_X * scene.Rate;
						double slide_Y = destSlide_Y * scene.Rate;

						DDCurtain.DrawCurtain();
						DDDraw.DrawSimple(wallMapScreen.ToPicture(), slide_X, slide_Y);

						DDEngine.EachFrame();
					}
				}
				DDCurtain.SetCurtain(0, -1.0);
			}

			// ★★★★★
			// プレイヤー・ステータス反映(マップ退場時)
			// その他の反映箇所:
			// -- マップ入場時
			// -- セーブ時
			{
				this.Status.StartChara = this.Player.Chara;
				this.Status.StartHP = this.Player.HP;
				this.Status.StartFacingLeft = this.Player.FacingLeft;
			}

			// ★★★ end of Perform() ★★★
		}