Thread: GDI sprite (Win32 API)

  1. #1
    Registered User
    Join Date
    Jun 2005
    Posts
    24

    GDI sprite (Win32 API)

    Please help... how can I make sprite (simple picture moving when pressed arrows)

    I thought something like this:
    when arrow pressed, then
    1) delete previous picture from screen
    2) calculate new coordinates
    3) show picture using BitBlt()

    I have done step 2 and step 3 (it works), put how can I do step 1 -> "delete" previous picture from screen? Or is there any better way making sprite?

    I have tried to delete previous picture using rectangle ->
    FillRect(..., ..., GetStockObject(WHITE_BRUSH)); but thats no solution what if the background is a image?... and using this the picture starts to blink.

    Here's my code and I' am using DevC++ compilator:

    Code:
    #include <string>
    #include <iostream>
    #include <sstream>
    #include <math.h>
    #include <windows.h>
    #define KEYSTATE(vknum) ((GetAsyncKeyState(vknum) & 0x8000) ? TRUE : FALSE)
    using namespace std;
    
    HINSTANCE hInst;
    LRESULT CALLBACK WindProcedure(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
    
    double x = 50;
    double y = 50;
    double speed = 0.05;
    
    int max_x = 400;
    int max_y = 200;
    int min_x = 0;
    int min_y = 0;
    
    
    HWND hWnd;
    HDC hDC, MemDCExercising;
    HANDLE bmpExercising;  
        
    
    INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                       LPSTR lpCmdLine, int nCmdShow)
    {
        WNDCLASSEX  WndCls;
        static char szAppName[] = "BitmapIntro";
        MSG         Msg;
        
    	hInst       = hInstance;
        WndCls.cbSize        = sizeof(WndCls);
        WndCls.style         = CS_OWNDC | CS_VREDRAW | CS_HREDRAW;
        WndCls.lpfnWndProc   = WindProcedure;
        WndCls.cbClsExtra    = 0;
        WndCls.cbWndExtra    = 0;
        WndCls.hInstance     = hInst;
        WndCls.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
        WndCls.hCursor       = LoadCursor(NULL, IDC_ARROW);
        WndCls.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
        WndCls.lpszMenuName  = NULL;
        WndCls.lpszClassName = szAppName;
        WndCls.hIconSm       = LoadIcon(hInstance, IDI_APPLICATION);
        RegisterClassEx(&WndCls);
    
        hWnd = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW,
                              szAppName,
                              "Sprite",
                              WS_OVERLAPPEDWINDOW | WS_VISIBLE,
                              CW_USEDEFAULT,
                              CW_USEDEFAULT,
                              CW_USEDEFAULT,
                              CW_USEDEFAULT,
                              NULL,
                              NULL,
                              hInstance,
                              NULL);
    
     
                      
            hDC = GetDC(hWnd);
               
    	    bmpExercising = LoadImage(hInst, "C:\\mypic.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
    	    // Create a memory device compatible with the above DC variable
    	    MemDCExercising = CreateCompatibleDC(hDC);
                 // Select the new bitmap
         SelectObject(MemDCExercising, bmpExercising);
    
    
        while( GetMessage(&Msg, NULL, 0, 0) )
        {
            TranslateMessage(&Msg);
            DispatchMessage( &Msg);
        }
    
        return static_cast<int>(Msg.wParam);
    }
    
    
    void point (HWND hWnd)
    {
                
               int xC =  (int) round(x);
               int yC =  (int) round(y);           
               
               if(xC>max_x){ xC=max_x; x=max_x; }
               if(yC>max_y){ yC=max_y; y=max_y; }
               if(xC<min_x){ xC=min_x; x=min_x; }
               if(yC<min_y){ yC=min_y; y=min_y; }
    
    	     
    //////////////////////////////////////////////////////////////////////////
    /* THIS IS THE PLACE WHERE DELETE PREVOIUS IMAGE */
    ////////////////////////////////////////////////////////////////////////
    
    
    
    	    BitBlt(hDC, xC, yC, 400, 400, MemDCExercising, 0, 0, SRCCOPY);
    	      
    	      
    	    CancelDC(hDC);
            ReleaseDC(hWnd, hDC);
               
    }
    
    LRESULT CALLBACK WindProcedure(HWND hWnd, UINT Msg,
    			   WPARAM wParam, LPARAM lParam)
    {
    
            if(KEYSTATE(VK_UP)){  y-=speed;  point(hWnd); }
            if(KEYSTATE(VK_DOWN)){  y+=speed;  point(hWnd); }
            if(KEYSTATE(VK_LEFT)){  x-=speed;  point(hWnd); }
            if(KEYSTATE(VK_RIGHT)){  x+=speed;  point(hWnd); }
    
            
        switch(Msg)
        {
                           
            
    	case WM_DESTROY:
    	    PostQuitMessage(WM_QUIT);
    	    break;
    	    case WM_PAINT:
    
    	    break;
    
    	default:
    	    return DefWindowProc(hWnd, Msg, wParam, lParam);
        }
        return 0;
    }

    Thank you!

  2. #2
    Hi ay_okay's Avatar
    Join Date
    Dec 2004
    Location
    Here
    Posts
    69
    wrong message board, try windows programming or game programming

  3. #3
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    As mentioned by ay_okay, this should be under the Windows or Game message boards.

    First, I'd just like to point out:
    Code:
    CancelDC(hDC);
    ReleaseDC(hWnd, hDC);
    You don't want these two lines here. Every time you call point(), in other words whenever you have an arrow pressed down, you:

    1) Try to draw something
    2) Cancel drawing it, although (I think) that only works if called from a different thread
    3) Release your HDC, so you can't use it anymore

    Number 1 is OK. #2 is pointless if not harmful, and #3 is sinister.

    Next, you have your if(KEYSTATE) stuff in the wrong place - it's in the Window procedure, which is NOT called in each frame. I'd be surprise if you didn't get jerky and unpredictable movement. You'll need to modify your while(GetMessage()) loop to use PeekMessage() with the PM_REMOVE flag, and then get it to pump your if(KEYSTATE) code only after all pending messages have already been handled by TranslateMessage() and DispatchMessage(). Note that your if(KEYSTATE) code goes together with the message loop, NOT inside the window procedure. Also, after your message loop, you need to clean up your HDC and HBITMAP (not inside the Window procedure).

    After you've got that fixed up, you can solve the flickering problem by reading about double-buffering. It involves having a separate HDC that you draw everything to (first draw the background, then draw your sprites on top of the background) each frame, and after you're done drawing on it, you BitBlt the entire HDC to your main window.

    Good luck!
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

  4. #4
    Registered User
    Join Date
    Jun 2005
    Posts
    24
    thank you for a reply... I fix those things.

    I am very grateful, if someone can give me a working code (or link) for something similary... I have searched so many days from Google and MSDN. Best way to learn is to examine working code.

    I posted this thread in "Game Programming" ->
    http://cboard.cprogramming.com/showthread.php?t=66807

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Win32 API or Win32 SDK?
    By jverkoey in forum A Brief History of Cprogramming.com
    Replies: 2
    Last Post: 07-20-2005, 03:26 PM
  2. GDI sprite (Win32 API)
    By fiff in forum Game Programming
    Replies: 4
    Last Post: 06-24-2005, 09:09 AM
  3. OpenSSL and Win32 SSL API :: SSL/TLS
    By kuphryn in forum Networking/Device Communication
    Replies: 0
    Last Post: 03-10-2004, 07:46 PM
  4. FILES in WinAPI
    By Garfield in forum Windows Programming
    Replies: 46
    Last Post: 10-02-2003, 06:51 PM
  5. OLE Clipboard :: Win32 API vs. MFC
    By kuphryn in forum Windows Programming
    Replies: 3
    Last Post: 08-11-2002, 05:57 PM