Diary of a Browsergame: Setting up the database

One of the first things I do for any new project of mine is design the database – so that’s what’s going to happen to Working Title today. This design will probably change slowly over the course of development – it’s just a good starting point for now.

To begin with, we’ll need a users table.

CREATE TABLE users (
	id int NOT NULL AUTO_INCREMENT,
	username text,
	password text,
	PRIMARY KEY(id)
);

And once we have that, a stats table:

CREATE TABLE stats (
	id int NOT NULL AUTO_INCREMENT,
	display_name text,
	short_name varchar(25),
	PRIMARY KEY(id)
);

If this all looks familiar so far, that’s because it should – this is the exact same table structure(currently, anyway) as the game we’ve been working on. I’m taking all of the design decisions and changes that we made in our other project, and doing my best to apply them here – thereby continually improving my code, and my design.

Because Working Title will have a few distinct ‘entities’, my entity_stats is going to look a little bit different than the one we’re using right now. According to the design document, there are 4 main entities – players, rooms, monsters, and items. Those will make the enum in the entity_stats table:

CREATE TABLE entity_stats (
	id int NOT NULL AUTO_INCREMENT,
	stat_id int,
	entity_id int,
	value text,
	entity_type ENUM('User','Monster','Item','Room'),
	PRIMARY KEY(id)
);

Thinking about it a little more, I’m pretty sure that I don’t need separate tables for each of the entities that can exist within Working Title – all I need is a single table to keep track of their name, ID, description, and type. So that’s what I’m going to do:

CREATE TABLE entities (
	id int NOT NULL AUTO_INCREMENT,
	name text,
	entity_type ENUM('Monster','Item','Room'),
	description text,
	PRIMARY KEY(id)
);

One of the things that the design document mentions is that “users will move between rooms” – which means that I will need way to track which room a user is currently in. I’m going to use a stat to do this:

INSERT INTO stats(display_name,short_name) VALUES ('Current Room','cur_room');

There are also supposed to be players, monsters, and items inside rooms – so I’ll need a table to keep track of all the entities within a room:

CREATE TABLE room_entities (
	id int NOT NULL AUTO_INCREMENT,
	room int,
	entity_id int,
	entity_type ENUM('Monster','User','Item'),
	PRIMARY KEY(id)	
);

Monsters will be able to drop items, so I’m going to need to add a table to do that. Because all they’re going to be able to drop is items(not other monsters or rooms or anything), I can make it so that the monster_drops table only contains information on what items, and what the percentage chance is for them to drop:

CREATE TABLE monster_drops (
	id int NOT NULL AUTO_INCREMENT,
	monster int,
	item int,
	drop_rate int,
	PRIMARY KEY(id)
);

The next table I need to add is one to track a user’s inventory – so I’ll add the user_items table:

CREATE TABLE user_items (
	id int NOT NULL AUTO_INCREMENT,
	user_id int,
	item int,
	quantity int,
	PRIMARY KEY(id)
);

The design document mentions “____ of holding”'s, which is something I haven’t quite figured out yet. I could just use a stat to keep track of the player’s current inventory limit, or I could come up with a better idea. For the moment, I’m going to leave this piece of functionality out of my database design – I’m not sure how to build it yet.(If you know a good way to do this, send me an e-mail at buildingbrowsergames@gmail.com, or comment on this blog post)

Based on the list of commands players can use, there are a few stats that I can add into the database right now:

INSERT INTO stats(display_name,short_name) VALUES ('Maximum Health','max_hp');
INSERT INTO stats(display_name,short_name) VALUES ('Current Health','cur_hp');
INSERT INTO stats(display_name,short_name) VALUES ('Current Weapon','cur_weapon');
INSERT INTO stats(display_name,short_name) VALUES ('Current Armor','cur_armor');
INSERT INTO stats(display_name,short_name) VALUES ('Current Ring (Left Hand)','cur_ring_left');
INSERT INTO stats(display_name,short_name) VALUES ('Current Ring (Right Hand)','cur_ring_right');
INSERT INTO stats(display_name,short_name) VALUES ('Gold In Bank','bank_gc');
INSERT INTO stats(display_name,short_name) VALUES ('Gold In Hand','hand_gc');
INSERT INTO stats(display_name,short_name) VALUES ('Current Level','cur_lvl');
INSERT INTO stats(display_name,short_name) VALUES ('Current Experience','cur_exp');
INSERT INTO stats(display_name,short_name) VALUES ('Experience to Next Level','next_exp');

That sets me up with some of my starter stats, although it’s definitely not all of them – I’m sure I’ll end up adding more stats as Working Title grows into more of a finished product.

The last table that I’m going to add for now is simply for keeping track of exits off of rooms: room_exits:

CREATE TABLE room_exits (
	id int NOT NULL AUTO_INCREMENT,
	name text,
	from_room int,
	to_room int,
	PRIMARY KEY(id)
);

I’ll be tracking the entity_id of both of the rooms, and using the name value to select which exit. For example, an exit to the North from room 1 to 2 might look like this:

INSERT INTO room_exits(name,from_room,to_room) VALUES ('North',1,2);

With all this finished, there’s only one more system to add – spells. I’m not quite sure how I want to implement spells yet, either – do I want to have them do a set amount of damage, or base it on level, or something else? I’m going to hold off on designing any database tables for my spells system for now – once I have Working Title in a playable state, I’ll work on adding spells. For now though, I’m going to stick with what I have – I’ve got the basics of my database in place, and I can safely start developing now.

Wish there was more?

I'm considering writing an ebook - click here.

.

Luke is the primary editor of Building Browsergames, and has written a large portion of the articles that you read here. He generally has no idea what to say when asked to write about himself in the third person.

Monday, July 14th, 2008 SQL, code, database, design, diaryofabrowsergame, workingtitle
  • Mark,

    I think you might have missed the subtle difference between the two fields - in one case, they have a "Monster", "Item", or "Room" value - and in the other case, it's "Item", "Monster", or "User".

  • Mark Little

    Not sure you need the entity_type field in the room_entities table as this is allready declared in the entites table.

    Mark.

blog comments powered by Disqus

About

Building Browsergames is a blog about browsergames(also known as PBBG's). It's geared towards the beginner to intermediate developer who has an interest in building their own browsergame.

Sponsors

Got Something to Say?

Send an e-mail to luke@buildingbrowsergames.com, or get in touch through Twitter at http://twitter.com/bbrowsergames