zoukankan      html  css  js  c++  java
  • ECS 游戏架构 应用

    转载自:http://blog.csdn.net/i_dovelemon/article/details/30250049

    如何在cocos2d-x中使用ECS(实体-组件-系统)架构方法开发一个游戏? - 博客频道

     

                  在我的博客中,我曾经翻译了几篇关于ECS的文章。这些文章都是来自于Game Development网站。如果你对这个架构方式还不是很了解的话,欢迎阅读理解 组件-实体-系统实现 组件-实体-系统

                  我发现这个架构方式,是在浏览GameDev上的文章的时候了解到的。很久以前,就知道了有这么个架构方法,只是一直没有机会自己实践下。这一次,我就抽空,根据网上对ECS系统的讨论,采用了一种实现方法,来实现一个。

                 我很喜欢做游戏,所以同样的,还是用游戏实例来实践这个架构方法。我将会采用cocos2d-x来作为游戏开发的主要工具,这是一款十分强大的跨平台游戏引擎,感兴趣的读者,可以自行搜索了解。

                 我一直觉得,作为游戏程序员,能够自己独立的绘制游戏中的图片资源是一件非常好玩的事情。所以,没有美术功底的我,就选择了一种复古风格的艺术——像素艺 术来学习。经过一段时间的学习,发现做像素画还是很有趣的,所以我就将我以前做的简单的像素图片,来融合成现在的这个游戏实例——ShapeWar 。

                这个游戏很简单,玩家通过键盘上的左右键来移动发射器,通过按下space键,来进行攻击,将所有掉落下来的立方体全都打掉。如果有立方体遗漏掉,那么将 会丢掉一颗血,直到玩家死亡为止。这个游戏,开始的时候,可能会非常容易,但是,立方体下落的速度是逐渐增加的,到了后面,如果玩家还能够坚持住的话,那 非常了不起!!!

                好了,游戏规则很简单,来看看游戏的截图吧!

                     好了,这个游戏很简单,有兴趣的同学,可以到这里来下载,试玩一下,并且在留言中,告诉我,你最高得了多少分哦!!!

                    从上面的截图,大家也能够明白,游戏只有两个场景,分别是开始场景,和游戏进行场景。需要完成的功能如下:

    •   能够产生立方体,控制立方体产生
    •   能够控制发射器,发射出球体
    •   能够检测出球体和立方体之间的碰撞
    •   对不同的立方体,需要碰撞不同的次数才能消灭
    •   立方体消灭之后,要播放动画
    •   玩家拥有血量和积分

                   这个游戏大致就有这些功能。

                   在ECS系统中,我们没有像传统的面向对象方法那样,为游戏中每一个实体定义一个类。比如,对于这里的玩家(Player)定义一个类,然后为绿色的立方 体(GreenCube),红色的立方体(RedCube),橙色的立方体(OrangeCube)和紫色的立方体(PurpleCube)都定义一个 类。对于这样的小游戏来说,你可以这么做,但是对于大一点的游戏来说,里面的实体有非常的多,如果每一个都定义一个类的话,那么系统将难以维护。所以,在 ECS系统中,它将“多使用组合,少使用继承”的概念发挥到极致。

    组件

                  在系统中,并没有为每一个实体都定义一个类,而是为构成这些实体的基本单元,也就是前面两篇博文中讲述的Component(组件),一个一个的定义。下面是我游戏中,需要用到的所有的组件类型:

    // File: Component.h
    //------------------------------------------------------------------
    // declaration	: Copyright (c), by XJ , 2014 . All right reserved .
    // brief		: This file will define the Component base class of the 
    //                Entity-Component-System.
    // author		: XJ
    // date			: 2014 / 6 / 8
    // version		: 1.0
    //-------------------------------------------------------------------
    #pragma once
    #include<cocos2d.h>
    using namespace cocos2d ;
    
    namespace ShapeWar
    {
    #define COMPONENT_NONE 0x0
    
    class Component
    {
    public:
    	Component(){}
    	virtual ~Component(){}
    };
    
    /**
    * Define the Render Component
    */
    #define COMPONENT_RENDER (1 << 1)
    class RenderComponent: public Component
    {
    public:
    	RenderComponent(){}
    	~RenderComponent()
    	{
    		sprite->removeFromParentAndCleanup(true);
    		delete sprite ;
    	}
    
    public:
    	CCSprite* sprite ;
    };
    
    /**
    * Define the Position Component
    */
    #define COMPONENT_POSITION (1 << 2 )
    class PositionComponent: public Component
    {
    public:
    	PositionComponent(){}
    	~PositionComponent(){}
    
    public:
    	float x ;
    	float y ;
    };
    
    /**
    * Define the Velocity Component
    */
    #define COMPONENT_VELOCITY (1 << 3)
    class VelocityComponent: public Component
    {
    public:
    	VelocityComponent(){}
    	~VelocityComponent(){}
    
    public:
    	float vx ;
    	float vy ;
    };
    
    /**
    * Define the Health Component
    */
    #define COMPONENT_HEALTH (1 << 4)
    class HealthComponent: public Component
    {
    public:
    	HealthComponent(){}
    	~HealthComponent(){}
    
    public:
    	unsigned int health ;
    };
    
    /**
    * Define the Collidable Component
    * brief	: Use the AABB's Min-Max representation
    */
    #define COMPONENT_COLLID (1 << 5)
    class CollidableComponent:public Component
    {
    public:
    	CollidableComponent(){}
    	~CollidableComponent(){}
    
    public:
    	float min_x ;
    	float min_y ;
    	float max_x ;
    	float max_y ;
    };
    
    /**
    * Define the EntityType component
    * brief	: This component will indicate which type the entity is.
    */
    #define COMPONENT_ENTITY_TYPE (1 << 6)
    class EntityTypeComponent: public Component
    {
    public:
    	EntityTypeComponent(){}
    	~EntityTypeComponent(){}
    
    public:
    	static const unsigned int RED_CUBE = (1 << 1) ;
    	static const unsigned int PURPLE_CUBE = (1 << 2) ;
    	static const unsigned int ORANGE_CUBE = (1 << 3) ;
    	static const unsigned int GREEN_CUBE = (1 << 4) ;
    	static const unsigned int SPHERE_BALL = (1 << 5) ;
    	static const unsigned int PLAYER = (1 << 6) ;
    
    public:
    	unsigned int type ;
    };
    
    /**
    * Define the AnimateComponent
    */
    #define COMPONENT_ANIMATE (1 << 7)
    class AnimateComponent:public Component
    {
    public:
    	AnimateComponent(){}
    	~AnimateComponent(){}
    
    public:
    	cocos2d::CCAnimate* animate ;
    	unsigned frames ;
    };
    
    };

                从上面的代码中,大家可以看到,我首先定义了一个基类Component,然后让所有的组件都继承于这个基类。这里,我并没有用到继承,读者可以发现 Component中什么内容也没有。 我将其他组件继承于Component的组要原因是能够将他们统一的进行处理,仅此而已。

                在定义完了基类之后,分别定义了如下的组件类型:

    • RenderComponent, 用于支持渲染
    • PositionComponent, 用于定义位置属性
    • VelocityComponent,用于定义速度属性
    • HealthComponent,用于定义健康属性
    • CollidableComponent,用于定义AABB碰撞检测盒
    • EntityTypeComponent,用于定义实体类型
    • AnimateComponent, 用于定义动画渲染属性

             读者可能发现,在每一个组件上方,我都为它定义了一个标示符,如#define COMPONENT_RENDER  (1 << 1)。这是因为,我们需要知道一个实体中到底有哪些组件,所以,我们为每一个组件定义一个标示符,然后就可以通过判断这个标示符,来知道,一个实体是否拥 有指定的组件了。我们将在后面看到它的用处。

    实体

             如果读者,你仔细的阅读了我前面介绍的几篇文章,那么你就会知道,实体实际上就是一个ID值而已,所以,我并没有专门为这个概念定义什么,它在我开发的游 戏中,仅仅是一个下标值而已。但是,我们需要知道,游戏中那么多的实体,需要进行统一的管理。所以为此,我创建了如下的一个类,用来对游戏中所有的实体进 行管理。

    1.   
    2.   
    3.   
    4.   
    5.   
    6.   
    7.   
    8.   
    9.   
    10. #pragma once  
    11.   
    12. #include<vector>  
    13. #include"Component.h"  
    14. using namespace std ;  
    15.   
    16. namespace ShapeWar  
    17. {  
    18.  
    19.  
    20.   
    21. class EntityManager  
    22. {  
    23. private:  
    24.     EntityManager();  
    25.     ~EntityManager();  
    26.   
    27.       
    28. public:  
    29.     static EntityManager* getEntityManager();  
    30.   
    31.       
    32. public:  
    33.      
    34.  
    35.   
    36.     _int64 createEntity() ;  
    37.   
    38.      
    39.  
    40.   
    41.     void removeEntity(_int64 entity);  
    42.   
    43.      
    44.  
    45.  
    46.  
    47.  
    48.   
    49.     void registComponents(_int64 component_size);  
    50.   
    51.      
    52.  
    53.   
    54.     void addComponent(Component* component, _int64 component_type, _int64 entity);  
    55.   
    56.      
    57.  
    58.   
    59.     void removeComponent(_int64 component_type, _int64 entity);  
    60.   
    61.      
    62.  
    63.   
    64.     std::vector<Component*>* getComponentList(_int64 component_type) const ;  
    65.   
    66.      
    67.  
    68.   
    69.     Component* getComponent(_int64 component_type, _int64 entity);  
    70.   
    71.      
    72.  
    73.   
    74.     _int64 getEntityFlag(_int64 entity) const ;  
    75.   
    76.      
    77.  
    78.   
    79.     void setEntityFlag(_int64 entity, _int64 entity_type);  
    80.   
    81.      
    82.  
    83.   
    84.     unsigned int getEntitySize() const ;  
    85.   
    86.      
    87.  
    88.   
    89.     typedef std::vector<Component*> Component_List;  
    90.   
    91. private:  
    92.      
    93.  
    94.   
    95.     void _destroy();  
    96.   
    97. private:  
    98.     std::vector<_int64> m_EntityFlagArray ;                             
    99.     <pre name="code" class="cpp">        std::vector<Component_List>  m_ComponentContainer ;                  
    //File:EntityManager
    //------------------------------------------------------------------
    // declaration	: Copyright (c), by XJ , 2014 . All right reserved .
    // brief		: This file will define the Entity of the Entity-Componet-
    //                System and the entity manager.
    // author		: XJ
    // date			: 2014 / 6 / 8
    // version		: 1.0
    //-------------------------------------------------------------------
    #pragma once
    
    #include<vector>
    #include"Component.h"
    using namespace std ;
    
    namespace ShapeWar
    {
    /**
    * Define the EntityManager
    */
    class EntityManager
    {
    private:
    	EntityManager();
    	~EntityManager();
    
    	/** Singleton getter*/
    public:
    	static EntityManager* getEntityManager();
    
    	/** Core method */
    public:
    	/**
    	* Create an empty entity
    	*/
    	_int64 createEntity() ;
    
    	/**
    	* Remove an entity
    	*/
    	void removeEntity(_int64 entity);
    
    	/**
    	* Register component
    	* brief	: This method will make the entity manager to alloc the memory to store
    	*         the registed componet.If you want to use one componet in the ECS , you
    	*         must registed it at the start time.
    	*/
    	void registComponents(_int64 component_size);
    
    	/**
    	* Add an component to the entity
    	*/
    	void addComponent(Component* component, _int64 component_type, _int64 entity);
    
    	/**
    	* Remove an component of the entity
    	*/
    	void removeComponent(_int64 component_type, _int64 entity);
    
    	/**
    	* Get component list
    	*/
    	std::vector<Component*>* getComponentList(_int64 component_type) const ;
    
    	/**
    	* Get the specificed component of the entity
    	*/
    	Component* getComponent(_int64 component_type, _int64 entity);
    
    	/**
    	* Get entity flag
    	*/
    	_int64 getEntityFlag(_int64 entity) const ;
    
    	/**
    	* Set entity flag
    	*/
    	void setEntityFlag(_int64 entity, _int64 entity_type);
    
    	/**
    	* Get the entity size
    	*/
    	unsigned int getEntitySize() const ;
    
    	/**
    	* Define the Component_List
    	*/
    	typedef std::vector<Component*> Component_List;
    
    private:
    	/**
    	* Destroy all the component
    	*/
    	void _destroy();
    
    private:
    	std::vector<_int64> m_EntityFlagArray ;							//Contain the Entity flag 
    	<pre name="code" class="cpp">        std::vector<Component_List>  m_ComponentContainer ;				//Contain all the entity

    };};

    
    

              正如读者看到的那样,这个类是一个单例类,里面提供了很多的方法。要理解这个类,我们先来看看组件是如何在这个类里面进行保存的。

              在这个类中,我定义了一个这样的成员:

    1. std::vector<Component_List>  m_ComponentContainer ;                 
    std::vector<Component_List>  m_ComponentContainer ;				//Contain all the entity

                而Component_List定义为如下:

    1.  
    2.  
    3.   
    4. typedef std::vector<Component*> Component_List;  
    /**
    * Define the Component_List
    */
    typedef std::vector<Component*> Component_List;
    

                也就是说,这个ComponentContainer,包含了所有的在游戏中使用的组件实例。同一种组件实例,放在同一个Component_List 中,然后不同的Component_List,放在Component_Container中。如果读者对这个不是很清楚的话,可以看下面的图片:

              

                 从上图中可以看出,这是一个二维的空间盒子,纵向表示了一个组件类型中所有的组件实例,横向表示了一个实体拥有哪些组件。所以,这里的实体,也就是这里的容器中的下标了。

                好了,在明白了组件是如何保存了的之后,我们还需要了解在EntityManager中定义的这个数组是什么意思:

    1. std::vector<_int64> m_EntityFlagArray ;                             
    std::vector<_int64> m_EntityFlagArray ;							//Contain the Entity flag 
    

                这个数组,保存了相对应的实体中组件的标示符。还记得我们在组件那一节讲述的组件表示符吗?通过这个数组,我们保存了每个实体对应的组件中有哪些组件。比如说,在这个数组下标为1的单元中,也就是实体1中,有如下的组件标示符保存:

               COMPONENT_RENDER | COMPONENT_POSITION | COMPONENT_VELOCITY

                那么就意味着,这个实体是由RenderComponent,和PositionComponent,VelocityComponent组合而成的。

                好了,在明白了这个数组的功能之后,我们来看看上面管理器中各个函数的作用吧。

    _int64 CreateEntity

               这个函数用来创建一个空的实体,并且返回实体的下标。用户可以通过这个方法来创建一个实体

    void removeEntity(_int64 entity)

               这个函数,根据传递进来的实体下标,将实体从容器中移除,并且释放相关的资源

    void registComponent(int num)

               这个函数,用来根据参数,开辟相应的组件类型空间。在开始的时候,我们并不知道有多少个组件需要使用,所以让用户自行决定需要使用多少个组件。

    void addComponent(Component* component, _int64 component_type, _int64 entity)

              这个函数,根据传进来的组件,还有组件类型,以及实体下标,将组件加入到相对应的位置去。

    void removeComponent(_int64 component_type, _int64 entity);

             这个函数,用来将制定类型的组件,从实体中移除。

             由于篇幅限制,这里不再一一的讲述。上面的代码能够很好的自我解释出每一个函数的功能。

              这里有个问题需要注意,读者可能想知道,我是如何通过组建标示符,来找到那个组建的容器的???并且实体只是定义了横向的坐标,而纵向的坐标是如何获取的了?

              这个还要讲解下我定义的容器的组织方式。

              对于不同的组件,我分别定义了标示符,而标示符中都有不同的位置标示,如COMPONENT_RENDER为 10,这个标示符中1在第1位(从0计算),那么我们将这个组件的纵向位置定义为1 - 1 = 0 ,也就是0号下标的组件容器中。所以,这就是为什么我要定义不同的组件标示符。为了能够从64位的标示符中获取‘1’在哪一位上,我在前面的博客中算法设计:如何从64位数中获取哪一位数为1采用分治算法,设计了这个方法来获取位数。

               好了,通过上面的描述,读者应该明白我是以怎么样的方式来维护游戏中所有的实体的了!!!

               在实现了上面的组件,实体之后,接下来就应该实现系统了。我这里实现系统的方式,是根据这篇博客中提出的方法来实现的。

              首先,抽象一个系统的类,如下所示:

    1.         
    2.  
    3.   
    4. class System  
    5. {  
    6. public:  
    7.     System(int _priority);  
    8.     virtual ~System();  
    9.   
    10. public:  
    11.     virtual void enter() = 0 ;  
    12.     virtual void excute(float dt) = 0;  
    13.     virtual void exit() = 0 ;  
    14.   
    15. public:  
    16.     int priority ;  
    17. };  
            /**
    	* Define the base system class. All system will inherit from this base class.
    	*/
    	class System
    	{
    	public:
    		System(int _priority);
    		virtual ~System();
    
    	public:
    		virtual void enter() = 0 ;
    		virtual void excute(float dt) = 0;
    		virtual void exit() = 0 ;
    
    	public:
    		int priority ;
    	};

            在这个抽象的系统中,我定义了一个优先级,这样,我们就可以定义哪一些系统需要在另外一些系统之前进行运行。有了系统之后,我们就需要一个管理的方式,所以,在定义了一个系统管理器,如下所示:

    1.  
    2.  
    3.   
    4. class SystemManager  
    5. {  
    6. private:  
    7.     SystemManager();  
    8.     ~SystemManager();  
    9.   
    10.       
    11. public:  
    12.     static SystemManager* getSystemManager() ;  
    13.   
    14.       
    15. public:  
    16.      
    17.  
    18.   
    19.     void addSystem(System * system);  
    20.   
    21.      
    22.  
    23.   
    24.     void update(float dt);  
    25.   
    26.      
    27.  
    28.   
    29.     void pause();  
    30.   
    31.      
    32.  
    33.   
    34.     void resume();  
    35.   
    36. private:  
    37.      
    38.  
    39.   
    40.     void _destroy();  
    41.   
    42. private:  
    43.     std::vector<System*> system_list ;  
    44.     bool bPaused ;  
    45. };  
    	/**
    	* Define the system manager
    	*/
    	class SystemManager
    	{
    	private:
    		SystemManager();
    		~SystemManager();
    
    		/** Singleton getter*/
    	public:
    		static SystemManager* getSystemManager() ;
    
    		/** Core method*/
    	public:
    		/**
    		* Add one system to the system list
    		*/
    		void addSystem(System * system);
    
    		/**
    		* Update all the system
    		*/
    		void update(float dt);
    
    		/**
    		* Pause all the system
    		*/
    		void pause();
    
    		/**
    		* Resume all the system
    		*/
    		void resume();
    
    	private:
    		/**
    		* Destroy all the systems
    		*/
    		void _destroy();
    
    	private:
    		std::vector<System*> system_list ;
    		bool bPaused ;
    	};

                 这个类同样也是单例的,用户可以通过调用addSystem来添加系统到系统管理器中。系统管理器,会在每一帧,调用update方法,update方法如下所示:

    1. void SystemManager::update(float dt)  
    2. {  
    3.     if(bPaused == true)  
    4.         return ;  
    5.   
    6.       
    7.     for(int i = 0  ; i < system_list.size() ; i ++)  
    8.     {  
    9.         system_list[i]->excute(dt);  
    10.     }  
    11. }  
    void SystemManager::update(float dt)
    {
    	if(bPaused == true)
    		return ;
    
    	//Excute all the system
    	for(int i = 0  ; i < system_list.size() ; i ++)
    	{
    		system_list[i]->excute(dt);
    	}// end for
    }// end for update

                 很简单,它调用已经根据优先级排好序的系统中的excute方法,来执行每一个系统的任务。

                 在我的这个简单的游戏中,我定义了如下的几个系统,根据优先级从低到进行排序:

    • RenderSystem,负责进行渲染
    • MovementSystem, 负责进行实体的移动
    • HealthSystem,负责判断哪些实体已死亡
    • CreatorSystem,负责游戏中立方体的创建规则
    • InputSystem, 负责处理键盘输入
    • CollidDetectionSystem,负责进行碰撞检测
    • BoundaryCheckSystem,负责进行边界检查,当立方体和球体出了边界之后,进行相应的操作  

                  下面我们来分别看看这些系统的实现过程:

    RenderSystem

    1. #include"RenderSystem.h"  
    2. #include"EntityMananger.h"  
    3. using namespace ShapeWar ;  
    4.   
    5. RenderSystem::RenderSystem(int _priority, CCNode* _scene)  
    6.     :System(_priority),  
    7.     scene(_scene)  
    8. {  
    9.   
    10. }  
    11.   
    12. RenderSystem::~RenderSystem()  
    13. {  
    14.   
    15. }  
    16.   
    17. void RenderSystem::enter()  
    18. {  
    19.   
    20. }  
    21.   
    22. void RenderSystem::excute(float dt)  
    23. {  
    24.     unsigned int size = EntityManager::getEntityManager()->getEntitySize();  
    25.     for(unsigned int i = 0 ; i < size ; i ++)  
    26.     {  
    27.         _int64 flag = EntityManager::getEntityManager()->getEntityFlag(i);  
    28.         if((flag & (COMPONENT_RENDER | COMPONENT_POSITION)) == (COMPONENT_RENDER | COMPONENT_POSITION))  
    29.         {  
    30.             RenderComponent* pRender = (RenderComponent*)EntityManager::getEntityManager()->getComponent(COMPONENT_RENDER,i);  
    31.             PositionComponent* pPos =  (PositionComponent*)EntityManager::getEntityManager()->getComponent(COMPONENT_POSITION,i);  
    32.   
    33.             if(pRender->sprite->getParent() == NULL)  
    34.             {  
    35.                 EntityTypeComponent* pType = (EntityTypeComponent*)EntityManager::getEntityManager()->getComponent(COMPONENT_ENTITY_TYPE,i);  
    36.                 if(pType->type != EntityTypeComponent::PLAYER)  
    37.                 {  
    38.                     pRender->sprite->runAction(CCRepeatForever::create(CCRotateBy::create(1.0/60, 5)));  
    39.                     scene->addChild(pRender->sprite);  
    40.                 }  
    41.                 else  
    42.                     scene->addChild(pRender->sprite, 10);  
    43.             }  
    44.   
    45.             pRender->sprite->setPosition(ccp(pPos->x, pPos->y));  
    46.         }  
    47.     }  
    48.   
    49. }  
    50.   
    51. void RenderSystem::exit()  
    52. {  
    53.     unsigned int size = EntityManager::getEntityManager()->getEntitySize();  
    54.     for(unsigned int i = 0 ; i < size ; i ++)  
    55.     {  
    56.         RenderComponent* pRender = (RenderComponent*)EntityManager::getEntityManager()->getComponent(COMPONENT_RENDER,i);  
    57.         pRender->sprite->stopAllActions();  
    58.         pRender->sprite->removeFromParentAndCleanup(true);  
    59.     }  
    60. }  
    #include"RenderSystem.h"
    #include"EntityMananger.h"
    using namespace ShapeWar ;
    
    RenderSystem::RenderSystem(int _priority, CCNode* _scene)
    	:System(_priority),
    	scene(_scene)
    {
    
    }
    
    RenderSystem::~RenderSystem()
    {
    
    }
    
    void RenderSystem::enter()
    {
    
    }// ed for enter
    
    void RenderSystem::excute(float dt)
    {
    	unsigned int size = EntityManager::getEntityManager()->getEntitySize();
    	for(unsigned int i = 0 ; i < size ; i ++)
    	{
    		_int64 flag = EntityManager::getEntityManager()->getEntityFlag(i);
    		if((flag & (COMPONENT_RENDER | COMPONENT_POSITION)) == (COMPONENT_RENDER | COMPONENT_POSITION))
    		{
    			RenderComponent* pRender = (RenderComponent*)EntityManager::getEntityManager()->getComponent(COMPONENT_RENDER,i);
    			PositionComponent* pPos =  (PositionComponent*)EntityManager::getEntityManager()->getComponent(COMPONENT_POSITION,i);
    
    			if(pRender->sprite->getParent() == NULL)
    			{
    				EntityTypeComponent* pType = (EntityTypeComponent*)EntityManager::getEntityManager()->getComponent(COMPONENT_ENTITY_TYPE,i);
    				if(pType->type != EntityTypeComponent::PLAYER)
    				{
    					pRender->sprite->runAction(CCRepeatForever::create(CCRotateBy::create(1.0/60, 5)));
    					scene->addChild(pRender->sprite);
    				}// end for PLAYER
    				else
    					scene->addChild(pRender->sprite, 10);
    			}
    
    			pRender->sprite->setPosition(ccp(pPos->x, pPos->y));
    		}
    	}// end for sprite
    
    }// end for excute
    
    void RenderSystem::exit()
    {
    	unsigned int size = EntityManager::getEntityManager()->getEntitySize();
    	for(unsigned int i = 0 ; i < size ; i ++)
    	{
    		RenderComponent* pRender = (RenderComponent*)EntityManager::getEntityManager()->getComponent(COMPONENT_RENDER,i);
    		pRender->sprite->stopAllActions();
    		pRender->sprite->removeFromParentAndCleanup(true);
    	}// end for
    }// end for exit

    MovementSystem

    1. #include"MovementSystem.h"  
    2. #include"EntityMananger.h"  
    3. using namespace ShapeWar ;  
    4.   
    5. MovementSystem::MovementSystem(int _priority)  
    6.     :System(_priority)  
    7. {  
    8.   
    9. }  
    10.   
    11. MovementSystem::~MovementSystem()  
    12. {  
    13.   
    14. }  
    15.   
    16. void MovementSystem::enter()  
    17. {  
    18.   
    19. }  
    20.   
    21. void MovementSystem::excute(float dt)  
    22. {  
    23.     unsigned int size = EntityManager::getEntityManager()->getEntitySize();  
    24.     for(unsigned int i =  0 ; i < size ; i ++)  
    25.     {  
    26.         _int64 flag = EntityManager::getEntityManager()->getEntityFlag(i);  
    27.           
    28.         if((flag & (COMPONENT_POSITION | COMPONENT_VELOCITY)) == (COMPONENT_POSITION | COMPONENT_VELOCITY))  
    29.         {  
    30.             PositionComponent* pPos = (PositionComponent*)EntityManager::getEntityManager()->getComponent(COMPONENT_POSITION, i);  
    31.             VelocityComponent* pVelocity = (VelocityComponent*)EntityManager::getEntityManager()->getComponent(COMPONENT_VELOCITY, i);  
    32.   
    33.             pPos->x += (1.0 / 60) * pVelocity->vx ;  
    34.             pPos->y += (1.0 / 60) * pVelocity->vy ;  
    35.         }  
    36.     }  
    37. }  
    38.   
    39. void MovementSystem::exit()  
    40. {  
    41.   
    42. }  
    #include"MovementSystem.h"
    #include"EntityMananger.h"
    using namespace ShapeWar ;
    
    MovementSystem::MovementSystem(int _priority)
    	:System(_priority)
    {
    
    }
    
    MovementSystem::~MovementSystem()
    {
    
    }
    
    void MovementSystem::enter()
    {
    
    }// end for enter
    
    void MovementSystem::excute(float dt)
    {
    	unsigned int size = EntityManager::getEntityManager()->getEntitySize();
    	for(unsigned int i =  0 ; i < size ; i ++)
    	{
    		_int64 flag = EntityManager::getEntityManager()->getEntityFlag(i);
    		
    		if((flag & (COMPONENT_POSITION | COMPONENT_VELOCITY)) == (COMPONENT_POSITION | COMPONENT_VELOCITY))
    		{
    			PositionComponent* pPos = (PositionComponent*)EntityManager::getEntityManager()->getComponent(COMPONENT_POSITION, i);
    			VelocityComponent* pVelocity = (VelocityComponent*)EntityManager::getEntityManager()->getComponent(COMPONENT_VELOCITY, i);
    
    			pPos->x += (1.0 / 60) * pVelocity->vx ;
    			pPos->y += (1.0 / 60) * pVelocity->vy ;
    		}
    	}// end for
    }// end for excute
    
    void MovementSystem::exit()
    {
    
    }// end for exit
    
    
    
    

    HealthSystem

    1. #include"HealthSystem.h"  
    2. #include"EntityMananger.h"  
    3. #include"GameInfo.h"  
    4. using namespace ShapeWar ;  
    5.   
    6. HealthSystem::HealthSystem(int priority)  
    7.     :System(priority)  
    8. {  
    9.   
    10. }  
    11.   
    12. HealthSystem::~HealthSystem()  
    13. {  
    14.   
    15. }  
    16.   
    17. void HealthSystem::enter()  
    18. {  
    19.   
    20. }  
    21.   
    22. void HealthSystem::excute(float dt)  
    23. {  
    24.       
    25.     EntityManager::Component_List* pHealth = EntityManager::getEntityManager()->getComponentList(COMPONENT_HEALTH);  
    26.   
    27.     for(unsigned int entity = 0 ; entity < EntityManager::getEntityManager()->getEntitySize() ;)  
    28.     {  
    29.         HealthComponent* health = (HealthComponent*)(*pHealth)[entity] ;  
    30.   
    31.         if(health != NULL)  
    32.         {  
    33.             EntityTypeComponent* pType = (EntityTypeComponent*)EntityManager::getEntityManager()->getComponent(COMPONENT_ENTITY_TYPE, entity);  
    34.             if(pType->type == EntityTypeComponent::PLAYER)  
    35.             {  
    36.                 GameInfo::getGameInfo()->CUR_HEALTH_PLAYER = health->health ;  
    37.             }  
    38.   
    39.             if(health->health == 0)  
    40.             {  
    41.                 if((EntityManager::getEntityManager()->getEntityFlag(entity) & COMPONENT_ANIMATE) == 0)  
    42.                 {  
    43.                     switch(pType->type)  
    44.                     {  
    45.                     case EntityTypeComponent::GREEN_CUBE:  
    46.                     case EntityTypeComponent::RED_CUBE:  
    47.                         GameInfo::getGameInfo()->CUR_SCORE += 1 ;  
    48.                         break ;  
    49.                       
    50.                     case EntityTypeComponent::ORANGE_CUBE:  
    51.                         GameInfo::getGameInfo()->CUR_SCORE += 2 ;  
    52.                         break ;  
    53.   
    54.                     case EntityTypeComponent::PURPLE_CUBE:  
    55.                         GameInfo::getGameInfo()->CUR_SCORE += 3 ;  
    56.                         break ;  
    57.                     }  
    58.   
    59.                     EntityManager::getEntityManager()->removeEntity(entity);  
    60.                 }  
    61.                 else  
    62.                     entity ++ ;  
    63.             }  
    64.             else  
    65.                 entity ++ ;  
    66.         }  
    67.         else  
    68.             entity ++ ;  
    69.     }  
    70. }  
    71.   
    72. void HealthSystem::exit()  
    73. {  
    74.   
    75. }  
    #include"HealthSystem.h"
    #include"EntityMananger.h"
    #include"GameInfo.h"
    using namespace ShapeWar ;
    
    HealthSystem::HealthSystem(int priority)
    	:System(priority)
    {
    
    }
    
    HealthSystem::~HealthSystem()
    {
    
    }
    
    void HealthSystem::enter()
    {
    
    }// end for enter
    
    void HealthSystem::excute(float dt)
    {
    	//Get all the HealthComponent list
    	EntityManager::Component_List* pHealth = EntityManager::getEntityManager()->getComponentList(COMPONENT_HEALTH);
    
    	for(unsigned int entity = 0 ; entity < EntityManager::getEntityManager()->getEntitySize() ;)
    	{
    		HealthComponent* health = (HealthComponent*)(*pHealth)[entity] ;
    
    		if(health != NULL)
    		{
    			EntityTypeComponent* pType = (EntityTypeComponent*)EntityManager::getEntityManager()->getComponent(COMPONENT_ENTITY_TYPE, entity);
    			if(pType->type == EntityTypeComponent::PLAYER)
    			{
    				GameInfo::getGameInfo()->CUR_HEALTH_PLAYER = health->health ;
    			}
    
    			if(health->health == 0)
    			{
    				if((EntityManager::getEntityManager()->getEntityFlag(entity) & COMPONENT_ANIMATE) == 0)
    				{
    					switch(pType->type)
    					{
    					case EntityTypeComponent::GREEN_CUBE:
    					case EntityTypeComponent::RED_CUBE:
    						GameInfo::getGameInfo()->CUR_SCORE += 1 ;
    						break ;
    					
    					case EntityTypeComponent::ORANGE_CUBE:
    						GameInfo::getGameInfo()->CUR_SCORE += 2 ;
    						break ;
    
    					case EntityTypeComponent::PURPLE_CUBE:
    						GameInfo::getGameInfo()->CUR_SCORE += 3 ;
    						break ;
    					}// end switch
    
    					EntityManager::getEntityManager()->removeEntity(entity);
    				}
    				else
    					entity ++ ;
    			}// end if
    			else
    				entity ++ ;
    		}// end if
    		else
    			entity ++ ;
    	}// end for
    }// end for excute
    
    void HealthSystem::exit()
    {
    
    }// end for exit

    CreatorSystem

    1. #include"CreatorSystem.h"  
    2. #include"EntityCreator.h"  
    3. using namespace ShapeWar ;  
    4.   
    5. CreatorSystem::CreatorSystem(int _priority)  
    6.     :System(_priority),  
    7.     frames(0)  
    8. {  
    9.   
    10. }  
    11.   
    12. CreatorSystem::~CreatorSystem()  
    13. {  
    14.   
    15. }  
    16.   
    17. void CreatorSystem::enter()  
    18. {  
    19.   
    20. }  
    21.   
    22. void CreatorSystem::excute(float dt)  
    23. {  
    24.     frames ++ ;  
    25.   
    26.     static int delta = 0 ;  
    27.     delta = frames / 1800 ;  
    28.   
    29.     if(delta >= 30)  
    30.         delta = 30 ;  
    31.   
    32.     if(frames % (60 - delta ) == 0)  
    33.     {  
    34.         int value = rand()%100 ;  
    35.         float vy = -60 - (frames / 300.0) * 10 ;  
    36.   
    37.         if(0 <= value&& value < 40)  
    38.         {  
    39.             EntityCreator::createGreenCube(0, vy);  
    40.         }  
    41.         else if(40 <= value&& value < 80)  
    42.         {  
    43.             EntityCreator::createRedCube(0, vy);  
    44.         }  
    45.         else if(80 <= value && value < 90)  
    46.         {  
    47.             EntityCreator::createOrangeCube(0, 0.6*vy);  
    48.         }  
    49.         else if(90 <= value && value<100)  
    50.         {  
    51.             EntityCreator::createPurpleCube(0,0.4*vy);  
    52.         }  
    53.     }  
    54.   
    55. }  
    56.   
    57. void CreatorSystem::exit()  
    58. {  
    59.   
    60. }  
    #include"CreatorSystem.h"
    #include"EntityCreator.h"
    using namespace ShapeWar ;
    
    CreatorSystem::CreatorSystem(int _priority)
    	:System(_priority),
    	frames(0)
    {
    
    }
    
    CreatorSystem::~CreatorSystem()
    {
    
    }
    
    void CreatorSystem::enter()
    {
    
    }// end for enter
    
    void CreatorSystem::excute(float dt)
    {
    	frames ++ ;
    
    	static int delta = 0 ;
    	delta = frames / 1800 ;
    
    	if(delta >= 30)
    		delta = 30 ;
    
    	if(frames % (60 - delta ) == 0)
    	{
    		int value = rand()%100 ;
    		float vy = -60 - (frames / 300.0) * 10 ;
    
    		if(0 <= value&& value < 40)
    		{
    			EntityCreator::createGreenCube(0, vy);
    		}
    		else if(40 <= value&& value < 80)
    		{
    			EntityCreator::createRedCube(0, vy);
    		}
    		else if(80 <= value && value < 90)
    		{
    			EntityCreator::createOrangeCube(0, 0.6*vy);
    		}
    		else if(90 <= value && value<100)
    		{
    			EntityCreator::createPurpleCube(0,0.4*vy);
    		}
    	}//end if
    
    }// end for excute
    
    void CreatorSystem::exit()
    {
    
    }// end for exit

    InputSystem

    #include "InputSystem.h"
    #include "EntityMananger.h"
    #include "EntityCreator.h"
    #include "AudioSystem.h"
    using namespace ShapeWar ;
    
    InputSystem::InputSystem(int _priority)
    	:System(_priority)
    {
    
    }
    
    InputSystem::~InputSystem()
    {
    
    }
    
    void InputSystem::enter()
    {
    
    }// end for enter
    
    void InputSystem::excute(float dt)
    {
    	//Get the Component list
    	EntityManager::Component_List* pPos = EntityManager::getEntityManager()->getComponentList(COMPONENT_POSITION);
    	EntityManager::Component_List* pType = EntityManager::getEntityManager()->getComponentList(COMPONENT_ENTITY_TYPE);
    
    	//Find the player and the un-shooted ball
    	unsigned int size = EntityManager::getEntityManager()->getEntitySize();
    
    	int player = -1 , ball = -1 ;
    	for(unsigned int i = 0 ; i < size ; i ++)
    	{
    		unsigned int type = ((EntityTypeComponent*)(*pType)[i])->type ;
    		if(type == EntityTypeComponent::PLAYER)
    		{
    			player = i ;
    		}// end if
    
    		if(type == EntityTypeComponent::SPHERE_BALL)
    		{
    			_int64 flag = EntityManager::getEntityManager()->getEntityFlag(i);
    			if((flag & COMPONENT_VELOCITY) == 0)
    			{
    				ball = i ;
    			} // end if
    		}// end if
    
    		if(player != -1 && ball != -1)
    			break ;
    	}// end for
    
    	PositionComponent* pPlayer_Pos = NULL ;
    	PositionComponent* pBall_Pos = NULL ;
    
    	if(player != -1)
    		pPlayer_Pos = (PositionComponent*)(*pPos)[player] ;
    	if(ball != -1)
    		pBall_Pos = (PositionComponent*)(*pPos)[ball] ;
    
    	if(GetKeyState(VK_RIGHT) & 0x8000)
    	{
    		if(pPlayer_Pos != NULL)
    		{
    			pPlayer_Pos->x += 5 ;
    			if(pPlayer_Pos->x >= 320 - 22)
    				pPlayer_Pos->x = 320 - 22 ;
    
    			if(pBall_Pos != NULL)
    				pBall_Pos->x = pPlayer_Pos->x ;
    		}
    	}else if(GetKeyState(VK_LEFT)&0x8000)
    	{
    		if(pPlayer_Pos != NULL)
    		{
    			pPlayer_Pos->x -= 5 ;
    			if(pPlayer_Pos->x <= 22)
    				pPlayer_Pos->x = 22 ;
    
    			if(pBall_Pos != NULL)
    				pBall_Pos->x = pPlayer_Pos->x ;
    		}
    	}
    
    	static int nFrame = 0 ;
    	if((GetKeyState(VK_SPACE)& 0x8000) && (nFrame >= 15))
    	{
    		VelocityComponent* pVelocity = new VelocityComponent();
    		pVelocity->vx = 0 ;
    		pVelocity->vy = 600 ;
    		EntityManager::getEntityManager()->addComponent(pVelocity, COMPONENT_VELOCITY, ball);
    
    		//Create another ball
    		EntityCreator::createSphereBall(pPlayer_Pos->x, pPlayer_Pos->y);
    
    		//Player Effect
    		AudioSystem::sharedAudioSystem()->playSound("Shoot.wav");
    		nFrame = 0 ;
    	}
    
    	nFrame ++ ;
    
    }// end for excute
    
    void InputSystem::exit()
    {
    
    }// end for exit

    CollidDetectionSystem

    #include"CollidDetectionSystem.h"
    #include"EntityMananger.h"
    #include"AudioSystem.h"
    using namespace ShapeWar ;
    
    CollidDetectionSystem::CollidDetectionSystem(int _priority)
    	:System(_priority)
    {
    
    }
    
    CollidDetectionSystem::~CollidDetectionSystem()
    {
    
    }
    
    void CollidDetectionSystem::enter()
    {
    
    }// end for enter
    
    void CollidDetectionSystem::excute(float dt)
    {
    	//Get all PositionComponent list
    	EntityManager::Component_List* pPos = EntityManager::getEntityManager()->getComponentList(COMPONENT_POSITION);
    
    	//Get all the CollidableComponent list
    	EntityManager::Component_List* pCollid = EntityManager::getEntityManager()->getComponentList(COMPONENT_COLLID);
    
    	//Get all the EntityTypeComponent list
    	EntityManager::Component_List* pType = EntityManager::getEntityManager()->getComponentList(COMPONENT_ENTITY_TYPE);
    
    	//Get all the HealthComponent list
    	EntityManager::Component_List* pHealth = EntityManager::getEntityManager()->getComponentList(COMPONENT_HEALTH);
    
    	unsigned int size = EntityManager::getEntityManager()->getEntitySize();
    
    	//Find all sphere ball
    	std::vector<unsigned int> index_array ;
    	for(unsigned int i = 0 ; i < size ; i ++)
    	{
    		if(((EntityTypeComponent*)(*pType)[i])->type == EntityTypeComponent::SPHERE_BALL)
    		{
    			if((EntityManager::getEntityManager()->getEntityFlag(i) & COMPONENT_VELOCITY) == COMPONENT_VELOCITY)
    			{
    				index_array.push_back(i);
    			}// end if
    		}// end if
    	}// end for
    
    	for(unsigned int i = 0 ; i < index_array.size() ; i ++)
    	{
    		CollidableComponent* collidAreaA = ((CollidableComponent*)((*pCollid)[index_array[i]])) ;
    		PositionComponent* posA = ((PositionComponent*)((*pPos)[index_array[i]])) ;
    		collidAreaA->min_x = posA->x - 16 ;
    		collidAreaA->min_y = posA->y - 16 ;
    		collidAreaA->max_x = posA->x + 16 ;
    		collidAreaA->max_y = posA->y + 16 ;
    
    		size = EntityManager::getEntityManager()->getEntitySize();
    		for(unsigned int j = 0 ; j < size ; j ++)
    		{
    			if((EntityManager::getEntityManager()->getEntityFlag(j) & COMPONENT_COLLID) == COMPONENT_COLLID &&
    				((EntityTypeComponent*)(*pType)[j])->type != EntityTypeComponent::SPHERE_BALL)
    			{
    				CollidableComponent* collidAreaB = ((CollidableComponent*)((*pCollid)[j])) ;
    				PositionComponent* posB = ((PositionComponent*)((*pPos)[j])) ;
    				collidAreaB->min_x = posB->x - 16 ;
    				collidAreaB->min_y = posB->y - 16 ;
    				collidAreaB->max_x = posB->x + 16 ;
    				collidAreaB->max_y = posB->y + 16 ;
    
    				if(collidAreaA->min_x > collidAreaB->max_x
    					||collidAreaA->max_x < collidAreaB->min_x) continue ;
    				if(collidAreaA->min_y > collidAreaB->max_y ||
    					collidAreaA->max_y < collidAreaB->min_y) continue ;
    
    				HealthComponent* cube = (HealthComponent*)(*pHealth)[j] ;
    				cube->health -- ;
    
    				if(cube->health == 0)
    				{
    					AnimateComponent* pAnimate = new AnimateComponent();
    					pAnimate->animate = new CCAnimate();
    					
    					CCAnimation* pAnimation =  CCAnimation::create();
    					
    					for(int i = 0 ; i < 10 ; i ++)
    					{
    						char buffer[32] ;
    						sprintf(buffer,"Explosion000%d.png",i);
    						pAnimation->addSpriteFrameWithFileName(buffer);
    					}// end for
    
    					pAnimation->setDelayPerUnit(1.0/10);
    					pAnimate->animate->initWithAnimation(pAnimation);
    					pAnimate->frames = 60 ;
    
    					//Add the Animate Component to the entity
    					EntityManager::getEntityManager()->addComponent(pAnimate, COMPONENT_ANIMATE, j);
    
    					//Remove the CollidDetection Component
    					EntityManager::getEntityManager()->removeComponent(COMPONENT_COLLID, j);
    
    					//Remove the Velocity Component
    					EntityManager::getEntityManager()->removeComponent(COMPONENT_VELOCITY, j);
    
    				}// end if
    
    				HealthComponent* ball = (HealthComponent*)(*pHealth)[index_array[i]] ;
    				ball->health -- ;
    
    				//Play hurt effect
    				AudioSystem::sharedAudioSystem()->playSound("Hurt.wav");
    
    				break ;
    			}// end if
    		}// end for cube
    	}// end for sphere ball
    }// end for excute
    
    void CollidDetectionSystem::exit()
    {
    
    }// end for exit

    BoundaryCheckSystem

    1. #include"BoundaryCheckSystem.h"  
    2. #include"EntityMananger.h"  
    3. using namespace ShapeWar ;  
    4.   
    5. BoundaryCheckSystem::BoundaryCheckSystem(int priority)  
    6.     :System(priority)  
    7. {  
    8.   
    9. }  
    10.   
    11. BoundaryCheckSystem::~BoundaryCheckSystem()  
    12. {  
    13.   
    14. }  
    15.   
    16. void BoundaryCheckSystem::enter()  
    17. {  
    18.   
    19. }  
    20.   
    21. void BoundaryCheckSystem::excute(float dt)  
    22. {  
    23.       
    24.     EntityManager::Component_List* pPos = EntityManager::getEntityManager()->getComponentList(COMPONENT_POSITION);  
    25.   
    26.       
    27.     EntityManager::Component_List* pType = EntityManager::getEntityManager()->getComponentList(COMPONENT_ENTITY_TYPE);  
    28.       
    29.     unsigned int size = EntityManager::getEntityManager()->getEntitySize();  
    30.   
    31.       
    32.     unsigned int player_entity = -1 ;  
    33.     for(int i = 0 ; i < size ; i ++)  
    34.     {  
    35.         if(((EntityTypeComponent*)(*pType)[i])->type == EntityTypeComponent::PLAYER)  
    36.         {  
    37.             player_entity = i ;  
    38.             break ;  
    39.         }  
    40.     }  
    41.   
    42.     HealthComponent * health = (HealthComponent*)EntityManager::getEntityManager()->getComponent(COMPONENT_HEALTH, player_entity);  
    43.   
    44.       
    45.     for(unsigned int i = 0 ; i < size ; )  
    46.     {  
    47.         if(((EntityTypeComponent*)(*pType)[i])->type == EntityTypeComponent::SPHERE_BALL)  
    48.         {  
    49.             if(((PositionComponent*)(*pPos)[i])->y > 480)  
    50.             {  
    51.                 EntityManager::getEntityManager()->removeEntity(i);  
    52.                 size -= 1 ;  
    53.                 continue ;  
    54.             }  
    55.         }  
    56.         else  
    57.         {  
    58.             if(((PositionComponent*)(*pPos)[i])->y < 0)  
    59.             {  
    60.                 EntityManager::getEntityManager()->removeEntity(i);  
    61.                 size -= 1 ;  
    62.                 health->health-- ;  
    63.                 continue ;  
    64.             }  
    65.         }  
    66.   
    67.         i ++ ;  
    68.     }  
    69. }  
    70.   
    71. void BoundaryCheckSystem::exit()  
    72. {  
    73.       
    74. }  
    #include"BoundaryCheckSystem.h"
    #include"EntityMananger.h"
    using namespace ShapeWar ;
    
    BoundaryCheckSystem::BoundaryCheckSystem(int priority)
    	:System(priority)
    {
    
    }
    
    BoundaryCheckSystem::~BoundaryCheckSystem()
    {
    
    }
    
    void BoundaryCheckSystem::enter()
    {
    
    }// end for enter
    
    void BoundaryCheckSystem::excute(float dt)
    {
    	//Get all PositionComponent list
    	EntityManager::Component_List* pPos = EntityManager::getEntityManager()->getComponentList(COMPONENT_POSITION);
    
    	//Get all the EntityTypeComponent list
    	EntityManager::Component_List* pType = EntityManager::getEntityManager()->getComponentList(COMPONENT_ENTITY_TYPE);
    	
    	unsigned int size = EntityManager::getEntityManager()->getEntitySize();
    
    	//Find the Player's health Component
    	unsigned int player_entity = -1 ;
    	for(int i = 0 ; i < size ; i ++)
    	{
    		if(((EntityTypeComponent*)(*pType)[i])->type == EntityTypeComponent::PLAYER)
    		{
    			player_entity = i ;
    			break ;
    		}
    	}// end for
    
    	HealthComponent * health = (HealthComponent*)EntityManager::getEntityManager()->getComponent(COMPONENT_HEALTH, player_entity);
    
    	//Check if the entity is out of the screen
    	for(unsigned int i = 0 ; i < size ; )
    	{
    		if(((EntityTypeComponent*)(*pType)[i])->type == EntityTypeComponent::SPHERE_BALL)
    		{
    			if(((PositionComponent*)(*pPos)[i])->y > 480)
    			{
    				EntityManager::getEntityManager()->removeEntity(i);
    				size -= 1 ;
    				continue ;
    			}
    		}// end if for sphere ball
    		else
    		{
    			if(((PositionComponent*)(*pPos)[i])->y < 0)
    			{
    				EntityManager::getEntityManager()->removeEntity(i);
    				size -= 1 ;
    				health->health-- ;
    				continue ;
    			}
    		}
    
    		i ++ ;
    	}// end for
    }// end for excute
    
    void BoundaryCheckSystem::exit()
    {
    	
    }// end for exit

                系统内部是如何工作的,不是本文章讨论的范畴。这篇文章旨在告诉读者,我们可以通过ECS系统,实现更加弹性的设计。通过使用组合的方法,大大降低系统的 耦合性。同时,这里将数据和处理过程,通过组建和系统的方法实现了分离。通过这样的系统,我们很容易的能够实现网络游戏,因为只需要对组件数据进行单独的 传输即可,并且很容易的实现诸如关卡保存,这样的内容。

                但是,任何事情都是双面的,在带来这些好处的同时,在另外的方面也会带来限制。

               通过上面的描述,我们大概可以明确这样的系统有如下的缺点:

    •  内存利用较低。我们在容器中为每一个实体都开辟了同样大的空间,如果某个实体并不具有那样的组件的时候,那个空间依然为它保留着,这浪费了大量的空间
    •  同一个实体,没有办法拥有同一个组件的两份实例。也就说,对于像动画这样的组件,一个实体,可能不只有一个动画属性。它可能需要在死亡时,同时播放两种动画,那么这个系统就没有办法完成这样的工作。
    • 最 重要的一个缺点就是性能问题。读者可能发现,系统和实体的交互方式,完全是系统主动的轮询,来进行系统的处理。我们知道,高效的设计方法,应该是让实体在 有需要的时候,调用系统来进行工作。如果系统持续的运行,在很多情况下,系统并没有做什么有效的工作。所以,应该将这种主动轮询的方式改成由事件驱动的可 能更好一点。但是,博主暂时没有想到如何设计这样的系统,可能在后面的实践中,掌握这样的设计方法的时候,再来向大家讲述。

            好了,ECS架构实践的第一篇博客就到此结束了。

            如果您有什么不明白的地方,或者发现了文中设计上的缺陷,欢迎大家在评论中指出。毕竟,旁观者清,当局者迷。希望能够和大家互相的学习!互相进步!

            这个游戏的源代码和程序以及上传至CSDN,感兴趣的同学可以自行下载来阅读和试玩,不要忘了在评论中给出你获得的最高分哦,大家比比看谁的反应是最好的哦哦!!!

           ShapeWar_SourceCode.zip

           ShapeWar_exe.zip(部分资源来至于网络,请大家不要用于商业用途哦!!!)

     
  • 相关阅读:
    VMware安装Centos7过程记载
    php服务器设置指示
    php变化变量
    php参数
    php变量类型
    php外界PHP变量
    php语句的脱离方法
    PHP算术操作符
    PHP通过调用传递(Passingbyreference)
    php初始化数组
  • 原文地址:https://www.cnblogs.com/FuTaimeng/p/5572190.html
Copyright © 2011-2022 走看看