动画特效框架

来源:互联网 发布:梦里花落知多少2郭敬明 编辑:程序博客网 时间:2024/06/06 03:44

#pragma once


class HDCMemo
{
public:
 HDCMemo(RECT rtImg);
 virtual ~HDCMemo(void);

 void Record(HDC hDC);
 void Recover(HDC hDC);
 RECT getSize();
private:
 HANDLE  m_hMutex;
 RECT  m_rtImg;
 HBITMAP  m_bmpMemo;
};

 

 

#pragma once
#include "../CE600.h"
#include "../HDCMemo.h"

 

class Cartoon
{
public:
 bool Run(LPVOID pPar);
 bool IsOver();

protected:
 Cartoon(CDialog* pDlg, HDCMemo* pHDCMemo);
 virtual ~Cartoon(void);
 virtual void Render(LPVOID pPar) = 0;

 CDialog  *m_pDlg;
 HDCMemo  *m_pHDCMemo;
 HANDLE  m_hMutex;
 ThreadEx* m_pThread;
 HANDLE  m_hClose;
 LPVOID  m_pRenderPar;
 friend DWORD CartoonThread(LPVOID pThis);
};

 

 

 

 

#pragma once
#include "Cartoon.h"

 


class CartoonPiece: public Cartoon
{
public:
 CartoonPiece(CDialog* pDlg, HDCMemo* pHDCMemo);
 virtual ~CartoonPiece(void);

private:
 virtual void Render(LPVOID pPar);
};

 

 

使用:

BOOL CCartoonDlg::OnInitDialog()
{
 CDialog::OnInitDialog();
 CRect rtImg;
 GetClientRect(rtImg);
 m_pMemo = new HDCMemo(rtImg);
 CDC* pDC = GetDC();
 CDCBuf buf(pDC,&rtImg);
 buf.fillRect(RGB(0,0,255));
 m_pMemo->Record(buf);
 m_pCartoon = new CartoonPiece(this,m_pMemo);
 m_pCartoon->Run(NULL);

 return TRUE;  // return TRUE  unless you set the focus to a control
}

 

void CCartoonPieceDlg::OnDestroy()
{
 // TODO: Add your message handler code here
 if( NULL != m_pCartoon)
  delete m_pCartoon;
 m_pCartoon = NULL;
 if( NULL != m_pMemo)
  delete m_pMemo;
 m_pMemo = NULL;

 CDialog::OnDestroy();
}

 

BOOL CCartoonPieceDlg::OnEraseBkgnd(CDC* pDC)
{
 m_pMemo->Recover(*pDC);

 return FALSE;
}

 

、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

png格式的渲染速度较慢,画一张480*272的图要200毫秒左右,而人眼的辨别能力为100毫秒左右,故会出现反应延迟现象。而这个现象试图通过画取部份空间来解决并不现实。因为这样会导致两种渲染逻辑:1,如果是首次画,需全画。 2, 如果是补画,需重画部份空间。但是判断是首画还是补画会比较麻烦,因为触发画图函数的消息可以是用户触发的,也可以是由系统触发的(例如窗口被遮挡住等)。而要对所有的触发情况做标志,并针对标志做相应的全画和补画,不现实也不可靠。安全的方法可能还是得每次都全画,只是在全画的过程中想办法提高效率。  另还有一个渲染动画的问题一直也没有很好的解决,因为渲染过程中系统无法响应其它消息, 所以如果是一个动画,那么只有等动画执行完毕了。 虽然还可以用线程等方法,但是目前却没有很好的打包和设计模式来解决,导致明明是一个连续的动作,却要分割成一个个图画,然后再添加相关消息处理过程控制在程序里四处散放等,导致实现不影响用户动作的一个动画很麻烦。

         解决方案:通过线程,计时器和备忘录模式(带互斥作用)解决。流程如下:

         客户端:

         动作线程:

         服务器->开启刷新定时器。

         While(X)

         {       

                   渲染。

                  备忘录记录记录(画面)。

}

         服务器->关闭刷新定时器。

 

         服务器端:

         OnPaint()

         {

                   画图(获得备忘录记录)

         }

 

         备: 通过备忘录模式,使每次修改扩展渲染功能都不用去服务器的OnPaint功能里修改(画图一定要经过OnPaint才行,不然一些重画的情况时,画面会丢失)。通过线程,使动画过程不影响其它消息的响应。通过定时器来刷新使动画的渲染速度稳定。另,备忘录需带互斥功能,以防画面读写过程出错。

 

 

/********************************************************************
 created: 2011/03/01
 created: 1:3:2011   10:52
 filename:  g:/20110221文件整理/源码/小工具_实现代码(20110221版)/CE600/HDCMemo.h
 file path: g:/20110221文件整理/源码/小工具_实现代码(20110221版)/CE600
 file base: HDCMemo
 file ext: h
 author:  Clark
 
 purpose: 用于动画渲染的备忘录模式
*********************************************************************/

 

 

#include "StdAfx.h"
#include "HDCMemo.h"

HDCMemo::HDCMemo(RECT rtImg)
{
 CopyRect(&m_rtImg,&rtImg);
 HDC hDC = GetDC(NULL);
 m_bmpMemo = CreateCompatibleBitmap(hDC,m_rtImg.right-m_rtImg.left, m_rtImg.bottom-m_rtImg.top);
 ReleaseDC(NULL,hDC); 

 TCHAR szTemp[MAX_PATH];
 _stprintf(szTemp,_T("MUTEX_FOR_HDCMEMO_%x"),this);
 m_hMutex = CreateMutex(NULL,FALSE,szTemp);
}

HDCMemo::~HDCMemo(void)
{
 DeleteObject(m_bmpMemo);
 if( WAIT_OBJECT_0 == WaitForSingleObject(m_hMutex,5000))
 {
  ReleaseMutex(m_hMutex);
 }
 CloseHandle(m_hMutex);
}

void HDCMemo::Record(HDC hDC)
{
 if( WAIT_OBJECT_0 == WaitForSingleObject(m_hMutex,INFINITE))
 {
  HDC dcBitmap = CreateCompatibleDC(hDC);
  HGDIOBJ hOldBitmap = SelectObject(dcBitmap, m_bmpMemo);
  BitBlt(dcBitmap,0,0,m_rtImg.right-m_rtImg.left, m_rtImg.bottom-m_rtImg.top,hDC,0,0,SRCCOPY);
  SelectObject(dcBitmap, hOldBitmap);
  DeleteDC(dcBitmap);

  ReleaseMutex(m_hMutex);
 }
}

void HDCMemo::Recover(HDC hDC)
{
 if( WAIT_OBJECT_0 == WaitForSingleObject(m_hMutex,INFINITE))
 {
  HDC dcBitmap = CreateCompatibleDC(hDC);
  HGDIOBJ hOldBitmap = SelectObject(dcBitmap,m_bmpMemo);
  BitBlt(hDC,0,0,m_rtImg.right-m_rtImg.left, m_rtImg.bottom-m_rtImg.top,dcBitmap,0,0,SRCCOPY);
  SelectObject(dcBitmap,hOldBitmap);
  DeleteDC(dcBitmap);

  ReleaseMutex(m_hMutex);
 }
}

RECT HDCMemo::getSize()
{
 return m_rtImg;
}

 

、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

 

 

/********************************************************************
 created: 2011/03/01
 created: 1:3:2011   11:34
 filename:  g:/20110221文件整理/源码/小工具_实现代码(20110221版)/CE600/Cartoon.h
 file path: g:/20110221文件整理/源码/小工具_实现代码(20110221版)/CE600
 file base: Cartoon
 file ext: h
 author:  Clark
 
 purpose: 动画渲染
*********************************************************************/

#include "StdAfx.h"
#include "Cartoon.h"


DWORD CartoonThread(LPVOID pThis)
{
 Cartoon* pCartoon = (Cartoon*)pThis;
 pCartoon->Render(pCartoon->m_pRenderPar);
 if( WAIT_OBJECT_0 == WaitForSingleObject(pCartoon->m_hMutex,INFINITE))
 {
  pCartoon->m_pThread = NULL;
  ReleaseMutex(pCartoon->m_hMutex);
 }
 return 0;
}

Cartoon::Cartoon(CDialog* pDlg, HDCMemo* pHDCMemo):
m_pThread(NULL)
{
 m_pDlg = pDlg;
 m_pHDCMemo = pHDCMemo;
 TCHAR szTemp[MAX_PATH];
 _stprintf(szTemp,_T("MUTEX_FOR_CARTOON_%x"),this);
 m_hMutex = CreateMutex(NULL,FALSE,szTemp);
}

Cartoon::~Cartoon(void)
{
 if( NULL != m_pThread)
  delete m_pThread;
 m_pThread = NULL;
 if( WAIT_OBJECT_0 == WaitForSingleObject(m_hMutex,5000))
 {
  ReleaseMutex(m_hMutex);
 }
 CloseHandle(m_hMutex);
}

bool Cartoon::Run(LPVOID pPar)
{
 bool bSign = false;
 if( WAIT_OBJECT_0 == WaitForSingleObject(m_hMutex,INFINITE))
 {
  if( NULL == m_pThread)
  {
   m_pRenderPar = pPar;
   m_pThread = new ThreadEx(m_hClose,CartoonThread,this);
   bSign = true;
  }
  ReleaseMutex(m_hMutex);
 }
 return bSign;
}

bool Cartoon::IsOver()
{
 bool bSign = false;
 if( WAIT_OBJECT_0 == WaitForSingleObject(m_hMutex,INFINITE))
 {
  if( NULL == m_pThread)
  {
   bSign = true;
  }
  ReleaseMutex(m_hMutex);
 }
 return bSign;
}

 

、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

 

 

/********************************************************************
 created: 2011/03/01
 created: 1:3:2011   11:34
 filename:  g:/20110221文件整理/源码/小工具_实现代码(20110221版)/CE600/Cartoon.h
 file path: g:/20110221文件整理/源码/小工具_实现代码(20110221版)/CE600
 file base: Cartoon
 file ext: h
 author:  Clark
 
 purpose: 动画渲染
*********************************************************************/

#include "StdAfx.h"
#include "CartoonPiece.h"
#include "../CDCBuf.h"


CartoonPiece::CartoonPiece(CDialog* pDlg, HDCMemo* pHDCMemo):
Cartoon(pDlg,pHDCMemo)
{
 NULL;
}

CartoonPiece::~CartoonPiece(void)
{
 NULL;
}

void CartoonPiece::Render(LPVOID pPar)
{
 CRect rtDlg;
 m_pDlg->GetClientRect(rtDlg);
 CDC* pDC = m_pDlg->GetDC();
 CDCBuf buf(pDC,&rtDlg);
 m_pDlg->ReleaseDC(pDC);
 buf.SetAuto(false);
 m_pMemo->Recover(buf);

 const int iCount = 8;
 const int iROWS = 4;
 const int iLINES = 4;
 const int iUW = rtDlg.Width()/iLINES+0.5;
 const int iUH = rtDlg.Height()/iROWS+0.5;
 const int iUW_L = iUW/iCount+0.5;
 const int iUH_L = iUH/iCount+0.5;
 int iPosX, iPosY, iW, iH;

 iW = iH = 0;
 for(int k=0; k<iCount; k++)
 {
  iPosX = iPosY = 0;
  iW += iUW_L;
  iH += iUH_L;
  for(int i=0; i<=iROWS; i++)
  {
   iPosX = 0;
   for(int j=0; j<=iLINES; j++)
   {
    CRect rtImg(iPosX,iPosY,iPosX+iW,iPosY+iH);
    if( NULL == pPar)
     buf.fillRect(RGB(0,255,0),&rtImg);
    else
     buf.drawBmp((CBitmap*)pPar,&rtImg,&rtImg);
    iPosX += iUW;
   }
   iPosY += iUH;
  }
  m_pMemo->Record(buf);
  m_pDlg->Invalidate();
  Sleep(10);
 }
 if( NULL == pPar)
  buf.fillRect(RGB(0,255,0),&rtDlg);
 else
  buf.drawBmp((CBitmap*)pPar,&rtDlg,&rtDlg);
 m_pMemo->Record(buf);
 m_pDlg->Invalidate();
}

原创粉丝点击