Sign in to follow this  
alieniZe

bitmap come down

Recommended Posts

alieniZe    122
Hello guys, I started to learn DirectX. I understand now the function "display" and the function with that sound handling. But i want know, that a bitmap come down from the top to the ground pixel for pixel. How can i make that? So far... alien ;D

Share this post


Link to post
Share on other sites
adam4813    729
Like have it move a line, pause, then move again, or just have it slide? Either way you need to have something that pauses for a certain length of time, changes the Y coordinate of the bitmap, then redraw with the new Y value.

Share this post


Link to post
Share on other sites
adam4813    729
you need to change the Y coordinate that you are drawing the bitmap at each time you call render. so this means clear the screen and redraw the bitmap. some code would be helpful like post your for or while loop.

Share this post


Link to post
Share on other sites
Evil Steve    2017
Quote:
Original post by alieniZe
no, im using directX...

when i make it with my for loop, it doenst come slow down. Its just a big distorted image on the screen.
Because you're not rendering it - just moving it. Your code does this:
  • Move the bitmap 100 times.
  • Draw it.

    You want:
  • Move the bitmap 1 line
  • Draw it
  • Move the bitmap another line
  • Draw it
  • Etc

    That means you need to do a whole render loop (Clear, BeginScene, render, EndScene, Present) each time you move your bitmap.

    Share this post


    Link to post
    Share on other sites
    remigius    1172

    Well, it depends on how the code from your book is structured. Typically you'll have some kind of render loop which will call some main draw and/or update method X times per second. In this method you'd typically increase a variable y coordinate and then use dsply.Blt(someX, yourY, yourSprite); to draw it to the screen at the new position.

    Going from your last topic I don't know if this is the case with your code, so it'll probably only get confusing to try and explain the general approach further. Looking at the book index you posted last time, you might want to check out paragraph 3.2 (page 138-159), since that seems to deal with movements.

    This way you know the info correctly applies to the code you're using, which should prove more useful than our random guesses as to how your code works [smile]

    Share this post


    Link to post
    Share on other sites
    alieniZe    122
    im atm rly, rly , rlly confused ::confused::

    here's my code :/


    # include <stdio.h>
    # include <windows.h>
    # include <ddraw.h>
    # include <dsound.h>
    # include "ddutil.h"
    # include "dsutil.h"
    # include "resource.h"

    const int ultris_nettobreite = 360; // Breite des Inneren des Haupfensters
    const int ultris_nettohoehe = 520; // Hoehe des Inneren des Hauptfensters
    int ultris_bruttobreite; // Breite des gesamten Haupfensters (incl. Rahmen)
    int ultris_bruttohoehe; // Hoehe des gesamten Haupfensters (incl. Rahmen)

    HINSTANCE ultris_instance; // Instanz der Ultris Applikation
    HWND ultris_window; // Das Hauptfenster von Ultris
    HMENU ultris_menu; // Das Menu von Ultris

    const int sound_start = 0;
    const int sound_dreh = 1;
    const int sound_mode = 2;
    const int sound_down = 3;
    const int sound_row1 = 4;
    const int sound_row2 = 5;

    const int sound_ende = 6;
    const int sound_win = 7;

    const int anzahl_sounds = 8;

    char *soundfiles[anzahl_sounds] =
    {
    "ul_start.wav",
    "ul_dreh.wav",
    "ul_move.wav",
    "ul_down.wav",
    "ul_row1.wav",
    "ul_row2.wav",
    "ul_ende.wav",
    "ul_win.wav"
    };

    class sounds
    {
    private:
    CSoundManager smgr;
    CSound *snd[anzahl_sounds];
    public:
    int on;
    sounds();
    int init( HWND wnd);
    void play( int snr);
    ~sounds();
    };

    sounds::sounds()
    {
    int i;

    for( i = 0; i < anzahl_sounds; i++)
    snd[i] = 0;
    on = 1;
    }


    int sounds::init( HWND wnd)
    {
    HRESULT ret;
    int i;

    ret = smgr.Initialize( wnd, DSSCL_PRIORITY, 2, 22050, 16);
    if( ret < 0)
    return ret;

    for( i = 0; i < anzahl_sounds; i++)
    {
    ret = smgr.Create( snd+i, soundfiles[i]);
    if( ret < 0)
    return ret;
    }
    return S_OK;
    }

    sounds::~sounds()
    {
    int i;

    for( i = 0; i < anzahl_sounds; i++)
    {
    if( snd[i])
    delete snd[i];
    }
    }

    void sounds::play( int i)
    {
    if( !on)
    return;
    if( snd[i]->IsSoundPlaying())
    {
    snd[i]->Stop();
    snd[i]->Reset();
    }
    snd[i]->Play(0,0);
    }

    sounds ultris_sounds;

    class display
    {
    private:
    CDisplay dsply;
    CSurface *hgrnd;
    CSurface *fldst;
    CSurface *fllst;
    CSurface *prvst;
    CSurface *spam;
    CSurface *ziff[10];
    public:
    display();
    void free_all();
    ~display() {free_all();}
    HRESULT init( HWND wnd);
    void hintergrund() { dsply.Blt( 0, 0, hgrnd);}
    void abdeckung(int i) { dsply.Blt(i+150 , 50, spam);}
    void ziffer( int pos, int val) { dsply.Blt( 120+pos*20, 50, ziff[val]);}
    void feldstein( int z, int s) { dsply.Blt( 80+s*20, 100+z*20, fldst);}
    void fallstein( int z, int s, int offset) { dsply.Blt( 80+s*20, 100+z*20+offset, fllst);}
    void prevstein( int p, int z, int s, int b, int h){ dsply.Blt( 290+s*15+(4-b)*15/2, 410-p*70+z*15+(4-h)*15/2, prvst);}
    void update(){ dsply.UpdateBounds();}
    HRESULT cooperative(){return dsply.GetDirectDraw()->TestCooperativeLevel();}
    HRESULT restore();
    HRESULT present();
    };

    display::display()
    {
    int i;

    hgrnd = 0;
    fldst = 0;
    fllst = 0;
    prvst = 0;
    spam = 0;

    for (int i = 0; i < 10; i++)
    ziff[i] = 0;

    }

    void display::free_all()
    {
    int i;

    if( hgrnd)
    delete hgrnd;
    if( fldst)
    delete fldst;
    if( fllst)
    delete fllst;
    if( prvst)
    delete prvst;
    if( spam)
    delete spam;
    for( i = 0; i < 10; i++)
    {
    if( ziff[i])
    delete ziff[i];
    }
    }

    HRESULT display::init( HWND wnd)
    {
    HRESULT hr;
    int i;
    char fname[20];

    hr = dsply.CreateWindowedDisplay( wnd, ultris_nettobreite, ultris_nettohoehe );
    if( hr < 0)
    return hr;
    hr = dsply.CreateSurfaceFromBitmap( &hgrnd, "ul_hgrnd.bmp", ultris_nettobreite, ultris_nettohoehe);
    if( hr < 0)
    return hr;
    hr = dsply.CreateSurfaceFromBitmap( &fldst, "ul_feld.bmp", 20, 20);
    if( hr < 0)
    return hr;
    hr = dsply.CreateSurfaceFromBitmap( &fllst, "ul_stein.bmp", 20, 20);
    if( hr < 0)
    return hr;
    hr = dsply.CreateSurfaceFromBitmap( &prvst, "ul_prev.bmp", 15, 15);
    if( hr < 0)
    return hr;
    hr = dsply.CreateSurfaceFromBitmap( &spam, "spam.bmp", 50, 50);
    if( hr < 0)
    return hr;
    for( i = 0; i < 10; i++)
    {
    sprintf( fname, "ul_z%d.bmp", i);
    hr = dsply.CreateSurfaceFromBitmap( &ziff[i], fname, 20, 40);
    if( hr < 0)
    return hr;
    }
    return S_OK;
    }
    HRESULT display::restore()
    {
    HRESULT hr;
    int i;
    char fname[20];
    LPDIRECTDRAWPALETTE pal = 0;

    hr = dsply.GetDirectDraw()->RestoreAllSurfaces();
    if( hr < 0)
    return hr;
    hr = hgrnd->DrawBitmap( "ul_hgrnd.bmp", ultris_nettobreite, ultris_nettohoehe);
    if( hr < 0)
    return hr;
    hr = fldst->DrawBitmap( "ul_feld.bmp", 20, 20);
    if( hr < 0)
    return hr;
    hr = fllst->DrawBitmap( "ul_stein.bmp", 20, 20);
    if( hr < 0)
    return hr;
    hr = prvst->DrawBitmap( "ul_prev.bmp", 15, 15);
    if( hr < 0)
    return hr;
    hr = spam->DrawBitmap( "spam.bmp", 50, 50);
    if( hr < 0)
    return hr;

    for( i = 0; i < 10; i++)
    {
    sprintf( fname, "ul_z%d.bmp", i);
    hr = ziff[i]->DrawBitmap( fname, 20, 40);
    if( hr < 0)
    return hr;
    }
    return S_OK;
    }

    HRESULT display::present()
    {
    HRESULT hr;

    hr = dsply.Present();
    if(hr == DDERR_SURFACELOST)
    return restore();

    return hr;
    }
    display ultris_display;




    /*
    ** ultris_windowhandler
    */
    LRESULT CALLBACK ultris_windowhandler( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
    switch(msg)
    {
    case WM_COMMAND:
    switch( LOWORD( wParam))
    {
    case IDM_EXIT:
    PostMessage( hWnd, WM_CLOSE, 0, 0);
    return 0;
    case ID_ULTRIS_SOUND:
    ultris_sounds.on = !ultris_sounds.on;
    CheckMenuItem( ultris_menu, ID_ULTRIS_SOUND, ultris_sounds.on ? MF_CHECKED:MF_UNCHECKED);
    return 0;
    case IDM_TEST:

    return 0;
    }
    break;
    case WM_GETMINMAXINFO:
    ((MINMAXINFO *)lParam)->ptMinTrackSize.x = ((MINMAXINFO *)lParam)->ptMaxTrackSize.x = ultris_bruttobreite;
    ((MINMAXINFO *)lParam)->ptMinTrackSize.y = ((MINMAXINFO *)lParam)->ptMaxTrackSize.y = ultris_bruttohoehe;
    return 0;
    case WM_DESTROY:
    PostQuitMessage( 0);
    return 0;
    // V3 Beginn
    case WM_MOVE:
    ultris_display.update();
    return 0;
    case WM_PAINT:


    ultris_display.hintergrund();


    for(int i = 0; i < 100; i++)
    {
    ultris_display.abdeckung(i);

    }



    //for( i = 0; i < 6; i++)
    // ultris_display.ziffer( i, i+1);


    //for( i = 0; i < 10; i++)
    // ultris_display.feldstein(19,1);
    /*for( i = 0; i < 10; i++)
    ultris_display.fallstein( 1, i, 2*i);
    for( i = 0; i < 4; i++)
    ultris_display.prevstein( 3, 0, i, 4, 1);
    */


    ultris_display.present();

    break;
    // V3 Ende
    }
    return DefWindowProc(hWnd, msg, wParam, lParam);
    }


    /*
    ** WinMain
    */
    int APIENTRY WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR pCmdLine, int nCmdShow)
    {
    MSG msg;
    HACCEL acc;
    WNDCLASSEX wcx;

    ultris_instance = hInst;

    wcx.cbSize = sizeof( wcx);
    wcx.lpszClassName = TEXT( "Ultris");
    wcx.lpfnWndProc = ultris_windowhandler;
    wcx.style = CS_VREDRAW | CS_HREDRAW;
    wcx.hInstance = hInst;
    wcx.hIcon = LoadIcon( hInst, MAKEINTRESOURCE( IDI_MAIN));
    wcx.hIconSm = LoadIcon( hInst, MAKEINTRESOURCE( IDI_MAIN));
    wcx.hCursor = LoadCursor( NULL, IDC_ARROW);
    wcx.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wcx.lpszMenuName = MAKEINTRESOURCE( IDR_MENU);
    wcx.cbClsExtra = 0;
    wcx.cbWndExtra = 0;

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

    acc = LoadAccelerators( hInst, MAKEINTRESOURCE(IDR_ACCEL));

    ultris_bruttohoehe = ultris_nettohoehe + 2*GetSystemMetrics( SM_CYSIZEFRAME)
    + GetSystemMetrics( SM_CYMENU)
    + GetSystemMetrics( SM_CYCAPTION);
    ultris_bruttobreite = ultris_nettobreite + 2*GetSystemMetrics( SM_CXSIZEFRAME);

    ultris_window = CreateWindowEx( 0, TEXT( "Ultris"), TEXT( "Ultris"), WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX,
    CW_USEDEFAULT, CW_USEDEFAULT,
    ultris_bruttobreite, ultris_bruttohoehe, NULL, NULL, hInst, NULL);
    if( !ultris_window)
    return 0;

    ultris_menu = GetMenu( ultris_window);

    if( ultris_sounds.init( ultris_window) < 0)
    {
    MessageBox( ultris_window, "Fehler beim Initialisieren der Sounds", "Ultris-Fehlermeldung", MB_OK | MB_ICONERROR | MB_SETFOREGROUND);
    return 0;
    }
    CheckMenuItem( ultris_menu, ID_ULTRIS_SOUND, ultris_sounds.on ? MF_CHECKED:MF_UNCHECKED);

    // V3 Beginn
    if( ultris_display.init( ultris_window) < 0)
    {
    MessageBox( ultris_window, "Fehler beim Initialisieren der Grafik", "Ultris-Fehlermeldung", MB_OK | MB_ICONERROR | MB_SETFOREGROUND);
    return 0;
    }
    // V3 Ende

    MoveWindow( ultris_window, (GetSystemMetrics(SM_CXSCREEN)-ultris_bruttobreite)/2,
    (GetSystemMetrics(SM_CYSCREEN)-ultris_bruttohoehe)/2,
    ultris_bruttobreite, ultris_bruttohoehe, TRUE);

    ShowWindow( ultris_window, nCmdShow);

    while( TRUE)
    {
    if( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE))
    {
    if( GetMessage( &msg, NULL, 0, 0 ) == 0)
    return 0; // Message ist WM_QUIT

    if( TranslateAccelerator( ultris_window, acc, &msg) == 0)
    {
    TranslateMessage( &msg);
    DispatchMessage( &msg);
    }
    }
    else
    {
    // V3 Beginn
    HRESULT hr;
    hr = ultris_display.cooperative();
    if( hr < 0)
    {
    switch( hr )
    {
    case DDERR_EXCLUSIVEMODEALREADYSET:
    Sleep(10);
    break;
    case DDERR_WRONGMODE:
    ultris_display.free_all();
    ultris_display.init( ultris_window);
    PostMessage( ultris_window, WM_PAINT, 0, 0);
    break;
    }
    }
    else
    {
    // Hier koennen wir uns um das Spiel kuemmern
    }
    // V3 Ende
    }
    }
    }



    I just want to move the sprite "spam" that it comes from the top to the ground :/

    Share this post


    Link to post
    Share on other sites
    Evil Steve    2017
    Your code isn't running any frame based system - If you want to update something periodically, you'll have to have some function that's updated every frame.
    As it is, your app will only draw when the window is made dirty, which isn't what you want for any sort of animation.

    You'll have to either set up a window timer (See SetTimer), or just update the window after every loop. As an aside, using PosteMessage to send WM_PAINT isn't a good idea; InvalidateRect(hWnd, NULL, FALSE) is far preferable.

    Once you have some sort of update loop going on, you just need to change the position of the bitmap once per loop, and then draw it at that position when you render.

    Also, going a bit off topic here, DirectDraw is not a good API to use. It's not being developed any more, is slow as hell, and is emulated under Vista. D3D is far preferable.

    Share this post


    Link to post
    Share on other sites
    alieniZe    122
    I just want to learn first of all 2d, and then i want to swap on 3d.

    I'm rly confused atm ;/ I know how i can fix that, but i dont know, how that i can make that to a code:(

    Can u give me just a LITTLE example? Not the whole code, i want to learn something ;D

    Share this post


    Link to post
    Share on other sites
    remigius    1172

    Ok, one little example then [smile]

    Still I think you should refer to your book, since that's probably what you're going from. We don't know what you've already learned from the book, so as I said our tips prove only to be confusing. If you feel the book doesn't explain things properly, I'd recommend getting a better one.

    The very basic idea of what you're trying to do would be this (don't take this as usable code, it's just to clarify!)


    int y = 0;

    while(gameRunning)
    {
    y += 1;
    dsply.Blt(someX, y, spam);
    }


    Basically this will move the 'spam' sprite down one pixel and draw it each loop iteration. With the code snippet above however, you're not processing any window messages, which will make Windows think that the game is hanging (which is why you should really not use it). As Steve said however, you can get a loop running by calling InvalidateRect after you're done rendering (so at the end of your WM_PAINT case, before break), since this will cause the WM_PAINT message to be fired and has the game re-render itself.

    This way your window messages get handled and the game will remain responsive. Another problem with this code is that the speed of the rendering depends on the speed of your machine, since it'll go through the loop as fast as possible. Here's where Steve's suggestion of using a timer comes in, so you can make sure the game runs at the same on all machines.

    ...

    Well, I reckon this is only getting more confusing, but that's the basic idea. I really think your book should contain information on update/render loops, how they work, why they're needed and other considerations. If it doesn't provide that information but just dumps the above code on you without explaination, you might want to consider getting another book.

    Share this post


    Link to post
    Share on other sites
    alieniZe    122
    in my book its only the code and then a few words. Not explain why we do that, what it do etc...

    but thanks for your help, i'll try it, then i post my problems again, ;D

    thank you!

    Share this post


    Link to post
    Share on other sites
    Evil Steve    2017
    It's not a whole project, but this should give you a rough idea - there's not much point in people giving you a whole project, since it'll almost certainly be too different from what you're used to to be useful; that and I haven't touched DirectDraw in years (For a good reason [smile]):

    static bool PumpWindowMessages()
    {
    MSG msg;
    bool bQuit = false;
    while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
    {
    if(msg.message == WM_QUIT)
    bQuit = true;
    TranslateMessage(&msg);
    DispatchMessage(&msg);
    }

    return bQuit;
    }

    static void MainLoop()
    {
    int y = 0;
    for(;;)
    {
    // Get the current time
    DWORD dwStartTime = GetTickCount();

    // Process all window messages, and exit if required
    if(PumpWindowMessages())
    break;

    // Render 'sprite' at (someX, y)
    Blt(someX, y, sprite);

    // Wait so that we run at roughly 60FPS (60FPS = 1000/60 = 16.666ms)
    while(GetTickCount() - dwStartTime < 16)
    Sleep(0);

    // Increase Y so the sprite is rendered further down next time
    ++y;
    }
    }

    The Blt() call should be replaced with however you do your rendering - I had a quick look at your previous code, but it all looks fairly abstracted away from DirectDraw (As an aside - it's recommended that you use D3D rather than DirectDraw, since DD isn't hardware accelerated at all).
    I'd also like to point out that the way of waiting at the end of the frame so it runs at ~60FPS is a very cheap and nasty way of doing things; using a more accurate timer (GetTickCount() is only accurate to something like 15ms, and Sleep(0) is a bit dodgey too), and changing the loop to change Y depending on the time taken to render a frame would be better.

    Share this post


    Link to post
    Share on other sites

    Create an account or sign in to comment

    You need to be a member in order to leave a comment

    Create an account

    Sign up for a new account in our community. It's easy!

    Register a new account

    Sign in

    Already have an account? Sign in here.

    Sign In Now

    Sign in to follow this