Sprite Class not working

Started by
2 comments, last by User1234 9 years, 11 months ago
hi, it´s me again

i have tried to write a class that handles my sprites but i can´t make it work and i ´m not sure why...

i will give you my code:

the class header:



 
#include <D3D11.h>
#include <D3DX11.h>
#include <xnamath.h>
#include <d3dcompiler.h>

#include "Globals.h"

#ifndef _GameSprite_H
#define _GameSprite_H

struct MySpriteVertex
{
	XMFLOAT3 pos;
	XMFLOAT2 tex0;
};

class GameSprite
{
public:
	GameSprite(char* texturePath, char* shaderPath, float startX, float startY, float sizeX, float sizeY);
	~GameSprite();

	void Initialize();
	void SetUpVertices();
	void DetermineValues();
	bool LoadTexture();
	bool CreateBuffers();
	bool ActivateAlphaBlending();
	void SetView(XMMATRIX &View);
	void CalculateWorld();
	void SetProj(XMMATRIX &Proj);
	void SetPosition(float X, float Y);
	void SetRotation(float rotation);
	void SetScale(float X, float Y);
	void Update();
	void DrawSprite();

	MySpriteVertex spriteVertices[6];

	float startX;
	float startY;
	float sizeX;
	float sizeY;
	float scaleX;
	float scaleY;
	float rotation;

	float spriteWidth;
	float spriteHeight;

	char* texturePath;
	char* shaderPath;

	ID3D11Buffer* spriteVertexBuffer;

	ID3D11ShaderResourceView* spriteMap;
	ID3D11SamplerState* spriteSampler;
	ID3D11InputLayout* spriteInputLayout;

	ID3DBlob* spriteErrorBuffer;
	ID3DBlob* spriteVSBuffer;
	ID3DBlob* spritePSBuffer;

	ID3D11VertexShader* spriteVertexShader;
	ID3D11PixelShader* spritePixelShader;

	ID3D11Buffer* mwvpCB;

	XMMATRIX* spriteView;
	XMMATRIX* spriteProj;
	XMMATRIX* spriteWorld;

	ID3D11BlendState *originalBS;
	float originalBlendColor[4];
	UINT originalSampleMask;

	ID3D11BlendState *newBS;

	bool ResetOriginalBlendState();
};

#endif
 


the .cpp file:




#include "GameSprite.h"

GameSprite::GameSprite(char* texturePath, char* shaderPath, float startX, float startY, float sizeX, float sizeY)
{
	this->texturePath = texturePath;
	this->shaderPath = shaderPath;
	this->startX = startX;
	this->startY = startY;
	this->sizeX = sizeX;
	this->sizeY = sizeY;
	this->rotation = 0;
	this->scaleX = 1.0f;
	this->scaleY = 1.0f;
	this->spriteWorld = &XMMatrixIdentity();
	this->spriteView = &XMMatrixIdentity();
	this->spriteProj = &XMMatrixIdentity();

	Initialize();
}

GameSprite::~GameSprite()
{

}

void GameSprite::Initialize()
{
	LoadTexture();
	DetermineValues();
	SetUpVertices();
	CreateBuffers();
}

void GameSprite::SetUpVertices()
{
	/*
	vertices[0].pos = XMFLOAT3(spriteWidth/2, spriteHeight/2, 1.0f);
	vertices[0].tex0 = XMFLOAT2( 1.0f, 1.0f);

	vertices[1].pos = XMFLOAT3(spriteWidth/2, -spriteHeight/2, 1.0f);
	vertices[1].tex0 = XMFLOAT2( 1.0f, 0.0f);

	vertices[2].pos = XMFLOAT3(-spriteWidth/2, -spriteHeight/2, 1.0f);
	vertices[2].tex0 = XMFLOAT2( 0.0f, 0.0f);

	vertices[3].pos = XMFLOAT3(-spriteWidth/2, -spriteHeight/2, 1.0f);
	vertices[3].tex0 = XMFLOAT2( 0.0f, 0.0f);

	vertices[4].pos = XMFLOAT3(-spriteWidth/2, spriteHeight/2, 1.0f);
	vertices[4].tex0 = XMFLOAT2( 0.0f, 1.0f);

	vertices[5].pos = XMFLOAT3(spriteWidth/2, spriteHeight/2, 1.0f);
	vertices[5].tex0 = XMFLOAT2(1.0f, 1.0f);
	*/

	vertices[0].pos = XMFLOAT3(1.0f, 1.0f, 1.0f);
	vertices[0].tex0 = XMFLOAT2( 1.0f, 1.0f);

	vertices[1].pos = XMFLOAT3(1.0f, -1.0f, 1.0f);
	vertices[1].tex0 = XMFLOAT2( 1.0f, 0.0f);

	vertices[2].pos = XMFLOAT3(-1.0f, -1.0f, 1.0f);
	vertices[2].tex0 = XMFLOAT2( 0.0f, 0.0f);

	vertices[3].pos = XMFLOAT3(-1.0f, -1.0f, 1.0f);
	vertices[3].tex0 = XMFLOAT2( 0.0f, 0.0f);

	vertices[4].pos = XMFLOAT3(-1.0f, 1.0f, 1.0f);
	vertices[4].tex0 = XMFLOAT2( 0.0f, 1.0f);

	vertices[5].pos = XMFLOAT3(1.0f, 1.0f, 1.0f);
	vertices[5].tex0 = XMFLOAT2(1.0f, 1.0f);
}

void GameSprite::DetermineValues()
{
	float spriteWidth = sizeX;
	float spriteHeight = sizeY;

	SetPosition(startX, startY);
	SetRotation(0.0f);
}

bool GameSprite::LoadTexture()
{
	HRESULT result = D3DX11CreateShaderResourceViewFromFileA(Device, texturePath, 0, 0, &spriteMap, 0);

	if(FAILED(result))
	{
		MessageBoxA(NULL, "Failed to load the texture image!", "Error", MB_OK);
		return false;
	}

	D3D11_SAMPLER_DESC colorMapDesc;
	ZeroMemory( &colorMapDesc, sizeof(colorMapDesc));
	colorMapDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
	colorMapDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
	colorMapDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
	colorMapDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
	colorMapDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
	colorMapDesc.MaxLOD = D3D11_FLOAT32_MAX;

	result = Device->CreateSamplerState(&colorMapDesc, &spriteSampler);

	if(FAILED(result))
	{
		MessageBoxA(NULL, "Failed to create color map sampler state!", "Error", MB_OK);
		return false;
	}

	return false;
}

bool GameSprite::CreateBuffers()
{
	D3D11_BUFFER_DESC vertexDesc;
    ZeroMemory(&vertexDesc, sizeof(vertexDesc));
    vertexDesc.Usage = D3D11_USAGE_DEFAULT;
    vertexDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
	vertexDesc.ByteWidth = sizeof(MySpriteVertex) * ARRAYSIZE(spriteVertices);

    D3D11_SUBRESOURCE_DATA resourceData;
    ZeroMemory( &resourceData, sizeof(resourceData));
    resourceData.pSysMem = spriteVertices;

	HRESULT hresult = Device->CreateBuffer(&vertexDesc, &resourceData, &spriteVertexBuffer);

    if(FAILED(hresult))
    {
		MessageBoxA(NULL, "Failed to create vertex buffer!", "Error", MB_OK);
        return true;
    }

	D3D11_BUFFER_DESC constDesc;
	ZeroMemory( &constDesc, sizeof(constDesc));
	constDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
	constDesc.ByteWidth = sizeof(XMMATRIX);
	constDesc.Usage = D3D11_USAGE_DEFAULT;

	hresult = Device->CreateBuffer(&constDesc, 0, &mwvpCB);

	if( FAILED(hresult))
    {
		MessageBoxA(NULL, "Failed to create Constant Buffer", "Error", MB_OK);
        return false;
    }

	spriteErrorBuffer = 0;

	hresult = D3DX11CompileFromFileA(shaderPath, 0, 0, "VS_Main", "vs_4_0", D3DCOMPILE_ENABLE_STRICTNESS, 0, 0, &spriteVSBuffer, &spriteErrorBuffer, 0);

	if(FAILED(hresult))
	{
		MessageBoxA(NULL, "Error Loading Vertex Shader", "Error", MB_OK);
	}

	hresult = Device->CreateVertexShader(spriteVSBuffer->GetBufferPointer(), spriteVSBuffer->GetBufferSize(), 0, &spriteVertexShader);

	if(FAILED(hresult))
	{
		MessageBoxA(NULL, "Error Creating Vertex Shader", "Error", MB_OK);
	}

	D3D11_INPUT_ELEMENT_DESC vertexLayout[] =
	{
		{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
		{"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0}
	};

	hresult = Device->CreateInputLayout(vertexLayout, ARRAYSIZE(vertexLayout), spriteVSBuffer->GetBufferPointer(), spriteVSBuffer->GetBufferSize(), &spriteInputLayout);

	if(FAILED(hresult))
	{
		MessageBoxA(NULL, "Error Creating Input Layout", "Error", MB_OK);
	}

	hresult = D3DX11CompileFromFileA(shaderPath, 0, 0, "PS_Main", "ps_4_0", D3DCOMPILE_ENABLE_STRICTNESS, 0, 0, &spritePSBuffer, &spriteErrorBuffer, 0);

	if(FAILED(hresult))
	{
		MessageBoxA(NULL, "Error Loading Pixel Shader", "Error", MB_OK);
	}

	hresult = Device->CreatePixelShader(spritePSBuffer->GetBufferPointer(), spritePSBuffer->GetBufferSize(), 0, &spritePixelShader);

	if(FAILED(hresult))
	{
		MessageBoxA(NULL, "Error Creating Pixel Shader", "Error", MB_OK);
	}

	return true;
}

void GameSprite::SetView(XMMATRIX &View)
{
	this->spriteView = &View;
}

void GameSprite::SetProj(XMMATRIX &Proj)
{
	this->spriteProj = &Proj;
}

void GameSprite::CalculateWorld()
{
	XMMATRIX translation = XMMatrixTranslation(startX, startY, 0.0f);
	XMMATRIX rotationZ = XMMatrixRotationZ(rotation);
	XMMATRIX scaleMatrix = XMMatrixScaling(scaleX, scaleY, 1.0f);

	*spriteWorld = translation * rotationZ * scaleMatrix;
}

bool GameSprite::ActivateAlphaBlending()
{
	originalBlendColor[0] = 0;
	originalBlendColor[1] = 0;
	originalBlendColor[2] = 0;
	originalBlendColor[3] = 0;
	originalSampleMask = 0;
	originalBS = NULL;

	d3dContext->OMGetBlendState(&originalBS, originalBlendColor, &originalSampleMask);
	
	D3D11_BLEND_DESC blendStateDesc; 
	ZeroMemory(&blendStateDesc, sizeof(D3D11_BLEND_DESC));
	blendStateDesc.AlphaToCoverageEnable = FALSE;
	blendStateDesc.IndependentBlendEnable = FALSE;        
	blendStateDesc.RenderTarget[0].BlendEnable = TRUE;
	blendStateDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
	blendStateDesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
	blendStateDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
	blendStateDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ZERO;
	blendStateDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
	blendStateDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
	blendStateDesc.RenderTarget[0].RenderTargetWriteMask = 0x0F;


	if(FAILED(Device->CreateBlendState(&blendStateDesc, &newBS))) 
	{
		MessageBoxA(NULL, "Error Could not Adjust Blend State", "Error", MB_OK);
		return false;
	}

	d3dContext->OMSetBlendState(newBS, NULL, 0xFFFFFF);

	return true;
}

bool GameSprite::ResetOriginalBlendState()
{
	d3dContext->OMSetBlendState(originalBS, originalBlendColor, originalSampleMask);

	return true;
}

void GameSprite::SetPosition(float X, float Y)
{
	this->startX = X;
	this->startY = Y;
}

void GameSprite::SetRotation(float rotation)
{
	this->rotation = rotation;
}

void GameSprite::SetScale(float X, float Y)
{
	this->scaleX = X;
	this->scaleY = Y;
}

void GameSprite::Update()
{
	CalculateWorld();
}

void GameSprite::DrawSprite()
{
	ActivateAlphaBlending();

	unsigned int stride = sizeof(MySpriteVertex);
	unsigned int offset = 0;

	d3dContext->IASetInputLayout(spriteInputLayout);
	d3dContext->IASetVertexBuffers(0, 1, &spriteVertexBuffer, &stride, &offset);
	d3dContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

	XMMATRIX mwvp = XMMatrixMultiply(*spriteView, *spriteProj);
	mwvp = XMMatrixMultiply(mwvp, *spriteWorld);
	mwvp = XMMatrixTranspose(mwvp);

	d3dContext->UpdateSubresource(mwvpCB, 0, 0, &mwvp, 0, 0);
	d3dContext->VSSetConstantBuffers(0, 1, &mwvpCB);

	d3dContext->PSSetShaderResources( 0, 1, &spriteMap);
	d3dContext->PSSetSamplers(0, 1, &spriteSampler);
	d3dContext->VSSetShader(spriteVertexShader, 0, 0);
	d3dContext->PSSetShader(spritePixelShader, 0, 0);

	d3dContext->Draw(ARRAYSIZE(spriteVertices), 0);

	ResetOriginalBlendState();
}



and here is the shader i use:



 
Texture2D
 
 
colorMap : register(t0);
SamplerState
 
 
colorSampler : register(s0);
cbuffer
 
 
cbChangesEveryFrame : register( b0 )
{
 
 
matrix mwvp;
};
struct
 
 
VS_Input
{
 
 
float4 pos : POSITION;
 
 
float2 tex0 : TEXCOORD0;
};
struct
 
 
PS_Input
{
 
 
float4 pos : SV_POSITION;
 
 
float2 tex0 : TEXCOORD0;
};
PS_Input VS_Main(VS_Input vertex)
{
vertex.pos.w = 1.0f;
PS_Input vsOut = (PS_Input)0;
vsOut.pos = mul(vertex.pos, mwvp);
vsOut.tex0 = vertex.tex0;
 
 
return vsOut;
}
float4
 
 
PS_Main(PS_Input frag) : SV_TARGET
{
 
 
float4 color = colorMap.Sample(colorSampler, frag.tex0);
 
 
return color;
}
 



this is how i set the projection and the view, in my main routines initialisation:



 
	View = XMMatrixIdentity();
	Projection = XMMatrixOrthographicOffCenterLH(0.0f, width, 0.0f, height, 0.1f, 100.0f);

	sprite1 = new GameSprite("Resources\\spriteTest.bmp", "Resources\\SpriteShader.fx", 0.0f, 0.0f, 40, 40);
	sprite1->SetView(View);
	sprite1->SetProj(Projection);
	sprite1->CalculateWorld();
 


the world matrix is re-calculated with every update call.

Am i doing something wrong with the Matrices?

i can´t figure out why it doesn´t work....

and sorry if its a silly error, it´s a bit hard to learn this by yourself unsure.png

edit: sry for the formation... i don´t know where that comes from

edit2: ok i had the bb codes turned off... i fixed it now
Advertisement
ok i fixed it now, i just used the wrong vertices...

but i have another question. How is the collision detection handled in 2D games?
and does somebody know a good resource to read about 2D collision detection?

Collision can be a pretty complex topic.

There are 2 main parts, collision detection and collision handling.

I recently answered a post that asked a similar question http://www.gamedev.net/topic/655552-searching-for-a-good-tutorial-sfml/#entry5147080

This is fine if all you need to do is compare rectangles that are aligned to x and y. If your rectangles can be rotated however, you need

a way to map both rectangles onto an axis to compare them, I believe you can do this using something called the separating axis theorem

http://gamedevelopment.tutsplus.com/tutorials/collision-detection-using-the-separating-axis-theorem--gamedev-169

One of the easiest types of collision is circular collision. All you need to know here is the position and radius of each circle.

You can calculate the distance between them by taking one position from the other and finding the magnitude of the resulting vector. If that distance is greater than the sum of each radius, then collision is impossible.

From this you should be able to figure out what system will work for you, but if you provide more details on the type of game, I might be able to give a better answer.

Good luck

actually i´m not working on a game...

I`m just trying to learn game programming with programming moving sprites and other techniques. I Will try to program a game when i`ve got enough experiance.

So i don`t have to ask such questions anymore^^

thanks for yor answer!

This topic is closed to new replies.

Advertisement