Dynamic RPG Game
This is sort of ideas demo for a shared RPG type game.
The aim is:
- A world that can easily be extended by new objects, locations
and characters
- A persistent state, so you always restore the game where you left
it.
- A game-time clock
This demo uses very simple, tile-based graphics and runs at a leisurely
15fps. You can wander around and enter the two sub-areas. This is not too
exciting, it's just a minimal scenario. There's very little error checking,
either.
The program works by loading all the property sheets in the current
directory. A property sheet is stored in a *.oi file and consists of 'name:
value' pairs. All values are strings. Here is an example ollerton.oi:
id: ollerton
name: Ollerton
base: map
location: world
x:70
y:40
img:city2.pcx
map:oll1.pcx
overlay: oll2.pcx
tiles: ollt.pcx
Important properties are
id (other objects refer to this one by its id),
location (says where the city image appears)
base (what type of thing it is)
In this case, the object serves a double duty. It is a small icon on
the world map (properties img, x, y, location) and a map in its own right
(properties map, overlay, tiles)
To add another object, just write a property sheet for it. It will automatically
appear in its proper location. For example, copy this bit out and call it
sword.oi
id: sword
name: Sword
base: item
location: ollerton
img: sword.pcx
x: 3
y: 5
Now the sword will appear in Ollerton (n.b. you can't do anything with
it, yet!) You could just as easily create a new village or town, using 'map'
as a base
When you exit the program, all changed properties are saved in a file
called game.si. Next time, the program loads all the *.oi then all the
data in game.si. Just have a look at the files; they're all text-only.
Altering the code
Each object has a vtable which says how it behaves. The functions are
void draw(OBJ* o, BITMAP* b, int x0, int y0)
- draw the object on b, where the top-left corner of b is (x0,y0) in
world coordinates.
i.e. if the object is (x,y) then you should draw at (16*(x-x0), 16*(y-y0)).
The 16 is the size of tiles. All objects are drawn on tile boundaries for
the moment.
void update(OBJ* o, MAP* m)
- update the object. Many things do nothing, the player will move in
response to key commands and npcs just whizz about at the moment.
void sync(OBJ* o, int direction)
- prepare the object. As properties are strings, it is inefficient to
use them for frequently accessed properties, e.g. (x,y) coordinates. These
are stored as normal member variables in a struct when sync(obj, SYNC_OUT)
is called, then copied back to the property sheet when 'sync(obj, SYNC_IN)'
is called.
So, to define a new object, which shows different behaviour from already-defined
ones, you must write a vtable, then customise 'mapobj_create' to look for
your new 'base' property and call an appropriate creation function.
I hope this is clear. All the vtable stuff you'd have to do for any
game, it's really the property sheets and the way they are loaded up that
is what I wanted to discuss. You can download the source,
here. Please give it a go!
Pete
peterhull90@hotmail.com