/// <summary> /// 系统向前进一个状态 /// 她只有在对话推进和选择项出现时才被触发 /// </summary> public static void SteadyForward(bool fromWheel, SceneAction saPtr, MusicianDescriptor mdescriptor, BacklogHolder backlogHolder) { lock (typeof(RollbackManager)) { // 回滚后返回,移栈并演绎 if (fromWheel && RollbackManager.IsRollingBack) { // 取上一状态 var recentStep = RollbackManager.backwardStack.Last(); RollbackManager.backwardStack.RemoveLast(); RollbackManager.forwardStack.AddLast(recentStep); // 重演绎 RollbackManager.GotoSteadyState(recentStep); } // 非回滚状态时才重新构造 else if (fromWheel == false) { // 处理回顾 if (saPtr.Type == SActionType.act_dialog) { backlogHolder.AddLog(saPtr.Tag); } // 构造当前状态的拷贝 var vm = Director.RunMana.CallStack.Fork() as StackMachine; vm.SetMachineName(String.Format("Yuri!Forked?{0}?{1}", DateTime.Now.Ticks, rand.Next(0, int.MaxValue))); RollbackableSnapshot ssp = new RollbackableSnapshot() { TimeStamp = DateTime.Now, IsBranchingRefer = Director.GetInstance().GetMainRender().IsBranching, MusicRef = ForkableState.DeepCopyBySerialization(mdescriptor), BacklogRef = ForkableState.DeepCopyBySerialization(backlogHolder), ReactionRef = saPtr, VMRef = vm, globalDao = SymbolTable.GetInstance().GlobalCtxDao.Fork() as GlobalContextDAO, sceneDao = SymbolTable.GetInstance().SceneCtxDao.Fork() as SceneContextDAO, ScreenStateRef = ScreenManager.GetInstance().Fork() as ScreenManager, SemaphoreDict = ForkableState.DeepCopyBySerialization(Director.RunMana.SemaphoreBindings), EnableRClickRef = Director.RunMana.EnableRClick, PerformingChapterRef = Director.RunMana.PerformingChapter }; // 如果栈中容量溢出就剔掉最早进入的那个 if (RollbackManager.forwardStack.Count >= GlobalConfigContext.MaxRollbackStep) { RollbackManager.forwardStack.RemoveFirst(); } // 入栈 RollbackManager.forwardStack.AddLast(ssp); } } }
/// <summary> /// 将系统跳转到指定的稳定状态 /// </summary> /// <param name="ssp">要演绎的状态包装</param> public static void GotoSteadyState(RollbackableSnapshot ssp) { // 停止消息循环 Director.PauseUpdateContext(); // 结束全部动画 SpriteAnimation.ClearAnimateWaitingDict(); // 检查是否需要回滚当前的并行处理和信号绑定 bool needRepara = false; if (ssp.VMRef.ESP.BindingSceneName != Director.RunMana.CallStack.SAVEP.BindingSceneName) { Director.RunMana.PauseParallel(); needRepara = true; } // 退到SSP所描述的状态 SymbolTable.GetInstance().SetDAO(ssp.sceneDao.Fork() as SceneContextDAO, ssp.globalDao.Fork() as GlobalContextDAO); ScreenManager.ResetSynObject(ssp.ScreenStateRef.Fork() as ScreenManager); Director.RunMana.ResetCallstackObject(ssp.VMRef.Fork() as StackMachine); Director.RunMana.Backlogs = ForkableState.DeepCopyBySerialization(ssp.BacklogRef); Director.RunMana.Musics = ForkableState.DeepCopyBySerialization(ssp.MusicRef); Director.RunMana.DashingPureSa = ssp.ReactionRef.Clone(true); Director.RunMana.SemaphoreBindings = ForkableState.DeepCopyBySerialization(ssp.SemaphoreDict); Director.RunMana.EnableRClick = ssp.EnableRClickRef; Director.RunMana.PerformingChapter = ssp.PerformingChapterRef; Director.ScrMana = ScreenManager.GetInstance(); // 刷新主渲染器上的堆栈绑定 Director.GetInstance().RefreshMainRenderVMReference(); Director.GetInstance().GetMainRender().IsBranching = ssp.IsBranchingRefer; // 重绘整个画面 ViewManager.GetInstance().ReDraw(true); // 恢复音效 UpdateRender render = Director.GetInstance().GetMainRender(); if (GlobalConfigContext.UseBassEngine) { MusicianBass.GetInstance().RePerform(Director.RunMana.Musics); } else { Musician.GetInstance().RePerform(Director.RunMana.Musics); } // 清空字符串缓冲 render.dialogPreStr = String.Empty; render.pendingDialogQueue.Clear(); // 关闭自动播放 Director.RunMana.IsAutoplaying = false; // 弹空全部等待,复现保存最后一个动作 Director.RunMana.ExitUserWait(); Interrupt reactionNtr = new Interrupt() { Type = InterruptType.LoadReaction, Detail = "Reaction for rollback", InterruptSA = ssp.ReactionRef, InterruptFuncSign = String.Empty, ReturnTarget = null, PureInterrupt = true }; // 提交中断到主调用堆栈 Director.RunMana.CallStack.Submit(reactionNtr); // 重启并行处理和信号系统 if (needRepara) { var sc = ResourceManager.GetInstance().GetScene(ssp.VMRef.EBP.BindingSceneName); Director.RunMana.ConstructParallelForRollingBack(sc); Director.RunMana.BackTraceParallel(); Director.RunMana.LastSceneName = sc.Scenario; SemaphoreDispatcher.ReBinding(sc, Director.RunMana.SemaphoreBindings); } // 重启消息循环 Director.ResumeUpdateContext(); }
public void StoryBookForwardNextSteady() { // 如果在看背景就先切回故事模式 if (this.ShowingBackground) { DecorateSprite.Descriptor.ToOpacity = 1; DialogueSprite.Descriptor.ToOpacity = 1; SpriteAnimation.OpacityToAnimation(DecorateSprite, TimeSpan.FromMilliseconds(100), 1); SpriteAnimation.OpacityToAnimation(DialogueSprite, TimeSpan.FromMilliseconds(100), 1); //SpriteAnimation.BlurMutexAnimation(MainFrameSprite, TimeSpan.FromMilliseconds(100), 0, 30); this.ShowingBackground = false; return; } // 选择项就忽略 if (this.IsStoryBranching) { return; } // 打字动画中就跳过 if (MsgStoryboard != null) { lock (MsgStoryboard) { if (MsgStoryboard != null) { MsgStoryboard.SkipToFill(); return; } } } // 瞄下队列头,是否是空队列,是的话说明要换页 if (CurrentMessageQueue.Count == 0) { // 全部都结束啦 if (PendingMessageQueue.Count == 0) { this.PrepareClose(); return; } this.StackPanel_DialogList.Children.Clear(); CurrentMessageQueue = PendingMessageQueue.Dequeue(); if (IntentBacklog != null) { BacklogStack.Push(IntentBacklog); } IntentBacklog = ForkableState.DeepCopyBySerialization(CurrentMessageQueue); } // 取下一条要显示的内容 var currentRun = CurrentMessageQueue.Dequeue(); // 选择支:SELECT@分支1@分支2@... if (currentRun.StartsWith("SELECT@")) { var selectionItem = currentRun.Split('@'); var insertBlock = new TextBlock { Opacity = 1, Margin = new Thickness(10, 16, 10, 50), TextWrapping = TextWrapping.Wrap, Foreground = new SolidColorBrush(Colors.White), FontSize = 30, FontFamily = new FontFamily(new Uri("pack://application:,,,/"), "Resources/#Source Han Serif CN SemiBold"), Text = selectionItem[1] }; this.StackPanel_DialogList.Children.Add(insertBlock); for (var i = 2; i < selectionItem.Length; i++) { var selectionLable = new Label { Background = new SolidColorBrush(Color.FromArgb(70, 0, 0, 0)), Margin = new Thickness(10, 80, 10, 0), Foreground = new SolidColorBrush(Colors.White), Height = 60, FontSize = 30, FontFamily = new FontFamily(new Uri("pack://application:,,,/"), "Resources/#Source Han Serif CN SemiBold"), HorizontalContentAlignment = HorizontalAlignment.Center, VerticalContentAlignment = VerticalAlignment.Center, Content = selectionItem[i], Tag = i.ToString() }; selectionLable.MouseEnter += this.Selection_OnMouseEnter; selectionLable.MouseLeave += this.Selection_OnMouseLeave; selectionLable.MouseLeftButtonUp += this.Selection_OnMouseLeftButtonUp; this.StackPanel_DialogList.Children.Add(selectionLable); } this.IsStoryBranching = true; } // 背景:BG@变换时间@图片资源名 else if (currentRun.StartsWith("BG@")) { var selectionItem = currentRun.Split('@'); var bgTransformTime = Convert.ToInt32(selectionItem[1]); var bgResourceName = selectionItem[2]; if (bgResourceName != String.Empty) { // backlay if (this.Image_StoryBook_BgTransitor.Source == null) { this.Grid_StoryBook.Background = new SolidColorBrush(Colors.Transparent); } else { this.Grid_StoryBook.Background = new ImageBrush(this.Image_StoryBook_BgTransitor.Source); } BgTransitorSprite.Descriptor.Opacity = 0; BgTransitorSprite.DisplayBinding.Opacity = 0; this.Image_StoryBook_BgTransitor.Source = resMana.GetPicture(bgResourceName, ResourceManager.FullImageRect).SpriteBitmapImage; BgTransitorSprite.Descriptor.ToOpacity = 1; SpriteAnimation.OpacityToAnimation(BgTransitorSprite, TimeSpan.FromMilliseconds(bgTransformTime), 1); } else { this.Grid_StoryBook.Background = new SolidColorBrush(Colors.Transparent); BgTransitorSprite.Descriptor.ToOpacity = 0; SpriteAnimation.OpacityToAnimation(BgTransitorSprite, TimeSpan.FromMilliseconds(bgTransformTime), 0); } this.StoryBookForwardNextSteady(); } // 声效:SE@音量@SE资源名 else if (currentRun.StartsWith("SE@")) { var selectionItem = currentRun.Split('@'); var volume = Convert.ToDouble(selectionItem[1]); Musician.GetInstance().PlaySE(resMana.GetSE(selectionItem[2]), (float)volume); this.StoryBookForwardNextSteady(); } else { var dialogItem = currentRun.Split('@'); var fgColor = Colors.White; if (dialogItem.Length > 1) { if (CharacterColorDict.ContainsKey(dialogItem[0])) { fgColor = CharacterColorDict[dialogItem[0]]; } currentRun = dialogItem[1]; } var insertBlock = new TextBlock { Opacity = 1, Margin = new Thickness(10, 16, 10, 10), TextWrapping = TextWrapping.Wrap, Foreground = new SolidColorBrush(fgColor), FontSize = 30, FontFamily = new FontFamily(new Uri("pack://application:,,,/"), "Resources/#Source Han Serif CN SemiBold"), Text = String.Empty }; // 把前一条内容透明化 if (this.StackPanel_DialogList.Children.Count > 0) { var lastMsgBlock = this.StackPanel_DialogList.Children[this.StackPanel_DialogList.Children.Count - 1] as TextBlock; var OpacingDescriptor = new YuriSprite() { DisplayBinding = lastMsgBlock, AnimationElement = lastMsgBlock, Descriptor = new SpriteDescriptor() }; OpacingDescriptor.Descriptor.ToOpacity = 0.4; SpriteAnimation.OpacityToAnimation(OpacingDescriptor, TimeSpan.FromMilliseconds(500), 0.4); } this.StackPanel_DialogList.Children.Add(insertBlock); this.TypeWriter(String.Empty, currentRun, insertBlock, GlobalConfigContext.GAME_MSG_TYPING_DELAY); } }