Cocos2d-x là 1 trong những engine mạnh để phát triển game hiện nay. Mặc dù thư viện này đã hỗ trợ một hệ thống các thành phần hỗ trợ đồ sộ, tuy nhiên do đặc thù dự án mà có những thành phần hỗ trợ sẵn không thể đáp ứng được.
Đặt vấn đề dự án cần tạo hiệu ứng rung chuyển bàn chơi trong một thời gian ngắn, hiệu ứng được tạo ra giống như mặt đất rung chuyển khi xảy ra động đất. Cocos2d-x đã cung cấp lớp CCActionInterval
để phát triển hành động cho những đối tượng Cocos2d-x. Hành động này diễn ra trong một khoảng thời gian nhất định, vì vậy hiệu ứng này được mở rộng từ CCActionInterval
Hiện thực
#ifndef __SHAKEACTION_H__ #define __SHAKEACTION_H__ #include "cocos2d.h" using namespace cocos2d; namespace stdio { namespace effect { // utils inline float randFloat(float minValue, float maxValue) { float randomNumber = ((float)rand()/(float)RAND_MAX); return randomNumber*(maxValue-minValue) + minValue; } // ~utils class ShakeAction : public CCActionInterval { public: ShakeAction(); static ShakeAction* create(float duration, float strengthX, float strengthY, int numFramesPerShake = 1, float maxAngle = 0.0f); bool initWithDuration(float duration, float strengthX, float strengthY, int numFramesPerShake, float maxAngle); virtual void startWithTarget(CCNode *pTarget); virtual void update(float dt); virtual void stop(void); protected: float _initialPosX, _initialPosY; float _initialRotation; float _strengthX, _strengthY; float _maxAngle; int _numFramesPerShake; int _frameCounter; }; } // ~effect } // ~stdio #endif //__SHAKEACTION_H__
- Dòng 11-16: hàm sinh số ngẫu nhiên trong khoảng cho trước.
- Dòng 24: phương thức tạo đối tượng ShakeAction.
- Dòng 29: phương thức khởi tạo đối tượng ShakeAction.
- Dòng 33: phương thức này được Cocos2d-x tự động gọi khi đối tượng chạy hành động được dùng để lưu lại trạng thái của đối tượng được chạy.
- Dòng 34: phương thức được gọi trong mỗi frame, trạng thái của đối tượng được cập nhật trong phương thức này.
- Dòng 35: phương thức được gọi khi hành động chạy xong, dùng khôi phục lại trạng thái ban đầu của đối tượng.
- Dòng 38: biến thành viên lưu vị trí của đối tượng trước khi thực hiện hành động.
- Dòng 39: biến thành viên lưu góc quay của đối tượng nhằm giúp cho hiệu ứng thêm chân thực, không chỉ tác động tới độ dời mà còn góc xoay của đối tượng.
- Dòng 40: độ dời tối đa theo 2 trục của đối tượng.
- Dòng 41: độ xoay tối đa của đối tượng.
- Dòng 42: biến để tính toán tần số rung của đối tượng, biến này càng lớn tần số rung của đối tượng càng nhỏ.
- Dòng 43: biến tạm để lưu số frame đã được render.
Dưới đây là phần hiện thực của hiệu ứng:
#include "ShakeAction.h" namespace stdio { namespace effect { ShakeAction::ShakeAction() :_strengthX(0.0f), _strengthY(0.0f), _initialPosX(0.0f), _initialPosY(0.0f), _initialRotation(0.0f), _maxAngle(0.0f), _frameCounter(0), _numFramesPerShake(0) { } ShakeAction* ShakeAction::create(float duration, float strengthX, float strengthY, int numFramesPerShake, float maxAngle) { ShakeAction *pAction = new ShakeAction(); pAction->initWithDuration(duration, strengthX, strengthY, numFramesPerShake, maxAngle); pAction->autorelease(); return pAction; } bool ShakeAction::initWithDuration(float duration, float strengthX, float strengthY, int numFramesPerShake, float maxAngle) { if (CCActionInterval::initWithDuration(duration)) { _strengthX = strengthX; _strengthY = strengthY; _numFramesPerShake = numFramesPerShake; _maxAngle = maxAngle; return true; } return false; } void ShakeAction::update(float dt) { _frameCounter--; if(_frameCounter <= 0) { _frameCounter = _numFramesPerShake; float randX = randFloat(-_strengthX, _strengthX); float randY = randFloat(-_strengthY, _strengthY); CCPoint currentPos = m_pTarget->getPosition(); m_pTarget->setPosition(ccpAdd(currentPos, ccp(randX, randY))); m_pTarget->setRotation(CCRANDOM_MINUS1_1()*_maxAngle); } } void ShakeAction::startWithTarget(CCNode *pTarget) { CCActionInterval::startWithTarget( pTarget ); _initialPosX = pTarget->getPosition().x; _initialPosY = pTarget->getPosition().y; _initialRotation = pTarget->getRotation(); } void ShakeAction::stop(void) { m_pTarget->setPosition(ccp(_initialPosX, _initialPosY)); m_pTarget->setRotation(_initialRotation); CCActionInterval::stop(); } } // ~effect } // ~stdio