• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
cheese4432

Can't get sprite to rotate

10 posts in this topic

I have been following Beginning directx11 game programming by allen sherod and wendy jones and I'm trying to make an asteroids game. I've been able to get my ship sprite moving, but I can't get it to rotate. I've gathered that a rotation matrix needs to be multiplied with a translation and scale matrix, and that result is then used for rendering; but the sprite still doesn't rotate.

 

Here is the ship header:

struct VertexPos
{
    XMFLOAT3 pos;
    XMFLOAT2 tex0;
};

class Ship : public Dx11Base, SpriteBase
{
public:
	Ship();
	virtual ~Ship();

	bool LoadContent();
	void UnloadContent();

	void Update( float dt);
	void Render();

private:
		VertexPos vertices[6]; //a rectangle
        ID3D11VertexShader* solidColorVS_;
        ID3D11PixelShader* solidColorPS_;

        ID3D11InputLayout* inputLayout_;
        ID3D11Buffer* vertexBuffer_;

        ID3D11ShaderResourceView* colorMap_;
        ID3D11SamplerState* colorMapSampler_;
        ID3D11BlendState* alphaBlendState_;

	SpriteBase sprites_[2];
	ID3D11Buffer* mvpCB_;
	XMMATRIX vpMatrix_;

	float dy;
	float dx;
        float rotation;
};

update function, it gets the input:

#define SHIPSPEED 1.2f
#define SHIPACCEL 0.2f

void Ship::Update(float dt)
{
	XMFLOAT2 sprite0;
	sprite0.x = sprites_[0].getPositionX(); 
	sprite0.y = sprites_[0].getPositionY();
	

keyboardDevice_->GetDeviceState( sizeof( keyboardKeys_ ), ( LPVOID )&keyboardKeys_ );

    // Button press event.
    if( KEYDOWN( prevKeyboardKeys_, DIK_F ) && !KEYDOWN( keyboardKeys_, DIK_F ) )
	{ 
		dy = 0;
		dx = 0;
	}

    // Button up event.
	if( KEYDOWN( prevKeyboardKeys_, DIK_S ) && !KEYDOWN( keyboardKeys_, DIK_S ) )
	{ 
		dy -= SHIPACCEL;
		if (dy <= -SHIPSPEED)
		dy = -1.3f;
	}

    // Button up event.
	if( KEYDOWN( prevKeyboardKeys_, DIK_W ) && !KEYDOWN( keyboardKeys_, DIK_W ) )
	{ 
		dy += SHIPACCEL;
		if (dy >= SHIPSPEED)
		dy = 1.3f;
	}

	if( KEYDOWN( prevKeyboardKeys_, DIK_A ) && !KEYDOWN( keyboardKeys_, DIK_A ) )
	{ 
		dx -= SHIPACCEL;
		if (dx >= SHIPSPEED)
		dx = SHIPSPEED;
	}

	if( KEYDOWN( prevKeyboardKeys_, DIK_D ) && !KEYDOWN( keyboardKeys_, DIK_D ) )
	{ 
		dx += SHIPACCEL;
		if (dx <= -SHIPSPEED)
			dx = -SHIPSPEED;
	}

	if( KEYDOWN( prevKeyboardKeys_, DIK_Q ) && !KEYDOWN( keyboardKeys_, DIK_Q ) )
	{ 
		rotation -= 0.1f; 
	}

	if( KEYDOWN( prevKeyboardKeys_, DIK_E ) && !KEYDOWN( keyboardKeys_, DIK_E ) )
	{ 
		rotation += 0.1f;
	}

	if( BUTTONDOWN( mouseState_, 0 ) && !BUTTONDOWN( prevMouseState_, 0 ) ) 
    {
		 //fire!!!!
        ;
    }
 

    memcpy( prevKeyboardKeys_, keyboardKeys_, sizeof( keyboardKeys_ ) );
	 memcpy( &prevMouseState_, &mouseState_, sizeof( mouseState_ ) );
	
	 if (dy >= SHIPSPEED)
		dy = SHIPSPEED;
	else if (dy <= -SHIPSPEED)
		dy = -SHIPSPEED;
	if (dx >= SHIPSPEED)
		dx = SHIPSPEED;
	else if (dx <= -SHIPSPEED)
		dx = -SHIPSPEED;
	if (rotation >= 6.2)
		rotation = 6.2f;
	else if (rotation <= 0)
		rotation = 0.0f;

	/* mousePosX_ += mouseState_.lX;
    mousePosY_ += mouseState_.lY;
    mouseWheel_ += mouseState_.lZ;*/
	  setRotation(rotation);

	sprite0.y += dy;
	sprite0.x += dx;
	bool wrap = sprites_[0].wrap(sprite0);
	
	sprites_[0].setPosition(sprite0);
}

sprite base class:

class SpriteBase
{
public:
	SpriteBase();
	virtual ~SpriteBase();

	XMMATRIX GetWorldMatrix();

	void setPosition(XMFLOAT2 &position);
	void setRotation(float rotation);
	void setScale(XMFLOAT2 & scale);

	float getPositionX() { return position_.x;}
	float getPositionY() { return position_.y;}

	bool wrap(XMFLOAT2 &position);

private:
	XMFLOAT2 position_;
	float rotation_;
	XMFLOAT2 scale_;
};

the getWorldMatrix function, which should be causing the rotation:

XMMATRIX SpriteBase::GetWorldMatrix()
{
	XMMATRIX translation = XMMatrixTranslation(position_.x, position_.y, 0.0f);
	XMMATRIX rotationZ = XMMatrixRotationZ(rotation_);
	XMMATRIX scale = XMMatrixScaling(scale_.x, scale_.y, 1.0f);

	return rotationZ*translation*scale;
}

and the ship render function, which should be showing the rotated sprite:

void Ship::Render()
{
	if(d3dContext_ == 0)
		return;

	float clearColor[4] = {0.0f, 0.0f, 0.0f, 0.0f};
	d3dContext_->ClearRenderTargetView(backBufferTarget_, clearColor);

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

	d3dContext_->IASetInputLayout( inputLayout_);
	d3dContext_->IASetVertexBuffers(0, 1, &vertexBuffer_, &stride, &offset);
	d3dContext_->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

	d3dContext_->VSSetShader( solidColorVS_, 0, 0);
	d3dContext_->PSSetShader(solidColorPS_, 0, 0);
	d3dContext_->PSSetShaderResources(0, 1, &colorMap_);
	d3dContext_->PSSetSamplers(0, 1, &colorMapSampler_);


	XMMATRIX world = sprites_[0].GetWorldMatrix();
	XMMATRIX mvp = XMMatrixMultiply(world, vpMatrix_);
	mvp = XMMatrixTranspose(mvp);

	d3dContext_->UpdateSubresource( mvpCB_, 0, 0, &mvp, 0, 0 );
	d3dContext_->VSSetConstantBuffers(0, 1, &mvpCB_);

	d3dContext_->Draw(6, 0 );

	swapChain_->Present(0, 0);
}

I'm wondering what I need to change in order for the rotation to actually happen, as I'm lost on it.

Edited by cheese4432
0

Share this post


Link to post
Share on other sites

You are correct, it's because the vpMatrix_ was not being written, I have now applied the rotation matrix to it and it rotates counter clockwise, but not clockwise. It currently also rotates around the spawning position, however I think that applying the translation matrix will fix that.

0

Share this post


Link to post
Share on other sites

Here's the updated ship render function:

void Ship::Render()
{
	if(d3dContext_ == 0)
		return;

	float clearColor[4] = {0.0f, 0.0f, 0.0f, 0.0f};
	d3dContext_->ClearRenderTargetView(backBufferTarget_, clearColor);

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

	d3dContext_->IASetInputLayout( inputLayout_);
	d3dContext_->IASetVertexBuffers(0, 1, &vertexBuffer_, &stride, &offset);
	d3dContext_->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

	d3dContext_->VSSetShader( solidColorVS_, 0, 0);
	d3dContext_->PSSetShader(solidColorPS_, 0, 0);
	d3dContext_->PSSetShaderResources(0, 1, &colorMap_);
	d3dContext_->PSSetSamplers(0, 1, &colorMapSampler_);

	
	vpMatrix_ = vpMatrix_*XMMatrixRotationZ(rotation);
	XMMATRIX world = sprites_[0].GetWorldMatrix();
	XMMATRIX mvp = XMMatrixMultiply(world, vpMatrix_);
	mvp = XMMatrixTranspose(mvp);
	

	d3dContext_->UpdateSubresource( mvpCB_, 0, 0, &mvp, 0, 0 );
	d3dContext_->VSSetConstantBuffers(0, 1, &mvpCB_);

	d3dContext_->Draw(6, 0 );

	swapChain_->Present(0, 0);
}

and the new ship update function:

void Ship::Update(float dt)
{
	XMFLOAT2 sprite0;
	sprite0.x = sprites_[0].getPositionX(); 
	sprite0.y = sprites_[0].getPositionY();
	rotation = 0; //don't spin constantly

keyboardDevice_->GetDeviceState( sizeof( keyboardKeys_ ), ( LPVOID )&keyboardKeys_ );

    // Button press event.
    if( KEYDOWN( prevKeyboardKeys_, DIK_F ) && !KEYDOWN( keyboardKeys_, DIK_F ) )
	{ 
		dy = 0;
		dx = 0;
		rotation = 0;
	}

    // Button up event.
	if( KEYDOWN( prevKeyboardKeys_, DIK_S ))
	{ 
		dy -= SHIPACCEL;
		if (dy <= -SHIPSPEED)
		dy = -SHIPSPEED;
	}

    // Button up event.
	if( KEYDOWN( prevKeyboardKeys_, DIK_W ))
	{ 
		dy += SHIPACCEL;
		if (dy >= SHIPSPEED)
		dy = SHIPSPEED;
	}

	if( KEYDOWN( prevKeyboardKeys_, DIK_A ))
	{ 
		dx -= SHIPACCEL;
		if (dx >= SHIPSPEED)
		dx = SHIPSPEED;
	}

	if( KEYDOWN( prevKeyboardKeys_, DIK_D ))
	{ 
		dx += SHIPACCEL;
		if (dx <= -SHIPSPEED)
			dx = -SHIPSPEED;
	}

	if( KEYDOWN( prevKeyboardKeys_, DIK_Q ))
	{ 
		rotation = 0.004f; 
	}

	if( KEYDOWN( prevKeyboardKeys_, DIK_E ))
	{ 
		rotation = -0.004f;
	}

	if( BUTTONDOWN( mouseState_, 0 ) && !BUTTONDOWN( prevMouseState_, 0 ) ) 
    {
		 //fire!!!!
        ;
    }
 

    memcpy( prevKeyboardKeys_, keyboardKeys_, sizeof( keyboardKeys_ ) );
	 memcpy( &prevMouseState_, &mouseState_, sizeof( mouseState_ ) );
	
	 if (dy >= SHIPSPEED)
		dy = SHIPSPEED;
	else if (dy <= -SHIPSPEED)
		dy = -SHIPSPEED;
	if (dx >= SHIPSPEED)
		dx = SHIPSPEED;
	else if (dx <= -SHIPSPEED)
		dx = -SHIPSPEED;

	/* mousePosX_ += mouseState_.lX;
    mousePosY_ += mouseState_.lY;
    mouseWheel_ += mouseState_.lZ;*/
	  setRotation(rotation);

	sprite0.y += dy;
	sprite0.x += dx;
	bool wrap = sprites_[0].wrap(sprite0);
	
	sprites_[0].setPosition(sprite0);
}

I fixed the ship so that it can rotate clockwise and counter clockwise, I had an if statement that was resetting the rotation value to 0 when it was less than 0, not allowing counter clockwise rotations. However I still haven't got the sprite to rotate around its own origin and not its starting position.

0

Share this post


Link to post
Share on other sites
When you multiply the rotation matrix with the world matrix, try switching the order of the matrices.

XMMATRIX mvp = XMMatrixMultiply(vpMatrix_, world);
When multiplying matrices, remember that the matrix closer to the vertex gets applied first. For example.

transformedPoint = vertex * R * W

suppose R and W are matrices. R rotates, W is the existing world matrix. Notice how the vertex is next to R first then W. That means the rotation happens first, then any transformations found in W.
0

Share this post


Link to post
Share on other sites

So I tried that and my sprite disappeared :( .  So I changed:

vpMatrix_ = vpMatrix_*XMMatrixRotationZ(rotation);

to:

vpMatrix_ = XMMatrixRotationZ(rotation)*vpMatrix_;

and the sprite changed to rotating around the bottom left corner of the screen.

0

Share this post


Link to post
Share on other sites
Oops, sorry. I didn't notice that you are multiplying the rotation matrix by vpMatrix_ when you make it. Rotating in the bottom corner means you are rotating properly, you just need t properly apply the translation matrix. Just multiply what you have now with your translation matrix and that should do it. Just as a side note you generally multiply transformation matrices in this order.

result = vertex * ScaleMatrix * RotationMatrix * TranslationMatrix

That means you scale it in place first, rotate around its local origin, then move the origin of the sprite.
0

Share this post


Link to post
Share on other sites

If it is rotating in the wrong direction, why don't you rotate in the opposite direction.

0

Share this post


Link to post
Share on other sites

I've gotten the sprite to rotate the correct direction, but still around the wrong point, right now I have this:

vpMatrix_ = XMMatrixRotationZ(rotation)*vpMatrix_*XMMatrixTranslation(sprites_[0].getPositionX(), sprites_[0].getPositionY(), 0.0f);
XMMATRIX world = sprites_[0].GetWorldMatrix();
XMMATRIX mvp = XMMatrixMultiply(world, vpMatrix_);
mvp = XMMatrixTranspose(mvp);

in the render function. Multiplying the translation matrix in makes the sprite disappear, and I can't find where else I could multiply it in in order to apply especially since that should already be happening in the getWorldMatrix function.

0

Share this post


Link to post
Share on other sites

To have it rotate around a point you want to translate to the point first then perform the rotation and translated it back to his original position.

0

Share this post


Link to post
Share on other sites

So I want the sprite to rotate around its origin, at the moment it's rotating around the bottom left hand corner. right now I am modifying vpMatrix_ and the world matrix to move the sprite around. vpMatrix_ is created in my loadContent function which sets up the shaders and buffers for directx, and vpMatrix_ is created by the following:

XMMATRIX view = XMMatrixIdentity();
XMMATRIX projection = XMMatrixOrthographicOffCenterLH(0.0f, 800.0f, 0.0f, 600.0f, 0.1f, 100.0f);

vpMatrix_ = XMMatrixMultiply(view, projection);

Now as far as I know I want to modifying a matrix that the sprite is part of, but I don't have a matrix for the sprite. Should I make one? Right now the vertices of the sprite are stored in an array. And if I should make one what do I put in it, and how do I initialize it?

 

The array of vertices for the sprite goes as follows:

struct VertexPos
{
    XMFLOAT3 pos;
    XMFLOAT2 tex0;
};

VertexPos vertices[6]; //a rectangle

	ID3D11Resource* colorTex;
	colorMap_->GetResource( &colorTex);

	//ID3D11Texture2D
	 D3D11_TEXTURE2D_DESC colorTexDesc;
    ( ( ID3D11Texture2D* )colorTex )->GetDesc( &colorTexDesc );
	 float halfWidth = ( float )colorTexDesc.Width / 2.0f;
    float halfHeight = ( float )colorTexDesc.Height / 2.0f;
	colorTex->Release();

	/*VertexPos*/
	 vertices[0].pos = XMFLOAT3( halfWidth, halfHeight, 1.0f); vertices[0].tex0 =  XMFLOAT2(1.0f, 0.0f);		
	 vertices[1].pos =	XMFLOAT3(halfWidth, -halfHeight, 1.0f); vertices[1].tex0 = XMFLOAT2( 1.0f, 1.0f);
	 vertices[2].pos =	XMFLOAT3(-halfWidth, -halfHeight, 1.0f); vertices[2].tex0 = XMFLOAT2(0.0f, 1.0f);
	 vertices[3].pos =	XMFLOAT3(-halfWidth, -halfHeight, 1.0f); vertices[3].tex0 = XMFLOAT2(0.0f, 1.0f);
	 vertices[4].pos =	XMFLOAT3(-halfWidth, halfHeight, 1.0f); vertices[4].tex0 = XMFLOAT2(0.0f, 0.0f);
	 vertices[5].pos =	XMFLOAT3(halfWidth, halfHeight, 1.0f); vertices[5].tex0 = XMFLOAT2(1.0f, 0.0f);
0

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0