public override void Initialize() { base.Initialize(); this.FadeOutImmediately(); _choicesTaken.Clear(); string content = Resources.Nodes; Node startNode = NodeHelper.GetStartNode(content); this._nodeTitle = this.AddText(""); this._nodeTitle.FontSize = TITLE_SIZE; this._nodeTitle.Font = Font.GetFont("Fonts/Orbitron"); this._nodeTitle.FadeOutComplete += () => { // Done; flip content showContentFor(this._nextNode); foreach (Button b in this._choiceButtons) { b.Alpha = 0; b.AlphaRate = CONTENT_FADE_RATE; } if (this._theEndButton != null) { this._theEndButton.Alpha = 0; this._theEndButton.AlphaRate = CONTENT_FADE_RATE; } this._nodeTitle.AlphaRate = CONTENT_FADE_RATE; this._contentText.AlphaRate = CONTENT_FADE_RATE; this._choicesTitle.AlphaRate = CONTENT_FADE_RATE; this._nextNode = null; }; this._contentText = this.AddText(""); this._contentText.Z = 1; // Always above (changing) images. this._choicesTitle = this.AddText("Actions"); this._choicesTitle.FontSize = TITLE_SIZE; this._choicesTitle.X = TEXT_TITLE_OFFSET; this._choicesTitle.Y = CHOICES_TITLE_POSITION_Y; this._choicesTitle.Font = Font.GetFont("Fonts/Orbitron"); this._textPanel = this.AddSprite("text-panel"); this._textPanel.Click += () => { if (this._currentPanel < this._contentPanels.Length - 1) { this._contentText.FadeOut(); } }; this._contentText.FadeOutComplete += () => { if (this._currentPanel < this._contentPanels.Length - 1) { this._currentPanel++; showCurrentContentPanel(); } }; this._textPanel.Z = 100; // float above all. this._contentText.Z = this._textPanel.Z + 1; // 2*TEXT_PANEL_PADDING suffices, but make space for the MORE button and stuff. TEXT_PANEL_READABLE_AREA_WIDTH = this._textPanel.Width - (3 * TEXT_PANEL_PADDING); showContentFor(startNode); CoreModel.Instance.StartTime = DateTime.Now; this.FadeIn(); }
private void showLinksFor(Node currentNode) { showContentLinks(currentNode); if (currentNode.Links.Count == 0) { this._theEndButton = this.AddButton("The End"); this._theEndButton.Skin = "Gold"; this._theEndButton.FontSize = 18; this._theEndButton.Click += () => { this.FadeOut(); this.FadeOutComplete += () => { CoreModel.Instance.ChoicesTaken = this._choicesTaken; ScreenController.ShowScreen(new SummaryScreen()); }; }; this._theEndButton.X = (SCREEN_WIDTH - this._theEndButton.Width) / 2; this._theEndButton.Y = calculateYForButton(this._theEndButton); if (this._currentPanel == this._contentPanels.Length - 1) { this._theEndButton.Alpha = 0; this._theEndButton.AlphaRate = CHOICES_BUTTON_FADE_RATE; } } positionButtons(); }
private void showContentLinks(Node currentNode) { IList<NodeLink> links = currentNode.Links; for (int i = 0; i < links.Count; i++) { Button choiceButton = this.AddButton(links[i].Caption); choiceButton.Skin = currentNode.Template; Node target = links[i].Target; string choice = links[i].Caption; choiceButton.Click += () => { if (target.Template == currentNode.Template) { fadeOutContentControls(); this._nextNode = target; } else { this.FadeOut(); // FadeOutComplete already has the right event. } this._choicesTaken.Add(choice); }; choiceButton.FontSize = 16; if (this._currentPanel == this._contentPanels.Length - 1) { choiceButton.Alpha = 0; choiceButton.AlphaRate = CHOICES_BUTTON_FADE_RATE; } this._choiceButtons.Add(choiceButton); } }
private void showContentFor(Node currentNode) { this._currentNode = currentNode; loadSpritesForCurrentNode(currentNode.Template); this._nodeTitle.Content = currentNode.Title; this._nodeTitle.X = TEXT_TITLE_OFFSET; this._nodeTitle.Y = TITLE_POSITION_Y; centerTextPanel(); this._currentPanel = 0; this._contentPanels = getTextInPanels(currentNode); clearLinks(); showCurrentContentPanel(); // Badge~! if (currentNode.Title.Equals("Martyred")) { new BadgeManager().GrantBadge("IZ_UTEBXkBeOe3pcKx8KC82dZ2jgLraG_smE313LCQWkHsIBodEZ1RzJ2n8MHJ6H"); } }
private string[] getTextInPanels(Node currentNode) { List<string> toReturn = new List<string>(); // Get the broken-up text. Add a little buffer for the "[more]" part. string rawText = Text.StringFittedToWidth(currentNode.Content, TEXT_PANEL_READABLE_AREA_WIDTH).Trim(); int textPanelReadableAreaHeight = this._textPanel.Height - (2 * TEXT_PANEL_PADDING); // Manual override, I hate you. WHYYY?!??! //int linesPerPanel = (int)Math.Floor(textPanelReadableAreaHeight * 1.0f / this._contentText.Font.Size); int linesPerPanel = 13; string[] textInLines = rawText.Split('\n'); StringBuilder builder = new StringBuilder(); for (int i = 0; i < textInLines.Length; i++) { if (i % linesPerPanel == linesPerPanel - 1) { // This was the last line in a panel. // Corner case: adding to a blank line. Remove last \n if (string.IsNullOrWhiteSpace(textInLines[i])) { builder.Remove(builder.Length - 1, 1); } builder.Append(textInLines[i]); // Corner case: don't add [more] on the last panel. Happens sometimes. if (i < textInLines.Length - 1) { builder.Append(" [more]").Append('\n'); } toReturn.Add(builder.ToString().Trim()); builder.Clear(); } else { builder.Append(textInLines[i]).Append('\n'); } } string lastPanel = builder.ToString().Trim(); if (!string.IsNullOrWhiteSpace(lastPanel)) { // Corner case: don't give us an empty panel at the end. toReturn.Add(lastPanel); } return toReturn.ToArray(); }
// Returns the starting node private static Node parseContentAndMakeGraph(string content) { Regex nodeStartRegex = new Regex("(Start )?Node: (.+)"); Regex linkRegex = new Regex("(.+) => (.+)"); Node startNode = null; Dictionary<string, Node> nodes = new Dictionary<string, Node>(); Node currentNode = new Node(); string[] lines = content.Split(new char[] { '\n' }); for (int i = 0; i < lines.Length; i++) { string line = lines[i]; if (string.IsNullOrWhiteSpace(line)) { continue; } if (nodeStartRegex.IsMatch(line)) { Match m = nodeStartRegex.Match(line); // Start of a node if (!string.IsNullOrEmpty(currentNode.Content)) { if (nodes.ContainsKey(currentNode.Title)) { throw new Exception("There are two nodes named " + currentNode.Title); } else { nodes[currentNode.Title] = currentNode; } } currentNode = new Node(); currentNode.Title = m.Groups[2].Value.Trim(); if (!string.IsNullOrEmpty(m.Groups[1].Value)) { if (startNode != null) { throw new Exception("Second start node occurred (" + currentNode.Title + "); original was " + startNode.Title); } startNode = currentNode; } } else if (line.Trim().Equals("Links:")) { i++; line = lines[i]; while (!(nodeStartRegex.IsMatch(line)) && !string.IsNullOrEmpty(line.Trim()) && i < lines.Length) { Match l = linkRegex.Match(line); NodeLink n = new NodeLink(); n.Caption = l.Groups[1].ToString().Trim(); n.TargetName = l.Groups[2].ToString().Trim(); // Map later once all nodes are loaded currentNode.AddLink(n); i++; if (i < lines.Length) { line = lines[i]; } } } else if (!line.StartsWith("#")) { // # indicates a comment currentNode.Content += line.Trim() + "\n\n"; } } // We're done; add the final node if (nodes.ContainsKey(currentNode.Title)) { throw new Exception("There are two nodes named " + currentNode.Title); } else { nodes[currentNode.Title] = currentNode; } nodes[currentNode.Title] = currentNode; // Link everything up foreach (Node n in nodes.Values) { foreach (NodeLink l in n.Links) { if (!nodes.ContainsKey(l.TargetName)) { throw new Exception("Link " + l.Caption + " in node " + n.Title + " links to non-existent node " + l.TargetName); } else { l.Target = nodes[l.TargetName]; } } } return startNode; }