游戏制作心得(一)

来源:互联网 发布:mac iphoto不能用了 编辑:程序博客网 时间:2024/05/21 10:31

谈了很多关于网络游戏的一些技术技巧和框架,但都是零散的,这有好处,但大多数新手或是爱好者都不知道该如何下手,下面谈谈我的游戏开发心得

 

游戏开发一般使用VC+DX,你可以使用Win32 API直接创建一个Windows应用程序框架,也可以使用MFC来创建一个Windows应用程序框架,注意,并不是像很多人想象的那样,用了MFC就觉得很慢,其实我们只是用MFC搭建了一个应用程序框架,而且MFC有很多很好用的类库,这些类库可以提高我们开发的效率,但并不影响我们的图形渲染和数据处理,因为在图形渲染和数据处理部分我们很少能用得上MFC,不会影响执行效率。

 

当然,不用MFC也可以,直接使用Win32 API 也并不是需要花很多时间。可以根据个人需求进行选择。

 

大多数人都知道游戏的基本结构

 

Game_Init( );

 

while ( )
{
    if ( )
    {
    }
    else
    {
        Update( );
        Render( );
    }
}

 

Game_Destroy( );

 

我先说简单的 Update( )和Render( ) 函数
一般说来不同的数据更新在自己不同的事件中处理,但有很多是带状态的数据,比如:IDirectInput的状态机,需要在一定的时间来处理这些数据,那么我们可以在Update函数里来处理。我们还可以模拟一些自定义的事件消息,比如自定义的UI,或者脚本。

 

Update( )
{
   while ( Events_Count > 0 )
   {
       Do_Events( );
   }
}

 

关于渲染函数很简单了,很多游戏资料都介绍了如何渲染,但渲染什么我稍后再说

 

Render ( )
{
    Begin_Render( );

 

    // 场景,角色,UI等等

 

    ...

 

    End_Render( );
}

 

下面说渲染内容,渲染内容都是预先准备好的。
我们一般有2种方式组织数据,一种我称之为集合式,一种我称之为派生式。
1、集合式
所有的对象都有2个类
class CObj
{
    // 对象的方法属性
};

 

typedef CObj* ObjPtr;

 

class CCObj
{
protected:

 

    map<ObjKey, ObjPtr> m_lstObjs;     // 对象清单

 

public:

 

    CCObj( );
    ~CCObj( )
    {
        clear( );
    } 
 
public:
   
    static CCObj * GetInst( );

 

public:

 

  LoadFromConfigFile( char * szFile );  // 从配置文件中批量读取对象

 

    ObjPtr New( );                         // 直接新建对象
    bool Add( ObjPtr p );                  // 增加新对象
    bool Remove( ObjKey );                 // 移除对象
    ObjPtr Find( );                        // 检索对象

 

    void clear( )                          // 全部清空
    {
        map<ObjKey, ObjPtr>::iterator it = m_lstObjs.begin( );
        for ( ; it != m_lstObjs.end( ); ++it )
        {
            ObjPtr p = (*it);
            if ( p )
            {
                delete p;
                p = NULL;
            }
        }

 

        m_lstObjs.clear( );        
    }
};

 

要特别注意的是那个集合的析构函数,另外还有一个函数就是GetInst( ),它是静态的,用来访问这个类,其实也就是说这个集合类是个全局性的实例,用来管理整个游戏中所用的该对象。那么我们在CPP文件里需要这样定义:

 

#include "Obj.h"

 

CCObj g_CCObj;

 

CCObj * CCObj::GetInst( )
{
   return &g_CCObj;
}

 

这样,关于Obj的数据我们就处理好了,用的时候是随需申请,集中释放,比如:

 

#include "Obj.h"

 

{
   ...
  
   ObjPtr pNewObj = new CObj;
   CCObj::GetInst( )->Add( pNewObj );

 

   ...
}

 

我们不需要去调用delete pNewObj来释放该对象,因为当程序退出的时候,集合CCObj会把所有申请的对象全部集中释放,不用担心内存问题,用的时候只管用就好了。

 

上面的是集合式管理

 

2、派生式管理
派生式管理就是我们定义一个基类
class CObjBase
{
public:

 

   typedef CObjBase * CObjBasePtr;

 

private:

 

   map<ObjKey, CObjBasePtr> m_lstObjs;     // 对象清单
 
public:
  
   bool AddSubObj( CObjBase * pChild )
   {
       m_lstObjs.insert( map<ObjKey, CObjBasePtr>::value_type( pChild->m_Key, pChild );
       return true;
   }

 

   CObjBase( CObjBase * pBase )
   {
       if ( pBase )
       {
           pBase->AddObj( this );
       }
   }

 

   ~CObjBase( )
   {
        map<ObjKey, CObjBasePtr>::iterator it = m_lstObjs.begin( );
        for ( ; it != m_lstObjs.end( ); ++it )
        {
            CObjBasePtr p = (*it);
            if ( p )
            {
                delete p;
                p = NULL;
            }
        }

 

        m_lstObjs.clear( );       
   }

 

};

 

这就像一棵大树,每个节点下面有几个子类,释放的时候一级一级的释放,主要是根节点需要手工释放,用的时候比较方便,但释放时其实是递归调用,所以一般用于休闲小游戏,用法如下:

 

CObjBase * pRoot = new pRoot( NULL );

 

new CObjBase( pRoot );
new CObjBase( pRoot );
...
new CObjBase( pRoot );

 

delete pRoot;

 

上面new的时候甚至不用返回值,我们只需要释放掉pRoot就可以了。所有其他的类都可以从这个基类派生,比如:

 

class CObj1 : public CObjBase
{
};

 

class CObj2 : public CObj1
{
};

 

用的时候

 

p1 = new CObj1( pRoot );
new CObj2( pRoot );
p2 = new CObj2( p1 );
new CObj2( p2 );

 

还是很方便的。

 

今天就讲这么多了,下次再聊

原创粉丝点击