Game Studio
Liên kế mạng xã hội

Game Studio


Hướng dẫn tạo hiệu ứng sét đánh trong Cocos 2D-X

Giới thiệu

Ngày nay, game nói chung và game di động nói riêng hấp dẫn người chơi không chỉ nhờ vào nội dung hấp dẫn mà còn dựa vào những hiệu ứng đồ hoạ, âm thanh sống động. Để giúp người chơi có những giây phút “mãn nhãn”, chúng tôi, nhà phát triển Sins – The Salvation đã tạo ra nhiều hiệu ứng đồ hoạ xuyên suốt quá trình chơi game. Một trong những hiệu ứng tạo ấn tượng cho người chơi là hiệu ứng sấm sét dây chuyền xuất hiện trong mode chơi cuối cùng của Sins – The Salvation. Tôi sẽ hướng dẫn các bạn tạo ra hiệu ứng đó trong bài viết này.

Tiền đề bài viết

Nhiều lập trình viên mới bước chân vào ngành công nghiệp game đã gửi email nhờ chúng tôi hướng dẫn cách tạo ra những hiệu ứng trong Sins – The Salvation. Để giúp đỡ các bạn, chúng tôi đã viết nhiều bài viết trên hệ thống STDIO Article để giúp các bạn tạo ra được những hiệu ứng giống như trong Sins – The Salvation. Bài viết này là một trong những bài thuộc loạt bài viết đó.

Đối tượng hướng đến

Bài viết này dành cho những lập trình viên mới làm quen với Cocos2d-x và muốn tạo hiệu ứng sống động cho game của mình.

Phân tích vấn đề

Sau khi hoàn thành bài viết này, các bạn có thể tạo ra hiệu ứng như sau:

Và tất nhiên rằng, hiệu ứng sấm sét sẽ chớp giật liên tục chứ không tĩnh như hình vẽ chúng ta thấy ở trên. Để tạo ra hiệu ứng như trên, chúng tôi đã sử dụng mẫu sét dưới đây. Hình ảnh này được tạo ra bởi các hoạ sĩ của STDIO.

Ý tưởng của chúng tôi là tạo hình sấm sét bằng cách ghép nhiều mẫu sét nhỏ để tạo thành một đường sét dài và vị trí của các mẫu sét được chọn ngẫu nhiên để hiệu ứng giống với thực tế hơn. Để hiểu rõ hơn, các bạn có thể theo dõi hình minh hoạ dưới đây:

Hiện thực

Để đơn giản trong quá trình hiện thực, chúng tôi đã tạo mẫu sét bằng cách chia đều hình ảnh thành một bảng có kích thước MxN. M là số mẫu sét theo chiều đứng, N là số mẫu sét theo chiều ngang. Hiệu ứng được khởi tạo bởi hình ảnh chứa các mẫu sét và 2 thông số kèm theo M, N. Như hình ảnh mẫu sét chúng tôi đã minh hoạ ở trên, M và N tương ứng có giá trị là 1 và 8.

  1. static StormEfx* create(const char* textureName, int numRows, int numCols);

Đây là hàm khởi tạo hiệu ứng:

  1. void initStorm(CCPoint startPoint, CCPoint endPoint, float lightSpread,
  2. float boltLength, int numFramesPerChange, float endBoltLength);

Trong đó:

  • startPoint, endPoint: vị trí bắt đầu và kết thúc của hiệu ứng.
  • lightSpread: thông số xác định độ lan rộng sang 2 bên của hiệu ứng. Giá trị của lightSpread càng lớn, hiệu ứng sẽ các rộng.
  • boltLength: độ dài của mỗi mẫu sét khi vẽ lên màn hình.
  • numFramesPerChange: hình dạng của hiệu ứng sẽ được cập nhật sau mỗi numFramesPerChange frame.
  • endBoltLength: độ dài tối đa của mẫu cuối cùng.

Đoạn chương trình khởi tạo hiệu ứng:

  1. CCTexture2D* pTex = CCTextureCache::sharedTextureCache()->addImage(textureName);
  2.  
  3. m_iNumTextureRows = numRows;
  4. m_iNumTextureCols = numCols;
  5.  
  6. m_fTextureBoltLen = (float) pTex->getPixelsHigh() / m_iNumTextureRows;
  7.  
  8. float sampleWidth = pTex->getPixelsWide() / m_iNumTextureCols;
  9. float sampleHeight = pTex->getPixelsHigh() / m_iNumTextureRows;
  10.  
  11. int numBoltSamples = m_iNumTextureRows*m_iNumTextureCols;
  12. m_vSpriteBolts = new CCSprite*[numBoltSamples];
  13.  
  14. for(int i = 0; i < numBoltSamples; i++)
  15. {
  16. int r = i / m_iNumTextureCols;
  17. int c = i % m_iNumTextureCols;
  18.  
  19. m_vSpriteBolts[i] = CCSprite::createWithTexture(pTex,
  20. CCRectMake(c*sampleWidth, r*sampleHeight, sampleWidth, sampleHeight));
  21.  
  22. m_vSpriteBolts[i]->retain();
  23. }

Mỗi mẫu sét sẽ được ánh xạ tương ứng với một đối tượng CCSprite, chúng tôi sẽ dùng những đối tượng này để tạo hình cho hiệu ứng.

Hiệu ứng sẽ được sinh ngẫu nhiên và liên tục:

  1. float distToEnd = 0.0f;
  2.  
  3. CCPoint vectToEnd;
  4. CCPoint curPosition = m_tStartPoint;
  5.  
  6. int idx = 0;
  7.  
  8. do
  9. {
  10. m_vBolts[idx] = curPosition;
  11.  
  12. vectToEnd = ccpSub(m_tEndPoint, curPosition);
  13. vectToEnd.y += randFloat(-m_fLightningSpread,m_fLightningSpread)*vectToEnd.x;
  14. vectToEnd.x += randFloat(-m_fLightningSpread,m_fLightningSpread)*vectToEnd.y;
  15. distToEnd = ccpLength(vectToEnd);
  16. vectToEnd = ccpNormalize(vectToEnd);
  17. vectToEnd = ccpMult(vectToEnd, m_fBoltLen);
  18.  
  19. curPosition = ccpAdd(curPosition, vectToEnd);
  20.  
  21. idx++;
  22. }
  23. while(distToEnd > m_fEndBoltLength);
  24.  
  25. m_vBolts[idx++] = m_tEndPoint;
  26.  
  27. m_iNumBolts = idx;

Các đối tượng CCSprite tương ứng với các mẫu sét sẽ được thiết đặt các thông số vị trí, góc quay tương ứng để tạo hình hiệu ứng chúng ta đã sinh ở trên.

  1. for(int i = 0; i < m_iNumBolts-1; i++)
  2. {
  3. CCPoint start = m_vBolts[i];
  4. CCPoint end = m_vBolts[i+1];
  5.  
  6. CCPoint pDirection = ccpSub(end, start);
  7.  
  8. float rotatedAngle = ccpToAngle(pDirection);
  9. float degreeAngle = CC_RADIANS_TO_DEGREES(rotatedAngle);
  10. float boltLength = ccpLength(ccpSub(end, start));
  11.  
  12. float scaleFactor = boltLength / m_fTextureBoltLen;
  13.  
  14. int randomBoltIdx = CCRANDOM_0_1()*(m_iNumTextureRows*m_iNumTextureCols-1);
  15. CCSprite* pBolt = m_vSpriteBolts[randomBoltIdx];
  16. pBolt->setScaleY(scaleFactor);
  17. pBolt->setScaleX(scaleFactor*m_fBoltWidthScale);
  18. pBolt->setRotation(90-degreeAngle);
  19. // average position between start and end
  20. pBolt->setPosition(ccpMult(ccpAdd(start, end), 0.5f));
  21. pBolt->visit();
  22. }

Cuối cùng, để tạo hiệu ứng sấm xét chéo màn hình như hình mình hoạ ở đầu bài viết, tôi đã sử dụng đoạn mã nguồn sau:

  1. CCSize winSize = CCDirector::sharedDirector()->getWinSize();
  2.  
  3. StormEfx* effect = StormEfx::create("efx_thunder.png", 1, 8);
  4. effect->initStorm(ccp(0, 0), ccp(winSize.width, winSize.height), 0.5f, 48.0f, 15, 96.0f);
  5. effect->setLifeTime(10.0f);
  6. this->addChild(effect);

Mã nguồn của component StormEfx các bạn có thể xem tại:

  • DOWNLOAD StormEfx.h
  • DOWNLOAD StormEfx.cpp

Kết luận

Tạo hiệu ứng dựa trên các engine có sẵn không khó nếu bạn là người có kinh nghiệm. Chỉ cần một ý tưởng đơn giản và độc đáo, các bạn có thể chinh phục người chơi một cách dễ dàng.

Theo: Stdio


Đăng sự kiện cho developer