STDIO
Tìm kiếm gần đây
    • Nội dung
    • QR Code
    • 0
    • 0
    • Sao chép

    CBP-7: Cài Đặt Phản Ứng Cho Entity

    Thiết lập phản ứng của Entity nhằm điều khiển các Component trong CBP.
    20/08/2015
    15/09/2020
    6 phút đọc
    CBP-7: Cài Đặt Phản Ứng Cho Entity

    Giới thiệu

    Bài viết hướng dẫn độc giả hiện thực hệ thống cài đặt phản ứng cho Entity. Đây là nhân tố quyết định, giúp các lập trình viên có thể dễ dàng lập trình các Entity như ý, hệ thống cài đặt phản ứng phong phú, chi tiết cũng có thể giúp tạo ra được rất nhiều loại Entity khác nhau.

    Tải project mẫu

    Đây là project ví dụ dùng trong bài viết: CBP-7-2019.zip.

    Project này có thể mở bằng Visual Studio 2019, project này chứa các file mã C++ của CBP, project có thể không tương thích với nhiều môi trường Visual Studio khác nhau nhưng có thể dành để tham khảo.

    Thế nào là phản ứng của Entity?

    Phản ứng của Entity là cách gọi những thao tác xử lý của Entity đối với Command mà nó nhận được. Có thể là thao tác pushCommand cho 1 Component, có thể là thực thi 1 hàm do lập trình viên định nghĩa.

    Phản ứng của Entity được cài đặt lúc khởi tạo EntityEntity sẽ xem đó là cơ chế hoạt động trong suốt thời gian mà nó tồn tại. Ví dụ:

    • Khi nhấn 1 phím di chuyển, Entity sẽ nhận được Entity Command điều khiển di chuyển. Căn cứ vào Command này, Entity sẽ điều khiển Component hoạt ảnh, đổi hoạt ảnh sang di chuyển, chuyển hướng Animation sang hướng di chuyển (lật sang trái, sang phải), điều khiển Component di chuyển, gia tốc cho Entity. Đây là 1 bộ phản ứng của Entity, sử dụng Component Command.
    • Khi Entity rơi vào trạng thái chết, Component hoạt ảnh sẽ chuyển hoạt ảnh của Entity cho phù hợp, bộ xử lý hiệu ứng thêm hiệu ứng quanh khu vực Entity (nếu có), Entity được đưa ra khỏi bộ update bình thường để sẵn sàng hủy khi có thể. Đây là 1 bộ phản ứng vừa sử dụng Command, vừa sử dụng phương thức được định nghĩa ngoài.

    Phân loại phản ứng

    Phản ứng sử dụng Component Command

    Đây là kiểu phản ứng đơn giản đang sử dụng cho phương thức update của Entity. Kết quả của phản ứng này là push 1 Component Command vào danh sách Command của 1 Component xác định. Dạng phản ứng này thường dùng để định nghĩa logic cơ bản của đối tượng.

    Phản ứng sử dụng phương thức tự định nghĩa

    Đây là kiểu phản ứng ứng dụng con trỏ hàm, các hàm phản ứng do lập trình viên định nghĩa có dạng trả về là void và đối số là 1 con trỏ đến Entity phản ứng. Với dạng này, lập trình viên dễ dàng thao tác với những phương thức được định nghĩa trong Entity như get/set Property hoặc lấy Entity phản ứng làm đối số truyền vào những hàm khác (như khi hủy Entity). Dạng phản ứng này thường được dùng để định nghĩa các thao tác xử lý như va chạm, cổng dịch chuyển, ...

    Cài đặt phản ứng

    Phương thức commandProcess cho Entity nhằm tổng quát hóa quá trình xử lý Entity Command. Bước này tối ưu xử lý cho danh sách phản ứng với std::map.

    Với sự hỗ trợ của 2 struct mới: ReactCommandReactFunction, có thể lưu trữ các phản ứng dưới dạng mảng 1 chiều, đối với các phản ứng sử dụng phương thức được định nghĩa ngoài, dùng con trỏ hàm để giải quyết, mọi chuyện thật sự rất đơn giản:

    1. So sánh Command nhận được với Command khóa.
    2. Nếu trùng với Command khóa thì push Command phản ứng vào Component có ID tương ứng hoặc thực thi phương thức đã định. Nếu không thì bỏ qua.

    File Entity.h

    class Entity
    {
    	...
    public:
    	typedef void(*EntityReactFunction)(Entity* reactor);
    	...
    	struct ReactCommand
    	{
    		Entity::COMMAND command;
    		ID::COMPONENT	componentID;
    		int				reactCommand;
    
    		// @param _command: The Entity Command cause this react.
    		// @param _componentID: The Component ID mark the component get react.
    		// @param _reactCommand: The given command.
    		ReactCommand(Entity::COMMAND _command, ID::COMPONENT _componentID, int _reactCommand)
    		{
    			command = _command;
    			componentID = _componentID;
    			reactCommand = _reactCommand;
    		}
    	};
    
    	struct ReactFunction
    	{
    		Entity::COMMAND command;
    		EntityReactFunction	reactFunction;
    
    		// @param _command: The Entity Command cause this react.
    		// @param _reactCommand: The .
    		ReactFunction(Entity::COMMAND _command, EntityReactFunction _reactFunction)
    		{
    			command = _command;
    			reactFunction = _reactFunction;
    		}
    	};
    	...
    	// To process the received Entity Command.
    	// @param: the processing command.
    	int commandProcess(Entity::COMMAND command);
    
    private:
    	...
    	vector<ReactCommand>	m_reactCommands;
    	vector<ReactFunction>	m_reactFunctions;
    };

    File Entity.cpp

    int Entity::commandProcess(COMMAND command)
    {
    	for (ReactCommand react : m_reactCommands)
    	{
    		if (command == react.command)
    			m_components.at(react.componentID)->pushCommand(react.reactCommand);
    	}
    
    	for (ReactFunction react : m_reactFunctions)
    	{
    		if (command == react.command)
    			react.reactFunction(this);
    	}
    
    	return FSUCCESS;
    }
    

    Vậy là hệ thống phản ứng của Entity đã hoàn chỉnh, việc còn lại là định nghĩa phương thức thêm phản ứng vào danh sách phản ứng.

    File Entity.h

    class Entity
    {
           ...
    public:
           ...
           // To add new react to this Entity.
           // IMPORTANT: The reacts are orderly
           //     the ReactFunction(s) are called after ReactCommand(s).
           // @param react: the new pushed react.
           int settingReact(ReactCommand react);
           int settingReact(ReactFunction react);
    ...
    };

    File Entity.cpp

    int Entity::settingReact(ReactCommand react)
    {
    	m_reactCommands.push_back(react);
    	return FSUCCESS;
    }
    
    int Entity::settingReact(ReactFunction react)
    {
    	m_reactFunctions.push_back(react);
    	return FSUCCESS;
    }

    File main.cpp

    void init(HINSTANCE instance, HWND handler)
    {
    	FTexture::init(instance, handler);
    
    	g_entity = new Entity();
    	CAnimation::addComponentTo(g_entity, "Resource\\logo.bmp");
    	CPosition::addComponentTo(g_entity, 50, 50);
    
    	g_entity->settingReact(Entity::ReactCommand(Entity::COMMAND::HIDE, 
                                                    ID::COMPONENT::ANIMATION, 
                                                    CAnimation::COMMAND::HIDE));
    	g_entity->settingReact(Entity::ReactCommand(Entity::COMMAND::SHOW, 
                                                    ID::COMPONENT::ANIMATION, 
                                                    CAnimation::COMMAND::SHOW));
    	g_entity->settingReact(Entity::ReactFunction(Entity::SHOW, [](Entity* entity)
    	{
    		ComponentProperty newPos(new Vector2(rand() % 400 + 50, rand() % 400 + 50), 
                                     ComponentProperty::Type::PTYPE_VECTOR2, true);
    		entity->setProperty(ID::COMPONENT::POSITION, newPos, 
                                CPosition::PropertyFlag::PFLAG_POSITION);
    	}
    	));
    }
    

    Đây là bước thiết lập phản ứng cho Entity đã sử dụng cả 2 cách thiết lập, sử dụng ReactCommandReactFunction. Để rút gọn, trong bước thiết lập ReactFunction đã sử dụng lambda, có thể định nghĩa phương thức như bình thường và truyền vào hàm dưới dạng con trỏ hàm.

    File Entity.cpp

    int Entity::update(float delta)
    {
    	while (true)
    	{
    		Entity::COMMAND command = popCommand();
    		if (command == NULL_COMMAND)
    			break;
    
    		commandProcess(command);
    	}
    
    	// Component updating.
    	for (Pair_ID_ptrCBase componentPair : m_components)
    		componentPair.second->update(delta);
    
    	return 0;
    }
    

    Ở bước này xóa đi phần giả lập phản ứng để thử nghiệm ở các bài viết trước, thay vào đó là vòng lặp xử lý Entity Command. Mục đích hướng tới của thử nghiệm này là làm cho project hoạt động giống như ví dụ trước sau tất cả những thay đổi trên.

    Tổng kết

    Bài viết này là 1 phần rất quan trọng trong hệ thống CBP, những phản ứng này kết hợp với các Component càng đơn giản, càng sơ khai, các Command càng chi tiết thì khả năng tùy biến của lập trình viên đối với Entity càng cao, tuy nhiên kéo theo đó là bước lập trình Entity càng dài, càng phức tạp, người thiết kế cần có sự đánh giá đúng đắn về project đang làm để cân bằng hợp lý.

    Bài chung series

    0 Bình luận
    Lập Trình Game

    Lập Trình Game

    Kiến thức, kỹ thuật, kinh nghiệm lập trình game.

    Đề xuất

    CBP-8: Component Điều Khiển và AI – Component Ra Lệnh
    Component ra lệnh - các Component có khả năng gửi Entity Command cho ...
    CBP-3: Khai Báo Component Cơ Bản, Tích Hợp Component vào Entity
    Khai báo component CAnimation để thêm hình ảnh hiển thị cho Entity, đây ...

    Khám phá

    CBP-9: Bộ Khởi Tạo Entity – Factory và Hệ Thống ID
    Tổ chức lại CBP bằng cách tạo ra Factory, sản xuất Entity dựa vào các ID ...
    CBP-2: Khai Báo Component Cơ Sở và Entity Cơ Bản
    Tư tưởng của hệ thống Component - Entity trong Component Base ...
    CBP-4: Giao Tiếp với Entity – Hệ Thống Chỉ Lệnh
    Hướng dẫn về hệ thống chỉ lệnh, bước đầu hiện thực ứng dụng hệ thống chỉ ...
    CBP-5: Truyền và Lấy Thông Số từ Component
    Giao tiếp giữa Component và Entity thông qua Command trong mô hình CBP.
    CBP-1: Tổng Quan về Project Ví Dụ
    Giới thiệu về Component Base Programming (CBP) - sơ lược về project ví ...
    CBP-6: Hàng Đợi Chỉ Lệnh
    Chuẩn hóa các thao tác nhận và xử lý chỉ lệnh từ Component trong mô hình ...
    CBP-0: Giới Thiệu về Component Base Development
    Phương pháp lập trình Hướng thành phần (Component-base Development - ...
    Cài Đặt Môi Trường Lập Trình Android Studio trên Windows và Tạo Project Đầu Tiên
    Hướng dẫn cài đặt môi trường lập trình Android Studio và tạo project đầu ...
    29/05/2015
    Khi bạn nhấn vào liên kết sản phẩm do STDIO đề xuất và mua hàng, STDIO có thể nhận được hoa hồng. Điều này hỗ trợ STDIO tạo thêm nhiều nội dung hữu ích. Tìm hiểu thêm.
    STDIO
    Trang chính
    Công ty TNHH STDIO

    30, Trịnh Đình Thảo, Hòa Thạnh, Tân Phú, Hồ Chí Minh
    +84 28.36205514 - +84 942.111912
    developer@stdio.vn

    383/1 Quang Trung, Phường 10, Quận Gò Vấp, Hồ Chí Minh
    Số giấy phép ĐKKD: 0311563559 do sở Kế hoạch và Đầu Tư TPHCM cấp ngày 23/02/2012

    ©STDIO, 2013 - 2020