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

📄 donuts.c

📁 Windows Mobile 6 DirectX 2D源码
💻 C
📖 第 1 页 / 共 4 页
字号:
        lpCube->lpVtbl->Release( lpCube );

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

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

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

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

    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;
    DDSURFACEDESC   ddsd;
    DDSURFACEDESC   DDSurfDesc;
    DDCAPS ddCaps;
    DDCAPS ddHelCaps;

    if (bWantSound)
    {
        if (! InitializeSound()) {
            return FALSE;
        }
    }

    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;            

    ddrval = DirectDrawCreate( NULL, &lpDD, NULL );

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

    lpDD->lpVtbl->GetCaps(lpDD, &ddCaps, &ddHelCaps);

    if (!(ddCaps.ddsCaps.dwCaps & DDSCAPS_BACKBUFFER) || !(ddCaps.ddsCaps.dwCaps & DDSCAPS_FLIP)) 
    {
        bSingleBuffer = TRUE;
    }

    // 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 = DDBLT_KEYSRC;
    ddcaps.dwSize = sizeof( ddcaps );

    // Create surfaces
    memset( &ddsd, 0, sizeof( ddsd ) );
    ddsd.dwSize = sizeof( ddsd );
    if (bSingleBuffer)
    {
        ddsd.dwFlags = DDSD_CAPS;
        ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
    }
    else 
    {
        ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
        ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP;
        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!"));
    }

    if (bSingleBuffer)
    {
        ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
        ddsd.dwWidth = ScreenX;
        ddsd.dwHeight = ScreenY;
        ddrval = lpDD->lpVtbl->CreateSurface( lpDD, &ddsd, &lpBackBuffer, NULL );
        if (ddrval != DD_OK)
        {
            return CleanupAndExit(TEXT("CreateSurface BackBuffer Failed!"));
        }
    }
    else
    {
        ddrval = lpFrontBuffer->lpVtbl->EnumAttachedSurfaces( lpFrontBuffer, &lpBackBuffer, EnumFunction);
        if (ddrval != DD_OK)
        {
            return CleanupAndExit(TEXT("EnumAttachedSurfaces Failed!"));
        }
    }

    ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
    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();

    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.
    
    HRESULT hr = StringCchPrintf (
                    DebugBuf, 
                    sizeof(DebugBuf)/sizeof(DebugBuf[0]), 
                    TEXT("%s: CleanupAndExit  err = %s\n"), 
                    cszAppName, 
                    err);
    if (SUCCEEDED(hr))
        OutputDebugString(DebugBuf);
    else
        OutputDebugString(TEXT("DONUTS: Internal application error\n"));    

    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();
}

//
// 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)
{
    SndObjPlayPanned(hSO, (LONG)((20000.0 * ((object->dst.right + object->dst.left) / 2) / ScreenX) - 10000.0));
}

void UpdateFrame( void )
{
    switch( ProgramState )
    {
        case PS_SPLASH:
            // display the splash screen
            bltSplash();
            return;
        case PS_ACTIVE:
            UpdateDisplayList();
            CheckForHits();
            DrawDisplayList();
            if ( isDisplayListEmpty() )
            {
                if(bWantSound)
                {
                    SndObjStop(hsoEngineIdle);
                    SndObjStop(hsoEngineRev);
                }
                bPlayIdle = FALSE;
                bPlayRev = FALSE;
                lastThrust = lastShield = FALSE;
                ProgramState = PS_BEGINREST;
                restCount = GetTickCount();
                initLevel( ++level );
            }
            return;
        case PS_BEGINREST:
            if(bWantSound)
            {
                SndObjPlay(hsoBeginLevel);
            }
            ProgramState = PS_REST;
            //
            // FALLTHRU
            //
        case PS_REST:
            if( ( GetTickCount() - restCount ) > ShowLevelCount )
            {
                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;
    RECT    dest;
    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;

            dest.left = x;
            dest.top  = y;
            dest.right = dest.left + (src.right - src.left);
            dest.bottom = dest.top + (src.bottom - src.top);

            ddrval = lpBackBuffer->lpVtbl->Blt( lpBackBuffer, &dest, lpNum, &src, dwTransType, NULL );

            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:
                        if(bWantSound)
                        {
                            playPanned(hsoDonutExplode, target);
                        }
                        addObject( OBJ_PYRAMID, target->dst.left,
                            target->dst.top, -1.0, -1.0 );
                        addObject( OBJ_PYRAMID, target->dst.left,
                            target->dst.top, -1.0, -1.0 );
                        addObject( OBJ_PYRAMID, target->dst.left,
                            target->dst.top, -1.0, -1.0 );
                        score += 10;
                        break;
                    case OBJ_PYRAMID:
                        if(bWantSound)
                        {

⌨️ 快捷键说明

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