This is an example of a C++ port of the C# MonoGame sprite loader and renderer for use sprite sheets created by the CodeAndWeb tool "TexturePacker" using the MonoGame project settings.
https://www.codeandweb.com/texturepacker/monogame
You can easily this code to work with other sprite sheet creation tools by modifying the metadata reading code in Load.
SpriteSheet.h
https://www.codeandweb.com/texturepacker/monogame
You can easily this code to work with other sprite sheet creation tools by modifying the metadata reading code in Load.
SpriteSheet.h
class SpriteSheet { public: struct SpriteFrame { RECT sourceRect; DirectX::XMFLOAT2 size; DirectX::XMFLOAT2 origin; bool rotated; }; void Load( ID3D11ShaderResourceView* texture, constwchar_t* szFileName ) { mSprites.clear(); mTexture = texture; if (szFileName) { //// This code parses the 'MonoGame' project txt file that is produced by// CodeAndWeb's TexturePacker.// https://www.codeandweb.com/texturepacker//// You can modify it to match whatever sprite-sheet tool you are using// std::wifstream inFile( szFileName ); if( !inFile ) throw std::exception( "SpriteSheet failed to load .txt data" ); wchar_t strLine[1024]; for(;;) { inFile >> strLine; if( !inFile ) break; if( 0 == wcscmp( strLine, L"#" ) ) { // Comment } else { staticconstwchar_t* delim = L";\n"; wchar_t* context = nullptr; wchar_t* name = wcstok_s(strLine, delim, &context); if ( !name || !*name ) throw std::exception(); if ( mSprites.find( name ) != mSprites.cend() ) throw std::exception(); wchar_t* str = wcstok_s(nullptr, delim, &context); if ( !str ) throw std::exception(); SpriteFrame frame; frame.rotated = (_wtoi(str) == 1); str = wcstok_s(nullptr, delim, &context); if ( !str ) throw std::exception(); frame.sourceRect.left = _wtol(str); str = wcstok_s(nullptr, delim, &context); if ( !str ) throw std::exception(); frame.sourceRect.top = _wtol(str); str = wcstok_s(nullptr, delim, &context); if ( !str ) throw std::exception(); LONG dx = _wtol(str); frame.sourceRect.right = frame.sourceRect.left + dx; str = wcstok_s(nullptr, delim, &context); if ( !str ) throw std::exception(); LONG dy = + _wtol(str); frame.sourceRect.bottom = frame.sourceRect.top + dy; str = wcstok_s(nullptr, delim, &context); if ( !str ) throw std::exception(); frame.size.x = static_cast<float>( _wtof(str) ); str = wcstok_s(nullptr, delim, &context); if ( !str ) throw std::exception(); frame.size.y = static_cast<float>( _wtof(str) ); str = wcstok_s(nullptr, delim, &context); if ( !str ) throw std::exception(); float pivotX = static_cast<float>( _wtof(str) ); str = wcstok_s(nullptr, delim, &context); if ( !str ) throw std::exception(); float pivotY = static_cast<float>( _wtof(str) ); if (frame.rotated) { frame.origin.x = dx * (1.f - pivotY); frame.origin.y = dy * pivotX; } else { frame.origin.x = dx * pivotX; frame.origin.y = dy * pivotY; } mSprites.insert( std::pair<std::wstring,SpriteFrame>( std::wstring(name), frame) ); } inFile.ignore( 1000, '\n' ); } } } const SpriteFrame* Find(constwchar_t* name) const { auto it = mSprites.find(name); if (it == mSprites.cend()) returnnullptr; return&it->second; } void XM_CALLCONV Draw(DirectX::SpriteBatch* batch, const SpriteFrame& frame, DirectX::XMFLOAT2 const& position, DirectX::FXMVECTOR color = DirectX::Colors::White, float rotation = 0, float scale = 1, DirectX::SpriteEffects effects = DirectX::SpriteEffects_None, float layerDepth = 0) const { assert(batch != 0); usingnamespace DirectX; if (frame.rotated) { rotation -= XM_PIDIV2; switch(effects) { case SpriteEffects_FlipHorizontally: effects = SpriteEffects_FlipVertically; break; case SpriteEffects_FlipVertically: effects = SpriteEffects_FlipHorizontally; break; } } XMFLOAT2 origin = frame.origin; switch (effects) { case SpriteEffects_FlipHorizontally: origin.x = frame.sourceRect.right - frame.sourceRect.left - origin.x; case SpriteEffects_FlipVertically: origin.y = frame.sourceRect.bottom - frame.sourceRect.top - origin.y; } batch->Draw(mTexture.Get(), position, &frame.sourceRect, color, rotation, origin, scale, effects, layerDepth ); } void XM_CALLCONV Draw(DirectX::SpriteBatch* batch, const SpriteFrame& frame, DirectX::XMFLOAT2 const& position, DirectX::FXMVECTOR color, float rotation, DirectX::XMFLOAT2 const& scale, DirectX::SpriteEffects effects = DirectX::SpriteEffects_None, float layerDepth = 0) const; // Draw overloads specifying position and scale via the first two components of an XMVECTOR.void XM_CALLCONV Draw(DirectX::SpriteBatch* batch, const SpriteFrame& frame, DirectX::FXMVECTOR position, DirectX::FXMVECTOR color = DirectX::Colors::White, float rotation = 0, float scale = 1, DirectX::SpriteEffects effects = DirectX::SpriteEffects_None, float layerDepth = 0) const; void XM_CALLCONV Draw(DirectX::SpriteBatch* batch, const SpriteFrame& frame, DirectX::FXMVECTOR position, DirectX::FXMVECTOR color, float rotation, DirectX::GXMVECTOR scale, DirectX::SpriteEffects effects = DirectX::SpriteEffects_None, float layerDepth = 0) const; // Draw overloads specifying position as a RECT.void XM_CALLCONV Draw(DirectX::SpriteBatch* batch, const SpriteFrame& frame, RECT const& destinationRectangle, DirectX::FXMVECTOR color = DirectX::Colors::White, float rotation = 0, DirectX::SpriteEffects effects = DirectX::SpriteEffects_None, float layerDepth = 0) const; private: Microsoft::WRL::ComPtr<ID3D11ShaderResourceView> mTexture; std::map<std::wstring, SpriteFrame> mSprites; };