Пример #1
0
        private static string GetMeterString(int value, int minval, int maxval, int meterLen)
        {
            int indicatorPos;

            if (value == minval)
            {
                indicatorPos = 0;
            }
            else if (value == maxval)
            {
                indicatorPos = meterLen - 1;
            }
            else
            {
                indicatorPos = SCommon.ToRange(
                    SCommon.ToInt(DDUtils.RateAToB(minval, maxval, value) * (meterLen - 1)),
                    1,
                    meterLen - 2
                    );
            }

            StringBuilder buff = new StringBuilder();

            buff.Append("[");

            for (int index = 0; index < meterLen; index++)
            {
                buff.Append(index == indicatorPos ? "■" : "-");
            }

            buff.Append("] ");
            buff.Append(value);

            return(buff.ToString());
        }
Пример #2
0
        public override void Draw()
        {
            if (Game.I.FreezeEnemy)
            {
                goto startDraw;
            }

            this.IRot += this.IRotSpeed;

            this.IRot += IROT_360;
            this.IRot %= IROT_360;

startDraw:
            double rot = this.IRot * (Math.PI * 2.0) / IROT_360;

            double x = this.X + Math.Cos(rot) * R;
            double y = this.Y + Math.Sin(rot) * R;

            if (!EnemyCommon.IsOutOfScreen_ForDraw(new D2Point(x - DDGround.Camera.X, y - DDGround.Camera.Y)))
            {
                //DDDraw.SetBright(new I3Color(32, 192, 32)); // old
                DDDraw.SetBright(Game.I.Map.Design.EnemyColor_Cookie);
                DDDraw.DrawBegin(Ground.I.Picture.WhiteBox, SCommon.ToInt(x - DDGround.ICamera.X), SCommon.ToInt(y - DDGround.ICamera.Y));
                DDDraw.DrawSetSize(GameConsts.TILE_W, GameConsts.TILE_H);
                DDDraw.DrawEnd();
                DDDraw.Reset();

                this.Crash = DDCrashUtils.Rect_CenterSize(new D2Point(x, y), new D2Size(GameConsts.TILE_W, GameConsts.TILE_H));

                Game.I.タイル接近_敵描画_Points.Add(new D2Point(x, y));
            }
        }
Пример #3
0
        public static void Perform(ref double x, ref double y, Predicate <MapCell> isWall)
        {
            IsWall = isWall;

            // 整数化
            IX = SCommon.ToInt(x);
            IY = SCommon.ToInt(y);

            A2 = new Around(IX, IY, 2);
            A3 = new Around(IX, IY, 3);

            Touch = Touch_e.AIRBORNE;

            I2Point a2RelPtBk = A2.RelativePoint;

            Perform_A(false, false);

            if (
                a2RelPtBk.X != A2.RelativePoint.X ||
                a2RelPtBk.Y != A2.RelativePoint.Y
                )
            {
                x = A2.CenterPoint.X + A2.RelativePoint.X;
                y = A2.CenterPoint.Y + A2.RelativePoint.Y;
            }
        }
Пример #4
0
        public static void INIT()
        {
            if (File.Exists(DDConsts.ResourceFile))             // ? 外部リリース
            {
                ReleaseMode = true;
            }
            else if (Directory.Exists(DDConsts.ResourceDir_InternalRelease))             // ? 内部リリース
            {
                ResourceDir = DDConsts.ResourceDir_InternalRelease;
            }
            else             // ? 開発環境
            {
                ResourceDir = DDConsts.ResourceDir_DevEnv;
            }

            if (ReleaseMode)
            {
                List <ResInfo> resInfos = new List <ResInfo>();

                using (FileStream reader = new FileStream(DDConsts.ResourceFile, FileMode.Open, FileAccess.Read))
                {
                    while (reader.Position < reader.Length)
                    {
                        int size = SCommon.ToInt(SCommon.Read(reader, 4));

                        if (size < 0)
                        {
                            throw new DDError();
                        }

                        resInfos.Add(new ResInfo()
                        {
                            ResFile = DDConsts.ResourceFile,
                            Offset  = reader.Position,
                            Size    = size,
                        });

                        reader.Seek((long)size, SeekOrigin.Current);
                    }
                }
                string[] files = SCommon.TextToLines(SCommon.ENCODING_SJIS.GetString(LoadFile(resInfos[0])));

                if (files.Length != resInfos.Count)
                {
                    throw new DDError(files.Length + ", " + resInfos.Count);
                }

                for (int index = 1; index < files.Length; index++)
                {
                    string file = files[index];

                    if (File2ResInfo.ContainsKey(file))
                    {
                        throw new DDError(file);
                    }

                    File2ResInfo.Add(file, resInfos[index]);
                }
            }
        }
Пример #5
0
        private void カメラ位置調整(bool 一瞬で)
        {
            double targCamX = this.Player.X - DDConsts.Screen_W / 2 + (this.CamSlideX * DDConsts.Screen_W / 3);
            double targCamY = this.Player.Y - DDConsts.Screen_H / 2 + (this.CamSlideY * DDConsts.Screen_H / 3);

            DDUtils.ToRange(ref targCamX, 0.0, this.Map.W * GameConsts.TILE_W - DDConsts.Screen_W);
            DDUtils.ToRange(ref targCamY, 0.0, this.Map.H * GameConsts.TILE_H - DDConsts.Screen_H);

            // 不要
            //if (this.Map.W * GameConsts.TILE_W - DDConsts.Screen_W < GameConsts.TILE_W) // ? カメラの横の可動域が1タイルより狭い場合
            //    targCamX = (this.Map.W * GameConsts.TILE_W - DDConsts.Screen_W) / 2; // 中心に合わせる。

            if (this.Map.H * GameConsts.TILE_H - DDConsts.Screen_H < GameConsts.TILE_H)             // ? カメラの縦の可動域が1タイルより狭い場合
            {
                targCamY = (this.Map.H * GameConsts.TILE_H - DDConsts.Screen_H) / 2;                // 中心に合わせる。
            }
            DDUtils.Approach(ref DDGround.Camera.X, targCamX, 一瞬で ? 0.0 : 0.8);
            DDUtils.Approach(ref DDGround.Camera.Y, targCamY, 一瞬で ? 0.0 : 0.8);

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

            DDGround.ICamera.X = SCommon.ToInt(DDGround.Camera.X);
            DDGround.ICamera.Y = SCommon.ToInt(DDGround.Camera.Y);
        }
Пример #6
0
        private IEnumerable <bool> DrawString(int x, int y, string text, int frameMax = 600)
        {
            double b     = 0.0;
            double bTarg = 1.0;

            foreach (DDScene scene in DDSceneUtils.Create(frameMax))
            {
                if (scene.Numer == scene.Denom - 300)
                {
                    bTarg = 0.0;
                }

                DDUtils.Approach(ref b, bTarg, 0.99);

                I3Color color = new I3Color(
                    SCommon.ToInt(b * 255),
                    SCommon.ToInt(b * 255),
                    SCommon.ToInt(b * 255)
                    );

                DDFontUtils.DrawString(x, y, text, DDFontUtils.GetFont("03\u711a\u706b-Regular", 30), false, color);

                yield return(true);
            }
        }
Пример #7
0
        private bool IsInsideWall(double xa, double ya)
        {
            int x = SCommon.ToInt(this.X + xa) / GameConsts.TILE_W;
            int y = SCommon.ToInt(this.Y + ya) / GameConsts.TILE_H;

            return(Game.I.Map.GetCell(x, y).Tile.GetKind() == Tile.Kind_e.WALL);
        }
Пример #8
0
        // ===============================
        // ==== プレイヤー動作・接地系処理 ====
        // ===============================

        public static bool ProcPlayer_側面()
        {
            int flag = GetPlayer_側面();

            if (flag == 3)             // 左右両方 -> 壁抜け防止のため再チェック
            {
                flag = GetPlayer_側面Sub();
            }

            if (flag == 3)             // 左右両方
            {
                // noop
            }
            else if (flag == 1)             // 左側面
            {
                Game.I.Player.X = (double)SCommon.ToInt(Game.I.Player.X / GameConsts.TILE_W) * GameConsts.TILE_W + GameConsts.PLAYER_側面判定Pt_X;
            }
            else if (flag == 2)             // 右側面
            {
                Game.I.Player.X = (double)SCommon.ToInt(Game.I.Player.X / GameConsts.TILE_W) * GameConsts.TILE_W - GameConsts.PLAYER_側面判定Pt_X;
            }
            else if (flag == 0)             // なし
            {
                // noop
            }
            else
            {
                throw null;                 // never
            }
            return(flag != 0);
        }
Пример #9
0
        private void カメラ位置調整(bool 一瞬で)
        {
            if (!this.CamSlideMode && (this.CamSlideX | this.CamSlideY) != 0)
            {
                double tx;
                double ty;

                switch (this.Player.FaceDirection)
                {
                case 1: tx = -1; ty = 1; break;

                case 2: tx = 0; ty = 1; break;

                case 3: tx = 1; ty = 1; break;

                case 4: tx = -1; ty = 0; break;

                case 6: tx = 1; ty = 0; break;

                case 7: tx = -1; ty = -1; break;

                case 8: tx = 0; ty = -1; break;

                case 9: tx = 1; ty = -1; break;

                default:
                    throw null;                             // never
                }
                DDUtils.Approach(ref this.TargCamSlideX, tx, 0.97);
                DDUtils.Approach(ref this.TargCamSlideY, ty, 0.97);
            }
            else
            {
                this.TargCamSlideX = this.CamSlideX;
                this.TargCamSlideY = this.CamSlideY;
            }
            double targCamX = this.Player.X - DDConsts.Screen_W / 2 + (this.TargCamSlideX * DDConsts.Screen_W / 3);
            double targCamY = this.Player.Y - DDConsts.Screen_H / 2 + (this.TargCamSlideY * DDConsts.Screen_H / 3);

            DDUtils.ToRange(ref targCamX, 0.0, this.Map.W * GameConsts.TILE_W - DDConsts.Screen_W);
            DDUtils.ToRange(ref targCamY, 0.0, this.Map.H * GameConsts.TILE_H - DDConsts.Screen_H);

            // 不要
            //if (this.Map.W * GameConsts.TILE_W - DDConsts.Screen_W < GameConsts.TILE_W) // ? カメラの横の可動域が1タイルより狭い場合
            //    targCamX = (this.Map.W * GameConsts.TILE_W - DDConsts.Screen_W) / 2; // 中心に合わせる。

            if (this.Map.H * GameConsts.TILE_H - DDConsts.Screen_H < GameConsts.TILE_H)             // ? カメラの縦の可動域が1タイルより狭い場合
            {
                targCamY = (this.Map.H * GameConsts.TILE_H - DDConsts.Screen_H) / 2;                // 中心に合わせる。
            }
            DDUtils.Approach(ref DDGround.Camera.X, targCamX, 一瞬で ? 0.0 : 0.8);
            DDUtils.Approach(ref DDGround.Camera.Y, targCamY, 一瞬で ? 0.0 : 0.8);

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

            DDGround.ICamera.X = SCommon.ToInt(DDGround.Camera.X);
            DDGround.ICamera.Y = SCommon.ToInt(DDGround.Camera.Y);
        }
Пример #10
0
        public static void SetBlendAdd(double a)
        {
            int pal = SCommon.ToInt(a * 255.0);

            pal = SCommon.ToRange(pal, 0, 255);

            Extra.BlendAdd = pal;
        }
Пример #11
0
        public static void SetAlpha(double a)
        {
            int pal = SCommon.ToInt(a * 255.0);

            pal = SCommon.ToRange(pal, 0, 255);

            Extra.A = pal;
        }
Пример #12
0
 public static void Perform(double rate)
 {
     DX.GraphFilter(
         DDSubScreenUtils.CurrDrawScreen.GetHandle(),
         DX.DX_GRAPH_FILTER_GAUSS,
         16,
         SCommon.ToInt(5000.0 * rate)
         );
 }
Пример #13
0
        private static void Print_Main2(string line, int x, int y, I3Color color, double centeringRate)
        {
            // centeringRate:
            // 0.0 == 右寄せ (最初の文字の左側面が x になる)
            // 0.5 == 中央寄せ
            // 1.0 == 左寄せ (最後の文字の右側面が x になる)

            x -= SCommon.ToInt(DDFontUtils.GetDrawStringWidth(line, _font) * centeringRate);

            DDFontUtils.DrawString(x, y, line, _font, false, color);
        }
Пример #14
0
        public static void SetBright(double r, double g, double b)
        {
            int pR = SCommon.ToInt(r * 255.0);
            int pG = SCommon.ToInt(g * 255.0);
            int pB = SCommon.ToInt(b * 255.0);

            pR = SCommon.ToRange(pR, 0, 255);
            pG = SCommon.ToRange(pG, 0, 255);
            pB = SCommon.ToRange(pB, 0, 255);

            Extra.Bright = new I3Color(pR, pG, pB);
        }
Пример #15
0
        public static void SetVolume(int handle, double volume)
        {
            volume = SCommon.ToRange(volume, 0.0, 1.0);

            int pal = SCommon.ToInt(volume * 255.0);

            if (pal < 0 || 255 < pal)
            {
                throw new DDError();                       // 2bs
            }
            if (DX.ChangeVolumeSoundMem(pal, handle) != 0) // ? 失敗
            {
                throw new DDError();
            }
        }
Пример #16
0
        public void Draw_02()
        {
            if (1 <= this.DeadFrame)
            {
                this.DrawOnDead((double)this.DeadFrame / GameConsts.PLAYER_DEAD_FRAME_MAX);
                return;
            }
            if (1 <= this.RebornFrame)
            {
                this.DrawOnDead(1.0 - (double)this.RebornFrame / GameConsts.PLAYER_REBORN_FRAME_MAX);
                return;
            }

            DDDraw.DrawBegin(Ground.I.Picture.WhiteBox, SCommon.ToInt(this.X - DDGround.ICamera.X), SCommon.ToInt(this.Y - DDGround.ICamera.Y));
            DDDraw.DrawSetSize(GameConsts.TILE_W, GameConsts.TILE_H);
            DDDraw.DrawEnd();
        }
Пример #17
0
        public override void Draw()
        {
            if (!EnemyCommon.IsOutOfScreen_ForDraw(this))
            {
                double p = Math.Sin(DDEngine.ProcFrame / 10.0 + this.X + this.Y) * 0.5 + 0.5;                 // color phaese

                DDDraw.SetBright(new I3Color(
                                     SCommon.ToInt(DDUtils.AToBRate(Game.I.Map.Design.EnemyColor_Death_A.R, Game.I.Map.Design.EnemyColor_Death_B.R, p)),
                                     SCommon.ToInt(DDUtils.AToBRate(Game.I.Map.Design.EnemyColor_Death_A.G, Game.I.Map.Design.EnemyColor_Death_B.G, p)),
                                     SCommon.ToInt(DDUtils.AToBRate(Game.I.Map.Design.EnemyColor_Death_A.B, Game.I.Map.Design.EnemyColor_Death_B.B, p))
                                     ));
                DDDraw.DrawBegin(Ground.I.Picture.WhiteBox, SCommon.ToInt(this.X - DDGround.ICamera.X), SCommon.ToInt(this.Y - DDGround.ICamera.Y));
                DDDraw.DrawSetSize(GameConsts.TILE_W, GameConsts.TILE_H);
                DDDraw.DrawEnd();
                DDDraw.Reset();

                this.Crash = DDCrashUtils.Rect_CenterSize(new D2Point(this.X, this.Y), new D2Size(GameConsts.TILE_W, GameConsts.TILE_H));

                //Game.I.タイル接近_敵描画_Points.Add(new D2Point(this.X, this.Y)); // 地形の一部なので、追加しない。
            }
        }
Пример #18
0
        public override void Draw()
        {
            if (Game.I.Player.DeadFrame != 0)             // ? プレイヤー死亡
            {
                DDUtils.Approach(ref this.Speed, 4.0, 0.9);
            }
            else
            {
                DDUtils.Approach(ref this.Speed, 9.0, 0.975);
            }

            D2Point currSpeed = DDUtils.AngleToPoint(this.Angle, this.Speed);

            this.X += currSpeed.X;
            this.Y += currSpeed.Y;

            DDDraw.SetBright(this.Color);
            DDDraw.DrawBegin(Ground.I.Picture.WhiteBox, SCommon.ToInt(this.X - DDGround.ICamera.X), SCommon.ToInt(this.Y - DDGround.ICamera.Y));
            DDDraw.DrawSetSize(GameConsts.TILE_W, GameConsts.TILE_H);
            DDDraw.DrawRotate(this.Rot);
            DDDraw.DrawEnd();
            DDDraw.Reset();

            this.RotAdd += this.RotAddAdd;
            this.Rot    += this.RotAdd;

            //this.Crash = DDCrashUtils.Rect_CenterSize(new D2Point(this.X, this.Y), new D2Size(GameConsts.TILE_W, GameConsts.TILE_H)); // old
            this.Crash = DDCrashUtils.Circle(new D2Point(this.X, this.Y), GameConsts.TILE_W / 2.0);

            Game.I.タイル接近_敵描画_Points.Add(new D2Point(this.X, this.Y));

            if (
                Game.I.Player.DeadFrame == 0 &&                 // ? プレイヤー生存
                DDUtils.IsOutOfCamera(new D2Point(this.X, this.Y), 50.0)
                )
            {
                this.DeadFlag = true;
            }
        }
Пример #19
0
        protected override IEnumerable <bool> E_Draw()
        {
            double SCALE = LevelToScale(this.Level);
            double R     = SCommon.ToInt(24.0 * SCALE);

            double yAdd = 0.0;

            // 初期位置調整
            {
                this.X += (36.0 + R * (1 + 2 * this.Order)) * (this.FacingLeft ? -1 : 1);
                //this.Y += 0.0;
            }

            for (; ;)
            {
                yAdd -= (0.2 + 0.05 * this.Order) * SCALE;

                this.X += (4.0 + 0.5 * this.Order) * SCALE * (this.FacingLeft ? -1 : 1);
                this.Y += yAdd;

                DDDraw.SetBright(new I3Color(0, 192, 192));
                DDDraw.DrawBegin(Ground.I.Picture.WhiteCircle, this.X - DDGround.ICamera.X, this.Y - DDGround.ICamera.Y);
                DDDraw.DrawSetSize(R * 2, R * 2);
                DDDraw.DrawEnd();
                DDDraw.Reset();

                DDPrint.SetDebug(
                    (int)this.X - DDGround.ICamera.X - 12,
                    (int)this.Y - DDGround.ICamera.Y - 8
                    );
                DDPrint.SetBorder(new I3Color(0, 0, 0));
                DDPrint.Print("AS" + this.Level);
                DDPrint.Reset();

                this.Crash = DDCrashUtils.Circle(new D2Point(this.X, this.Y), R);

                yield return(!DDUtils.IsOutOfCamera(new D2Point(this.X, this.Y), R));                // カメラから出たら消滅する。
            }
        }
Пример #20
0
        protected override IEnumerable <bool> E_Draw()
        {
            double SCALE = LevelToScale(this.Level);
            double R     = SCommon.ToInt(24.0 * SCALE);

            int yAddDir = 0;

            for (; ;)
            {
                if (yAddDir == 0)
                {
                    this.X += 10.0 * (this.FacingLeft ? -1 : 1);
                    yAddDir = this.索敵(R);
                }
                else
                {
                    this.Y += 10.0 * yAddDir;
                }

                DDDraw.SetBright(new I3Color(0, 192, 255));
                DDDraw.DrawBegin(Ground.I.Picture.WhiteCircle, this.X - DDGround.ICamera.X, this.Y - DDGround.ICamera.Y);
                DDDraw.DrawSetSize(R * 2, R * 2);
                DDDraw.DrawEnd();
                DDDraw.Reset();

                DDPrint.SetDebug(
                    (int)this.X - DDGround.ICamera.X - 12,
                    (int)this.Y - DDGround.ICamera.Y - 8
                    );
                DDPrint.SetBorder(new I3Color(0, 0, 0));
                DDPrint.Print("MA" + this.Level);
                DDPrint.Reset();

                this.Crash = DDCrashUtils.Circle(new D2Point(this.X, this.Y), R);

                yield return(!DDUtils.IsOutOfCamera(new D2Point(this.X, this.Y), R));                // カメラから出たら消滅する。
            }
        }
Пример #21
0
        public override void DrawPlayer()
        {
            double map_b = Game.I.Map.H * GameConsts.TILE_H;
            double pl_y  = Game.I.Player.Y;

            double y = (map_b - 70) - pl_y;

            y /= 300.0;
            y  = Math.Abs(y);

            if (y < 1.0)
            {
                DDDraw.SetAlpha(y);
            }
            DDDraw.DrawBegin(
                Ground.I.Picture.WhiteBox,
                SCommon.ToInt(Game.I.Player.X - DDGround.ICamera.X),
                SCommon.ToInt(Game.I.Player.Y - DDGround.ICamera.Y)
                );
            DDDraw.DrawSetSize(GameConsts.TILE_W, GameConsts.TILE_H);
            DDDraw.DrawEnd();
            DDDraw.Reset();
        }
Пример #22
0
        public override void Draw()
        {
            this.X += this.XSpeed;
            this.Y += this.YSpeed;

            if (this.Y < this.Highest_Y)
            {
                DDUtils.Approach(ref this.YSpeed, 重力加速度, 0.9);
            }
            this.YSpeed = Math.Min(落下最高速度, this.YSpeed);

            int ix = SCommon.ToInt(this.X);
            int iy = SCommon.ToInt(this.Y);

            Around a2 = new Around(ix, iy, 2);

            int xDirSign = 0;
            int yDirSign = 0;

            if (this.Y < this.Highest_Y + 24.0)             // ? 最高高度に近い
            {
                if (
                    a2.Table[0, 0].IsEnemyPataWall() ||
                    a2.Table[0, 1].IsEnemyPataWall()
                    )
                {
                    xDirSign++;
                }

                if (
                    a2.Table[1, 0].IsEnemyPataWall() ||
                    a2.Table[1, 1].IsEnemyPataWall()
                    )
                {
                    xDirSign--;
                }
            }
            else
            {
                if (
                    a2.Table[0, 0].IsEnemyPataWall() &&
                    a2.Table[0, 1].IsEnemyPataWall()
                    )
                {
                    xDirSign++;
                }

                if (
                    a2.Table[1, 0].IsEnemyPataWall() &&
                    a2.Table[1, 1].IsEnemyPataWall()
                    )
                {
                    xDirSign--;
                }
            }

            if (
                !a2.Table[0, 0].IsEnemyPataWall() && a2.Table[0, 1].IsEnemyPataWall() ||
                !a2.Table[1, 0].IsEnemyPataWall() && a2.Table[1, 1].IsEnemyPataWall()
                )
            {
                yDirSign = -1;
            }
            else if (
                a2.Table[0, 0].IsEnemyPataWall() &&
                a2.Table[1, 0].IsEnemyPataWall()
                )
            {
                yDirSign = 1;
            }
            else
            {
                this.YSpeed += 重力加速度;
            }

            if (xDirSign != 0)
            {
                this.XSpeed = Math.Abs(this.XSpeed) * xDirSign;
            }

            if (yDirSign != 0)
            {
                this.YSpeed = Math.Abs(this.YSpeed) * yDirSign;
            }

            if (!EnemyCommon.IsOutOfScreen_ForDraw(this))
            {
                //DDDraw.SetBright(new I3Color(192, 32, 32)); // old
                DDDraw.SetBright(Game.I.Map.Design.EnemyColor_Pata);
                DDDraw.DrawBegin(Ground.I.Picture.WhiteBox, SCommon.ToInt(this.X - DDGround.ICamera.X), SCommon.ToInt(this.Y - DDGround.ICamera.Y));
                DDDraw.DrawSetSize(GameConsts.TILE_W, GameConsts.TILE_H);
                DDDraw.DrawEnd();
                DDDraw.Reset();

                this.Crash = DDCrashUtils.Rect_CenterSize(new D2Point(this.X, this.Y), new D2Size(GameConsts.TILE_W, GameConsts.TILE_H));

                Game.I.タイル接近_敵描画_Points.Add(new D2Point(this.X, this.Y));
            }
        }
Пример #23
0
        private void 基本設定()
        {
            DDSE[] seSamples = new DDSE[]
            {
                Ground.I.SE.Poka01,
                Ground.I.SE.Poka02,
            };

            DDEngine.FreezeInput();

            for (; ;)
            {
                // ====
                // 入力判定ここから
                // ====

                if (
                    DDInput.A.GetInput() == 1 ||
                    DDInput.B.GetInput() == 1 ||
                    DDMouse.R.GetInput() == -1
                    )
                {
                    this.Mode = Mode_e.END;
                    break;
                }

                if (DDMouse.L.GetInput() == -1)
                {
                    if (this.GetTabTitleCrash_拡張設定().IsCrashed(DDCrashUtils.Point(new D2Point(DDMouse.X, DDMouse.Y))))
                    {
                        this.Mode = Mode_e.拡張設定;
                        break;
                    }
                    if (this.LastHoveringButton == Ground.I.Picture.SettingButton_フルスクリーン)
                    {
                        DDMain.SetFullScreen();
                    }
                    if (this.LastHoveringButton == Ground.I.Picture.SettingButton_ウィンドウ)
                    {
                        const int def_screen_w = DDConsts.Screen_W / 2;
                        const int def_screen_h = DDConsts.Screen_H / 2;

                        DDMain.SetScreenSize(def_screen_w, def_screen_h);
                    }
                    if (this.LastHoveringButton == Ground.I.Picture.SettingButton_デフォルトに戻す)
                    {
                        this.デフォルトに戻す();
                    }
                    if (this.LastHoveringButton == Ground.I.Picture.SettingButton_戻る)
                    {
                        this.Mode = Mode_e.END;
                        break;
                    }
                }

                // ====
                // 入力判定ここまで
                // ====

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

                this.BeforeDrawContents();

                DDDraw.DrawSimple(Ground.I.Picture.基本設定枠, 0, 0);

                this.DrawTabTitles(false);

                this.DrawPrompt(100, 250, "画面モード");
                this.DrawPrompt(100, 380, "BGM音量");
                this.DrawPrompt(100, 510, "SE音量");
                this.DrawPrompt(100, 640, "メッセージ表示速度");
                this.DrawPrompt(100, 770, "メッセージウィンドウ透明度");

                bool fullScreenFlag =
                    DDGround.RealScreen_W == DDGround.MonitorRect.W &&
                    DDGround.RealScreen_H == DDGround.MonitorRect.H;

                this.DrawButton(1100, 280, Ground.I.Picture.SettingButton_フルスクリーン, fullScreenFlag);
                this.DrawButton(1550, 280, Ground.I.Picture.SettingButton_ウィンドウ, !fullScreenFlag);
                this.DrawTrackBar(1325, 410, "小", "大", DDGround.MusicVolume, volume =>
                {
                    DDGround.MusicVolume = volume;
                    DDMusicUtils.UpdateVolume();
                });
                this.DrawTrackBar(1325, 540, "小", "大", DDGround.SEVolume, volume =>
                {
                    DDGround.SEVolume = volume;
                    //DDSEUtils.UpdateVolume(); // v_20210215 -- メソッド終了時に全て更新する。

                    foreach (DDSE se in seSamples)
                    {
                        se.UpdateVolume();
                    }
                },
                                  () =>
                {
                    DDUtils.Random.ChooseOne(seSamples).Play();
                });
                this.DrawTrackBar(1325, 670, "遅い", "速い",
                                  DDUtils.RateAToB(GameConsts.MESSAGE_SPEED_MIN, GameConsts.MESSAGE_SPEED_MAX, Ground.I.MessageSpeed),
                                  value => Ground.I.MessageSpeed = SCommon.ToInt(
                                      DDUtils.AToBRate(GameConsts.MESSAGE_SPEED_MIN, GameConsts.MESSAGE_SPEED_MAX, value)
                                      )
                                  );
                this.DrawTrackBar(1325, 800, "透明", "不透明",
                                  DDUtils.RateAToB(0, 100, Ground.I.MessageWindow_A_Pct),
                                  value => Ground.I.MessageWindow_A_Pct = SCommon.ToInt(
                                      DDUtils.AToBRate(0, 100, value)
                                      )
                                  );

                this.DrawUnderButtons();

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

                DDEngine.EachFrame();
            }
            DDEngine.FreezeInput();

            DDSEUtils.UpdateVolume();             // v_20210215
        }
Пример #24
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.SetPrint(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.SetPrint(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();             // ★★★ マップをセーブする ★★★
        }
Пример #25
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 (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)                 // プレイヤー死亡中の処理
                {
                    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++;

                    // ----

                    const int HITBACK_FRAME_MAX = 30;

                    if (frame < HITBACK_FRAME_MAX)
                    {
                        double rate    = (double)frame / HITBACK_FRAME_MAX;
                        double invRate = 1.0 - rate;

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

                        this.Player.X -= speed.X;
                        this.Player.Y -= speed.Y;
                    }
                }
                //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++;

                    // ----

                    {
                        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)                 // プレイヤー無敵時間中の処理
                {
                    int frame = this.Player.InvincibleFrame - 1;

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

                    // ----

                    // 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() ★★★
        }
Пример #26
0
 private static int RateToVolumeValue(double rate, int minval, int maxval)
 {
     return(minval + SCommon.ToInt(rate * (maxval - minval)));
 }
Пример #27
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();

            bool jumpLock = false;             // ? ジャンプ・ロック // ジャンプしたらボタンを離すまでロックする。

            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 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 (jump == 0)
                    {
                        jumpLock = false;
                    }

                    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.JumpCount == 0 && !jumpLock)
                        {
                            this.Player.JumpCount = 1;
                            this.Player.JumpFrame = 1;
                            jumpLock = true;
                        }
                    }

                    if (this.Player.JumpFrame == 1)                     // ? ジャンプ開始
                    {
                        Ground.I.SE.PlayerJump.Play();
                    }

                    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)                 // プレイヤー死亡中の処理
                {
                    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

                    const int HIT_BACK_FRAME_MAX = 30;

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

                        this.Player.X -= 10.0 * (1.0 - hitBackRate) * (this.Player.FacingLeft ? -1 : 1);
                    }
                }
                //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);

                    // ---- 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 * 0.2;
                            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);
                    }

                    if (1 <= this.Player.JumpFrame)
                    {
                        this.Player.YSpeed = GameConsts.PLAYER_ジャンプによる上昇速度;
                    }
                    else
                    {
                        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_L =
                        this.Map.GetCell(GameCommon.ToTablePoint(this.Player.X - GameConsts.PLAYER_脳天判定Pt_X, this.Player.Y - GameConsts.PLAYER_脳天判定Pt_Y)).Tile.IsWall();

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

                    if (touchCeiling_L && touchCeiling_R)
                    {
                        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;
                            this.Player.JumpFrame = 0;
                        }
                    }
                    else if (touchCeiling_L)
                    {
                        this.Player.X = (double)SCommon.ToInt(this.Player.X / GameConsts.TILE_W) * GameConsts.TILE_W + GameConsts.PLAYER_脳天判定Pt_X;
                    }
                    else if (touchCeiling_R)
                    {
                        this.Player.X = (double)SCommon.ToInt(this.Player.X / GameConsts.TILE_W) * GameConsts.TILE_W - GameConsts.PLAYER_脳天判定Pt_X;
                    }

                    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.JumpCount     = 0;
                        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)                 // ? 衝突
                                )
                            {
                                // ★ 敵_被弾ここから

                                enemy.HP -= shot.AttackPoint;

                                if (!shot.敵を貫通する)                                 // 自弾の攻撃力と敵のHPを相殺
                                {
                                    if (0 <= enemy.HP)                            // ? 丁度削りきった || 削りきれなかった -> 攻撃力を使い果たしたので、ショットは消滅
                                    {
                                        shot.Kill();
                                    }
                                    else
                                    {
                                        shot.AttackPoint = -enemy.HP;                                         // 過剰に削った分を残りの攻撃力として反映
                                    }
                                }

                                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() ★★★
        }
Пример #28
0
        public static DDPicture Reduct(string file, int denom)
        {
            return(new DDPicture(
                       () =>
            {
                int siHandle = DDPictureLoaderUtils.FileData2SoftImage(DDPictureLoaderUtils.File2FileData(file));
                int w;
                int h;

                DDPictureLoaderUtils.GetSoftImageSize(siHandle, out w, out h);

                {
                    int new_w = w / denom;
                    int new_h = h / denom;
                    int new_si_h = DDPictureLoaderUtils.CreateSoftImage(new_w, new_h);

                    for (int x = 0; x < new_w; x++)
                    {
                        for (int y = 0; y < new_h; y++)
                        {
                            int tR = 0;
                            int tG = 0;
                            int tB = 0;
                            int tA = 0;

                            for (int sx = 0; sx < denom; sx++)
                            {
                                for (int sy = 0; sy < denom; sy++)
                                {
                                    DDPictureLoaderUtils.Dot dot = DDPictureLoaderUtils.GetSoftImageDot(siHandle, x * denom + sx, y * denom + sy);

                                    tR += dot.R;
                                    tG += dot.G;
                                    tB += dot.B;
                                    tA += dot.A;
                                }
                            }
                            double div = (double)(denom * denom);

                            {
                                DDPictureLoaderUtils.Dot dot = new DDPictureLoaderUtils.Dot()
                                {
                                    R = SCommon.ToInt(tR / div),
                                    G = SCommon.ToInt(tG / div),
                                    B = SCommon.ToInt(tB / div),
                                    A = SCommon.ToInt(tA / div),
                                };

                                DDPictureLoaderUtils.SetSoftImageDot(new_si_h, x, y, dot);
                            }
                        }
                    }
                    DDPictureLoaderUtils.ReleaseSoftImage(siHandle);
                    siHandle = new_si_h;
                }

                return DDPictureLoaderUtils.GraphicHandle2Info(DDPictureLoaderUtils.SoftImage2GraphicHandle(siHandle));
            },
                       DDPictureLoaderUtils.ReleaseInfo,
                       DDPictureUtils.Add
                       ));
        }
Пример #29
0
        protected override IEnumerable <bool> E_Draw()
        {
            double SCALE = LevelToScale(this.Level);
            double R     = SCommon.ToInt(24.0 * SCALE);

            double xAdd = this.FacingLeft ? -1.0 : 1.0;
            double yAdd = Game.I.Player.YSpeed * 0.2;

            DDUtils.MakeXYSpeed(0.0, 0.0, xAdd, yAdd, 20.0 * SCALE, out xAdd, out yAdd);

            for (int frame = 0; ; frame++)
            {
                if (Game.I.Status.Equipment != GameStatus.Equipment_e.ハンマー陰陽玉)                 // 武器を切り替えたら消滅
                {
                    this.Kill();
                    break;
                }
                double xaa;
                double yaa;

                // バネの加速度
                {
                    xaa = (Game.I.Player.X - this.X) * 0.01;
                    yaa = (Game.I.Player.Y - this.Y) * 0.01;
                }

                yaa += 1.0;                 // 重力加速度

                xAdd += xaa;
                yAdd += yaa;

                // 空気抵抗
                {
                    double 空気抵抗 = LevelTo空気抵抗(this.Level);

                    xAdd *= 空気抵抗;
                    yAdd *= 空気抵抗;
                }

                this.X += xAdd;
                this.Y += yAdd;

                DDDraw.DrawBegin(Ground.I.Picture2.陰陽玉, this.X - DDGround.ICamera.X, this.Y - DDGround.ICamera.Y);
                DDDraw.DrawSetSize(R * 2, R * 2);
                DDDraw.DrawRotate(frame / 10.0);
                DDDraw.DrawEnd();

                // プレイヤーとハンマーを繋ぐバネのような何かを描画する。
                {
                    double d = DDUtils.GetDistance(this.X - Game.I.Player.X, this.Y - Game.I.Player.Y);

                    if (10.0 < d)
                    {
                        double x   = (this.X + Game.I.Player.X) / 2.0;
                        double y   = (this.Y + Game.I.Player.Y) / 2.0;
                        double rot = DDUtils.GetAngle(this.X - Game.I.Player.X, this.Y - Game.I.Player.Y) + Math.PI / 2;

                        DDDraw.SetAlpha(0.5);
                        DDDraw.DrawBegin(Ground.I.Picture2.Laser[4], x - DDGround.ICamera.X, y - DDGround.ICamera.Y);
                        DDDraw.DrawSetSize_H(d);
                        DDDraw.DrawRotate(rot);
                        DDDraw.DrawEnd();
                        DDDraw.Reset();
                    }
                }

                this.Crash = DDCrashUtils.Circle(new D2Point(this.X, this.Y), R);

                yield return(true);
            }
        }
Пример #30
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 (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)                 // プレイヤー死亡中の処理
                {
                    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

                    // ----

                    // noop
                }
                //endDead:

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

                    if (GameConsts.PLAYER_DAMAGE_FRAME_MAX < frame)
                    {
                        this.Player.DamageFrame = 0;

                        if (1 <= this.Player.HP)
                        {
                            this.Player.InvincibleFrame = 1;
                            goto endDamage;
                        }
                        else
                        {
                            this.Player.DeadFrame = 1;
                            goto startDead;
                        }
                    }
                    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 / 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() ★★★
        }