Jump to content

  • Log In with Google      Sign In   
  • Create Account

Banner advertising on our site currently available from just $5!


1. Learn about the promo. 2. Sign up for GDNet+. 3. Set up your advert!


Sprite rotation woes


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
17 replies to this topic

#1 Interminable   Members   -  Reputation: 127

Like
0Likes
Like

Posted 03 December 2011 - 10:42 AM

Hello there, I've registered in the hope of resolving some issues I've been having.

I've been working on teach myself how to code with DirectX etc.

To the point, I've been trying to make a 2D game. The time has come where I need to rotate sprites. It appears the way to do this is using D3DXMatrix, ID3DXSprite's SetTransform, with either D3DXMatrixRotationZ or D3DXMatrixTransformation2D.

I have tried both D3DXMatrixRotationZ and D3DXMatrixTransformation2D and have run in to problems with each.

With D3DXMatrixRotationZ, everything appears to rotate. All my walls, along with the player. In addition, it appears to rotate the axis as well; if I say, rotated my player 90 degrees clockwise and hit left, he would move down.

With D3DXMatrixTransformation2D, the above happens, but it also moves all the walls when I move the player as well, which is even worse.


As it was evident that SetTransform applied changes to EVERY sprite I had, I decided that it might be possible to set it to something else for each time I draw a sprite (I believe I 'could' use multiple ID3DXSprite objects, but I from what I've read I gather that would be highly inefficient and the wrong way to go about dealing with this).

So:


g_pD3DXSprite->Begin(D3DXSPRITE_ALPHABLEND);
		D3DXMatrixRotationZ(&player01.matrixRotation, player01.rotation);
		g_pD3DXSprite->SetTransform(&player01.matrixRotation);
		g_pD3DXSprite->Draw(player01.returnTexture(), NULL, new D3DXVECTOR3(0,0,0), &player01.coordinates, 0xffffffff);

		if(!walls.empty())
		{
			for(unsigned int i=0;i<=walls.size()-1;i++)
			{
				if(g_pD3DXSprite && walls[i].texture)
				{
					D3DXMatrixRotationZ(&walls[i].matrixRotation, 0.0);
					g_pD3DXSprite->SetTransform(&walls[i].matrixRotation);
					g_pD3DXSprite->Draw(walls[i].returnTexture(), NULL, new D3DXVECTOR3(0,0,0), &walls[i].coordinates, 0xffffffff);
				}
			}
		}
		g_pD3DXSprite->End();



Initially it looked promising, it drew the walls orientated in the right direction, and it appeared to draw the player rotated as I wanted it. However, it WAS rotating the wall, just not visibly. At this point I was tearing my hair out as it took me ages to get to that position. :P

So basically, the problems:
  • Rotating just one sprite, not every sprite.
  • Rotating a sprite visibly, but not its axis.

I would greatly appreciate any help and input. I can provide further code that I have if needed.

Thanks in advance. :)

Sponsor:

#2 ValMan   Members   -  Reputation: 466

Like
0Likes
Like

Posted 03 December 2011 - 08:48 PM

Looks like you are on the right path. The workflow for drawing rotated and non-rotated sprites is typically the following:

Begin Batch
Set Identity Transform (means no transform will take place)
Draw some non-transformed sprites...
End Batch

Begin Batch
Set Transform (matrix generated by RotationX, RotationY, RotationZ or Transformation2D functions in your case)
Draw some rotated or otherwise transformed sprites...
End Batch

Begin Batch
Set Identity Transform
Draw some non-transformed sprites...
End Batch

Here are the things you are missing:

1. Every time you change transform, you need to Begin/End a sprite batch before calling Sprite->SetTransform to set another transform. The way rendering works, a sprite batch will get drawn all at the same time (which is the whole point of sprite batching), with the last transform you set for that batch. Setting transform more than once for the same batch will not have any effect.

2. To "reset" a transform, you pass an identity matrix to SetTransform to cancel out any previous rotation, etc. D3DXMatrixIdentity will generate you an identity matrix. So in your case, call Sprite->Begin, set your transform matrix generated by D3DXMatrixRotationZ, draw player sprite, call Sprite->End, call Sprite->SetTransform passing identity matrix generated by D3DXMatrixIdentity, then Begin, then draw your walls, then End. This will draw the player sprite rotated and walls will be untransformed.

When rotating sprites, you also should be aware of the point you are rotating by, called pivot point or hot spot depending on terminology. If I remember correctly, D3DXSprite will generate its vertices so that any Z rotation applied will automatically rotate the sprite using center as the pivot point. However, if you should want to change this pivot point, you can do so with a Translation matrix generated by D3DXMatrixTranslation and then multiply that with RotationZ matrix to get a rotation about a different pivot point. The translation before rotation will be an offset from current pivot point to the new point.

The last thing I saw in your code is you are using new operator to pass D3DXVECTORs into Sprite->Draw method. If you are using C++ this will create a memory leak, so I recommend allocating the position vars on the stack and taking their address instead. Of course when you progress to the point of having a real game, your data structures for the walls and the player should already use D3DXVECTORs and you can just take an address of those.

For your walls you will probably not want to use transform matrices, because it will make collision detection more difficult later. If you represent your walls as AABBs internally (meaning x, y, width, height rectangle structure) drawing them will be more efficient and collision detection will be easier later on. If you still have problems, maybe post a screen or two. I don't know what "rotating the wall, but not visibly" means.

#3 Interminable   Members   -  Reputation: 127

Like
0Likes
Like

Posted 04 December 2011 - 12:12 AM

Looks like you are on the right path. The workflow for drawing rotated and non-rotated sprites is typically the following:

Begin Batch
Set Identity Transform (means no transform will take place)
Draw some non-transformed sprites...
End Batch

Begin Batch
Set Transform (matrix generated by RotationX, RotationY, RotationZ or Transformation2D functions in your case)
Draw some rotated or otherwise transformed sprites...
End Batch

Begin Batch
Set Identity Transform
Draw some non-transformed sprites...
End Batch

Here are the things you are missing:

1. Every time you change transform, you need to Begin/End a sprite batch before calling Sprite->SetTransform to set another transform. The way rendering works, a sprite batch will get drawn all at the same time (which is the whole point of sprite batching), with the last transform you set for that batch. Setting transform more than once for the same batch will not have any effect.

2. To "reset" a transform, you pass an identity matrix to SetTransform to cancel out any previous rotation, etc. D3DXMatrixIdentity will generate you an identity matrix. So in your case, call Sprite->Begin, set your transform matrix generated by D3DXMatrixRotationZ, draw player sprite, call Sprite->End, call Sprite->SetTransform passing identity matrix generated by D3DXMatrixIdentity, then Begin, then draw your walls, then End. This will draw the player sprite rotated and walls will be untransformed.

When rotating sprites, you also should be aware of the point you are rotating by, called pivot point or hot spot depending on terminology. If I remember correctly, D3DXSprite will generate its vertices so that any Z rotation applied will automatically rotate the sprite using center as the pivot point. However, if you should want to change this pivot point, you can do so with a Translation matrix generated by D3DXMatrixTranslation and then multiply that with RotationZ matrix to get a rotation about a different pivot point. The translation before rotation will be an offset from current pivot point to the new point.

The last thing I saw in your code is you are using new operator to pass D3DXVECTORs into Sprite->Draw method. If you are using C++ this will create a memory leak, so I recommend allocating the position vars on the stack and taking their address instead. Of course when you progress to the point of having a real game, your data structures for the walls and the player should already use D3DXVECTORs and you can just take an address of those.

For your walls you will probably not want to use transform matrices, because it will make collision detection more difficult later. If you represent your walls as AABBs internally (meaning x, y, width, height rectangle structure) drawing them will be more efficient and collision detection will be easier later on. If you still have problems, maybe post a screen or two. I don't know what "rotating the wall, but not visibly" means.


Well the only reason the walls have any transform stuff at all is because I was trying to 'reverse the changes' caused by the first transform functions used on the player. For the wall they don't do anything. I do not use transforms for positioning or movement. I use separate coordinates that are stored in the sprite objects I have.

Isn't spritebatch for XNA? Or is there something else I need to do?


Also are you basically saying that I should have multiple id3dSprite->Begin() and id3dSprite->End() function calls? Isn't that a bad thing to do? I thought I was only supposed to call Begin() and End() once per frame.

Also I was unaware of the memory leak thing. Do you have anything I could use to read up further on this?

Regards.


#4 ValMan   Members   -  Reputation: 466

Like
0Likes
Like

Posted 04 December 2011 - 01:47 AM

"Isn't spritebatch for XNA? Or is there something else I need to do?"

ID3DXSprite interface is used to render a sprite batch. This increases efficiency when sprites (each being 4 vertices and 2 triangle primitives) share the same texture, transform and shaders because all sprites that share these render options can be submited to video card in one Draw call (meaning DrawIndexedPrimitive). Sprite batches are also convenient because ID3DXSprite will sort your sprites within a batch by Z order or texture if you specify. For 2D games, you usually want both options on when drawing the world, and none when drawing UI. In your case, the player sprite does NOT share the same transform as the walls, so it cannot be drawn in the same batch since render states have to be set. Chances are, you are also using a different texture, in which case drawing player will break the batch no matter what.

3D games face exactly the same issues, and you start worrying about the number of batches you submit only when you find your performance unacceptable. I personally target 60 FPS with v-sync, and if my game runs at least at 59-60 on debug build I find no reason to worry about optimizing.

"Also are you basically saying that I should have multiple id3dSprite->Begin() and id3dSprite->End() function calls?"

Yes, let me correct my previous post - there is no need to end the batch by calling End() after every batch. End() will attempt to restore all render states on the device to values captured at the time of Begin() call, which is unnecessary until you finish all drawing for the frame. Call Flush() instead to submit current batch and change render states for the next batch. SetTransform may cause Flush() to be called automatically - I use a custom sprite class in my engine so I don't remember the nuts and bolts of D3DXSprite as well as I used to. In any case, make sure to set transform to identity matrix before drawing things that aren't supposed to be transformed, as opposed to using D3DXMatrixRotateZ with angle of 0.

"Also I was unaware of the memory leak thing. Do you have anything I could use to read up further on this?"

new operator in C++ will allocate an object on the heap. This object will remain allocated until you explicitly deallocate it with delete. If the object is never deallocated, this creates a memory leak - your program bit off a chunk of memory and never returned it back. This is especially problematic inside loops, such as this render loop. Every time the loop is run, a new D3DXVECTOR3 object is allocated to pass to Draw method, and never released. So every frame, you loose at least 24 bytes of heap memory (D3DXVECTOR3 takes at least 12 bytes and you have two heap allocations with new). With time, this will make your program run slower and then crash. Read about heap memory allocation and new/delete operators in C++.


#5 Interminable   Members   -  Reputation: 127

Like
0Likes
Like

Posted 04 December 2011 - 02:01 AM

Brief question, how I've set my D3DXVECTOR3 value in the Draw calls below is different, is it a right way to do things or is it still wrong (ie leaky)?


		g_pD3DXSprite->Begin(D3DXSPRITE_ALPHABLEND);
		D3DXMatrixRotationZ(&player01.matrixRotation, player01.rotation);
		g_pD3DXSprite->SetTransform(&player01.matrixRotation);
		g_pD3DXSprite->Draw(player01.returnTexture(), NULL, &D3DXVECTOR3(0,0,0), &player01.coordinates, 0xffffffff);

		if(!walls.empty())
		{
			for(unsigned int i=0;i<=walls.size()-1;i++)
			{
				if(g_pD3DXSprite && walls[i].texture)
				{
					D3DXMatrixIdentity(&walls[i].matrixRotation);
					g_pD3DXSprite->SetTransform(&walls[i].matrixRotation);
					g_pD3DXSprite->Draw(walls[i].returnTexture(), NULL, &D3DXVECTOR3(0,0,0), &walls[i].coordinates, 0xffffffff);
				}
			}
		}
		g_pD3DXSprite->End();


Calling D3DXMatrixIdentity before the drawing of each wall appears to draw them in the right place, but my collisions still don't work properly, it treats the walls as though they HAVE rotated, but visibly they appear normal.

Also is there any way to rotate a texture so that it doesn't affect the axis of the thing rotating?

EDIT: It might be possible the walls haven't rotated, but the axis of the world have!? I've realised that my collisions are currently broken the way they are because axis are not what they are supposed to be. ie y is no longer up or down. Is there any way I can preserve or restore axis after rotating like this?

#6 ValMan   Members   -  Reputation: 466

Like
0Likes
Like

Posted 04 December 2011 - 01:27 PM

Set identity transform only once before drawing all the walls, no need to set it for each wall.

How does your collision work?

What do you mean by rotating the thing and not its axes? You are not using a camera transform in your program, so no axis should be affected.

#7 Interminable   Members   -  Reputation: 127

Like
0Likes
Like

Posted 05 December 2011 - 06:02 AM

Set identity transform only once before drawing all the walls, no need to set it for each wall.

How does your collision work?

What do you mean by rotating the thing and not its axes? You are not using a camera transform in your program, so no axis should be affected.


Well, basically the way I move my player is, the sprite class stores its coordinates as members. I increment these when I move it, and then I draw the sprite at the appropriate location like this:

g_pD3DXSprite->Draw(player01.returnTexture(), NULL, &D3DXVECTOR3(0,0,0), &player01.coordinates, 0xffffffff);


When the sprite is rotated very slightly clockwise, if I want to move along the x axis in a positive direction, ie right, the sprite moves diagonally right and down, rather than just right. It's like what the sprite uses for its axis have changed. x is no longer a horizontal line.

My collision detection works using the size of the walls and player. ie the sprite's x coordinate plus its width, and its y coordinate plus its height. If I have a vertical wall, but its y axis is no longer vertical, then its collisions will be at an angle.

#8 Interminable   Members   -  Reputation: 127

Like
0Likes
Like

Posted 07 December 2011 - 02:45 AM

Sorry for the bump but I am very interested in resolving this, if anyone can help.

#9 ryan20fun   Members   -  Reputation: 1242

Like
0Likes
Like

Posted 08 December 2011 - 07:46 AM

i think this will solve your problem
Never say Never, Because Never comes too soon. - ryan20fun

Disclaimer: Each post of mine is intended as an attempt of helping and/or bringing some meaningfull insight to the topic at hand. Due to my nature, my good intentions will not always be plainly visible. I apologise in advance and assure you I mean no harm and do not intend to insult anyone.

#10 Interminable   Members   -  Reputation: 127

Like
0Likes
Like

Posted 09 December 2011 - 02:25 AM

i think this will solve your problem


Thanks for the reply. Unfortunately I've already read this, and it doesn't explain how to stop the sprite's axis from being transformed as well. Or rather, how to rotate the image of the sprite without altering how it interprets the world.

#11 ryan20fun   Members   -  Reputation: 1242

Like
0Likes
Like

Posted 09 December 2011 - 08:37 AM

this is the code from a method i use to draw my sprites:

D3DXMATRIX matRotate;
D3DXVECTOR2 center( Center.X , Center.Y );
D3DXVECTOR2 position( Position.X , Position.Y );
D3DXVECTOR2 scale( 1, 1 );
D3DXMatrixTransformation2D( &matRotate, NULL, NULL, &scale, &center, 0, &position);

PV_SpriteRenderer->SetTransform( &matRotate );

PV_SpriteRenderer->Draw( PV_Texture, pSrcRect, NULL, NULL, D3DCOLOR_XRGB( 255, 255, 255 ) );

D3DXMatrixRotationZ( &matRotate, 0 );
PV_SpriteRenderer->SetTransform( &matRotate );

does this help ?
Never say Never, Because Never comes too soon. - ryan20fun

Disclaimer: Each post of mine is intended as an attempt of helping and/or bringing some meaningfull insight to the topic at hand. Due to my nature, my good intentions will not always be plainly visible. I apologise in advance and assure you I mean no harm and do not intend to insult anyone.

#12 Interminable   Members   -  Reputation: 127

Like
0Likes
Like

Posted 09 December 2011 - 11:32 AM

this is the code from a method i use to draw my sprites:

D3DXMATRIX matRotate;
D3DXVECTOR2 center( Center.X , Center.Y );
D3DXVECTOR2 position( Position.X , Position.Y );
D3DXVECTOR2 scale( 1, 1 );
D3DXMatrixTransformation2D( &matRotate, NULL, NULL, &scale, &center, 0, &position);

PV_SpriteRenderer->SetTransform( &matRotate );

PV_SpriteRenderer->Draw( PV_Texture, pSrcRect, NULL, NULL, D3DCOLOR_XRGB( 255, 255, 255 ) );

D3DXMatrixRotationZ( &matRotate, 0 );
PV_SpriteRenderer->SetTransform( &matRotate );

does this help ?


Unfortunately not. The code achieves what I already have. Everything is drawn in the right position, the sprite appears rotated, the walls appear the right way up, BUT the axis for the world seem to be rotated in some way. When I hold right to move right, the sprite moves diagonally towards the bottom left if I have rotated a bit clockwise.

There has to be a simple answer to this, there must be something obvious I'm doing wrong here. Is how I am doing my movement wrong? I have my sprite store in a D3DXVECTOR3, it's x and y coordinates (z is there in case I wanted to do layers or some such, but it's just 0, this is why I do player01.coordinates.x, etc). When I hold right, I increment that value by a speed variable. I then draw my sprite using this:

g_pD3DXSprite->Draw(player01.returnTexture(), NULL, &D3DXVECTOR3(0,0,0), &player01.coordinates, 0xffffffff);

What AM I doing wrong? Should I be using something other than ID3DXSprite to draw my sprites? Is there another way? Do I need to find out how to write some new different way of drawing images to the screen in a way that doesn't transform their axis?

#13 ryan20fun   Members   -  Reputation: 1242

Like
0Likes
Like

Posted 09 December 2011 - 12:24 PM

Do I need to find out how to write some new different way of drawing images to the screen

you will end up building a "customized" version of ID3DXSprite.

drawing images to the screen in a way that doesn't transform their axis?


can you post screenshots ?

Unfortunately not. The code achieves what I already have. Everything is drawn in the right position, the sprite appears rotated, the walls appear the right way up, BUT the axis for the world seem to be rotated in some way. When I hold right to move right, the sprite moves diagonally towards the bottom left if I have rotated a bit clockwise.

There has to be a simple answer to this, there must be something obvious I'm doing wrong here. Is how I am doing my movement wrong? I have my sprite store in a D3DXVECTOR3, it's x and y coordinates (z is there in case I wanted to do layers or some such, but it's just 0, this is why I do player01.coordinates.x, etc). When I hold right, I increment that value by a speed variable. I then draw my sprite using this:

g_pD3DXSprite->Draw(player01.returnTexture(), NULL, &D3DXVECTOR3(0,0,0), &player01.coordinates, 0xffffffff);


the code fragment you posted looks alright.
can you post more complete code that shows how you "move" your sprite ?

because if i take a stab at this in the dark( without looking at your player movement code ) i would say you need to use somethin like this:
yPosition += cos(RotationInDegrees) * speed;
xPosition += sin(RotationInDegrees) * speed;

Never say Never, Because Never comes too soon. - ryan20fun

Disclaimer: Each post of mine is intended as an attempt of helping and/or bringing some meaningfull insight to the topic at hand. Due to my nature, my good intentions will not always be plainly visible. I apologise in advance and assure you I mean no harm and do not intend to insult anyone.

#14 Interminable   Members   -  Reputation: 127

Like
0Likes
Like

Posted 09 December 2011 - 01:33 PM

the code fragment you posted looks alright.
can you post more complete code that shows how you "move" your sprite ?

because if i take a stab at this in the dark( without looking at your player movement code ) i would say you need to use somethin like this:

yPosition += cos(RotationInDegrees) * speed;
xPosition += sin(RotationInDegrees) * speed;


So the answer to my question is that I can't stop it from transforming the axis, I have to compensate for it when moving after rotation?

Here is the code for movement and collision detection:


VOID UpdateSpritePosition(LPDIRECT3DTEXTURE9 texture, float xSpeedInput, float ySpeedInput)
{
	D3DSURFACE_DESC spriteDesc;
	D3DSURFACE_DESC wallDesc;
	int spriteWidth = 0;
	int spriteHeight = 0;

	int wallWidth = 0;
	int wallHeight = 0;

	texture->GetLevelDesc(0,&spriteDesc);
	spriteWidth = spriteDesc.Width;
	spriteHeight = spriteDesc.Height;
	float xDistance = 0;
	float yDistance = 0;

	if(!walls.empty())
	{
		for(unsigned int i = 0;i<=walls.size()-1;i++)
		{
			walls[i].texture->GetLevelDesc(0,&wallDesc);
			wallWidth = wallDesc.Width;
			wallHeight = wallDesc.Height;
			bool testCorners = false;
			
			if(player01.coordinates.x == walls[i].coordinates.x+wallWidth &&
				player01.coordinates.y == walls[i].coordinates.y+wallHeight)
			{
				testCorners = true;
			}

			else if(player01.coordinates.x+spriteWidth == walls[i].coordinates.x &&
			player01.coordinates.y == walls[i].coordinates.y+wallHeight)
			{
				testCorners = true;
			}

			else if(player01.coordinates.x + spriteWidth == walls[i].coordinates.x &&
				player01.coordinates.y + spriteHeight == walls[i].coordinates.y)
			{
				testCorners = true;
			}

			else if(player01.coordinates.x == walls[i].coordinates.x + wallWidth &&
			player01.coordinates.y +spriteHeight == walls[i].coordinates.y)
			{
				testCorners = true;
			}

			if(testCorners == false)
			{
				if((player01.coordinates.x+spriteWidth) <= walls[i].coordinates.x && (player01.coordinates.y+spriteHeight) >= walls[i].coordinates.y && player01.coordinates.y <= (walls[i].coordinates.y+wallHeight))
				{
					if((player01.coordinates.x + spriteWidth + xSpeedInput) >= walls[i].coordinates.x)
					{
						xDistance = walls[i].coordinates.x - (player01.coordinates.x + spriteWidth);
						xSpeedInput = xDistance;
					}
				}
				else if(player01.coordinates.x >= (walls[i].coordinates.x + wallWidth) && player01.coordinates.y <= (walls[i].coordinates.y+wallHeight) && (player01.coordinates.y+spriteHeight) >= walls[i].coordinates.y)
				{
					if((player01.coordinates.x + xSpeedInput) <= (walls[i].coordinates.x + wallWidth))
					{
						xDistance = (walls[i].coordinates.x + wallWidth) - player01.coordinates.x;
						xSpeedInput = xDistance;
					}
				}

				if((player01.coordinates.y+spriteWidth) <= walls[i].coordinates.y && (player01.coordinates.x+spriteWidth) >= walls[i].coordinates.x && player01.coordinates.x <= (walls[i].coordinates.x+wallWidth))                {
					if((player01.coordinates.y + spriteHeight + ySpeedInput) >= walls[i].coordinates.y)
					{
						yDistance = walls[i].coordinates.y - (player01.coordinates.y + spriteHeight);
						ySpeedInput = yDistance;
					}
				}
			
				else if(player01.coordinates.y >= (walls[i].coordinates.y + wallHeight) && player01.coordinates.x <= (walls[i].coordinates.x+wallWidth) && (player01.coordinates.x+spriteWidth) >= walls[i].coordinates.x)
				{
					if((player01.coordinates.y + ySpeedInput) <= (walls[i].coordinates.y + wallHeight))
					{
						yDistance = (walls[i].coordinates.y + wallHeight) - player01.coordinates.y;
						ySpeedInput = yDistance;
					}
				}
			}
		}
	}

	if(PacmanMovementModeEnabled)
	{
		player01.coordinates.x += xSpeedInput;
		player01.xSpeed = xSpeedInput;
		player01.coordinates.y += ySpeedInput;
		player01.ySpeed = ySpeedInput;
		player01.PacmanSpeed();
	}
	else
	{
		player01.coordinates.x += xSpeedInput;
		player01.coordinates.y += ySpeedInput;
	}
}


#15 ryan20fun   Members   -  Reputation: 1242

Like
0Likes
Like

Posted 09 December 2011 - 11:33 PM


the code fragment you posted looks alright.
can you post more complete code that shows how you "move" your sprite ?

because if i take a stab at this in the dark( without looking at your player movement code ) i would say you need to use somethin like this:

yPosition += cos(RotationInDegrees) * speed;
xPosition += sin(RotationInDegrees) * speed;


So the answer to my question is that I can't stop it from transforming the axis, I have to compensate for it when moving after rotation?


no, that is supposed to move the player in a relative forward / backward direction.

Here is the code for movement and collision detection:


VOID UpdateSpritePosition(LPDIRECT3DTEXTURE9 texture, float xSpeedInput, float ySpeedInput)
{
	D3DSURFACE_DESC spriteDesc;
	D3DSURFACE_DESC wallDesc;
	int spriteWidth = 0;
	int spriteHeight = 0;

	int wallWidth = 0;
	int wallHeight = 0;

	texture->GetLevelDesc(0,&spriteDesc);
	spriteWidth = spriteDesc.Width;
	spriteHeight = spriteDesc.Height;
	float xDistance = 0;
	float yDistance = 0;

	if(!walls.empty())
	{
		for(unsigned int i = 0;i<=walls.size()-1;i++)
		{
			walls[i].texture->GetLevelDesc(0,&wallDesc);
			wallWidth = wallDesc.Width;
			wallHeight = wallDesc.Height;
			bool testCorners = false;
			
			if(player01.coordinates.x == walls[i].coordinates.x+wallWidth &&
				player01.coordinates.y == walls[i].coordinates.y+wallHeight)
			{
				testCorners = true;
			}

			else if(player01.coordinates.x+spriteWidth == walls[i].coordinates.x &&
			player01.coordinates.y == walls[i].coordinates.y+wallHeight)
			{
				testCorners = true;
			}

			else if(player01.coordinates.x + spriteWidth == walls[i].coordinates.x &&
				player01.coordinates.y + spriteHeight == walls[i].coordinates.y)
			{
				testCorners = true;
			}

			else if(player01.coordinates.x == walls[i].coordinates.x + wallWidth &&
			player01.coordinates.y +spriteHeight == walls[i].coordinates.y)
			{
				testCorners = true;
			}

			if(testCorners == false)
			{
				if((player01.coordinates.x+spriteWidth) <=  walls[i].coordinates.x && (player01.coordinates.y+spriteHeight)  >= walls[i].coordinates.y && player01.coordinates.y <=  (walls[i].coordinates.y+wallHeight))
				{
					if((player01.coordinates.x + spriteWidth + xSpeedInput) >= walls[i].coordinates.x)
					{
						xDistance = walls[i].coordinates.x - (player01.coordinates.x + spriteWidth);
						xSpeedInput = xDistance;
					}
				}
				else if(player01.coordinates.x >=  (walls[i].coordinates.x + wallWidth) && player01.coordinates.y  <= (walls[i].coordinates.y+wallHeight) &&  (player01.coordinates.y+spriteHeight) >= walls[i].coordinates.y)
				{
					if((player01.coordinates.x + xSpeedInput) <= (walls[i].coordinates.x + wallWidth))
					{
						xDistance = (walls[i].coordinates.x + wallWidth) - player01.coordinates.x;
						xSpeedInput = xDistance;
					}
				}

				if((player01.coordinates.y+spriteWidth) <=  walls[i].coordinates.y && (player01.coordinates.x+spriteWidth)  >= walls[i].coordinates.x && player01.coordinates.x <=  (walls[i].coordinates.x+wallWidth))                {
					if((player01.coordinates.y + spriteHeight + ySpeedInput) >= walls[i].coordinates.y)
					{
						yDistance = walls[i].coordinates.y - (player01.coordinates.y + spriteHeight);
						ySpeedInput = yDistance;
					}
				}
			
				else if(player01.coordinates.y >=  (walls[i].coordinates.y + wallHeight) && player01.coordinates.x  <= (walls[i].coordinates.x+wallWidth) &&  (player01.coordinates.x+spriteWidth) >= walls[i].coordinates.x)
				{
					if((player01.coordinates.y + ySpeedInput) <= (walls[i].coordinates.y + wallHeight))
					{
						yDistance = (walls[i].coordinates.y + wallHeight) - player01.coordinates.y;
						ySpeedInput = yDistance;
					}
				}
			}
		}
	}

	if(PacmanMovementModeEnabled)
	{
		player01.coordinates.x += xSpeedInput;
		player01.xSpeed = xSpeedInput;
		player01.coordinates.y += ySpeedInput;
		player01.ySpeed = ySpeedInput;
		player01.PacmanSpeed();
	}
	else
	{
		player01.coordinates.x += xSpeedInput;
		player01.coordinates.y += ySpeedInput;
	}
}

it looks okey.

the sprite rendering code, how much of it did you try ?
did you try all of it ?
Never say Never, Because Never comes too soon. - ryan20fun

Disclaimer: Each post of mine is intended as an attempt of helping and/or bringing some meaningfull insight to the topic at hand. Due to my nature, my good intentions will not always be plainly visible. I apologise in advance and assure you I mean no harm and do not intend to insult anyone.

#16 Interminable   Members   -  Reputation: 127

Like
0Likes
Like

Posted 10 December 2011 - 03:56 AM

the sprite rendering code, how much of it did you try ?
did you try all of it ?


I did alter it slightly based on variables I already had, etc.

g_pD3DXSprite->Begin(D3DXSPRITE_ALPHABLEND);
D3DXVECTOR2 scale(1,1);
D3DXMatrixTransformation2D(&player01.matrixRotation, NULL, NULL, &scale, &D3DXVECTOR2(0,0), 0.5, &D3DXVECTOR2(player01.coordinates.x, player01.coordinates.y));
g_pD3DXSprite->SetTransform(&player01.matrixRotation);
g_pD3DXSprite->Draw(player01.returnTexture(), NULL, &D3DXVECTOR3(0,0,0), &player01.coordinates, 0xffffffff);

if(!walls.empty())
{
	for(unsigned int i=0;i<=walls.size()-1;i++)
	{
		if(g_pD3DXSprite && walls[i].texture)
		{				
			D3DXMatrixRotationZ(&walls[i].matrixRotation, 0.0);		
			g_pD3DXSprite->SetTransform(&walls[i].matrixRotation);
			g_pD3DXSprite->Draw(walls[i].returnTexture(), NULL, &D3DXVECTOR3(0,0,0), &walls[i].coordinates, 0xffffffff);
		}
	}
}
g_pD3DXSprite->End();


#17 ryan20fun   Members   -  Reputation: 1242

Like
0Likes
Like

Posted 10 December 2011 - 05:47 AM


the sprite rendering code, how much of it did you try ?
did you try all of it ?


I did alter it slightly based on variables I already had, etc.

g_pD3DXSprite->Begin(D3DXSPRITE_ALPHABLEND);
D3DXVECTOR2 scale(1,1);
D3DXMatrixTransformation2D(&player01.matrixRotation, NULL, NULL, &scale, &D3DXVECTOR2(0,0), 0.5, &D3DXVECTOR2(player01.coordinates.x, player01.coordinates.y));
g_pD3DXSprite->SetTransform(&player01.matrixRotation);
g_pD3DXSprite->Draw(player01.returnTexture(), NULL, &D3DXVECTOR3(0,0,0), &player01.coordinates, 0xffffffff);

if(!walls.empty())
{
	for(unsigned int i=0;i<=walls.size()-1;i++)
	{
		if(g_pD3DXSprite && walls[i].texture)
		{				
			D3DXMatrixRotationZ(&walls[i].matrixRotation, 0.0);		
			g_pD3DXSprite->SetTransform(&walls[i].matrixRotation);
			g_pD3DXSprite->Draw(walls[i].returnTexture(), NULL, &D3DXVECTOR3(0,0,0), &walls[i].coordinates, 0xffffffff);
		}
	}
}
g_pD3DXSprite->End();


on a hunch, can you try this instead ?
g_pD3DXSprite->Begin(D3DXSPRITE_ALPHABLEND);
D3DXVECTOR2 scale(1,1);
D3DXMatrixTransformation2D(&player01.matrixRotation, NULL, NULL, &scale, &D3DXVECTOR2(0,0), 0.5, &D3DXVECTOR2(player01.coordinates.x, player01.coordinates.y));
g_pD3DXSprite->SetTransform(&player01.matrixRotation);
[b]g_pD3DXSprite->Draw(player01.returnTexture(), NULL, NULL, NULL, 0xffffffff);[/b]

if(!walls.empty())
{
	for(unsigned int i=0;i<=walls.size()-1;i++)
	{
    	if(g_pD3DXSprite && walls[i].texture)
    	{       		
	       [b] D3DXMatrixTransformation2D(&walls[i].matrixRotation, NULL, NULL, &scale, &D3DXVECTOR2(0,0), 0.5, &D3DXVECTOR2(walls[i].coordinates.x, walls[i].coordinates.y));
        	g_pD3DXSprite->SetTransform(&walls[i].matrixRotation);
			g_pD3DXSprite->Draw(walls[i].returnTexture(), NULL, NULL, NULL, 0xffffffff);[/b]
    	}
	}
}
g_pD3DXSprite->End();

Never say Never, Because Never comes too soon. - ryan20fun

Disclaimer: Each post of mine is intended as an attempt of helping and/or bringing some meaningfull insight to the topic at hand. Due to my nature, my good intentions will not always be plainly visible. I apologise in advance and assure you I mean no harm and do not intend to insult anyone.

#18 Interminable   Members   -  Reputation: 127

Like
0Likes
Like

Posted 10 December 2011 - 06:31 AM



the sprite rendering code, how much of it did you try ?
did you try all of it ?


I did alter it slightly based on variables I already had, etc.

g_pD3DXSprite->Begin(D3DXSPRITE_ALPHABLEND);
D3DXVECTOR2 scale(1,1);
D3DXMatrixTransformation2D(&player01.matrixRotation, NULL, NULL, &scale, &D3DXVECTOR2(0,0), 0.5, &D3DXVECTOR2(player01.coordinates.x, player01.coordinates.y));
g_pD3DXSprite->SetTransform(&player01.matrixRotation);
g_pD3DXSprite->Draw(player01.returnTexture(), NULL, &D3DXVECTOR3(0,0,0), &player01.coordinates, 0xffffffff);

if(!walls.empty())
{
	for(unsigned int i=0;i<=walls.size()-1;i++)
	{
		if(g_pD3DXSprite && walls[i].texture)
		{				
			D3DXMatrixRotationZ(&walls[i].matrixRotation, 0.0);		
			g_pD3DXSprite->SetTransform(&walls[i].matrixRotation);
			g_pD3DXSprite->Draw(walls[i].returnTexture(), NULL, &D3DXVECTOR3(0,0,0), &walls[i].coordinates, 0xffffffff);
		}
	}
}
g_pD3DXSprite->End();


on a hunch, can you try this instead ?
g_pD3DXSprite->Begin(D3DXSPRITE_ALPHABLEND);
D3DXVECTOR2 scale(1,1);
D3DXMatrixTransformation2D(&player01.matrixRotation, NULL, NULL, &scale, &D3DXVECTOR2(0,0), 0.5, &D3DXVECTOR2(player01.coordinates.x, player01.coordinates.y));
g_pD3DXSprite->SetTransform(&player01.matrixRotation);
[b]g_pD3DXSprite->Draw(player01.returnTexture(), NULL, NULL, NULL, 0xffffffff);[/b]

if(!walls.empty())
{
	for(unsigned int i=0;i<=walls.size()-1;i++)
	{
    	if(g_pD3DXSprite && walls[i].texture)
    	{   			
   		[b] D3DXMatrixTransformation2D(&walls[i].matrixRotation, NULL, NULL, &scale, &D3DXVECTOR2(0,0), 0.5, &D3DXVECTOR2(walls[i].coordinates.x, walls[i].coordinates.y));
        	g_pD3DXSprite->SetTransform(&walls[i].matrixRotation);
			g_pD3DXSprite->Draw(walls[i].returnTexture(), NULL, NULL, NULL, 0xffffffff);[/b]
    	}
	}
}
g_pD3DXSprite->End();


I had to alter the advice in your example slightly (I don't want to rotate my walls, an obvious copy-paste from the first D3DXMatrixTransformation2D() line, but that's no big problem :P ), and I had to remove the bold BBcode tags as they don't work inside code tags but....it worked! :D

My collision detection seems to be a little off due to the rotation center not being the center, but I'll fix that, but it does now at least move in the right direction when rotated!

Many thanks for helping me with this, although I am curious as to why this issue occurred. It seems to be caused exclusively by setting the coordinates to draw the sprite in the ID3DXDraw() function, rather than leaving it all up to the ID3DXSprite object. As I am daft, I for some reason didn't make the connection that as I was applying the matrices with the coordinates of the sprite to the ID3DXSprite object, I was providing it with coordinates to draw it already. Still, I don't quite understand the behaviour that resulted...




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS