天行健 君子当自强而不息

游戏中物件的定义与使用(5)

 

本篇是游戏中物件的定义与使用(4)的续篇。

 

使用物品清单系统管理物件

物件被分散在四处,玩家们找到这些物件只不过是一个时间问题。对于这种情况,玩家需要运用一种方法去管理物件,包括使用物品清单控制系统(inventory control system,ICS)来进行分类整理。

请不要误解,一个ICS并不只适用于玩家,它同样适用于整个游戏世界。物件可以属于一张地图,一个角色,甚至是另一个物件(例如背包,有一些其他的物件在它里面),那就意味着物件需要指定它的所有者(ownership)。除此之外,一个所有者可以拥有一个物件的多个实例(multiple instance),例如货币。

所有者的物件收藏称之为物件清单列表(inventory list),任何物件都可以归属到这个列表中去(也包括物件的众多实例)。所有者,物件清单列表,以及数量之间的关系如下表所示:


 

ICS和MIL相互协调工作,MIL只保存了世界中每个物件惟一的实例,而ICS则使用了物件的众多实例。每当ICS需要一个物件的信息时,它可以引用MIL。以这种方式,可以仅使用ICS保存MIL中的物件引用编号(如下图所示),以节省大量内存。

For your game’s maps and levels, a simple ICS (called a map ICS) consists of only a
list of items and their locations within the map, which is just fine because you can
place objects throughout—ready for characters to pick them up. The real problem
comes when those characters pick them up and add them to their inventory.
Multiple instances pile up, new items are added, and other items are used or
dropped. Things quickly become a real jumble. Handling a collection of character’s
objects is the job of a character ICS, which is a little more complicated than its map
counterpart.

 

开发一个地图ICS

The map ICS tracks items that are placed within levels, including items that are
contained within other items—a sword contained within a treasure chest, for
example. The type of map you use determines how you position items within the
map. In 3-D maps, you use three coordinates for positioning an item—the X-, Y-,
and Z- coordinates. Because each map is also unique (each part of the world has
different maps), you can track each map’s items in separate files.

You can represent the map ICS with a structure and a class:

//==================================================================================
// This structure contains map item information list.
//==================================================================================
typedef struct sMapItem
{
    
long    item_index;             // MIL item index
    long    quantity;               // quantity of item (ie coins)
    float   x_pos, y_pos, z_pos;    // map coordinates

    sMapItem*   prev;
    sMapItem*   next;

    
long    index;          // map item index
    long    owner_index;

    sMapItem*   parent;     
// parent of a contained item
    
    sMapItem()
    {
        memset(
this, 0, sizeof(*this));
        owner_index = -1;
    }

    ~sMapItem()
    {
        delete next;   
    }
} *sMapItemPtr;

//==================================================================================
// This class encapsulate map inventory contrl system.
//==================================================================================
typedef class cMapIcs
{
private:
    
long        m_num_items;
    sMapItemPtr m_root_item;

private:
    
long    get_next_long(FILE* fp);
    
float   get_next_float(FILE* fp);

public:
    cMapIcs();
    ~cMapIcs();

    
bool load(const char* filename);
    
bool save(const char* filename);
    
void free();

    
void add(long item_index, long quantity,
             
float x_pos, float y_pos, float z_pos,
             sMapItemPtr owner_item);

    
void remove(sMapItemPtr item);

    
long get_num_items();
    sMapItemPtr get_root_item();
    sMapItemPtr get_item(
long index);
} *cMapIcsPtr;

First, you see the sMapItem structure, which holds the information for every item in
the map. item_index is the MIL item reference number (which ranges from 0 to 1,023
if you used the MILEdit program), and quantity is the number of item_index (to allow
things like a horde of coins to be represented as a single object). Then you see the
item’s map coordinates x_pos, y_pos, and z_pos.

Next comes the prev and next pointers. You insert them to track a linked list of
sMapItem structures. The next couple of variables, index and owner_index, are used when
loading and saving the items in a map. Index stores the current index number of
an item in the linked list. If an item is owned by another item, the Owner variable
holds the index number of the parent object (otherwise, Owner is set to -1). When
loading (or adding) an object, you set the final variable in sMapItem (parent) to point
to the actual owner item’s structure. You can see the sMapItem structure link list concept
illustrated in Figure 15.8.

The sMapItem uses both a constructor and destructor function called whenever a
structure instance is allocated or reallocated. Both functions ensure that the linked
list pointers are in check, and whenever a structure is deleted, all subsequent
sMapItem structures in the linked list are deleted as well.

CAUTION
If you’re removing only a single instance of sMapItem from the linked list, you first have to
set the instance’s Next variable to NULL. Doing so ensures that all subsequent instances in the
linked list are not deleted as well.

The cMapICS class has two private functions (get_next_long and get_next_float) used to read
in text and convert it into a long or float value. The cMapICS class also has eight usable
public functions. Take a closer look at those public functions.


posted on 2007-11-07 18:31 lovedday 阅读(218) 评论(0)  编辑 收藏 引用


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


公告

导航

统计

常用链接

随笔分类(178)

3D游戏编程相关链接

搜索

最新评论