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()); }
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)); } }
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; } }
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]); } } }
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); }
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); } }
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); }
// =============================== // ==== プレイヤー動作・接地系処理 ==== // =============================== 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); }
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); }
public static void SetBlendAdd(double a) { int pal = SCommon.ToInt(a * 255.0); pal = SCommon.ToRange(pal, 0, 255); Extra.BlendAdd = pal; }
public static void SetAlpha(double a) { int pal = SCommon.ToInt(a * 255.0); pal = SCommon.ToRange(pal, 0, 255); Extra.A = pal; }
public static void Perform(double rate) { DX.GraphFilter( DDSubScreenUtils.CurrDrawScreen.GetHandle(), DX.DX_GRAPH_FILTER_GAUSS, 16, SCommon.ToInt(5000.0 * rate) ); }
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); }
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); }
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(); } }
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(); }
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)); // 地形の一部なので、追加しない。 } }
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; } }
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)); // カメラから出たら消滅する。 } }
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)); // カメラから出たら消滅する。 } }
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(); }
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)); } }
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 }
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(); // ★★★ マップをセーブする ★★★ }
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() ★★★ }
private static int RateToVolumeValue(double rate, int minval, int maxval) { return(minval + SCommon.ToInt(rate * (maxval - minval))); }
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() ★★★ }
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 )); }
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); } }
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() ★★★ }