⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 donuts.c

📁 Windows CE .Net 下面 Direct DRAW编程的经典实例。对于初学Windows 平台下Direct DRAW技术的程序员颇具借鉴意义!
💻 C
📖 第 1 页 / 共 4 页
字号:
    if( lpFrontBuffer != NULL )
        lpFrontBuffer->lpVtbl->Release( lpFrontBuffer );

    if( lpArtPalette != NULL )
        lpArtPalette->lpVtbl->Release( lpArtPalette );

    if( lpSplashPalette != NULL )
        lpSplashPalette->lpVtbl->Release( lpSplashPalette );

    if( lpDD != NULL )
        lpDD->lpVtbl->Release( lpDD );
    
    if (DL.next != NULL)
    {
        while( DL.next != &DL )
        {
            DeleteFromList( DL.next );
        }
    }
}

BOOL InitializeGame( void )
{
    DDCAPS          ddcaps;
    HRESULT         ddrval;
    DDSURFACEDESC2  ddsd;
    DDSCAPS2        ddscaps;
    DDSURFACEDESC2  DDSurfDesc;
    LPDIRECTDRAW    pDD;

    score = 0;
    if( bTest )
        ShowLevelCount = 1000;

    // Initialize the display list to point at itself.  This denotes an empty
    // list.  We need to do this here because if CleanupAndExit/DestroyGame
    // will attempt to walk the display list and delete records.
    DL.next = DL.prev = &DL;            

    if( bUseEmulation )
        ddrval = DirectDrawCreate( (LPVOID) DDCREATE_EMULATIONONLY, &pDD, NULL );
    else
        ddrval = DirectDrawCreate( NULL, &pDD, NULL );

    if( ddrval != DD_OK )
        return CleanupAndExit(TEXT("DirectDrawCreate Failed!"));

    // Fetch DirectDraw4 interface
    ddrval = pDD->lpVtbl->QueryInterface( pDD, &IID_IDirectDraw4, (LPVOID*)&lpDD);
    if (ddrval != DD_OK)
        return CleanupAndExit(TEXT("QueryInterface Failed!"));
    pDD->lpVtbl->Release(pDD);
    pDD = NULL;

   
    ddrval = lpDD->lpVtbl->SetCooperativeLevel( lpDD, hWndMain,
                            DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN );
    if( ddrval != DD_OK )
        return CleanupAndExit(TEXT("SetCooperativeLevel Failed"));

    // Get mode info.

    memset(&DDSurfDesc, 0, sizeof(DDSurfDesc));
    DDSurfDesc.dwSize = sizeof(DDSurfDesc);

    ddrval = lpDD->lpVtbl->GetDisplayMode( lpDD, &DDSurfDesc );
    if ( ddrval != DD_OK )
        return CleanupAndExit(TEXT("GetDisplayMode Failed!"));

    ScreenX = DDSurfDesc.dwWidth;
    ScreenY = DDSurfDesc.dwHeight;
    ScreenBpp = DDSurfDesc.ddpfPixelFormat.dwRGBBitCount;

    // check the color key hardware capabilities
    dwTransType = DDBLTFAST_SRCCOLORKEY;
    ddcaps.dwSize = sizeof( ddcaps );

    // Create surfaces
    memset( &ddsd, 0, sizeof( ddsd ) );
    ddsd.dwSize = sizeof( ddsd );
    ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
    ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
                          DDSCAPS_FLIP |
                          DDSCAPS_COMPLEX;
    ddsd.dwBackBufferCount = 1;
    ddrval = lpDD->lpVtbl->CreateSurface( lpDD, &ddsd, &lpFrontBuffer, NULL );
    if (ddrval != DD_OK)
    {
        if (ddrval == DDERR_NOFLIPHW)
            return CleanupAndExit(TEXT("******** Display driver doesn't support flipping surfaces. ********"));
  
        return CleanupAndExit(TEXT("CreateSurface FrontBuffer Failed!"));
    }

    // get a pointer to the back buffer
    ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
    ddrval = lpFrontBuffer->lpVtbl->GetAttachedSurface(
                lpFrontBuffer,
                &ddscaps,
                &lpBackBuffer );
    if( ddrval != DD_OK )
        return CleanupAndExit(TEXT("GetAttachedDurface Failed!"));

    ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
    ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
#ifdef DEBUG
    if( bHELBlt )
        ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
#endif
    ddsd.dwWidth = 320;
    ddsd.dwHeight = 384;
    ddrval = lpDD->lpVtbl->CreateSurface( lpDD, &ddsd, &lpDonut, NULL );
    if( ddrval != DD_OK )
        return CleanupAndExit(TEXT("CreateSurface lpDonut Failed!"));

    ddsd.dwHeight = 128;
    ddrval = lpDD->lpVtbl->CreateSurface( lpDD, &ddsd, &lpPyramid, NULL );
    if( ddrval != DD_OK )
        return CleanupAndExit(TEXT("CreateSurface lpPyramid Failed!"));

    ddsd.dwHeight = 32;
    ddrval = lpDD->lpVtbl->CreateSurface( lpDD, &ddsd, &lpCube, NULL );
    if( ddrval != DD_OK )
        return CleanupAndExit(TEXT("CreateSurface lpCube Failed!"));

    ddsd.dwHeight = 32;
    ddrval = lpDD->lpVtbl->CreateSurface( lpDD, &ddsd, &lpSphere, NULL );
    if( ddrval != DD_OK )
        return CleanupAndExit(TEXT("CreateSurface lpSphere Failed!"));
    // Set the background color fill color

    ddsd.dwHeight = 256;
    ddrval = lpDD->lpVtbl->CreateSurface( lpDD, &ddsd, &lpShip, NULL );
    if( ddrval != DD_OK )
        return CleanupAndExit(TEXT("CreateSurface lpShip Failed!"));

    ddsd.dwHeight = 16;
    ddrval = lpDD->lpVtbl->CreateSurface( lpDD, &ddsd, &lpNum, NULL );
    if( ddrval != DD_OK )
        return CleanupAndExit(TEXT("CreateSurface lpNum Failed!"));

    if( !RestoreSurfaces() )
        return CleanupAndExit(TEXT("RestoreSurfaces Failed!"));

    DL.type = OBJ_SHIP;
    DL.surf = lpShip;
    lastTickCount = GetTickCount();

#ifdef USE_DSOUND
    if(bWantSound)
    {
        InitializeSound();
    }
#endif

    if(bTest)
    {
        ProgramState = PS_ACTIVE;
        setup_game();
    }
    else
    {
        ProgramState = PS_SPLASH;
    }
    return TRUE;
}

BOOL CleanupAndExit( TCHAR *err)
{
// Note: We're using OutputDebugString here instead of RETAILMSG to allow the user
// to read the error message, even when the sample app is running on a retail
// build of the OS. Not seeing a message in the debugger when the app mysteriously
// fails (as in the case when there is no hardware flipping support for example)
// has led to a lot of confusion.
    
    wsprintf(DebugBuf, TEXT("%s: CleanupAndExit  err = %s\n"), cszAppName, err );
    OutputDebugString( DebugBuf );

    DestroyGame();

    return FALSE;
}

void bltSplash( void )
{
    HRESULT     ddrval;
    HBITMAP     hbm;

    hbm = (HBITMAP)LoadImage( hInst, TEXT("SPLASH"), IMAGE_BITMAP, 0, 0, 0 );
    if ( NULL == hbm )
        return;

    // if the surface is lost, DDCopyBitmap will fail and the surface will
    // be restored in FlipScreen.
    ddrval = DDCopyBitmap( lpBackBuffer, hbm, 0, 0, 0, 0 );

    DeleteObject( hbm );

    FlipScreen();
}

#ifdef USE_DSOUND
//
// play a sound, but first set the panning according to where the
// object is on the screen.  fake 3D sound.
//
void playPanned(HSNDOBJ hSO, DBLNODE *object)
{
    IDirectSoundBuffer *pDSB = SndObjGetFreeBuffer(hSO);

        if(!bWantSound)
                return;   // No sound our Work is done

    if (pDSB)
    {
        switch(ScreenX)
        {
        case 320:
            IDirectSoundBuffer_SetPan(pDSB, (LONG)((20000.0 *
                ((object->dst.right + object->dst.left) / 2) / 320.0) - 10000.0));
            break;
        case 640:
            IDirectSoundBuffer_SetPan(pDSB, (LONG)((20000.0 *
                ((object->dst.right + object->dst.left) / 2) / 640.0) - 10000.0));
            break;
        case 1024:
            IDirectSoundBuffer_SetPan(pDSB, (LONG)((20000.0 *
                ((object->dst.right + object->dst.left) / 2) / 1024.0) - 10000.0));
            break;
        case 1280:
            IDirectSoundBuffer_SetPan(pDSB, (LONG)((20000.0 *
                ((object->dst.right + object->dst.left) / 2) / 1280.0) - 10000.0));
            break;
        }

        IDirectSoundBuffer_Play(pDSB, 0, 0, 0);
    }
}
#endif

void UpdateFrame( void )
{
    switch( ProgramState )
    {
        case PS_SPLASH:
            // display the splash screen
            bltSplash();
            return;
        case PS_ACTIVE:
            UpdateDisplayList();
            CheckForHits();
            DrawDisplayList();
            if ( isDisplayListEmpty() )
            {
#ifdef USE_DSOUND
                if(bWantSound)
                {
                    SndObjStop(hsoEngineIdle);
                    SndObjStop(hsoEngineRev);
                }
#endif
                bPlayIdle = FALSE;
                bPlayRev = FALSE;
                lastThrust = lastShield = FALSE;
                ProgramState = PS_BEGINREST;
                restCount = GetTickCount();
                initLevel( ++level );
            }
            return;
        case PS_BEGINREST:
#ifdef USE_DSOUND
            if(bWantSound)
            {
                SndObjPlay(hsoBeginLevel, 0);
            }
#endif
            ProgramState = PS_REST;
            //
            // FALLTHRU
            //
        case PS_REST:
            if( ( GetTickCount() - restCount ) > ShowLevelCount )
            {
#ifdef USE_DSOUND
                if(bWantSound)
                {
                    SndObjPlay(hsoEngineIdle, DSBPLAY_LOOPING);
                }
#endif
                bPlayIdle = TRUE;
                lastTickCount = GetTickCount();
                ProgramState = PS_ACTIVE;
            }
            else
            {
                DisplayLevel();
            }
            return;
    }
}

void DisplayLevel( void )
{
    TCHAR buf[10];

    EraseScreen();
    buf[0] = 10 + TEXT('0');
    buf[1] = 11 + TEXT('0');
    buf[2] = 12 + TEXT('0');
    buf[3] = 11 + TEXT('0');
    buf[4] = 10 + TEXT('0');
    buf[5] = TEXT('\0');
    bltScore( buf, ScreenX/2-64, ScreenY/2-8 );
    buf[0] = level / 100 + TEXT('0');
    buf[1] = level / 10 + TEXT('0');
    buf[2] = level % 10 + TEXT('0');
    buf[3] = TEXT('\0');
    bltScore( buf, ScreenX/2+22, ScreenY/2-8 );
    FlipScreen();
}

void bltScore( TCHAR *num, int x, int y )
{
    TCHAR *c;
    RECT    src;
    int     i;
    HRESULT ddrval;

    for(c=num; *c != TEXT('\0'); c++)
    {
        while( 1 )
        {
            i = *c - TEXT('0');
            src.left = i*16;
            src.top = 0;
            src.right = src.left + 16;
            src.bottom = src.top + 16;
            ddrval = lpBackBuffer->lpVtbl->BltFast( lpBackBuffer, x, y, lpNum, &src, dwTransType );
            if( ddrval == DD_OK )
            {
                break;
            }
            if( ddrval == DDERR_SURFACELOST )
            {
                if( !RestoreSurfaces() )
                    return;
            }
            if( ddrval != DDERR_WASSTILLDRAWING )
            {
                return;
            }
        }
        x += 16;
    }
}

void CheckForHits( void )
{
    LPDBLNODE   bullet, target, save;
    int         frame, x, y, l, t;
    BOOL        hit;

    // update screen rects
    target = &DL;
    do
    {
        frame = (DWORD)target->frame;
        switch( target->type )
        {
            case OBJ_DONUT:
                target->dst.left = (DWORD)target->posx;
                target->dst.top = (DWORD)target->posy;
                target->dst.right = target->dst.left + 64;
                target->dst.bottom = target->dst.top + 64;
                target->src.left = 64 * (frame % 5);
                target->src.top = 64 * (frame /5);
                target->src.right = target->src.left + 64;
                target->src.bottom = target->src.top + 64;
                break;
            case OBJ_PYRAMID:
                target->dst.left = (DWORD)target->posx;
                target->dst.top = (DWORD)target->posy;
                target->dst.right = target->dst.left + 32;
                target->dst.bottom = target->dst.top + 32;
                target->src.left = 32 * (frame % 10);
                target->src.top = 32 * (frame /10);
                target->src.right = target->src.left + 32;
                target->src.bottom = target->src.top + 32;
                break;
            case OBJ_SPHERE:
                target->dst.left = (DWORD)target->posx;
                target->dst.top = (DWORD)target->posy;
                target->dst.right = target->dst.left + 16;
                target->dst.bottom = target->dst.top + 16;
                target->src.left = 16 * (frame % 20);
                target->src.top = 16 * (frame /20);
                target->src.right = target->src.left + 16;
                target->src.bottom = target->src.top + 16;
                break;
            case OBJ_CUBE:
                target->dst.left = (DWORD)target->posx;
                target->dst.top = (DWORD)target->posy;
                target->dst.right = target->dst.left + 16;
                target->dst.bottom = target->dst.top + 16;
                target->src.left = 16 * (frame % 20);
                target->src.top = 16 * (frame /20);
                target->src.right = target->src.left + 16;
                target->src.bottom = target->src.top + 16;
                break;
            case OBJ_SHIP:
                target->dst.left = (DWORD)target->posx;
                target->dst.top = (DWORD)target->posy;
                target->dst.right = target->dst.left + 32;
                target->dst.bottom = target->dst.top + 32;
                if( lastShield )
                    target->src.top = 32 * (frame / 10) + 128;
                else
                    target->src.top = 32 * (frame /10);
                target->src.left = 32 * (frame % 10);
                target->src.right = target->src.left + 32;
                target->src.bottom = target->src.top + 32;
                break;
            case OBJ_BULLET:
                frame = (DWORD)target->frame/20 % 4;
                target->dst.left = (DWORD)target->posx;
                target->dst.top = (DWORD)target->posy;
                target->dst.right = target->dst.left + 3;
                target->dst.bottom = target->dst.top + 3;
                target->src.left = BULLET_X + frame*4;
                target->src.top = BULLET_Y;
                target->src.right = target->src.left + 3;
                target->src.bottom = target->src.top + 3;
                break;
        }
        target = target->next;
    }
    while( target != &DL );

    bullet=&DL;
    do
    {
        hit = FALSE;
        if((bullet->type != OBJ_BULLET) && (bullet != &DL))
        {
            bullet = bullet->next;
            continue;
        }

        x = (bullet->dst.left + bullet->dst.right) / 2;
        y = (bullet->dst.top + bullet->dst.bottom) / 2;
        for(target=DL.next; target != &DL; target = target->next)
        {
            if( ( target->type != OBJ_DONUT ) &&
                ( target->type != OBJ_PYRAMID ) &&
                ( target->type != OBJ_SPHERE ) &&
                ( target->type != OBJ_CUBE ) )
                continue;

            if( (x >= target->dst.left) &&
                (x <  target->dst.right) &&
                (y >= target->dst.top) &&
                (y <  target->dst.bottom) )
            {
                if ((bullet != &DL) || !lastShield)
                {
                    // the bullet hit the target
                    switch( target->type )
                    {
                    case OBJ_DONUT:
#ifdef USE_DSOUND
                        if(bWantSound)
                        {
                            playPanned(hsoDonutExplode, target);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -