| | |
learning WIN32 GDI
Please support our C++ advertiser: Intel Parallel Studio Home
![]() |
•
•
Join Date: Jul 2006
Posts: 73
Reputation:
Solved Threads: 0
I am trying to animate a bitmap in a window. I am able to load the bitmap in random locations multiple times, but I would like to have the previous instance of the bitmap erased each redraw, as I would like it to be a smoother animation instead of thousands of bitmaps on the screen.
I also do not quite understand how to change the random drawing of the bitmap below into a smooth linear animation.
I also do not quite understand how to change the random drawing of the bitmap below into a smooth linear animation.
C++ Syntax (Toggle Plain Text)
if (rect.right > 0) { _sleep(50); x = rand() % (rect.right - rect.left); y = rand() % (rect.bottom - rect.top); DrawBitmap(global_hdc, "asteroid.bmp", x, y); }
C++ Syntax (Toggle Plain Text)
#include <windows.h> #include <winuser.h> #include <stdio.h> #include <stdlib.h> #include <time.h> #define APPTITLE "Game Loop" //function prototypes LRESULT CALLBACK WinProc(HWND,UINT,WPARAM,LPARAM); ATOM MyRegisterClass(HINSTANCE); BOOL InitInstance(HINSTANCE,int); void DrawBitmap(HDC,char*,int,int); void Game_Init(); void Game_Run(); void Game_End(); //local variables HWND global_hwnd; HDC global_hdc; //the window event callback function LRESULT CALLBACK WinProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { global_hwnd = hWnd; global_hdc = GetDC(hWnd); switch (message) { case WM_DESTROY: Game_End(); PostQuitMessage(0); break; } return DefWindowProc(hWnd, message, wParam, lParam); } //helper function to set up the window properties ATOM MyRegisterClass(HINSTANCE hInstance) { //create the window class structure WNDCLASSEX wc; wc.cbSize = sizeof(WNDCLASSEX); //fill the struct with info wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = (WNDPROC)WinProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = NULL; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); wc.lpszMenuName = NULL; wc.lpszClassName = APPTITLE; wc.hIconSm = NULL; //set up the window with the class info return RegisterClassEx(&wc); } //helper function to create the window and refresh it BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { HWND hWnd; //create a new window hWnd = CreateWindow( APPTITLE, //window class APPTITLE, //title bar WS_OVERLAPPEDWINDOW, //window style CW_USEDEFAULT, //x position of window CW_USEDEFAULT, //y position of window 500, //width of the window 400, //height of the window NULL, //parent window NULL, //menu hInstance, //application instance NULL); //window parameters //was there an error creating the window? if (!hWnd) return FALSE; //display the window ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; } //entry point for a Windows program int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { int done = 0; MSG msg; // register the class MyRegisterClass(hInstance); // initialize application if (!InitInstance (hInstance, nCmdShow)) return FALSE; //initialize the game Game_Init(); // main message loop while (!done) { if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { //look for quit message if (msg.message == WM_QUIT) done = 1; //decode and pass messages on to WndProc TranslateMessage(&msg); DispatchMessage(&msg); } //process game loop Game_Run(); } return msg.wParam; } void DrawBitmap(HDC hdcDest, char *filename, int x, int y) { HBITMAP image; BITMAP bm; HDC hdcMem; //load the bitmap image image = (HBITMAP)LoadImage(0,"asteroid.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE); //read the bitmap's properties GetObject(image, sizeof(BITMAP), &bm); //create a device context for the bitmap hdcMem = CreateCompatibleDC(global_hdc); SelectObject(hdcMem, image); //draw the bitmap to the window (bit block transfer) BitBlt( global_hdc, //destination device context x, y, //x,y location on destination bm.bmWidth, bm.bmHeight, //width,height of source bitmap hdcMem, //source bitmap device context 0, 0, //start x,y on source bitmap SRCCOPY); //blit method //delete the device context and bitmap DeleteDC(hdcMem); DeleteObject((HBITMAP)image); } void Game_Init() { //initialize the game... //load bitmaps, meshes, textures, sounds, etc. srand(time(NULL)); } void Game_Run() { //this is called once every frame //do not include your own loop here! int x = 0, y = 0; RECT rect; GetClientRect(global_hwnd, &rect); if (rect.right > 0) { x = rand() % (rect.right - rect.left); y = rand() % (rect.bottom - rect.top); DrawBitmap(global_hdc, "asteroid.bmp", x, y); } } void Game_End() { }
Climbing the learning curve of C++
Becoming an expert seems light years away!
Becoming an expert seems light years away!
part one
Don't load "asteroid.bmp" from file every time you call DrawBitmap(). That's a huge slowdown. Load the bitmap first, (say in Game_Init()) and have DrawBitmap() take a handle to the bitmap to draw instead of a filename.
Don't forget to use DeleteObject() before terminating to get rid of the bitmap.
part two
To animate the asteroid moving about smoothly, you need:
1. a direction to travel. This should be (x, y) pixel offsets. Use floats, and round to the nearest integer before mapping the image. (If you use only integers your asteroid is limited in how fast or slow it travels.)
2. (possibly) a time to travel that distance. In the original asteroids game, the rocks only changed direction when impacted (hit by another rock or by the ship's weapon fire), so the time the asteroid traveled its direction was infinite, hence unnecessary to bother tracking. However, if you want it randomly changing direction, when time is up calculate a new direction to travel.
Next, you need to calculate the (x, y) direction --randomly if so desired-- then begin moving the asteroid's position by adding the (x, y) offset each frame. All you need to track is the previous asteroid location. You know the bitmap's width and height, so use FillRect() to blacken the previous image, update the asteroid's location, then BitBlt() the asteroid to its new location. Consider how you want it to react when it reaches the edge of the client area. Do you want it to bounce off? Do you want it to disappear? Wrap around?
Keep in mind you only calculate a new (x, y) direction when certain events occur, not every frame. You do, however, move the bitmap by adding the direction to the bitmap's current location each frame.
part three
Use double-buffering. Look up SetPixelFormat() for more information. Once you have updated everything for the frame, then SwapBuffers().
Hope this helps.
Don't load "asteroid.bmp" from file every time you call DrawBitmap(). That's a huge slowdown. Load the bitmap first, (say in Game_Init()) and have DrawBitmap() take a handle to the bitmap to draw instead of a filename.
Don't forget to use DeleteObject() before terminating to get rid of the bitmap.
part two
To animate the asteroid moving about smoothly, you need:
1. a direction to travel. This should be (x, y) pixel offsets. Use floats, and round to the nearest integer before mapping the image. (If you use only integers your asteroid is limited in how fast or slow it travels.)
2. (possibly) a time to travel that distance. In the original asteroids game, the rocks only changed direction when impacted (hit by another rock or by the ship's weapon fire), so the time the asteroid traveled its direction was infinite, hence unnecessary to bother tracking. However, if you want it randomly changing direction, when time is up calculate a new direction to travel.
Next, you need to calculate the (x, y) direction --randomly if so desired-- then begin moving the asteroid's position by adding the (x, y) offset each frame. All you need to track is the previous asteroid location. You know the bitmap's width and height, so use FillRect() to blacken the previous image, update the asteroid's location, then BitBlt() the asteroid to its new location. Consider how you want it to react when it reaches the edge of the client area. Do you want it to bounce off? Do you want it to disappear? Wrap around?
Keep in mind you only calculate a new (x, y) direction when certain events occur, not every frame. You do, however, move the bitmap by adding the direction to the bitmap's current location each frame.
part three
Use double-buffering. Look up SetPixelFormat() for more information. Once you have updated everything for the frame, then SwapBuffers().
Hope this helps.
![]() |
Similar Threads
- Graphics Program Help (C++)
- GDI+ with Win32 API Dev-C++ (C++)
- what on earth is MFC (C++)
- Vista? (C++)
- find files of certain type... (Assembly)
- Help with SOAP and C++ WIN32 (C++)
- help (C++)
- Graphics In Pixel: Part II B (C)
- GDI (C)
Other Threads in the C++ Forum
- Previous Thread: passby pointer or reference?
- Next Thread: The * in a function.
| Thread Tools | Search this Thread |
api array based beginner binary bitmap c++ c/c++ calculator char char* class code coding compile compiler console conversion count database delete deploy desktop developer dll download dynamic dynamiccharacterarray email encryption error file forms fstream function functions game givemetehcodez google graph gui homeworkhelp homeworkhelper iamthwee ifstream input int integer java lib linkedlist linker list loop looping loops map math memory multiple news node number numbertoword output parameter pointer problem program programming project python random read recursion recursive reference rpg sorting string strings struct temperature template test text text-file tree unix url variable vector video visualstudio win32 windows winsock word wordfrequency wxwidgets






