Рисование LPDIRECT3DTEXTURE9 на LPDIRECT3DSURFACE9

Есть ли в DirectX9 специальная функция, которая позволяет указать, где LPD3DXSPRITE воспроизводит спрайт? Я пытаюсь загрузить на поверхность информацию о плитках, а затем отобразить часть этой поверхности в фоновом буфере. Я понял, что с LPD3DXSPRITE :: Draw () нет параметра для целевой поверхности, вероятно, это автоматически буферный буфер. Затем мой рисунок поверхности игрового мира покрывает спрайты.

Есть ли решение или другой подход к этой проблеме? Мне нужна прозрачность, поэтому я подумал об использовании объекта LPDIRECT3DTEXTURE9 для обработки своих тайловых спрайтов, но карта не помещается в задний буфер, поэтому я подумал о загрузке карты на поверхность, а затем рисовании с нее.

//Filename: MyDirectX.h
//Direct3D objects
extern LPDIRECT3D9 d3d; 
extern LPDIRECT3DDEVICE9 d3ddev; 
extern LPDIRECT3DSURFACE9 backbuffer;
extern LPD3DXSPRITE spriteobj;

LPDIRECT3DTEXTURE9 LoadTexture(string filename, D3DCOLOR transcolor = D3DCOLOR_XRGB(0,0,0));

void DrawTile(LPDIRECT3DTEXTURE9 source, int frame, int width, int height, int columns, LPDIRECT3DSURFACE9 dest, int destx, int desty, D3DCOLOR color);
void BuildGameWorld();
void ScrollScreen();
/////////////////////////////////////////////////////////////////////////////
//Filename: MyGame.cpp
#include "MyDirectX.h"

//THIS FUNCTION HERE
void DrawTile(LPDIRECT3DTEXTURE9 source, int frame, int width, int height, int columns, LPDIRECT3DSURFACE9 dest, int destx, int desty, D3DCOLOR color)
{
    //get dimensions for the tile
    RECT r1;
    r1.left = (frame % columns) * width;
    r1.top = (frame / columns) * height;
    r1.right = r1.left + width;
    r1.bottom = r1.top + height;

    //can only draw to the backbuffer? Any work around?
    spriteobj->Draw(source, &r1, &D3DXVECTOR3(r1.right / 2, r1.bottom / 2, 0), &D3DXVECTOR3(destx, desty, 0), color);
}

void BuildGameWorld()
{
    int x, y;
    LPDIRECT3DTEXTURE9 tiles = nullptr;

    //load the texture file
    tiles = LoadTexture("goodly-2x.png", D3DCOLOR_XRGB(255, 0, 255));

    spriteobj->Begin(D3DXSPRITE_ALPHABLEND);

    for(y = 0; y < MAPHEIGHT; y++)
    {
        for(x = 0; x < MAPWIDTH; x++)
        {
            DrawTile(tiles, MAP_LAYER1[y * MAPWIDTH + x], 32, 32, 16, gameworld, x * 32, y * 32, D3DCOLOR_XRGB(255,255,255));
        }
    }

    spriteobj->End();

    //release the texture file
    tiles->Release();
}

//Without this function, and placing BuildGameWorld() inside the Game_Run()
//rendering phase the screen displays stripes of blue which I can only 
//assume is the transparent tiles working incorrectly*/
void ScrollScreen()
{
    //update horizontal scrolling position and speed
    ScrollX += SpeedX;
    if (ScrollX < 0) 
    {
        ScrollX = 0;
        SpeedX = 0;
    }
    else if (ScrollX > GAMEWORLDWIDTH - SCREENW)
    {
        ScrollX = GAMEWORLDWIDTH - SCREENW;
        SpeedX = 0;
    }

    //update vertical scrolling position and speed
    ScrollY += SpeedY;
    if (ScrollY < 0)
    {
        ScrollY = 0;
        SpeedY = 0;
    }
    else if (ScrollY > GAMEWORLDHEIGHT - SCREENH)
    {
        ScrollY = GAMEWORLDHEIGHT - SCREENH;
        SpeedY = 0;
    }

    //set dimensions of the source image
    RECT r1 = {ScrollX, ScrollY, ScrollX+SCREENW-1, 
        ScrollY+SCREENH-1};

    //set the destination rect
    RECT r2 = {0, 0, SCREENW-1, SCREENH-1};

    d3ddev->StretchRect(gameworld, &r1, backbuffer, &r2, 
        D3DTEXF_NONE);

}

person L.Moyer    schedule 20.12.2016    source источник
comment
Людей всегда будут критиковать, если они не включают код, но вы, возможно, включили слишком много. Если вы сможете выразить свой код в минимальном примере, это будет огромным подспорьем для респондентов. Я не уверен, кто захочет просмотреть весь загруженный вами код и попытаться определить проблему. Даже если вы оставили большой блок кода, но указали на бит, который, как вы почти уверены, не работает, это может помочь вам получить больше помощи и снизить количество голосов против.   -  person Anne Gunn    schedule 20.12.2016
comment
Я удалил лишний код и прокомментировал функцию, которая, по моему мнению, вызывает проблему; ScrollScreen ().   -  person L.Moyer    schedule 20.12.2016
comment
Спасибо за обновление. Удачи в получении помощи.   -  person Anne Gunn    schedule 20.12.2016
comment
Я не уверен, почему вы начинаете с устаревшего Direct3D 9 API, используя устаревшую вспомогательную библиотеку D3DX. Если у вас нет особо устаревших системных требований, лучшим решением будет использование DirectX 11, DirectX Tool Kit, и класс SpriteBatch.   -  person Chuck Walbourn    schedule 21.12.2016
comment
Я использовал API, который использовал Джонатан Харбор для Beginning Game Programming, который, как мне кажется, был DirectX 9.0c. Я видел, что прямой ввод по крайней мере устарел, и я не мог заставить его работать должным образом, но я не знал о D3DX. Я посмотрю на набор инструментов и, возможно, перенесу свой код на DirectX 11. Пока что я сделал только Pong и работаю над игрой на основе плитки. Изначально платформер, но, возможно, сначала собираюсь сделать Breakout.   -  person L.Moyer    schedule 22.12.2016


Ответы (1)


Поскольку вы используете ID3DXSprite, самый простой способ указать цель рендеринга - использовать ID3DXRenderToSurface следующим образом:

// inside IDirect3DDevice9::BeginScene() / EndScene() block
ID3DXRenderToSurface::BeginScene()
ID3DXSprite::Begin()

// draw your sprites

ID3DXSprite::End()
ID3DXRenderToSurface::EndScene()
person VuVirt    schedule 21.12.2016
comment
Вот несколько полезных ссылок: gamedev.net/topic/491590-rendering -sprites-off-screen codeampler.com/dx9src/dx9src_7.htm - person VuVirt; 21.12.2016
comment
Спасибо! Я не был уверен, как установить цель рендеринга. Мой первый запуск заставил его работать, за исключением прокрутки карты. Мои пробежки после этого все еще остаются черным экраном, но я собираюсь продолжить работу над ним. - person L.Moyer; 21.12.2016
comment
Мне не удалось заставить работать ID3DXRenderToSurface, но я увидел, что устройство Direct3D имеет функцию SetRenderTarget. Итак, моя программа работает так: d3ddev- ›SetRenderTarget (NULL, gameworld); d3ddev- ›BeginScene (); // Код рендеринга здесь d3ddev- ›EndScene (); d3ddev- ›SetRenderTarget (NULL, backbuffer); - person L.Moyer; 21.12.2016
comment
ID3DXRenderToSurface на самом деле является оболочкой для SetRenderTarget. - person VuVirt; 21.12.2016