Problem z podwójnym buforowaniem (GRA MARIO)

0

Witam mam problem, dotyczący migotania bitmap. Chciałbym dodać do mojej gry podwójne buforowanie, lecz wszelkie tego próby kończą się fiaskiem. Robię tak jak każą. Przkopiowuje obraz ludka do buforu, a nastepnie do kontekstu okna. I co i nic lipa. Jak ktoś ogrania temat. Niech poda na konkretnym przykładzie zasadę działanai podwójnego buforowania moj numer gg 8153898 lub niech napisze tutaj. Buforowanie zastosowane w funkcji animuj. Mam oto taką grę(ogólnie chcę coś zrobić w stylu mario):

 #include <windows.h>
#include <conio.h>
#include <cstdio>
#include <iostream>

#define SZEROKOSC 800
#define WYSOKOSC 640

LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);

bool czyWcisniety = false;
void Animuj(HWND hwnd);
RECT rozmiarOkna = {0, 0, SZEROKOSC, WYSOKOSC};

HWND g_hwnd;
HDC g_hdc;

struct POSITION
{
    unsigned int x;
    unsigned int y;
    int Vx;
    int Vy;

}posGAMER;

class cGamer
{
    public:

        bool DEAD;
        int coins;
		HBITMAP bmpMario;
		BITMAP infBmp;
		HDC hdcMem;
		HGDIOBJ gdiObj;

        cGamer()
        {
            DEAD  = false;
            coins = NULL;
			
			bmpMario = (HBITMAP)LoadImage(NULL, "bmpMario.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
			GetObject(bmpMario, sizeof(BITMAP), &infBmp);
			hdcMem = CreateCompatibleDC(0);
		    gdiObj = SelectObject(hdcMem, bmpMario);

            posGAMER.x = NULL;
            posGAMER.y = 420;

            posGAMER.Vx = NULL;
            posGAMER.Vy = NULL;

        }
        void ChangePos(POSITION &PosGAMER, WPARAM wParam, UINT message);
        void CountCoins(int &coins);

}GAMER;

void cGamer::ChangePos(POSITION &PosGAMER, WPARAM wParam, UINT message)
{
	if(wParam == VK_RIGHT && message == WM_KEYDOWN)
	{
		posGAMER.Vx = 10;
		posGAMER.x += posGAMER.Vx;
		Sleep(9);
	}

	if(wParam == VK_LEFT && message == WM_KEYDOWN)
	{
		posGAMER.Vx = -10;
		posGAMER.x += posGAMER.Vx;
		Sleep(9);
	}

	if(wParam == VK_UP && message == WM_KEYDOWN)
	{
		posGAMER.Vy = 50;
		posGAMER.y -= posGAMER.Vy;
		Sleep(9);
	}

	if(posGAMER.y < 420)
	{
		posGAMER.y+= 2;
		Sleep(3);
	}
}

class cMap
{
	public:
		HBITMAP bmpBackground;
		HDC hMemMAP;
		HGDIOBJ hGdiMap;
		BITMAP hInfoMap;

		cMap()
		{
			bmpBackground = (HBITMAP)LoadImage(0,"background.bmp", IMAGE_BITMAP, 0 ,0 ,LR_LOADFROMFILE);
			GetObject(bmpBackground, sizeof(BITMAP), &hInfoMap);
			hMemMAP = CreateCompatibleDC(0);
			hGdiMap = SelectObject(hMemMAP, bmpBackground);
		}
		void Przesowaj(WPARAM wParam, UINT message);
}MAP;

void CheckSTAN()
{
    CHAR bufor[20];
	sprintf_s(bufor, sizeof(bufor), "Px: %i Py: %i", posGAMER.x, posGAMER.y);
    SetWindowText(g_hwnd, bufor);
}

HBRUSH pedzel;

int WINAPI WinMain (HINSTANCE hThisInstance,
                    HINSTANCE hPrevInstance,
                    LPSTR lpszArgument,
                    int nCmdShow)
{
    HWND hwnd;                      
    WNDCLASSEX wincl;       
	MSG msg; 

    wincl.hInstance = hThisInstance;
    wincl.lpszClassName = "CLASS";
    wincl.lpfnWndProc = WindowProcedure;    
    wincl.style = CS_VREDRAW | CS_HREDRAW;                
    wincl.cbSize = sizeof (WNDCLASSEX);
    wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
    wincl.lpszMenuName = NULL;                
    wincl.cbClsExtra = 0;                    
    wincl.cbWndExtra = 0;        
    pedzel = (HBRUSH)GetStockObject(BLACK_BRUSH);
	wincl.hbrBackground = pedzel;

    if (!RegisterClassEx (&wincl))
        return 0;

    AdjustWindowRectEx(&rozmiarOkna, WS_OVERLAPPEDWINDOW ^ WS_THICKFRAME ^ WS_MAXIMIZEBOX, NULL, NULL);

    hwnd = CreateWindowEx (
           0,
           "CLASS",
           "RADIO & TOMIO: Adventures",
           WS_OVERLAPPEDWINDOW ^ WS_THICKFRAME ^ WS_MAXIMIZEBOX,
           100, 100,
           rozmiarOkna.right - rozmiarOkna.left,
           rozmiarOkna.bottom - rozmiarOkna.top,
           HWND_DESKTOP,
           NULL,
           hThisInstance,
           NULL
           );

    ShowWindow (hwnd, nCmdShow);
    UpdateWindow(hwnd);

	g_hwnd = hwnd;
	g_hdc = GetDC(hwnd);

    for(;;)
    {
        if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)!=0)
        {
            if(msg.message == WM_QUIT)break;

            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
		Animuj(hwnd);
		CheckSTAN();
    }
	return (int)msg.wParam;
}

LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	GAMER.ChangePos(posGAMER, wParam, message);
    switch (message)
    {

        case WM_KEYDOWN:
            switch(wParam)
            {
                case VK_LEFT:
					GAMER.ChangePos(posGAMER, wParam, message);
                    czyWcisniety = true;
                        break;

                case VK_RIGHT:
                    czyWcisniety = true;
					GAMER.ChangePos(posGAMER, wParam, message);
                        break;

                case VK_UP:
					GAMER.ChangePos(posGAMER, wParam, message);
                    czyWcisniety = true;
                        break;

                default: MessageBox(NULL,"No defined key", "Warning", MB_OK);
            }

            break;

		case WM_KEYUP:
            switch(wParam)
            {
                case VK_LEFT:
					GAMER.ChangePos(posGAMER, wParam, message);
                    czyWcisniety = false;
                        break;

                case VK_RIGHT:
					GAMER.ChangePos(posGAMER, wParam, message);
                    czyWcisniety = false;
                        break;

                case VK_UP:
					GAMER.ChangePos(posGAMER, wParam, message);
                    czyWcisniety = false;
                        break;        
            }
            break;

        case WM_DESTROY:
            PostQuitMessage (0);
            break;
    }
    return DefWindowProc (hwnd, message, wParam, lParam);
}

void Animuj(HWND hwnd)
{
	InvalidateRect(hwnd, &rozmiarOkna, TRUE);
	HDC buffor = CreateCompatibleDC(g_hdc);
	
//BitBlt(g_hdc, 0 , 0 ,MAP.hInfoMap.bmWidth, MAP.hInfoMap.bmHeight, MAP.hMemMAP, 0,0, SRCCOPY); // tło
	
BitBlt(buffor, posGAMER.x, posGAMER.y, GAMER.infBmp.bmWidth, GAMER.infBmp.bmHeight, GAMER.hdcMem, 0 ,0 , SRCCOPY);// GAMER.hdcMem to uchwyt do bitmapy z graczem
BitBlt(g_hdc, posGAMER.x, posGAMER.y, GAMER.infBmp.bmWidth, GAMER.infBmp.bmHeight, buffor, 0 ,0 , SRCCOPY);// 
}

2

Z grubsza powinno to być następująco.

Tworzenie bufora (raz):

g_bufor_dc = CreateCompatibleDC(g_hdc);
g_bufor = CreateCompatibleBitmap(g_bufor_dc, SZEROKOSC, WYSOKOSC);
SelectObject(g_bufor_dc, g_bufor);

Animacja:

void Animuj()
{
	/* Rysowanie sceny do bufora */
	BitBlt(g_bufor_dc, 0, 0, SZEROKOSC, WYSOKOSC, NULL, 0, 0, WHITENESS); // czyszczenie
	//BitBlt(g_bufor_dc, 0 , 0 ,MAP.hInfoMap.bmWidth, MAP.hInfoMap.bmHeight, MAP.hMemMAP, 0,0, SRCCOPY); // tło
	BitBlt(g_bufor_dc, posGAMER.x, posGAMER.y, GAMER.infBmp.bmWidth, GAMER.infBmp.bmHeight, GAMER.hdcMem, 0 ,0 , SRCCOPY);// GAMER.hdcMem to uchwyt do bitmapy z graczem

	/* Wrzucamy zawartość bufora na ekran */
	BitBlt(g_hdc, 0, 0, SZEROKOSC, WYSOKOSC, g_bufor_dc, 0, 0, SRCCOPY);
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1