游戏开发论坛

 找回密码
 立即注册
搜索
查看: 5692|回复: 14

[求助]关于SetColorKey

[复制链接]

3

主题

12

帖子

18

积分

新手上路

Rank: 1

积分
18
发表于 2006-1-23 17:16:00 | 显示全部楼层 |阅读模式
我从一张24bit的BMP图片读取信息后存在一个表面,然后设置了color key想将背景颜色略过,可是却没有用...这是怎么回事?我开始以为这和图片的颜色数有关,我把图片转为256色,但还是不行...
if( FAILED( hr = g_pDisplay->CreateSurfaceFromBitmap( &g_pChraSurface, "Character24b.bmp", CHAR_WIDTH * 5, CHAR_HEIGHT * 8 ) ) )

if( FAILED( hr = g_pChraSurface->SetColorKey( RGB( 255, 0, 255) ) ) )
        return hr;
RGB(255, 0, 255)是背景色.

图片如下
sf_200612317160.bmp

90

主题

797

帖子

833

积分

高级会员

论坛版主

Rank: 4

积分
833
QQ
发表于 2006-1-24 18:16:00 | 显示全部楼层

Re:[求助]关于SetColorKey

创建这个表面的时候,要设置是否使用colorkey,具体参数忘记了,ddsd这样子的缩写

7

主题

61

帖子

61

积分

注册会员

Rank: 2

积分
61
发表于 2006-1-25 12:51:00 | 显示全部楼层

Re:[求助]关于SetColorKey

还有其他的图片资源能提供吗?
设置colorkey和屏幕的色深度或者游戏设置的色深有关,试试24位色或者其他

3

主题

12

帖子

18

积分

新手上路

Rank: 1

积分
18
 楼主| 发表于 2006-1-25 15:57:00 | 显示全部楼层

Re:[求助]关于SetColorKey

发现了一个问题,好像和调用的图片有关,同样是两张256色的图,那张用SetColorKey就有用,而这张就不行....

32

主题

1583

帖子

1589

积分

金牌会员

Rank: 6Rank: 6

积分
1589
发表于 2006-1-25 20:10:00 | 显示全部楼层

Re:[求助]关于SetColorKey

你提供的代码太少了,不足以看出问题在哪。

首先你是用Dx7吗?如果是你Blt时加入相关参数了吗?

其次你的程序的颜色模式是多少?是24位的吗?

3

主题

12

帖子

18

积分

新手上路

Rank: 1

积分
18
 楼主| 发表于 2006-1-26 13:40:00 | 显示全部楼层

Re:[求助]关于SetColorKey

问题是这样的:首先我用的是DX8的SDK,用到里面面的ddutil.h里的CDisplay和CSurface两个类.
我是想实现人物的跑动动画,用的是窗口模式,图片是24位和8位的都用过了,问题是一样的.
首先,我先创建表面CDisplay->CreateSurfaceFromBitmap,然后用了SetColorKey,最后Blt.问题就在这个Blt上面.由于人物的动画在一张图上,所以我设了个timer,定时读取键盘的按键,然后用一个RECT来控制Blt的区域,这个时候SetColorKey就失效了....但是我试过将背景也用RECT区域Blt,SetColorKey缺可以用的....难道是因为多次Blt就会使ColorKey失效?

3

主题

12

帖子

18

积分

新手上路

Rank: 1

积分
18
 楼主| 发表于 2006-1-26 13:49:00 | 显示全部楼层

Re: [求助]关于SetColorKey

我把代码的关键地方贴出来:
简单说明一下,第一个是HRESULT InitDirectDraw( HWND hWnd ),主要是用来创建CDisplay对象还有CSurface表面,然后设置ColorKey....第二个是DisplayFrame()函数,用来将表面Blt和Flip,由于用了SDK里的类,Flip操作用present()就行了...

HRESULT InitDirectDraw( HWND hWnd )
{
    HRESULT                        hr;
    LPDIRECTDRAWPALETTE pDDPal   = NULL; //定义程序中的调色板
    LPDIRECTDRAWSURFACE pDDSurface = NULL;
       
    // Release all existing surfaces
        //模式要切换,现有的表面都要释放,然后创建新的表面
    SAFE_DELETE( g_pTextSurface );
        SAFE_DELETE( g_pBackSurface );
        SAFE_DELETE( g_pChraSurface );
        SAFE_DELETE( g_pDisplay );

    // The back buffer and primary surfaces need to be created differently
    // depending on if we are in full-screen or windowed mode
    g_pDisplay = new CDisplay();

   
    if( FAILED( hr = g_pDisplay->CreateWindowedDisplay( hWnd, SCREEN_WIDTH, SCREEN_HEIGHT ) ) )
        {
                MessageBox( hWnd, TEXT("创建窗口模式失败,\n可能您的显卡不支持这个模式,\n程序即将退出"),
                                TEXT("DirectDraw Sample"), MB_ICONERROR | MB_OK );
        return hr;
        }
       
        if( FAILED( hr = g_pDisplay->CreatePaletteFromBitmap( &pDDPal, "animate.bmp") ) )
        return hr;
       

    g_pDisplay->SetPalette( pDDPal );
       

    SAFE_RELEASE( pDDPal );

    // Create a surface, and draw a bitmap resource on it.  The surface must
    // be newly created every time the screen mode is switched since it
    // uses the pixel format of the primary surface

   
        if( FAILED( hr = g_pDisplay->CreateSurfaceFromBitmap( &g_pBackSurface, "BackGround256.bmp",
                                                 SCREEN_WIDTH,SCREEN_HEIGHT ) ) )
            return hr;

        //创建人物表面
        if( FAILED( hr = g_pDisplay->CreateSurfaceFromBitmap( &g_pChraSurface, "Character256.bmp",
                                                                   290, 784 ) ) )

   
    if( FAILED( hr = g_pChraSurface->SetColorKey( RGB( 255, 0, 255) ) ) )
        return hr;

        if( FAILED( hr = g_pBackSurface->SetColorKey( RGB( 255, 255, 255) ) ) )
                return hr;

        if( FAILED( hr = g_pDisplay->CreateSurfaceFromText(&g_pTextSurface,NULL,HELPTEXT,
                                                                 RGB(255,255,255),RGB(255, 0, 255) ) ) )
                return hr;

        if( FAILED( hr = g_pTextSurface->SetColorKey( RGB( 255, 255, 255) ) ) )
                return hr;

        if( FAILED( hr = g_pDisplay->CreateSurfaceFromBitmap(&g_pChraNextSurface, "animate.bmp",
                                                                       200, 200 ) ) )
                return hr;
       
        if( FAILED( hr = g_pChraNextSurface->SetColorKey( 0 ) ) )
                return hr;

    return S_OK;
}

HRESULT DisplayFrame()
{
    HRESULT hr;

    // Fill the back buffer with black, ignoring errors until the flip
    g_pDisplay->Clear( 0 );//清空后备缓冲区表面,即用黑色填满

    // Blt the help text on the backbuffer, ignoring errors until the flip
        //将文本信息拷贝到后备缓存区,坐标是10,10
    g_pDisplay->Blt( 10, 10, g_pTextSurface, NULL );

        //从BackSurface读取rc大小拷贝到后备缓存区中...
        //这样就可以实现动画了,哈哈...
       
        g_pDisplay->Blt( 0, 0 , g_pBackSurface, NULL );
       
        RECT rc;
        rc.top = g_Char.direc * CHAR_HEIGHT;
        rc.left = g_xChar * CHAR_WIDTH;
        rc.right = (g_xChar + 1) * CHAR_WIDTH;
        rc.bottom = (g_Char.direc + 1) * CHAR_HEIGHT;
        g_pDisplay->Blt( g_Char.xPos, g_Char.yPos, g_pChraSurface, &rc);

        g_pDisplay->Blt( 200, 200, g_pChraNextSurface, NULL );

    // We are in fullscreen mode, so perform a flip and return
    // any errors like DDERR_SURFACELOST
        //最关键的地方在这里,请看下面的语句,只要我们一执行翻页操作,就可以将改动了的图像了显示在屏幕上了
    if( FAILED( hr = g_pDisplay-&gtresent() /*翻页操作*/) )
        return hr;

    return S_OK;
}

下面这个是DirectInput里的读取键盘操作
for( i = 0; i < 256; i++ )
      {
            if( diks & 0x80 ) //记录此键的状态,低字节最高位是 1 表示按下,0 表示松开,一般用 diks&0x80 来测试
            {
                  switch(i)
                  {
                              //我们可以通过测试计数器i,来判断是哪个键被按下了。
                              //我们提供几个数据 UP:200 down:208 left:203 right:205 enter:28 space:57
                              //其实你可以用DirectX中的Samples\C++\DirectInput\Bin\Keyboard.exe程序来测试,只不过那是用
                              //16进制显示的。
                  case 0xc8: //上键
                                          {
                                                 //g_Char.direc = 4;
                                                 g_Char.yVel = -1;
                                                 if(g_Char.yPos >= 10 )
                                                         g_Char.yPos -= 10;
                                                 else
                                                         g_Char.yPos = 0;
                                                 
                                                 UpdateFrame();
                                          }
                        break;
                  case 0xd0: //下键
                                          {
                                                  //g_Char.direc = 0;
                                                  g_Char.yVel = 1;
                                                  if(g_Char.yPos <= (SCREEN_HEIGHT - CHAR_HEIGHT - 10 ) )
                                                          g_Char.yPos += 10;
                                                  else
                                                          g_Char.yPos = (SCREEN_HEIGHT - CHAR_HEIGHT);
                                                  
                                                  UpdateFrame();
                                          }
                        break;
                  case 0xcb://左键
                                          {
                                                  //g_Char.direc = 2;
                                                  g_Char.xVel =-1;
                                                  if(g_Char.xPos >= 10 )
                                                          g_Char.xPos -= 10;
                                                  else
                                                          g_Char.xPos = 0;
                                                  
                                                  UpdateFrame();
                                          }
                        break;
                  case 0xcd://右键
                                          {
                                                  //g_Char.direc = 6;
                                                  g_Char.xVel = 1;
                                                  if(g_Char.xPos <= (SCREEN_WIDTH - CHAR_WIDTH - 10 ) )
                                                          g_Char.xPos += 10;
                                                  else
                                                          g_Char.xPos = (SCREEN_WIDTH - CHAR_WIDTH);
                                                  
                                                  UpdateFrame();
                                          }
                        break;
                                  case 0x01://ESC键
                                          {
                                                PostQuitMessage( 0 );
                                          }
                                          break;
                                  default:
                                          
                                          break;
                                  }
                                  
            }

这个函数用来对RECT的范围进行操作
void UpdateFrame( )
{
        g_xChar++;
        if( g_xChar == 5 )
                g_xChar = 1;
   
                if( g_Char.xVel == 1 && g_Char.yVel == 1)
                        g_Char.direc = 7;
                if( g_Char.xVel == -1 && g_Char.yVel == -1)
                        g_Char.direc = 3;
                if( g_Char.xVel == 1 && g_Char.yVel == -1)
                        g_Char.direc = 5;
                if( g_Char.xVel == -1 && g_Char.yVel == 1)
                        g_Char.direc = 1;
       
                if( g_Char.xVel == 1 && g_Char.yVel == 0)
                        g_Char.direc = 6;
                if( g_Char.xVel == 0 && g_Char.yVel == 1)
                        g_Char.direc = 0;
                if( g_Char.xVel == -1 && g_Char.yVel == 0)
                        g_Char.direc = 2;
                if( g_Char.xVel == 0 && g_Char.yVel == -1)
                        g_Char.direc = 4;
       
        DisplayFrame();
}

7

主题

61

帖子

61

积分

注册会员

Rank: 2

积分
61
发表于 2006-1-26 15:23:00 | 显示全部楼层

Re:[求助]关于SetColorKey

还是老话,试试在桌面改变显示设置里面的颜色质量

3

主题

12

帖子

18

积分

新手上路

Rank: 1

积分
18
 楼主| 发表于 2006-1-26 16:12:00 | 显示全部楼层

Re:[求助]关于SetColorKey

没用,现在问题是在图片和屏幕设置不变的情况下.SetColorKey在其他时候是有用的,就是在实现人物动画是没有用,应该就是那句g_pDisplay->Blt( g_Char.xPos, g_Char.yPos, g_pChraSurface, &rc);开始我以为可能是和在Blt时限定区域有关,但是我在背景Blt时也试过限定一个区域,SetColorKey还是有用的....现在唯独就是g_pCharSurface这个表面上SetColorKey没用....而且人物和背景图片都是24bit的BMP图片.

32

主题

1583

帖子

1589

积分

金牌会员

Rank: 6Rank: 6

积分
1589
发表于 2006-1-26 22:56:00 | 显示全部楼层

Re:[求助]关于SetColorKey

这是Dx8吗?
我怎么看都是DDraw7的啊。
一个简单的测试方法:你把需要滤掉的背景色设为黑色(#00000000)看看是否可以滤过,如果是,说明是颜色设置的问题。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2026-1-23 08:02

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表