⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chanim.cpp

📁 Windows上的MUD客户端程序
💻 CPP
📖 第 1 页 / 共 3 页
字号:
		ChDibBmp* pDibNew = new ChDibBmp();
		ASSERT( pDibNew );
		pDibNew->Create( pDIB->GetBitmapInfoAddress()->bmiHeader.biWidth,
						pDIB->GetBitmapInfoAddress()->bmiHeader.biHeight,
						24 );
		pDIB->CopyBits( pDibNew, 
                    0, 0,
                    pDIB->GetBitmapInfoAddress()->bmiHeader.biWidth,  
                    pDIB->GetBitmapInfoAddress()->bmiHeader.biHeight,
                    0, 0 );
		delete pDIB;

		pDIB = pDibNew;

	} 
	m_pDibBkgnd = pDIB; 
	m_boolBackgroundDirty = true;
	Invalidate(true);
	UpdateWindow();
	return true;
	//DeferredNewBackground();
}

bool ChAnimView::DeferredNewBackground()
{
	ChDibBmp* pDIB = m_pDibBkgnd;

	m_boolBackgroundDirty = false;
    // Create a new buffer and palette
     if ( pDIB->GetBitmapInfoAddress()->bmiHeader.biBitCount <= 8 )
	 {
	   if (!Create(pDIB)) {
	        return false;
	    }

	    // Map the colors of the background DIB to
	    // the identity palette we just created for the background
	    pDIB->MapColorsToPalette(GetPalette());
	}
	else
	{
		m_bUseCreateDIBSection = false;

	    if (m_pOneToOneClrTab) free(m_pOneToOneClrTab);
		m_pOneToOneClrTab = 0;
	    if (m_pPal) delete m_pPal;
		m_pPal = 0;

	    if (m_pDIB) delete m_pDIB;
	    m_pDIB = new ChDibBmp;
        
        if( !m_pDIB->Create(pDIB->GetWidth(), pDIB->GetHeight(),
        			pDIB->GetBitmapInfoAddress()->bmiHeader.biBitCount ) )
		{
			return false;
		}
	    CSize sizeTotal;
	    sizeTotal.cx = m_pDIB->GetWidth();
	    sizeTotal.cy = m_pDIB->GetHeight();
	    SetScrollSizes(sizeTotal);

	}

    // Render the entire scene to the off-screen buffer
    Render();

    // Paint the off-screen buffer to the window
    //Draw();
	//Invalidate(true);

    return true;
}

// Render the scene to the off-screen buffer
// pClipRect defaults to NULL
void ChAnimView::Render(CRect* pClipRect)
{
    // make sure we have something to render to
    if (!m_pDIB) return;
    CRect rcDraw;
        
    // get the background DIB and render it
    m_pDibBkgnd->GetRect(&rcDraw);
    // If a clip rect was supplied use it
    if (pClipRect) {
        rcDraw.IntersectRect(pClipRect, &rcDraw);
    }

    // draw the image of the DIB to the os buffer
    ASSERT(m_pDIB);
    m_pDibBkgnd->CopyBits(m_pDIB,       
                   rcDraw.left,
                   rcDraw.top,     
                   rcDraw.right - rcDraw.left,
                   rcDraw.bottom - rcDraw.top,
                   rcDraw.left, 
                   rcDraw.top);

#if 1
    // Render the sprite list from the bottom of the list to the top
    // Note that we always clip to the background DIB
    POSITION pos = m_spriteList.GetTailPosition();
    CSprite *pSprite;
    while (pos) {
        pSprite = m_spriteList.GetPrev(pos);
        pSprite->Render(m_pDIB, &rcDraw);
    }
#endif    
}

// Draw a section of the off-screen image buffer to the screen.
void ChAnimView::Draw(CDC* pDC, LPRECT pRect)
{
    CDC* pdc;
    CRect rcDraw;

	if(m_boolBackgroundDirty)
	{
		DeferredNewBackground();
	}

    // Make sure we have what we need to do a paint.

    if ( m_pDIB && !m_pOneToOneClrTab) 
    {
		if ( m_pDIB->GetBitmapInfoAddress()->bmiHeader.biBitCount <= 8  )
		{
			return;
		}
	}
	else if (!m_pDIB || !m_pOneToOneClrTab) 
	{

		return;
    }

    // See if a DC was supplied, and get one if not.
    if (pDC) {
        pdc = pDC;
    } else {
        pdc = GetDC();
		ChScrollWnd::OnPrepareDC(pdc);	// jwd
    }

    // See if a clip rect was supplied, and use the client area if not.
    if (pRect) {
        rcDraw = *pRect;			  // this is in logicals; jwd
    } else {
        GetClientRect(rcDraw);
		pdc->DPtoLP(LPRECT(rcDraw));  // fixed scrolling bug; jwd
    }

    // Get the clip box.
    CRect rcClip;
    pdc->GetClipBox(rcClip);

    // Create a rect for the DIB.
    CRect rcDIB;
    rcDIB.left = rcDIB.top = 0;
    rcDIB.right = m_pDIB->GetWidth() - 1;
    rcDIB.bottom = m_pDIB->GetHeight() - 1;

    // Find a rectangle that describes the intersection of the draw
    // rect, clip rect, and DIB rect.
    CRect rcBlt;
    rcBlt.IntersectRect(&rcDraw, &rcClip);
    rcBlt.IntersectRect(&rcBlt, &rcDIB);

    // Copy the update rectangle from the off-screen DC to the
    // window DC. Note that the DIB origin is the bottom-left corner.
    int w, h, xs, xd, yd, ys;
    w = rcBlt.right - rcBlt.left;
    h = rcBlt.bottom - rcBlt.top;
    xs = xd = rcBlt.left;
    yd = rcBlt.top;
    if (m_bUseCreateDIBSection) {
        ys = rcBlt.top;
    } else {
        ys = m_pDIB->GetHeight() - rcBlt.bottom;
    }

	// Center the image, if requested, and it's smaller than window
	if( m_boolCenterIt )
	{
		if(m_pDIB->GetWidth() - 1 < rcDraw.right - rcDraw.left)
		{
			xd +=  ((rcDraw.right - rcDraw.left) - (m_pDIB->GetWidth() - 1)) / 2;
		}
		if(m_pDIB->GetHeight() - 1 < rcDraw.bottom - rcDraw.top)
		{
			yd +=  ((rcDraw.bottom - rcDraw.top) - (m_pDIB->GetHeight() - 1)) / 2;
		}
	}

    // If we have a palette, select and realize it.
    CPalette* ppalOld = NULL;
    if(m_pPal) {
        ppalOld = pdc->SelectPalette(m_pPal, 0);
        pdc->RealizePalette();
    }

    BYTE* pBits;
    if (m_bUseCreateDIBSection) {
        HDC dcMem = ::CreateCompatibleDC(pdc->GetSafeHdc());
        HBITMAP hbmOld = (HBITMAP) ::SelectObject(dcMem, m_hbmSection);
        // Note: you do not need to select the palette into
        // the memory DC because the DIB section is using palette
        // index values not colors.
        ::BitBlt(pdc->GetSafeHdc(),
                 xd, yd,
                 w, h,
                 dcMem,
                 xs, ys,
                 SRCCOPY);
        ::SelectObject(dcMem, hbmOld);
        ::DeleteDC(dcMem);
    } else {
        pBits = (BYTE*)m_pDIB->GetBitsAddress();
        ::StretchDIBits(pdc->GetSafeHdc(),
                    xd,                 // Destination x
                    yd,                 // Destination y
                    w,                  // Destination width
                    h,                  // Destination height
                    xs,                 // Source x
                    ys,                 // Source y
                    w,                  // Source width
                    h,                  // Source height
                    pBits,              // Pointer to bits
                    m_pOneToOneClrTab ? m_pOneToOneClrTab :
               		m_pDIB->GetBitmapInfoAddress(),  // BITMAPINFO
                    m_pOneToOneClrTab ? DIB_PAL_COLORS : DIB_RGB_COLORS,     // Options
                    SRCCOPY);           // Rop
    }

    // Select old palette if we altered it.
    if (ppalOld) pdc->SelectPalette(ppalOld, 0);

    // Release the DC if it was one we created.
    if (!pDC) ReleaseDC(pdc);
}

// Add a region to the dirty list.
void ChAnimView::AddDirtyRegion(CRect* prcNew)
{
    // Get the rectangle currently at the top of the list.
    POSITION pos = m_DirtyList.GetHeadPosition();
    if (pos) {
        CRect* prcTop = (CRect*)m_DirtyList.GetNext(pos);
        CRect rcTest;
        // If the new one intersects the top one merge them.
        if (rcTest.IntersectRect(prcTop, prcNew)) {
            prcTop->UnionRect(prcTop, prcNew);
            return;
        }
    }
    // List is empty, or there was no intersection.
    CRect* prc = new CRect;
    *prc = *prcNew; // Copy the data.
    // Add a new rectangle to the list.
    m_DirtyList.AddHead((CObject*)prc);
}

// Render and draw all the dirty regions.
void ChAnimView::RenderAndDrawDirtyList()
{
    POSITION pos = m_DirtyList.GetHeadPosition();
    // Render all the dirty regions.
    while (pos) {
        // Get the next region.
        CRect* pRect = (CRect*)m_DirtyList.GetNext(pos);
        // Render it.
        Render(pRect);
    }
    // Draw all the dirty regions to the screen.
    while (!m_DirtyList.IsEmpty()) {
        // Get the next region.
        CRect* pRect = (CRect*)m_DirtyList.RemoveHead();
        Draw(NULL, pRect);
        // Done with it.
        delete pRect;
    }
}

// Empty the dirty list.
void ChAnimView::EmptyDirtyList()
{
    while (!m_DirtyList.IsEmpty()) {
        CRect* prc = (CRect*)m_DirtyList.RemoveHead();
        delete prc;
    }
}


void ChAnimView::Animate( bool boolRun)
{
	if( boolRun )
	{
	    if (m_uiTimer) return;
	    m_uiTimer = SetTimer(1, 55, NULL);    
	    //m_uiTimer = SetTimer(1, 100, NULL);    
	}
	else
	{
	    if (m_uiTimer)
	    {
	    	KillTimer(1);
			m_uiTimer = 0;
		}
	}
}

						// called by system timer mgr (to be defined)
void ChAnimView::OnTick()
{
    if (!m_characters.IsEmpty())
    {// Walk the character list and update any which are moving
		ChPosition pos = m_characters.GetHeadPosition();
	// !!!!!!!!! ?????????? need to change for varying framerates
		chuint32 luCurrMsec = 1000; 
	    while (pos) {
	        ChAnimCastMember* pch = m_characters.GetNext(pos);
			pch->Tick(luCurrMsec);
	    }
	    // redraw the changes
	    RenderAndDrawDirtyList();
	}

	// Now set the cursor; Animating may bring an anchor under the cursor
	POINT	point;
	::GetCursorPos( &point );
								// Need to make sure it's in our area first
	LRESULT hitCode = ::SendMessage( GetSafeHwnd(), 
									 WM_NCHITTEST, 
									 0, 
									 MAKELONG((short)point.x, (short)point.y));
	if( HTCLIENT == hitCode)
	{
		ScreenToClient( &point );

		SetCursor( point );
	}
}

ChAnimView* ChAnimView::AnimateCharacter( chuint32 luId, bool boolRun )
{
    ChAnimCastMember* pch = FindChar(luId);
    
    if (pch) pch->Animate(boolRun);

	return this;
}

ChAnimView* ChAnimView::ShowCharacter( chuint32 luId, bool boolShow )
{
    ChAnimCastMember* pch = FindChar(luId);
    
    if (pch) pch->Show(boolShow);

	return this;
}

ChAnimCastMember * ChAnimView::FindChar(chuint32 luId)
{
	if (m_characters.IsEmpty()) return 0;

	ChPosition pos = m_characters.GetHeadPosition();

    while (pos) {
        ChAnimCastMember* pch = m_characters.GetNext(pos);
		if( pch->GetId() == luId) return pch;
    }

	return 0;
}
// A new sprite has been added to the document
void ChAnimView::NewSprite(CSprite* pSprite)
{   
    // map the colors in the sprite DIB to the
    // palette in the off-screen buffered view
    if (m_pPal) {
        pSprite->MapColorsToPalette(m_pPal);
    }

    // Render the scene
    Render();

    // Draw the new scene to the screen
    Draw();
}


// add a cast member to the view; checks for uniqueness by id and replaces if
// a dupe. consumes pChar and deletes it when char is deleted or replaced
void ChAnimView::AddCharacter( ChAnimCastMember * pChar )
{
	ChAnimCastMember * pOldChar = FindChar( pChar->GetId() );

	if (pOldChar)
	{
		DeleteCharacter(pChar->GetId());
	}

	m_characters.AddTail( pChar );
	pChar->OnAddition( this );

	// Add it to the character list
	return;
}

ChAnimView* ChAnimView::DeleteCharacter( chuint32 luId )
{
	if (m_characters.IsEmpty()) return this;

	ChPosition pos = m_characters.GetHeadPosition();
    while (pos)
    {
 		ChPosition oldpos = pos;
    	ChAnimCastMember* pch = m_characters.GetNext(pos);
		if( pch->GetId() == luId) 
		{
			m_characters.Remove(oldpos);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -