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

    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ỉ lệnh cơ bản để điều khiển CAnimation trong mô hình CBP.
    20/08/2015
    15/09/2020
    6 phút đọc
    CBP-4: Giao Tiếp với Entity – Hệ Thống Chỉ Lệnh

    Giới thiệu

    Bài viết trước đã hiện thực gần hoàn chỉnh CAnimation và đã kiểm tra được hoạt động của Component này. Bài viết này sẽ thêm hệ thống chỉ lệnh cho CAnimation và hiện thực dùng chỉ lệnh để điều khiển hình ảnh hiển thị của Entity.

    Tải project mẫu

    Đây là project ví dụ dùng trong bài viết: CBP-4-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.

    Ý tưởng về hệ thống chỉ lệnh (Command)

    Component hoạt động liên tục và song song với các Component khác nhằm điều khiển Entity, chính vì Entity không tự quản lý những hoạt động của chính nó, nên để điều khiển một Entity, không chỉ cần hệ thống điều khiển tầng cao (điều khiển Entity) mà còn cần một hệ thống khác, hỗ trợ Entity điều khiển tầng thấp hơn (các Component). Đây chính là mục đích của hệ thống chỉ lệnh.

    Căn cứ vào Entity Command nhận được, Entity sẽ không gửi hoặc gửi (một hoặc nhiều) Component Command cho (một hoặc nhiều) Component nhằm điều khiển phản ứng của Entity như đã giới thiệu ở CBP-2.

    Hiện thực Command

    Thực chất Command chỉ là một loại mã đánh dấu một hoạt động của Component, nên tính chất của Command chỉ cần phân biệt được với các Command khác là đủ. Ta có thể sử dụng macro, enum hoặc bất kỳ kiểu khai báo nào khác để có một hệ thống Command gồm những mã phân biệt là được, vì thực chất vẫn phải xử lý từng loại Command một cách riêng biệt trong phương thức commandProcess.

    Tuy nhiên, nếu xây dựng tập trung thì hệ thống Command có thể sẽ phình lên và rất khó kiểm soát khi ta có quá nhiều Component, thêm nữa là Developer cũng sẽ không biết có thể gửi Command nào cho đúng. Chính vì vậy, ta cũng cần có cách thông báo cho Developer biết là có thể gửi những Command nào cho Component mà họ muốn thao tác.

    Cách của tôi là khai báo những Command mà Component sẽ sử dụng bên trong khai báo lớp của Component đó, và dựa theo hệ thống gợi ý của IDE để làm việc.

    Phân tích mẫu các Component Command cho CAnimation

    CAnimation theo tôi xử lý một số Command cơ bản như sau:

    • Thay đổi hình ảnh hiển thị của Entity.
    • Lật ảnh (trái-phải hoặc trên-dưới).
    • Ẩn/hiện hình ảnh.

    Ngoài ra nếu có nhu cầu, CAnimation có thể có thêm một số Command đặc biệt nữa như hiệu ứng thu phóng, fade in/fade out, ... cơ chế CBP rất dễ nâng cấp, nên không cần phải lường trước những điều này.

    Trong phạm vi bài viết chỉ hiện thực Command ẩn/hiện hình ảnh.

    Khai báo COMMAND cho CAnimation

    Thêm COMMAND cho CAnimation và có được một khai báo như sau:

    class CAnimation : public CBase
    {
    public:
    	enum COMMAND
    	{
    		CHANGE_ANIMATION = 0,
    		FACE_LEFT,
    		FACE_RIGHT,
    		SHOW,
    		HIDE
    	};
    
    	static CAnimation* addComponentTo(Entity* object, const char* resourcePath);
    
    	virtual int update(float deltaTime);
    	virtual int commandProcess(int command);
    
    	int draw();
    
    private:
    	CAnimation();
    	~CAnimation();
    
    private:
    	vector<FTexture*>	m_animate;
    	unsigned int		m_currentAnimationIndex;
    };

    Ở đây tôi chỉ tạm đặt Command CHANGE_ANIMATION để thay đổi hình ảnh hiển thị, thực chất một Entity có thể có nhiều hơn 2 loại hoạt ảnh, lúc này ta có thể thay đổi cấu trúc của COMMAND lại cho phù hợp.

    Mục đích của enum COMMAND là khi sử dụng ở tầng development sẽ gọi theo dạng như sau:

    componentAnimation->commandProcess(CAnimation::COMMAND::CHANGE_ANIMATION);

    Nên ta có thể tùy nghi sử dụng enumstruct, class… để định nghĩa COMMAND cho từng class Component, miễn sao đảm bảo được cách gọi Command để truyền vào phương thức commandProcess như trên.

    Nâng cấp COMMAND một chút cho cách tạo một hệ thống Command dùng cho nhiều animation, định nghĩa như sau:

    struct COMMAND
    {
    	enum CHANGE_ANIMATION_TO
    	{
    		STAND = 0,
    		MOVE,
    		JUMP,
    		HIT,
    		NUM_OF_ANIMATION_INDEX
    	};
    
    	enum
    	{
    		FACE_LEFT = CHANGE_ANIMATION_TO::NUM_OF_ANIMATION_INDEX,
    		FACE_RIGHT,
    		SHOW,
    		HIDE
    	};
    };

    Lúc này cách gọi Command có dạng:

    componentAnimation->commandProcess(CAnimation::COMMAND::CHANGE_ANIMATION_TO::STAND);
    componentAnimation->commandProcess(CAnimation::COMMAND::FACE_LEFT);

    Khi sử dụng có thể dựa vào hệ thống gợi ý của IDE để gọi Command. Tuy nhiên do framework còn khá đơn giản và chỉ giới thiệu về CBP là chính nên bài viết không sử dụng cấu trúc này cho ví dụ.

    Nên suy nghĩ trước về hệ thống Command của từng Component để đưa ra cấu trúc hợp lý cho COMMAND, điều này không những giúp dễ dàng xử lý các chỉ lệnh trong commandProcess mà còn giúp cho câu chỉ lệnh đưa vào hàm trở nên có nghĩa. Như ví dụ trên dễ dàng dịch được nghĩa của chỉ lệnh CAnimation command: change animation to stand ở ngôn ngữ giao tiếp hằng ngày.

    Thử nghiệm xử lý Component Command

    Sau đây là hiện thực và thử nghiệm Command SHOWHIDE của CAnimation:

    Cần định nghĩa xử lý của CAnimation đối với 2 Command này trong CAnimation::commandProcess:

    int CAnimation::commandProcess(int command)
    {
    	switch (command)
    	{
    	case CAnimation::COMMAND::HIDE:
    		m_visible = false;
    		break;
    
    	case CAnimation::COMMAND::SHOW:
    		m_visible = true;
    		break;
    
    		// Other commands
    
    	default:
    		break;
    	}
    	return 0;
    }

    Tại đây xuất hiện một thuộc tính mới: m_visible, đây là thuộc tính kiểu bool tôi định nghĩa thêm cho CAnimation nhằm hỗ trợ xử lý cho 2 Command SHOWHIDE.

    Chỉ set giá trị cho m_visible thôi là chưa đủ, cần xử lý thao tác vẽ dựa trên thuộc tính này thì SHOWHIDE mới thực sự hoạt động. Thay đổi phương thức draw thành như sau:

    int CAnimation::draw(HDC hdc)
    {
    	if (m_visible)
    	{
    		m_animate.at(m_currentAnimationIndex)->draw(hdc);
    	}
    	return 0;
    }

    Và không quên đặt giá trị mặc định cho m_visible tại constructor:

    CAnimation::CAnimation()
    {
    	m_typeID = ID::COMPONENT::ANIMATION;
    	m_visible = true;
    	m_animate.clear();
    }

    Giờ tạo một biến đếm thời gian tại khu vực update của Entity để xử lý Command theo chu kỳ. Lưu ý rằng đây chỉ là code tạm nhằm thử nghiệm hệ thống Command, không được trực tiếp gọi phương thức commandProcess cho các Command mới.

    if (s_timer >= 1.0f)
    {
    	m_components.at(0)->commandProcess(CAnimation::COMMAND::HIDE);
    }
    
    if (s_timer >= 2.0f)
    {
    	m_components.at(0)->commandProcess(CAnimation::COMMAND::SHOW);
    	s_timer = 0.0f;
    }

    Lúc này chỉ có duy nhất CAnimation trong Entity, nên có thể trực tiếp gọi đến Component này trong danh sách tại index 0. Và như vậy, kết quả mong đợi là logo của STDIO sẽ chớp tắt với chu kỳ 2 giây.

    Bài chung series

    0
    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.

    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.

    Đề xuất

    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-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 ...

    Khám phá

    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-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-10: Hệ Thống Quản Lý Tập Trung Các Component Đặc Thù
    Hệ thống quản lý tập trung các Component sử dụng phương thức đặc trưng.
    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 ...
    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.
    CBP-1: Tổng Quan về Project Ví Dụ
    Giới thiệu về Component Base Programming (CBP) - sơ lược về project ví ...
    Zigbee Và Wi-Fi trong Giao Tiếp M2M
    Ngày nay việc giao tiếp M2M giữa các thiết bị IoT với nhau rất rắc rồi ...
    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