Jump to content




Photo
Posted by martyj, 12 January 2017 · 0 views

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!



Curious to what you see the benefits of this over using sqlite with it's C++ library to manage the data in a "database"?
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.
@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.
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?
@Rick that is another route to solve the same problem.
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?
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.

March 2017

S M T W T F S
   1234
567891011
12131415161718
19202122232425
26 27 28293031 

Recent Entries

Recent Comments

Search My Blog

Tags