| | |
learning WIN32 GDI
![]() |
•
•
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 binary bitmap c++ c/c++ char class classes code coding compaitibility compile console conversion count delete deploy desktop developer directshow dll download dynamic dynamiccharacterarray email encryption error factorial file floatingpoint forms fstream function functions game givemetehcodez graph guessing gui homeworkhelp homeworkhelper iamthwee ifstream input int integer java lib linkedlist linker loop looping loops map math matrix maze memory multiple net news node oop output parameter payment pointer problem program programming project projectassignmenthelp protection python random rank read recursion reference rpg skills string strings temperature template test text text-file tree url variable vector video win32 windows winsock wordfrequency wxwidgets






