Mouse controlled spaceship and chase cam. [SOLVED]

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
Catprog
Posts: 164
Joined: Wed Jan 31, 2007 9:07 am
Contact:

Mouse controlled spaceship and chase cam. [SOLVED]

Post by Catprog »

I am trying to set up a spaceship where it turns via the mouse cursor.

The mouse cursor is meant to act as a sort of joystick. Ie the further left the cursor is , the faster the ship turns.

The camera is parented to the ship and is a bit behind the ship.

My current attempt makes the ship go in loops a lot.


This is in the draw loop

Code: Select all

		position2d<irr::s32> mousePos = device->getCursorControl()->getPosition();


		if(mousePos.X  > screenSize.Width){mousePos.X  = screenSize.Width;}
		if(mousePos.Y  > screenSize.Height){mousePos.Y  = screenSize.Height;}
		if(mousePos.X  <0){mousePos.X  = 0;}
		if(mousePos.Y  <0){mousePos.Y  = 0;}

		float yPerCent = (mousePos.X - screenSize.Width/2 )  *2  ;
		float zPerCent = (mousePos.Y - screenSize.Height/2) * 2 ;

		yPerCent /=  screenSize.Width; 

		yPerCent *=45;



		zPerCent /=  screenSize.Height;		
		zPerCent *=-45;

		//if (zPerCent < 0){ yPerCent = yPerCent + zPerCent * 2; } //Flip for the bottem part of the screen

		
		core::stringw str 
			   = yPerCent;
			str += " ";
			str += zPerCent;
			device->setWindowCaption(str.c_str());
		
		core::vector3df curRot = myNode->getRotation() ; 

		myNode->setRotation(core::vector3df(zPerCent/120.0,yPerCent/120.0,0)); 
Yes I know the ship rotation speed depends on the frame rate but once I get it working I will then fix that part.
Last edited by Catprog on Fri Jan 25, 2008 12:04 am, edited 1 time in total.
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

Your code seems sound up to the last line. You appear to be setting the rotation to a value that only changes as the mouse position changes. If I understand you correctly, you want the node to continue to rotate right as long as the mouse is near the right edge of the window.

I haven't tested this yet, but I'm pretty sure it does what you want. You need to calculate the elapsed frame time elapsedSeconds, and you may need to invert the Y offset.

Code: Select all

#if 0
// this block will continue to rotate node when mouse is outside window
core::position2df relativePosition (cursor->getRelativePosition()); 

// the values returned by getRelativePosition() are supposed to be
// clamped to (0, 0) and (1, 1), but they aren't. do that here.
relativePosition.X = core::clamp (relativePosition.X, 0.f, 1.f);
relativePosition.Y = core::clamp (relativePosition.Y, 0.f, 1.f);
{
#else
// this block will not rotate node when mouse is outside window
const core::position2di mousePosition = cursor->getPosition();
const core::dimension2di windowSize = driver->getCurrentRenderTargetSize();

if ((0 < mousePosition.X && mousePosition.X < windowSize.Width) &&
    (0 < mousePosition.Y && mousePosition.Y < windowSize.Height))
{
  // fractional screen position, upper left is (0, 0) and lower right is (1, 1) 
  const core::vector2df relativePosition (1.f * mousePosition.X / windowSize.Width,
                                          1.f * mousePosition.Y / windowSize.Height);
#endif

  // use a vector2d to simplify some of the code below
  const core::vector2df rotateFactor0to1 (relativePosition.X, 1.f - relativePosition.Y); 

  // lerp from [0-1] to [-1, 1] 
  core::vector2df rotateFactorM1toP1 ((rotateFactor0to1 * 2.f) - 1.f); 

  // apply a factor to accelerate rotation near edges of screen slightly 
  rotateFactorM1toP1.X = powf (rotateFactorM1toP1.X, 3); 
  rotateFactorM1toP1.Y = powf (rotateFactorM1toP1.Y, 3); 

  // clamp that to .01 so rotation stops near center of screen 
  if (fabs (rotateFactorM1toP1.X) < .01f) 
      rotateFactorM1toP1.X = 0.f;
  if (fabs (rotateFactorM1toP1.Y) < .01f) 
      rotateFactorM1toP1.Y = 0.f; 

  const core::vector2df rotateSpeed (180.f, 180.f); 
  const core::vector2df rotateDelta (rotateFactorM1toP1 * (rotateSpeed * elapsedSeconds)); 

  // now apply the rotation delta 
  core::vector3df rotation = node->getRotation (); 

  // not a typo. up/down in screen coordinates [the Y axis] 
  // is a rotation on the X axis. 
  rotation.X -= rotateDelta.Y; 
  rotation.Y += rotateDelta.X; 

  // keep angles between -180 and 180 to make it readable for debugging
  while (180.f < rotation.X)
    rotation.X -= 360.f;
  while (rotation.X < 180.f)
    rotation.X += 360.f;

  while (180.f < rotation.Y)
    rotation.Y -= 360.f;
  while (rotation.Y < 180.f)
    rotation.Y += 360.f;

  node->setRotation (rotation); 
}
Travis
Last edited by vitek on Mon Jan 21, 2008 7:51 pm, edited 2 times in total.
sfncook
Posts: 36
Joined: Sun Jul 01, 2007 6:32 pm

Post by sfncook »

What do you mean by "goes in loops"? Is it rotating too fast? Is it only rotating in one direction? Does it not stop spinning?
Catprog
Posts: 164
Joined: Wed Jan 31, 2007 9:07 am
Contact:

Post by Catprog »

vitek wrote:Your code seems sound up to the last line. You appear to be setting the rotation to a value that only changes as the mouse position changes. If I understand you correctly, you want the node to continue to rotate right as long as the mouse is near the right edge of the window.

If you multiple a negative by a negative (pow 2) you get a positive and thus no left or up.

The ship rotates up and down on Z not X .

Those were the only problems with the code (except for a few misnamed variables).

The control works with a fixed camera now.

The major problem is getting a chase camera working in this arrangement. (parenting it to the back of the ship does not work well with this control scheme. The angles do not go back and thus they cause a slight problem. I have no y but it goes up and down. Also when it goes up or down a certain amount the ship flips and the y is inverted. )


Thanks for you help with getting me to this point anyway.
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

If you multiple a negative by a negative (pow 2) you get a positive and thus no left or up.
Whoops! I knew I started out with a cube in there for a reason...
The ship rotates up and down on Z not X.
Usually the Z axis points forward, the Y axis up, and the X axis to the side. Up and down on the screen would be the Y axis on screen, and a rotation on the X axis in 3D. Left and right is the X axis on screen, but the Y axis in 3D. I've now tested this, and it does work correctly.
I have no y but it goes up and down. Also when it goes up or down a certain amount the ship flips and the y is inverted. )
The Y axis is the yaw rotation. With no Y, you will have X and Z, so your ship will pitch and roll.

I've updated the code above for those who care.

Travis
Catprog
Posts: 164
Joined: Wed Jan 31, 2007 9:07 am
Contact:

Post by Catprog »

vitek wrote:
If you multiple a negative by a negative (pow 2) you get a positive and thus no left or up.
Whoops! I knew I started out with a cube in there for a reason...
The ship rotates up and down on Z not X.
Usually the Z axis points forward, the Y axis up, and the X axis to the side. Up and down on the screen would be the Y axis on screen, and a rotation on the X axis in 3D. Left and right is the X axis on screen, but the Y axis in 3D. I've now tested this, and it does work correctly.
My ship is the reverse with respect to Z and X.
vitek wrote:
I have no y but it goes up and down. Also when it goes up or down a certain amount the ship flips and the y is inverted. )
The Y axis is the yaw rotation. With no Y, you will have X and Z, so your ship will pitch and roll.

I've updated the code above for those who care.

Travis

I have managed to get a camera by itself working except the Y axis inverts at 90 and 270 degrees. (trying to figure out to invert the screen)
Post Reply