/// <summary> /// ゲーム中のロード画面 /// </summary> private void LoadMenu() { using (new SaveOrLoadMenu()) { SaveDataSlot sdSlot = SaveOrLoadMenu.I.Load(() => { DDPicture picture = Ground.I.Picture.Title; DDDraw.DrawRect( picture, DDUtils.AdjustRectExterior(picture.GetSize().ToD2Size(), new D4Rect(0, 0, DDConsts.Screen_W, DDConsts.Screen_H)) ); DDCurtain.DrawCurtain(-0.5); }); if (sdSlot != null) { this.Status = GameStatus.Deserialize(sdSlot.SerializedGameStatus); this.CurrPage = this.Status.Scenario.Pages[this.Status.CurrPageIndex]; this.DispSubtitleCharCount = 0; this.DispCharCount = 0; this.DispPageEndedCount = 0; this.DispFastMode = false; } } DDEngine.FreezeInput(GameConsts.LONG_INPUT_SLEEP); }
public void Perform(bool continueByTitleMenuFlag = false) { // reset { this.SkipMode = false; this.AutoMode = false; this.BacklogMode = false; Surface_MessageWindow.Hide = false; Surface_SystemButtons.Hide = false; } DDCurtain.SetCurtain(0, -1.0); DDCurtain.SetCurtain(); restartCurrPage: this.CurrPage = this.Status.Scenario.Pages[this.Status.CurrPageIndex]; if (!continueByTitleMenuFlag) { foreach (ScenarioCommand command in this.CurrPage.Commands) { command.Invoke(); } } continueByTitleMenuFlag = false; this.DispSubtitleCharCount = 0; this.DispCharCount = 0; this.DispPageEndedCount = 0; this.DispFastMode = false; DDEngine.FreezeInput(); for (; ;) { bool nextPageFlag = false; // ★★★ キー押下は 1 マウス押下は -1 で判定する。 // 入力:シナリオを進める。(マウスホイール) if (DDMouse.Rot < 0) { this.CancelSkipAutoMode(); if (this.DispPageEndedCount < GameConsts.NEXT_PAGE_INPUT_INTERVAL) // ? ページ表示_未完了 -> ページ表示_高速化 { this.DispFastMode = true; } else // ? ページ表示_完了 -> 次ページ { if (!this.Status.HasSelect()) { nextPageFlag = true; } } DDEngine.FreezeInput(GameConsts.SHORT_INPUT_SLEEP); } // 入力:シナリオを進める。(マウスホイール_以外) if ( DDMouse.L.GetInput() == -1 && this.SelectedSystemButtonIndex == -1 || // システムボタン以外を左クリック DDInput.A.GetInput() == 1 ) { if (this.DispPageEndedCount < GameConsts.NEXT_PAGE_INPUT_INTERVAL) // ? ページ表示_未完了 -> ページ表示_高速化 { this.DispFastMode = true; } else // ? ページ表示_完了 -> 次ページ { if (!this.Status.HasSelect()) // ? 選択肢表示中ではない。 { nextPageFlag = true; } else // ? 選択肢表示中 { int index = this.Status.GetSelect().GetMouseFocusedIndex(); if (index != -1) // 選択中の選択肢へ進む { string scenarioName = this.Status.GetSelect().Options[index].ScenarioName; this.Status.Scenario = new Scenario(scenarioName); this.Status.CurrPageIndex = 0; this.Status.RemoveSelect(); // 選択肢_終了 //this.SkipMode = false; // moved goto restartCurrPage; } } } } if (this.SkipMode) { if (!this.Status.HasSelect()) { if (1 <= this.DispPageEndedCount) { nextPageFlag = true; } } } if (this.AutoMode) { if (!this.Status.HasSelect()) { if (GameConsts.AUTO_NEXT_PAGE_INTERVAL <= this.DispPageEndedCount) { nextPageFlag = true; } } } if (nextPageFlag) // 次ページ { // スキップモード時はページを進める毎にエフェクトを強制終了する。 if (this.SkipMode) { foreach (Surface surface in this.Status.Surfaces) { surface.Act.Flush(); } } this.Status.CurrPageIndex++; if (this.Status.Scenario.Pages.Count <= this.Status.CurrPageIndex) { break; } goto restartCurrPage; } // 入力:過去ログ if ( //DDInput.DIR_8.GetInput() == 1 || // 選択肢の選択に反応してしまう。 DDInput.DIR_4.GetInput() == 1 || 0 < DDMouse.Rot ) { this.Backlog(); } // 入力:鑑賞モード if ( DDMouse.R.GetInput() == -1 || DDInput.B.GetInput() == 1 ) { this.Appreciate(); } // 入力:システムボタン if (DDMouse.L.GetInput() == -1 && this.SelectedSystemButtonIndex != -1) // システムボタンを左クリック { switch (this.SelectedSystemButtonIndex) { case 0: foreach (Surface surface in this.Status.Surfaces) { surface.Act.Flush(); } this.SaveMenu(); break; case 1: this.LoadMenu(); break; case 2: this.SkipMode = !this.SkipMode; break; case 3: this.AutoMode = !this.AutoMode; break; case 4: this.Backlog(); break; case 5: this.SystemMenu(); break; default: throw null; // never } if (this.SystemMenu_ReturnToTitleMenu) { break; } } if ( this.CurrPage.Subtitle.Length < this.DispSubtitleCharCount && this.CurrPage.Text.Length < this.DispCharCount ) { this.DispPageEndedCount++; } if (this.SkipMode) { this.DispSubtitleCharCount += 8; this.DispCharCount += 8; } else if (this.DispFastMode) { this.DispSubtitleCharCount += Ground.I.MessageSpeed; this.DispCharCount += Ground.I.MessageSpeed; } else { int speed = (GameConsts.MESSAGE_SPEED_MAX + GameConsts.MESSAGE_SPEED_MIN) - Ground.I.MessageSpeed; if (DDEngine.ProcFrame % speed == 0) { this.DispSubtitleCharCount++; } if (DDEngine.ProcFrame % (speed + 1) == 0) { this.DispCharCount++; } } DDUtils.ToRange(ref this.DispSubtitleCharCount, 0, SCommon.IMAX); DDUtils.ToRange(ref this.DispCharCount, 0, SCommon.IMAX); // ==== // 描画ここから // ==== this.DrawSurfaces(); // ==== // 描画ここまで // ==== DDEngine.EachFrame(); // ★★★ ゲームループの終わり ★★★ } DDCurtain.SetCurtain(30, -1.0); DDMusicUtils.Fade(); foreach (DDScene scene in DDSceneUtils.Create(40)) { this.DrawSurfaces(); DDEngine.EachFrame(); } DDEngine.FreezeInput(); // ★★★ end of Perform() ★★★ }
/// <summary> /// ゲーム中のセーブ・ロード画面 /// </summary> /// <param name="saveMode">セーブモードであるか</param> private void SaveOrLoadMenu(bool saveMode) { DDSimpleMenu simpleMenu = new DDSimpleMenu() { Color = new I3Color(255, 255, 255), BorderColor = saveMode ? new I3Color(192, 0, 0) : new I3Color(0, 0, 192), WallPicture = Ground.I.Picture.星屑物語02, WallCurtain = -0.5, }; int selectIndex = 0; for (; ;) { selectIndex = simpleMenu.Perform( saveMode ? "セーブメニュー" : "ロードメニュー", Ground.I.SaveDataSlots.Select(saveDataSlot => saveDataSlot.SavedTime.Year == 1 ? "----" : "[" + saveDataSlot.SavedTime.ToString() + "] " + saveDataSlot.Description).Concat(new string[] { "戻る" }).ToArray(), selectIndex ); if (selectIndex < Consts.SAVE_DATA_SLOT_NUM) { if (saveMode) // ? セーブモード { if (new Confirm() { BorderColor = Ground.I.SaveDataSlots[selectIndex].SerializedGameStatus != null ? new I3Color(255, 0, 0) : new I3Color(150, 150, 0) } .Perform( Ground.I.SaveDataSlots[selectIndex].SerializedGameStatus != null ? "スロット " + (selectIndex + 1) + " のデータを上書きします。" : "スロット " + (selectIndex + 1) + " にセーブします。", "はい", "いいえ") == 0) { string description = "シナリオ:" + this.Status.Scenario.Name + " の " + (this.Status.CurrPageIndex + 1) + " 頁"; Ground.I.SaveDataSlots[selectIndex].SerializedGameStatus = this.Status.Serialize(); Ground.I.SaveDataSlots[selectIndex].SavedTime = new SCommon.SimpleDateTime(SCommon.TimeStampToSec.ToSec(DateTime.Now)); Ground.I.SaveDataSlots[selectIndex].Description = description; } } else // ? ロードモード { if (Ground.I.SaveDataSlots[selectIndex].SerializedGameStatus != null) // ロードする。 { if (new Confirm() { BorderColor = new I3Color(50, 100, 200) } .Perform("スロット " + (selectIndex + 1) + " のデータをロードします。", "はい", "いいえ") == 0) { this.Status = GameStatus.Deserialize(Ground.I.SaveDataSlots[selectIndex].SerializedGameStatus); this.CurrPage = this.Status.Scenario.Pages[this.Status.CurrPageIndex]; this.DispSubtitleCharCount = 0; this.DispCharCount = 0; this.DispPageEndedCount = 0; this.DispFastMode = false; break; } } } } else // [戻る] { break; } //DDEngine.EachFrame(); // 不要 } DDEngine.FreezeInput(GameConsts.LONG_INPUT_SLEEP); }
public Scenario(string name) { if (string.IsNullOrEmpty(name)) { throw new DDError(); } this.Name = name; this.Pages.Clear(); string[] lines = ReadScenarioLines(name); ScenarioPage page = null; for (int index = 0; index < lines.Length; index++) { string line = lines[index].Trim(); if (line == "") { continue; } if (line[0] == '#') // ? 外部ファイル参照 { line = line.Substring(1); // # 除去 string[] tokens = SCommon.Tokenize(line, " ", false, true); string subName = tokens[0]; string[] arguments = tokens.Skip(1).ToArray(); string[] subLines = ReadScenarioLines(subName); subLines = SolveArguments(subLines, ParseArguments(arguments)); lines = lines.Take(index).Concat(subLines).Concat(lines.Skip(index + 1)).ToArray(); } } { Dictionary <string, string> def_dic = SCommon.CreateDictionary <string>(); for (int index = 0; index < lines.Length; index++) { string line = lines[index].Trim(); if (line == "") { continue; } if (line[0] == '^') // ? 定義 { line = line.Substring(1); // ^ 除去 string[] tokens = SCommon.Tokenize(line, " ", false, true, 2); string def_name = tokens[0]; string def_value = tokens[1]; def_dic.Add(def_name, def_value); lines[index] = ""; } } for (int index = 0; index < lines.Length; index++) { string line = lines[index]; foreach (KeyValuePair <string, string> pair in def_dic) { line = line.Replace(pair.Key, pair.Value); } lines[index] = line; } } bool 読み込み抑止中 = false; foreach (string f_line in lines) { string line = f_line.Trim(); if (line == "") { continue; } if (line[0] == ';') // ? コメント行 { continue; } if (line[0] == '/') { page = new ScenarioPage() { Subtitle = line.Substring(1) }; this.Pages.Add(page); } else if (page == null) { throw new DDError("シナリオの先頭は /xxx でなければなりません。"); } else if (line[0] == '!') // ? コマンド { string[] tokens = line.Substring(1).Split(' ').Where(v => v != "").ToArray(); if (tokens[0] == "_ifndef") { 読み込み抑止中 = Game.I != null && Game.I.Status.Surfaces.Any(surface => surface.InstanceName == tokens[1]); } else if (tokens[0] == "_endif") { 読み込み抑止中 = false; } else if (読み込み抑止中) { } else { page.Commands.Add(new ScenarioCommand(tokens)); } } else if (読み込み抑止中) { } else { page.Lines.Add(line); } } }
public void Perform() { DDCurtain.SetCurtain(0, -1.0); DDCurtain.SetCurtain(); restartCurrPage: this.CurrPage = this.Status.Scenario.Pages[this.Status.CurrPageIndex]; foreach (ScenarioCommand command in this.CurrPage.Commands) { command.Invoke(); } int dispSubtitleCharCount = 0; int dispCharCount = 0; int dispPageEndedCount = 0; bool dispFastMode = false; DDEngine.FreezeInput(); for (; ;) { DDMouse.UpdatePos(); // キー押下は 1 マウス押下は -1 で判定する。 // 入力:シナリオを進める。 if ( DDMouse.L.GetInput() == -1 || DDInput.A.GetInput() == 1 || DDKey.GetInput(DX.KEY_INPUT_SPACE) == 1 || DDKey.GetInput(DX.KEY_INPUT_RETURN) == 1 ) { if (dispPageEndedCount < NEXT_PAGE_KEY_INTERVAL) // ? ページ表示_未完了 -> ページ表示_高速化 { dispFastMode = true; } else // ? ページ表示_完了 -> 次ページ { this.Status.CurrPageIndex++; if (this.Status.Scenario.Pages.Count <= this.Status.CurrPageIndex) { break; } goto restartCurrPage; } } if ( this.CurrPage.Subtitle.Length < dispSubtitleCharCount && this.CurrPage.Text.Length < dispCharCount ) { dispPageEndedCount++; } if (dispFastMode) { dispSubtitleCharCount += 2; dispCharCount += 2; } else { if (DDEngine.ProcFrame % 2 == 0) { dispSubtitleCharCount++; } if (DDEngine.ProcFrame % 3 == 0) { dispCharCount++; } } DDUtils.ToRange(ref dispSubtitleCharCount, 0, IntTools.IMAX); DDUtils.ToRange(ref dispCharCount, 0, IntTools.IMAX); // ==== // 描画ここから // ==== this.DrawSurfaces(); // メッセージ枠 { const int h = 136; DDDraw.SetAlpha(0.9); DDDraw.DrawRect(Ground.I.Picture.MessageFrame_Message, 0, DDConsts.Screen_H - h, DDConsts.Screen_W, h); DDDraw.Reset(); } // システムボタン { const double BUTTON_L = 530.5; // 素材の幅が奇数なので n + 0.5 const double BUTTON_T = 412.5; // 素材の高さも奇数なので n + 0.5 const double BUTTON_X_STEP = 78.0; DDPicture[] buttons = new DDPicture[] { Ground.I.Picture.MessageFrame_Save, Ground.I.Picture.MessageFrame_Load, Ground.I.Picture.MessageFrame_Skip, Ground.I.Picture.MessageFrame_Auto, Ground.I.Picture.MessageFrame_Log, Ground.I.Picture.MessageFrame_Menu, //Ground.I.Picture.MessageFrame_Close, //Ground.I.Picture.MessageFrame_Config, //Ground.I.Picture.MessageFrame_QLoad, //Ground.I.Picture.MessageFrame_QSave, //Ground.I.Picture.MessageFrame_Screen, //Ground.I.Picture.MessageFrame_Title, }; for (int index = 0; index < buttons.Length; index++) { DDDraw.DrawCenter(buttons[index], BUTTON_L + index * BUTTON_X_STEP, BUTTON_T); } } // サブタイトル文字列 { int dispSubtitleLength = Math.Min(dispCharCount, this.CurrPage.Subtitle.Length); string dispSubtitle = this.CurrPage.Subtitle.Substring(0, dispSubtitleLength); DDFontUtils.DrawString(120, 320, dispSubtitle, DDFontUtils.GetFont("Kゴシック", 16)); } // シナリオのテキスト文字列 { int dispTextLength = Math.Min(dispCharCount, this.CurrPage.Text.Length); string dispText = this.CurrPage.Text.Substring(0, dispTextLength); string[] dispLines = dispText.Split('\n'); for (int index = 0; index < dispLines.Length; index++) { DDFontUtils.DrawString(10, 450 + index * 30, dispLines[index], DDFontUtils.GetFont("Kゴシック", 16), false, new I3Color(110, 100, 90)); } } DDEngine.EachFrame(); } DDCurtain.SetCurtain(30, -1.0); DDMusicUtils.Fade(); foreach (DDScene scene in DDSceneUtils.Create(40)) { this.DrawSurfaces(); DDEngine.EachFrame(); } DDEngine.FreezeInput(); }
public Scenario(string name) { if (string.IsNullOrEmpty(name)) { throw new DDError(); } this.Name = name; this.Pages.Clear(); byte[] fileData; { const string DEVENV_SCENARIO_DIR = "シナリオデータ"; const string DEVENV_SCENARIO_SUFFIX = ".txt"; if (Directory.Exists(DEVENV_SCENARIO_DIR)) { string file = Path.Combine(DEVENV_SCENARIO_DIR, name + DEVENV_SCENARIO_SUFFIX); fileData = File.ReadAllBytes(file); } else { string file = SCENARIO_FILE_PREFIX + name + SCENARIO_FILE_SUFFIX; fileData = DDResource.Load(file); } } string text = JString.ToJString(fileData, true, true, true, true); text = text.Replace('\t', ' '); // タブスペースと空白 -> 空白に統一 string[] lines = FileTools.TextToLines(text); ScenarioPage page = null; foreach (string fLine in lines) { string line = fLine.Trim(); if (line == "") { continue; } if (line[0] == ';') // ? コメント行 { continue; } if (line[0] == '/') { page = new ScenarioPage() { Subtitle = line.Substring(1) }; this.Pages.Add(page); } else if (page == null) { throw new DDError("シナリオの先頭は /xxx でなければなりません。"); } else if (line[0] == '!') { string[] tokens = line.Substring(1).Split(' ').Where(v => v != "").ToArray(); page.Commands.Add(new ScenarioCommand(tokens)); } else { page.Lines.Add(line); } } this.各ページの各行の長さ調整(); }