public void makeShow(thePlotItem theItem) { makeBigPicture(theItem); makeSmallPicture(theItem); makeBackPicture(theItem); maketalkBox(theItem); }
//建立各个分支之间的父子关系 //如果有分支的话,每一个分支都是都是在结尾的时候才会真的进行分叉活动 //排布方式为第一层为1,固有的 //第二层1-9 //第三层1-9 void setBranchParent() { //第一步,寻找root那个100项是根,不可撼动 List <thePlotItem> theRoot = new List <thePlotItem> (); List <List <thePlotItem> > theSecondLayer = new List <List <thePlotItem> > (); List <List <thePlotItem> > theThirdLayer = new List <List <thePlotItem> > (); List <int> theSecondLayerID = new List <int> (); List <int> theThirdLayerID = new List <int> (); //字典的每一个分支内部排序 for (int i = 0; i < theIDS.Count; i++) { int A = theIDS [i] / 100; int B = theIDS [i] % 100 - theIDS [i] % 10; int c = theIDS [i] % 10; //这个剧本文件的总root if (A >= 1 && B == 0 && c == 0) { theRoot = theStartItemSaver [theIDS [i]]; } //这个剧本文件的第二层root else if (A >= 1 && B != 0 && c == 0) { theSecondLayer.Add(theStartItemSaver [theIDS [i]]); theSecondLayerID.Add(B); //保留十位数字 } //余下的都是叶子节点 else { theThirdLayer.Add(theStartItemSaver [theIDS [i]]); theThirdLayerID.Add(B); } } //第二层的所有的头结点都是root的末尾的子节点 thePlotItem theEndOfRoot = theRoot [theRoot.Count - 1]; theRootTranform = theRoot [0].transform; //保留树根引用 //print (theEndOfRoot.name + " ++++++"); //区分出层之后,开始建立父子关系 for (int i = 0; i < theSecondLayer.Count; i++) { //print (theSecondLayer [i] [0].name +"-----"); theSecondLayer [i] [0].transform.SetParent(theEndOfRoot.transform); } //叶子结点需要嵌套循环了 for (int i = 0; i < theThirdLayer.Count; i++) { for (int j = 0; j < theSecondLayer.Count; j++) { //十位数相同,父子关系已经确定了 if (theThirdLayerID [i] == theSecondLayerID [j]) { //第二层的所有的头结点都是root的末尾的子节点 thePlotItem theEndOfRootE = theSecondLayer [j][theSecondLayer [j].Count - 1]; theThirdLayer [i] [0].transform.SetParent(theEndOfRootE.transform); } } } }
//这个脚本的计算开销很大,能减少一点就是一点 void quickSort(List <thePlotItem> theP, int low, int high) { if (low >= high) { return; } int first = low; int last = high; thePlotItem keyValue = theP[low]; while (low < high) { while (low < high && theP [high].theBranchTalkID >= keyValue.theBranchTalkID) { high--; } theP [low] = theP [high]; while (low < high && theP [low].theBranchTalkID <= keyValue.theBranchTalkID) { low++; } theP [high] = theP [low]; } theP [low] = keyValue; quickSort(theP, first, low - 1); quickSort(theP, low + 1, last); }
//---------------------------------------------------------------------------------------------------// //-------------------------------剧本树的相关操作------------------------------------------------------// //鼠标点击空白部分就意味着galgame要跳转到下一行剧本了 void moveToNextItem() { //剧本帧为空就不做操作了 if (theItemNow == null) { return; } //直接跳转的权限高于一切,虽然大多数情况下此项为空 if (theItemNow.aimPlotItemID > 0) { theDataController.loadItemForSkip(theItemNow.aimPlotItemID); return; } //如果是一个分支节点 if (theItemNow.isASpitRoot()) { //print ("这是一个分支节点,有待选择"); //进入选择界面,在这里不标明要走哪一条路线,在UI选择的时候才会真的有所选择 theChoiceController.openSelect(theItemNow.getChilds()); //可选功能,在选择的时候关闭文本框 //theTextController.shutTEXT (); } else { //如果是死亡场景,就直接进入道场 if (DeathFile.setDead(theItemNow.ThePlotItemID.ToString())) { UnityEngine.SceneManagement.SceneManager.LoadScene("DeadScene"); //进入到死亡道场 } else { //theTextController.openTEXT (); theItemNow = theItemNow.moveToNext(); //如果是回忆就需要检查一下是不是完事了 if (systemInformations.isScene && theItemNow.ThePlotItemID > systemInformations.SceneEndIndex) { UnityEngine.SceneManagement.SceneManager.LoadScene("start"); //直接返回到开始界面 } else { playTheItem(theItemNow); } } } }
//小的排序方法 //最从小到大排序的 void sort(List <thePlotItem> theP) { for (int i = 0; i < theP.Count; i++) { for (int j = i; j < theP.Count; j++) { if (theP[i].theBranchTalkID > theP [j].theBranchTalkID) { thePlotItem temp = theP[j]; theP [j] = theP [i]; theP [i] = temp; } } } //输出检查排序是否完成 //for (int i = 0; i < theP.Count; i++) // print (theP[i] +" "); }
//说话的时候的小图 void makeSmallPicture(thePlotItem theItem) { if (string.IsNullOrEmpty(theItem.theSpeekerName) || theItem.theSpeekerName.Equals("Caim")) { //不显示 getPart(theItem.theSpeekerName).sprite = theNoOnePicture; thePeopleSmallPictureName = "noOne"; } else { if (theItem.theSpeekerName.Equals(thePeopleSmallPictureName) == false) { string textureName = "people/small/" + theItem.theSpeekerName; //getPart(theItem.theSpeekerName).sprite = systemInformations.makeLoadSprite (textureName); loadWithCheckForSmallPicture(getPart(theItem.theSpeekerName), textureName); thePeopleSmallPictureName = theItem.theSpeekerName; } } }
//全体剧本树的初始化在这里完成 //完全自动化处理,只需要在控制面板里面处理好相应的父子关系就可以了 //初始化第二阶段 public void InitTheTree(TextAsset thePlot) { Transform theRoot = theTreeMake.makeATree(thePlot); theRoot.transform.SetParent(this.transform); //this.GetComponent <allStartController> ().makeATree (); int count = this.transform.childCount; for (int i = 0; i < count; i++) { Transform theChild = this.transform.GetChild(i); if (theChild.GetComponent <thePlotItem> ()) { thePlotItem theItem = theChild.GetComponent <thePlotItem> (); roots.Add(theItem); theItem.makeStart(); //递归初始化 } } theItemNow = theRoot.GetComponent <thePlotItem> (); //初始化当前处理的项目 watiForSkipTimer = theItemNow.waitTimeForAutoSkip; }
//操作剧本树单元的方法,这个程序真正用来玩的方法 //事实上,这个方法只会对单个分支节点生效 public void playTheItem(thePlotItem theItem = null) { //简单的防护措施 if (theItem == null) { //额外的文件处理 //既然已经完成了,就保存一下吧 systemInformations.SaveTheOverPlot(); CGModeFile.saveCGFile(); SceneModeFile.saveSceneFile(); extraHFile.saveHExtra(); //print ("没有可控制的剧本元素"); SceneManager.LoadScene("start"); return; } //尝试激活Scene //规则是当一个剧本帧的下标到达了某一个scene的最后一个下标,那么这个scerne就可以被解锁 SceneModeFile.activeScene(theItem.ThePlotItemID); //每一次新跑一个剧本帧的时候才会真的初始化这个剧本帧的儿子节点 //性能消耗均摊,这样看上去要比初始化的时候气归初始化要好一点 theItem.makeStart(); theItemNow = theItem; watiForSkipTimer = theItemNow.waitTimeForAutoSkip; //各种控制单元对这个单元的操作 theTextController.setTheString(theItem); theUIController.makeShow(theItem); //print ("theMusicController name is " + theMusicController.gameObject.name); theMusicController.playBackMusic(theItem); theSoundController.playSound(theItem); thePeopleSoundController.playSound(theItem, true); //剧本帧完成之后这些计算才能生效 //剧本完成度控制 systemInformations.addPlotOverPercent(theItem); //好感度控制 theItem.makeAddLoveValue(); }
//背景图 void makeBackPicture(thePlotItem theItem) { if (string.IsNullOrEmpty(theItem.theBackPictureName)) { //显示默认背景图,没有不行啊 //这也是显示出来的第一张的图了 theBackPicture.sprite = systemInformations.makeLoadSprite("backPicture/home"); theBackName = "home"; } else { //只有指定换图的时候才会换图 if (string.IsNullOrEmpty(theItem.theBackPictureName) == false && theItem.theBackPictureName.Equals(theBackName) == false) { //print ("back picture change"); theBackName = theItem.theBackPictureName; if (theBackName != "changeBack") { //print ("change the back"); //CG 控制 CGModeFile.CGActive(theBackName + "_Button"); //激活这个CG theBackPicture.sprite = systemInformations.makeLoadSprite("backPicture/" + theBackName); } else { //这个转换是一个非常细节的转换,需要保证转换的时间要比下一个剧本帧的转换时间短,要不然会出现图片转换会出现问题 Invoke("waitChangeInvoke", theItem.waitTimeForAutoSkip * 0.5f / Time.timeScale); if (theForwardPicture && theForwardPicture.gameObject.activeInHierarchy) { theForwardPicture.makeChange(theItem.waitTimeForAutoSkip * 1.6f); } } } } }
//建立所有的plotItem并作简单的初始化 //根据一个剧本控制生成一棵树 void create(TextAsset thePlot) { string[] theInformation = thePlot.text.Split('\n'); for (int j = 0; j < theInformation.Length; j++) { //下面制作已用了trycatch,其实就是有空格而不是空行的情况,因此可以在这里做一下处理 //在这里去掉了所有的空格,所以后面的剧本元素就没有必要在做这些操作了,这样就可以减少十次多出来的操作 //原先使用Trim来做的,这是一个非常巨大的危害 theInformation [j] = theInformation [j].Replace(" ", ""); if (theInformation[j].StartsWith("//") || string.IsNullOrEmpty(theInformation[j])) { continue; } //"//"是一个文本编辑用的分隔符号,顺带用于注释 try { //在这里需要追加更加细致的设定和分割 //并且首位随意添加空格 string[] theInformationIn = theInformation [j].Split(','); int thePlotBranchID = Convert.ToInt32(theInformationIn[0]); int theBranchTalkID = Convert.ToInt32(theInformationIn [1]); string theSpeekerName = theInformationIn [2]; /* * speakerName 说话的人 * SpeakerPictureName 说话的人的图的特征 * speakerName_picName 就是资源的名字 * 例如 alice_happy * 至于中文名称显示翻译,用一个数组做映射就行,反正也没几个人 */ string player1 = theInformationIn[3]; //参与说话的第一个人 string player2 = theInformationIn[4]; //参与说话的第二个人 string player3 = theInformationIn[5]; //参与说话的第三个人 string theBackPictureName = theInformationIn [6]; string theTalkInformation = theInformationIn [7]; string title = theInformationIn [8]; //额外标记 string musicName = theInformationIn [9]; //背景音乐名称 string soundName = theInformationIn [10]; //音效模名称 //print("music :" + musicName +" sound :"+ soundName); string aimIDIN = theInformationIn [11]; string speakName = theInformationIn[12]; string extraAction = theInformationIn[13]; int aimID = -1; if (string.IsNullOrEmpty(theInformationIn [11]) == false) { try { aimID = Convert.ToInt32(theInformationIn [11]); //跳转目标 } catch { aimID = -2; } } //制作剧本帧 GameObject theNewItem = GameObject.Instantiate <GameObject> (theProfabForItem); thePlotItem theItem = theNewItem.GetComponent <thePlotItem> (); theItem.makeCreate1(thePlotBranchID, theBranchTalkID, theSpeekerName, theBackPictureName, theTalkInformation, title); //print("====="+player1 +"======"+player2 +"======"+player3); theItem.makeCreate2(player1, player2, player3, musicName, soundName, aimID); theItem.makeCreate3(speakName, extraAction); theStartItems.Add(theItem); //直接按照分支进行整理,但是顺序和父子关系在这一步还没有确定 } catch { //这一行可能是空行,直接跳过就可以了 continue; } } }