管理系统:物品管理系统



作者:Victor Nicollet
翻译:杨冰(源代码的光)
个人主页:http://www.ngame2000.com
发布:GameRes http://www.gameres.com
创建时间:2004-11-18
介绍

  很多游戏都允许玩家捡取、携带、使用、买卖、丢弃、饮用穿戴各种物品这绝对是个庞大系统里面有太多需要关联东西在这篇文章中会展现个基础物件管理系统给大家


系统构架

  面对个问题是如何将物品信息对应到各自身上:比如血瓶有它名字、外观以及属性;某些物品拥有特定属性如数量、魔法属性、个性名字磨损度等等而且这些属性有可能是在稍后被添加

  那么我们用类cItem来表示某个物品这个类包含了个可以表示物品类型标示如果我们需要获得某个物品属性可通过cItemDatabase来获得这是个物品数据库它中包含所有物品信息

  物品会出现在区别地方比如在地上在交易中或是玩家背包里我们要展现这些物品就需要个集合来统表现类cItemPack就是物品集合我把它翻译成物品包你可以遍历这包中物品添加或移除他们


物品

  第我们来实现物品类这是我们所用功夫最多地方首先考虑物品属性他应该拥有如下属性:
可以设置到另个物品上
和另外个物品对比(看他们是否样)
物品指针
可以返回其唯ID
可以创建个拥有唯ID物品
根据ID排序

现在我们得出了如下类定义:
cItem {
unsigned long type;

public:
cItem( unsigned long );
cItem & operator= ( const cItem & );
bool operator ( const cItem & ) const;
bool operator< ( const cItem & ) const;
unsigned long getID( ) const;
};

上面类有个构造(参数ID)指针比较操作获取ID私有成员变量是物品ID通过这个ID可以从数据库中得到该物品属性

  这里要注意const关键字出现在很多地方在编程中要养成这种好习惯(具体作用大家都知道呵呵)通过const修饰当cItem变得很大时候可以增加更多安全性

下面是实现:
cItem::cItem( unsigned long t ) : type( t ) { }
cItem &cItem::operator =( const cItem & o) { type = copy.type; ( *this ); }

unsigned long cItem::getID( void ) const { ( type ); }
bool cItem::operator ( const cItem & i ) const { ( type i.type ); }
bool cItem::operator <( const cItem &i ) const { ( type < i.type ); }

这个类基础工作就做完了可以在上面添加自己所需要东西接下来我们来谈谈cItemPack


物品包

用户希望物品包拥有如下属性:
个物品放入个包中
创建个空包
个包中将所有物品移除
添加某物品到包中
从包中移除某类物品
计算物品某种类型
将两个包合并成为个包

  包中有列表存放物品类型以后我们就可以通过列表容器来访问集合中物品不过这里时间消耗为O(n)

  也可以使用vector来实现只需要O(1)访问时间但如果包中只存在个物品那就有点浪费另外如果物品很复杂包含很多属性或是两个物品有相同类型但区别属性那么依靠类型来获得物品就会出问题所以我们用map下面是类定义:

cItemPack类:
cItemPack {
std::map< cItem, unsigned long > contents;

public:
cItemPack( cItem & , unsigned long );
void clear( );
unsigned long add( const cItem & , const unsigned long );
unsigned long remove( const cItem & , const unsigned long );
unsigned long getAmount( const cItem & ) const;
const std::map< cItem, unsigned long > & getItems( ) const;
cItemPack & operator= ( const cItemPack & );
cItemPack & operator ( const cItemPack & );
cItemPack operator+ ( const cItemPack & ) const;
};

  通过getAmount接口获取物品数量可以很方便展现商品清单等功能通常cItemPack会表示个实体所以获取物品数量接口是非常重要下面是cItemPack实现部分:

cItemPack::cItemPack( cItem & i, unsigned long a ) { contents[i] = a; }
void cItemPack::clear( void ) { contents.clear( ); }
cItemPack & cItemPack::operator=( const cItemPack & o ) {
contents = o.contents;
( *this );
}

两个构造个清除个=操作:这里没有具体构造是依靠传进来物品接下来可以向集合中添加某种物品

unsigned long cItemPack::add( const cItem & i, const unsigned long a )
{
( contents[i] a );
}

下面会返回某种类型物品数量注意map中操作符并不是const而这个参数却是const所以必须用map const iterator
unsigned long cItemPack::getAmount( const cItem & i ) const
{
std::map< cItem,unsigned long >::const_iterator j;
j = contents.find( i );
( j contents.end( ) ) { ( 0 ); }
{ ( j->second ); }
}

这里我们还需要个移除代码如下:
unsigned long cItemPack::remove( const cItem & i, const unsigned long a )
{
unsigned long t = contents[i];
( a > t ) { contents[i] = 0; ( a-t ); }
{ contents[i] = t-a; ( 0 ); }
}

接下来是两个联合集合:
cItemPack & cItemPack::operator( const cItemPack & o )
{
std::map< cItem,unsigned long >::const_iterator i;
for( i = o.contents.begin( ); i != o.contents.end( ); i )
{
add( i->first, i->second );
}
( *this );
}

cItemPack cItemPack::operator+( const cItemPack & o ) const
{


( cItemPack(*this) o );
}

最后将map接口提供出来:
const std::map< cItem,unsigned long > & cItemPack::getItems( void ) { ( contents ); }


物品数据库

  我们在这里制定物品都有名字有简短描述以及值和重量他们保存在下面结构中:

struct sItemData {
std:: name, description;
unsigned long value, weight;
};

  我们使用monostate来表现这个数据库这个对象类似单件只存在不过不能直接进行全局访问

下面是该对象定义:
cItemDatabase {
const sItemData & getData( const cItem & );
cItem create( const std:: & );
void initialize( const std:: & );
void unload( void );
};

是获得物品数据
第 2个是创建个物品参数是该物品名字

  不过这里需要注意用这些操作物品时候都必要要保证被操作物品是已经被不过要注意如果操作失败这里并没有个返回机制第 2创建在创建物品时候并没有判断穿过来物品名是否有效;第 3用户在获取某个物品时如果该物品并不存在于数据库中同样没有个返回机制来通知用户那么我们现在来创建个返回机制:

enum eDatabaseError {
IDBERR_NOT_INITIALIZED,
IDBERR_INVALID_NAME,
IDBERR_INVALID_ITEM
};

这是数据库定义:
cItemDatabase {
std::deque< sItemData > item_database_entries;
bool item_database_initialized = false;
};

Deque用在这里好处就用不着再讲了呵呵看老外大段都是废话我就懒得翻译了接下来是实现:

void cItemDatabase::initialize( const std:: & s ) {
item_database_entries.clear( );
//FILE LOADING SEQUENCE
item_database_initialized = true;
}

void cItemDatabase::unload( void ) {
item_database_entries.clear( );
item_database_initialized = false;
}

这里并没有具体数据文件代码大家都会有自己套机制本文提供源代码里有作者系统大家可以参考

getData实现:
const sItemData & cItemDatabase::getData( const cItem & i ) {
( item_database_initialized ) {
unsigned long type = i.getID( );
( type >= item_database_entries.size( ) )
{ throw IDBERR_INVALID_ITEM; }
{ ( item_database_entries[type] ); }
}
{ throw IDBERR_NOT_INITIALIZED; }
}

创建实现:
cItem cItemDatabase::create( const std:: & s ) {
( !item_database_initialized ) { throw IDBERR_NOT_INITIALIZED; }
long i;
for( i = item_database_entries.size( )-1; i >= 0; --i ) {
( item_database_entries[i].name s ) { ( cItem(i) ); }
}
throw IDBERR_INVALID_NAME;
}


结论

  这篇文章展示了个高效基本物品系统文章末尾提供了举例文件

  我也在这里做个结论这个物品系统很简单但非常直观几乎所有游戏物品系统都可以在此上面进行延伸我已经打算把这个物品系统用到现在项目上了翻译这篇文章希望对大家有点作用欢迎访问主页: http://www.ngame2000.com



Tags:  信息管理系统 管理系统

延伸阅读

最新评论

发表评论