动画精灵问题 (C++/DirectX9)

Posted

技术标签:

【中文标题】动画精灵问题 (C++/DirectX9)【英文标题】:Animating Sprites issue (C++/DirectX9) 【发布时间】:2015-07-24 18:17:28 【问题描述】:

我正在学习有关使用 DirectX9 为精灵制作动画的教程,并且我做的一切都正确,我只需要一些帮助来解决我想要更正的问题。到目前为止,我可以正确地为精灵设置动画,但问题是当精灵进行动画处理时,它会在绘制下一帧之前留下前一帧中的图像。我该如何解决这个问题?

这是头文件中的声明:

LPDIRECT3DTEXTURE9 LoadTexture(string filename, D3DCOLOR transcolor = D3DCOLOR_XRGB(0, 0, 0));
void Sprite_Transform_Draw(LPDIRECT3DTEXTURE9 image, int x, int y, int width, int height, 
    int frame = 0, int columns = 1, float rotation = 0.0f, float scaling = 1.0f, 
    D3DCOLOR color = D3DCOLOR_XRGB(255,255,255));

这是它的 cpp 文件中的定义:

//Loads a bitmap onto a texture
LPDIRECT3DTEXTURE9 LoadTexture(std::string filename, D3DCOLOR transcolor)

    LPDIRECT3DTEXTURE9 texture = NULL;

    //get width and height from bitmap file
    D3DXIMAGE_INFO info;
    HRESULT result = D3DXGetImageInfoFromFile(filename.c_str(), &info);
    if (result != D3D_OK) return NULL;

    //create the new textur by loading a bitmap image file
    D3DXCreateTextureFromFileEx(
        d3ddev,
        filename.c_str(),
        info.Width, info.Height,
        1,
        D3DPOOL_DEFAULT,
        D3DFMT_UNKNOWN,
        D3DPOOL_DEFAULT,
        D3DX_DEFAULT, D3DX_DEFAULT,
        transcolor,
        &info,
        NULL,
        &texture);

    //make sure the bitmap texture was loaded correctly
    if (result != D3D_OK) return NULL;

    return texture;


void Sprite_Transform_Draw(LPDIRECT3DTEXTURE9 image, int x, int y, int width, int height, 
    int frame, int columns, float rotation, float scaling, D3DCOLOR color)

    //Create a scale vector
    D3DXVECTOR2 scale(scaling, scaling);

    //Create a translate vector
    D3DXVECTOR2 trans(x, y);

    //Set center by dividing width and height by two
    D3DXVECTOR2 center((float)(width * scaling) / 2, (float)(height * scaling)/2);

    //Create 2D transformation matrix
    D3DXMATRIX mat;
    D3DXMatrixTransformation2D(&mat, NULL, 0, &scale, &center, rotation, &trans);

    //Tell sprite object to use the transform
    spriteobj->SetTransform( &mat );

    //Calculate frame location in source image
    int fx = (frame % columns) * width;
    int fy = (frame / columns) * height;
    RECT srcRect = fx, fy, fx + width, fy + height;

    //draw the sprite frame
    spriteobj->Draw(image, &srcRect, NULL, NULL, color);

如何在 Game_Init 函数中加载图像:

bool Game_Init(HWND window)

    //initialize Direct3D
    if (!Direct3D_Init(window, SCREENW, SCREENH, false))
    
        MessageBox(0, "Error initializing Direct3D", "Error", 0);
        return false;
    

    //initialize DirectInput
    if (!DirectInput_Init(window))
    
        MessageBox(0, "Error initializing DirectInput", "Error", 0);
        return false;
    

    //load the sprite image
    sunflower = LoadTexture("images/Sun.bmp");
    if (!sunflower) return false;

    return true;

以及我如何在 Game_Run 函数中绘制图像:

void Game_Run(HWND window)

    static float scale = 0.001f;
    static float r = 0;
    static float s = 1.0f;

    //make sure the Direct3D device is valid
    if (!d3ddev) return;

    //update input devices
    DirectInput_Update();

    //clear the scene
    d3ddev->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 100), 1.0f, 0);

    //start rendering
    if (d3ddev->BeginScene())
    
        //start drawing
        spriteobj->Begin(D3DXSPRITE_ALPHABLEND);

        //set rotation and scaling
        r = timeGetTime() / 600.0f;
        s += scale;
        if (s < 0.1 || s > 1.25f) scale *= -1;

        //draw sprite
        width = height = 64;
        frame = 0;
        columns = 1;
        color = D3DCOLOR_XRGB(255,255,255);
        Sprite_Transform_Draw(sunflower, 300, 150, width, height, frame, columns, r, s, color);

        //stop drawing
        spriteobj->End();

        //stop rendering
        d3ddev->EndScene();
        d3ddev->Present(NULL, NULL, NULL, NULL);
    

    //escape key exits
    if (Key_Down(DIK_SPACE) || Key_Down(DIK_ESCAPE))
        gameover = true;


void Game_End()

    sunflower->Release();

    DirectInput_Shutdown();
    Direct3D_Shutdown();

就像我说的一切正常,它只是保持上一帧的图像仍然在屏幕上。我将如何清除帧之间的屏幕?

编辑: 作为参考,这里是我试图描述的问题的图像:

【问题讨论】:

检查d3ddev-&gt;Clear 的返回值是否失败。更一般地,您应该检查所有返回值以查看它们是否失败。 我把它改成检查清除场景,没有出现错误.. 如果您不是在 Windows 8 上,您可以使用 DirectX SDK 的 DirectX 控制面板来启用 D​​irectX9 的调试层。通常,它可以简化查找此类基本错误的过程,因为您会在无效调用时收到有用的错误消息通知。 【参考方案1】:

想通了,我没有正确设置演示参数。

这是原始代码:

//set Direct3D presentation parameters
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.Windowed = (!fullscreen);
d3dpp.SwapEffect = D3DSWAPEFFECT_COPY;
d3dpp.BackBufferCount = 1;
d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
d3dpp.BackBufferWidth = width;
d3dpp.BackBufferHeight = height;
d3dpp.hDeviceWindow = window;

这是正确需要的代码:

//set Direct3D presentation parameters
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.Windowed = (!fullscreen);
d3dpp.SwapEffect = D3DSWAPEFFECT_COPY;
d3dpp.EnableAutoDepthStencil = 1;
d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
d3dpp.Flags = D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL;
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
d3dpp.BackBufferCount = 1;
d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
d3dpp.BackBufferWidth = width;
d3dpp.BackBufferHeight = height;
d3dpp.hDeviceWindow = window;

【讨论】:

以上是关于动画精灵问题 (C++/DirectX9)的主要内容,如果未能解决你的问题,请参考以下文章

在一个动画剪辑中更改多个精灵

SpriteKit Swift动画一次只能在一个精灵上 - iOS

DirectX9.0或7以上的在哪下载啊

从精灵表中以 sfml 动画精灵

带有精灵表的 Android 动画

启用动画器时,运行时缺少游戏对象精灵