Jump to content
  • entries
    4
  • comments
    12
  • views
    3,489

Generating Code with Rails


martyj

2,891 views

 Share

In my day job I get a lot of experience with different technologies. Mostly related to mobile or website, but there is a lot of bleed over in the game industry. I've done a few Ruby on Rails applications, it's not my primary toolbox, but it has some benefits. Mostly the ease and speed of development.

 

I switched to using Ruby on Rails for the data management layer of my game. At the moment there isn't much data, only about 300 rows in a database for everything in the game. This is expected to more than triple within the next few months as I add achievements, more items, 7 new quests, and shops!

 

Eventually this will go extremely large and hard coding all that data will become very error prone and next to impossible to manage.

 

Ruby on Rails has the ability to have command line tasks which can be used to generate data.

 

Sample task:

namespace :codegen do
task :achievement_types => :environment do
 erb = ERB.new(File.read('lib/tasks/codegen/achievement_types.erb'))

 params = binding
 params.local_variable_set(:achievementTypes, AchievementType.all)

 data = erb.result(params)

 f = File.new('codegen/AchievementType.h', 'w')
 f.write(data)
 f.close()
end
end

 

What this code does is it loads an ERB file which is a templating file for Ruby.

Queries the database for all AchievementType objects,

Then creates a local binding scope for the template,

Renders the template to a string

Presto, Generated C++.

 

Erb file in question:

#ifndef ACHIEVEMENT_TYPE_H
#define ACHIEVEMENT_TYPE_H
<% achievementTypes.each do |at| %>
#define <%= at.macroname %> <%= at.id %>
<% end %>
#endif

 

Code generated:

#ifndef ACHIEVEMENT_TYPE_H
#define ACHIEVEMENT_TYPE_H

#define ACHIEVEMENT_TYPE_WOODCUTTING 1
#define ACHIEVEMENT_TYPE_FISHING 2
#define ACHIEVEMENT_TYPE_MINING 3
#define ACHIEVEMENT_TYPE_FIREMAKING 4

#endif

 

The use case above is fairly simple, but more complex situations can occur, such as Npc Conversations. Currently my NpcConversation_Gen.h file is 500 lines long. with lists of data similar to this:

 

new NpcConversation(34, 0, "69488b5b-cfd1-4255-bd74-a6b7eeb0e939",
{
 new NpcConversationAction(27, "AddInventoryItem", 39, 1),
 new NpcConversationAction(28, "CompleteMilestone", 3, 15),
},
{
 new NpcConversationConditional(12, "StartedQuest", 3, 0),
 new NpcConversationConditional(13, "HasItem", 57, 10),
}
),

 

Maintaining that code by hand would triple the amount of time to create quests.

 

So if your game uses a large amount of data, I really recommend using a web framework (Ruby on Rails, Codeigniter, Cakephp, Revel, Django, Spring, ect) to manage all your game data!

 Share

7 Comments


Recommended Comments

Curious to what you see the benefits of this over using sqlite with it's C++ library to manage the data in a "database"?

Link to comment

Never used ruby on rails before. When looking at the code it looks like C++ and Lua had a baby. Same question as Rick though. Is the performance so much better than mysql when it comes to basic querrying? For high performance I am still keen on using MonoDB.

Link to comment

@Aggror MySQL is the database I use with Ruby on Rails. The database is not the bottlekneck in performance. Ruby is generally slower than other frameworks, the idea is that hardware is cheaper than development hours.

 

As far as Mongo, be careful using mongo. If you don't use it the way it is intended to be used, it will destroy performance. I personally look at Mongo as like an API caching data layer, not a database itself.

 

@Rick

The major benefit I would say is easy of querying. Instead of my game having to SQL queries, everything is in a list or a hashmap. All the related items are already generated so the game has the best performance. It does add an extra step as far as changing things.

 

To add a quest I have to insert the items in the database (much like sqlite), then run a script to generate the native code, copy over the native code, then recompile.

Link to comment

Ok so you will put the data for quest in the database but instead of reading the database at runtime you're doing these other steps to get the data out at design time and it all gets loaded up on startup? Couldn't you just load all the quests on server startup from a query to the db to get it all in memory right away vs doing these extra steps each time you update a quest in the db?

Link to comment

Ok I'll just making sure I understood what was happening. This is server side stuff for your game right? I thought you went away from c++ for the server app?

Link to comment

I use golang for the server side networking aspect.

 

Ruby on Rails for the application data

 

C/C++ for the Client with plans of migrating client networking to Golang.

 

The end user doesn't touch the Ruby on Rails stuff. Although if you want to browse an old public data aspect of the games data you can visit it here: http://data.worldfactions.net/

 

It's a few months out of date and I haven't bothered to fix images yet as it hasn't been released to the public yet.

Link to comment
Guest
Add a comment...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...