Rapid Prototyping Tip: Defining data as code files

Published January 25, 2017 by Jakub Kasztalski, posted by Koobazaur
Do you see issues with this article? Let us know.
Advertisement

When you're trying to churn out a game fast, it might make more sense to define your items, texts or conversation in code files. Here's how to do it, an example from my current project. On my first two games (Postmortem and Karaski) I set up convenient tools for managing my data. Here is an example of my dialogue trees: karaski129-indie-game-dialogue-sneaking- I used the free yEd graph editor and a bit of custom coding to import the XML data into my game (read about it here!). I also parsed simple text files for all the in-game text items like newspapers. The system worked great, but took a while to set up and debug. As I started on my current experimental story/adventure game HEADLINER, I was embracing a more rapid-prototyping mindset. I did not want to come up with new fancy data structures and write parsers yet again in JavaScript. And it occurred to me - why not define my data directly in code?

Simple strings in newspapers

The "proper" way to read the newspaper data strings would be to create a neatly laid out JSON file, parse that, and create appropriate objects. But I skipped the middle-man, and instead defined them in a separate JavaScript file directly as objects and arrays. Here's what it looks like: headliner-newspaper-files-800x495.jpg It's barely a little bit of extra syntax fluff, and I had instantly-accessible data structure I could reference by simply including the JS file! I didn't need to do any "loading" or parsing either. I also dded a few scripting members (like the ReqApproved) that I'd just check each game day to see if given paper should show or not.

Conditional branching in conversations

Previously I used graphs for flexibility, and many RPG games used flat text files or the (godawfully difficult to follow) trees, like in Neverwinter Nights. neverwinter-nights-dialogue-editor-800x6 Since I didn't plan on too much branching but wanted conditional responses, I'd need to set up some if/else conditions, a way to reference world-state variables, and a way to set them. Meaning: coding a parser and implementing some form of scripting. Again, I realized - wait, why write code that interprets code? I can just write code directly. And so my conversations became yet another Javascript file. I wrote a few helper functions for setting what the NPC says or getting tokens like Player Name, and boom! headliner-conversation-files-800x498.jpg No need to parse code or tokens, since it's automatically executed. Yes, it does require more syntax fluff, but it's pretty manageable once you get the hang of the weird structure and helper functions (like SetThread() or AddResponse()).

Entities and NPCs

To create a world brimming with lively creatures and lucrative loot, most games have some sort of editor to visually place those in 3d or 2d space. The game then loads these "scenes" at startup and creates all the entities as defined. Parsing, parsing, parsing... 11_valve_hammer_editor1b-800x640.jpg I didn't have that with Phaser and JavaScript (though I recommend checking out the Phaser Editor if you'd like an out of the box solution), and each game day would vary a lot depending on numerous conditions. Like before, I differed to the code itself: headliner-npc-spawning-code-800x496.jpg With a few helper functions (Spawn two NPCS with a dialogue, spawn a group of protesters, spawn a rioter who runs and throws a molotov etc.) and pre-defined constants for locations markers, I could quickly create my game world. Because it is code, I could customize each game day by checking for variables, event triggers or randomizing results. All my changes showed up instantly without any exporting/parsing from a 3rd party editor.

This solution is not for everyone

An important caveat needs to be made. This data-in-code approach is really meant for prototyping or small games where you know the amount of data will always be manageable and everyone working with it knows the basics of coding. It can be a huge huge time saver when used properly, but a hindrance on bigger projects with more complex structures or delineated team roles. There is a reason why I set up a whole system to import XML data from a 3rd party graph editor with scripting support for conversations in my first two games. Over the two years of production, the ability to visually edit the dialogue was very important, and it allowed my non-tech savvy writers to work with it as well. Trying to define THIS purely in code would have been a disaster: karas64-indie-game-dialogue-tree-800x372 So, as with any online game dev tutorial, exercise a bit of common sense. It's just a specific tool meant to be used in specific situations.

Curious about my games?

The project that inspired this blog is HEADLINER, story-driven game where you control public opinion and (potentially) start a riot. Check out the official page here. Better yet, why not follow me on Facebook or Twitter for updates and other game dev nuggets of wisdom? headliner-32-riot-breaks-out.gif headliner-40-newsticker.gif
Cancel Save
0 Likes 9 Comments

Comments

Glissando

Wish I read this before I wrote my own parser.

December 29, 2016 09:54 PM
Gru
Gru

If anyone is interested in rapidly utilizing this and more with Unity, I have created a tool to save you much time: https://www.assetstore.unity3d.com/en/#!/content/49521

December 31, 2016 08:55 AM
Polydone

I came to the same conclusion not to long ago. I was planning to make a lot of things datadriven for my RPG, including things such as NPCs, items, player classes along with their skill and stats progression tables etc, but in the end I came to the conclusion: Why design a new syntax and write a parser for it when I can just as easily use my language of choice - C# to define such things... It's not like I'm gonna be working with a team of non-coders any time soon anyway since I'm just myself.

January 02, 2017 12:34 AM
Koobazaur
Glad you guys found it relevant :) And don't worry Glissando, there's always a next game ;)
January 02, 2017 04:07 AM
Kirlim

I believe that if things are properly separated, even for games that expect to grow up exponentially, data-in-code can be good deal, as it follows KISS and YAGNI. Overall, you can do small refactors and incrementally build a parser as needed. Of course, you'd lose time refactoring, but earn time in actually coding only the features you need (if ever). So, maybe, it might be a good way to go most of the times, as long as you don't already own/know a parser (which then you can just use it)

January 02, 2017 11:12 AM
Polydone

I believe that if things are properly separated, even for games that expect to grow up exponentially, data-in-code can be good deal, as it follows KISS and YAGNI. Overall, you can do small refactors and incrementally build a parser as needed. Of course, you'd lose time refactoring, but earn time in actually coding only the features you need (if ever). So, maybe, it might be a good way to go most of the times, as long as you don't already own/know a parser (which then you can just use it)

Good points about separation - Data Definition code files / classes should plug in to the rest of the game code the same way you would have otherwise plugged in file loading/parsing classes.

January 03, 2017 07:05 AM
Koobazaur

Oh yea excellent point, a little abstraction layer is especially effective with this approach. In the game described, I never reference the newspapers directly via the array defined in code, instead I had a NewspaperMan(ager) class that abstracted it via simple functions like GetNewspapersForDayX() or ApproveOrBanNewspaper(). I could then completely refactor how I store the data without teaching any of the other code.

January 04, 2017 09:31 PM
leetNightshade

This post seems like a no brainer to me? If you're trying to write lots of parsers and tools for a very small project you need to quickly iterate on and don't have a lot of time to work on, you're overengineering and have a problem. Cut through the bullshit, and work on what needs to get done instead of wasting your time on things that don't have to be done with the time you have. It's a personal problem, through lack of good organization and time management. I have that problem with my personal stuff.

But also because of that, this approach isn't useful to anyone in the work world where you do need to develop tools and provide good support for a project. I was hoping to get something useful out of this post to apply to the real world.

January 21, 2017 12:44 AM
Norman Barrows

>> It's barely a little bit of extra syntax fluff,

>> Yes, it does require more syntax fluff,

the extra keystrokes for coding is nothing compared to the extra keystrokes for implementing a data driven solution with parser, data files etc.

this makes non-data driven a very powerful tool for increasing productivity - but one which is most useful to solo devs, and not really an option for non-coders or large teams.

i use mostly non-data driven in Caveman 3.0. i can compile 150,000+ lines of c++ in 1 second, and link a 2+ meg executable in about 10 seconds. its only about 20 seconds + edit time to save, quit, make a change, recompile, restart the game, and load back up where i was to test the change.

to avoid writing parsers for data driven stuff, i have a generic data driven file format and API. the files are text files, with one data value per line. read / write order implicitly defines what var goes with what value - so you don't have to map key,value pairs to variables - like with a generic json read. The API provides routines for reading ints, floats, and strings. any line that begins with a "/" is a comment, and is skipped by the read routines. this lets you embed comments in the data file to help identify what the values are - since there are no explicit keys. this single format and 3 routine API can be used for just about anything, from lists of assets to load, to data driven entity definitions. and its less work than a json type approach, while still giving you data driven capabilities.

non-data driven is not just for prototyping. what matters most is what is most productive for your situation.

with short build times, one or just a few coders, and no non-coders, that can often be non-data driven, as opposed to data driven.

January 24, 2017 12:51 PM
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!

When you're trying to churn out a game fast, it might make more sense to define your items, texts or conversation in code files. Here's how to do it, an example from my current project.

Advertisement
Advertisement

Other Tutorials by Koobazaur

Advertisement