Here's some tips based on my experience with text and dialog.
LocalizationPersonally I like to use Google Docs and spreadsheets for the text. The first column is the text key (i.e. what it's called in code) and then I have a column for each language. The headers give the language names for me. I like this approach because it's far easier to see which languages are missing what text rather than having to compare multiple separate files.
Google Docs can nicely export CSV files which are fairly easy to parse but you can also find lots of open source solutions as well:
https://github.com/search?l=C%23&q=csv&ref=searchresults&type=Repositories&utf8=✓I have a build step for our game that reads in our CSV file and generates separate language binary files we read in at runtime. This makes it easier to update individual languages post-ship as well as not requiring that we load all languages all the time (though in our game we have little text so we just load everything to make life easy). Also we generate an enum with all the text keys so that we have some type safety around our string lookups.
That said, in
Shipwreck we did use a basic text file which looked something like this:
string_key_001
This is a string!
We read each line one at a time. If we saw a line that didn't start with spaces, we knew it was a string key. Otherwise we built up the string given the lines and associated it with the last key we read. This worked, but was also a bit of a pain. I'd recommend CSV instead.
DialogWe had dialog in
Shipwreck, albeit in a fairly basic form. All of our dialog was also a text format that looked something like this:
== take_care ==
start: true
condition: visited_node give_pickaxe
text: miner_pickaxe_take_care
== no_pickaxe ==
start: true
text: miner_pickaxe_not_available
switch:
check_marker mayor_permission_pickaxe : yes_pickaxe
== yes_pickaxe ==
start: false
text: miner_pickaxe_mayor_permission
goto: give_pickaxe
== give_pickaxe ==
start: false
add_item: pickaxe
destroy_object: pickaxe
goto: lantern
== lantern ==
start: false
text: miner_pickaxe_lantern
goto: take_care
Each of the lines with the == wrapped around is the name of a "node". Each node then has a set of properties. Start is whether or not the dialog can start there. Condition let us set up some basic scripting conditions that could check variables. We also had a text property for the string key to lookup. Switch was like a set of conditions that are checked in order, which let us jump around a bit. Then we had things like goto to jump between nodes, add_item to give the player stuff, destroy_object to remove things from the world, and others.
Parsing this was also pretty straightforward since we could look for the == starting a line to know we had a new node and each property was its own line so we just checked the start of each line for our keywords. Here's a chunk from our parser that shows how we handled the text:
http://pastebin.com/AkVaSMFj. As you can see it's not terribly complicated or clever. But we also ran this code at build time to generate more optimized binary files to read at runtime, so our text parsing didn't have to think about performance or garbage collection, really.
General ParsingGeneral tips for text parsing in C#:
- StreamReader is a great class for reading in text from files.
- String has some great methods you can use: IndexOf, StartsWith, and Split.
- Focus on making it work rather than being super complicated. You don't need every feature for every game; you only need the features for your game.
Hope that helps!