Перемещение и повороты
  В статье будут рассмотрены двухмерные и трехмерные случаи перемещения и поворотов. Начну я, пожалуй, с очень важной функции - приведение длинны вектора к единичной.


Vector Normalize( Vector vInc )
{
	Vector	vRes = vInc;

	// Вычисление длины вектора 
	float	fLen = sqrt( vInc.x * vInc.x + vInc.y * vInc.y + vInc.z * vInc.z );
	
	// Нормализация вектора, то есть длина вектора становится единичной 
	vRes.x /= fLen;
	vRes.y /= fLen;
	vRes.z /= fLen;

	// Возвращение результата 
	return vRes;
}

  Для двухмерного случая координату z просто нужно опустить. В данном примере функция существует сама по себе, но лучше ее включить в класс для работы с векторами.   Перемещение и поворот можно реализовать разными способами, я рассмотрю несколько. Допустим существует переменная fAngle, в которой хранится угол поворота персонажа. Этот угол можно менять, например, при нажатии на клавиши VK_LEFT, VK_RIGHT, либо на любые другие. Тогда при нажатии на VK_UP, VK_DOWN, персонаж должен двигаться вперед либо назад, с учетом угла поворота. Это легко реализуемо.


	VK_LEFT:	// Персонаж поворачивается налево
	...
	fAngle += 0.1f;	// Изменение угла, значение может быть любым
	...

	VK_RIGHT:	// Персонаж поворачивается направо
	...
	fAngle -= 0.1f;
	...

	VK_UP:		// Персонаж идет вперед
	...
	Player.x += cos( fAngle );
	Player.y += sin( fAngle );
	...

	VK_DOWN:	// Персонаж идет назад
	...
	Player.x -= cos( fAngle );
	Player.y -= sin( fAngle );
	...

  Так же угол fAngle, можно менять с помощью движений мыши, при всем этом сам процесс перемещения остается неизменным. Для этого поэкспериментируйте с функциями GetCursorPos( POINT ), SetCursorPos( int, int ). Эти функции будут востребованы, при работе в трехмерном пространстве.   Но что делать если мы мышкой управляем положением точки, в которую игрок должен постоянно быть направлен? Я столкнулся с этой проблемой, при разработке игры RedGutS, и решил ее там довольно странным способом. Можно конечно находить угол при помощи функции арксинуса или аркосинуса, но это слишком громоздко и медленно, в своей игре я сделал так - поворачивал единичный вектор( vDir ) на определенный угол, до тех пор, пока косинус угла между vDir и вектором, разности координат точки направления и игрока, не стал приблизительно равным 1. Такой способ можно использовать для плавного поворота игроков, но есть более простой способ( я не испытывал его ), направление вычисляется очень просто:


	Vector		vDir;	// Направление игрока
	Vector		vPlr;	// Координаты игрока
	Vector		vTar;	// Координаты точки направления
	
	vDir.x = vTar.x - vPlr.x;
	vDir.y = vTar.y - vPlr.y;

	vDir = Normalize( vDir );	// Вот мы и имеем единичный вектор направления

   Теперь не нужен никакой угол fAngle, а перемещение организовано так:


	float	fVel;	// Скорость персонажа

	VK_UP:
	...
	vPlr.x += vDir.x * fVel;
	vPlr.y += vDir.y * fVel;
	...

	VK_DOWN:
	...
	vPlr.x -= vDir.x * fVel;
	vPlr.y -= vDir.y * fVel;
	...

	VK_RIGHT:
	...
	vPlr.x += vDir.y * fVel;
	vPlr.y -= vDir.x * fVel;
	...

	VK_LEFT:
	...
	vPlr.x -= vDir.y * fVel;
	vPlr.y += vDir.x * fVel;
	...

  В данном случае vDir является нормалью игрока.   Теперь я приведу формулы перемещения в трехмерном пространстве. Ниже используются два угла : fAngleX - угол поворота по оси X, и fAngleY - угол поворота по оси Y.


	VK_UP:
	...
	vPlr.x -= sin( fAngleY ) * cos( fAngleX );
	vPlr.y += sin( fAngleX );
	vPlr.z += cos( fAngleY ) * cos( fAngleX );
	...
  	
	VK_DOWN:
	...
	vPlr.x += sin( fAngleY ) * cos( fAngleX );
	vPlr.y -= sin( fAngleX );
	vPlr.z -= cos( fAngleY ) * cos( fAngleX );
	...

	// При перемещении налево или направо координата y не должна меняться, 
	// так как движемся только в одной плоскости
	VK_LEFT:
	...
	vPlr.x += sin( fAngleY );
	vPlr.z += cos( fAngleY );
	...

	VK_RIGHT:
	...
	vPlr.x -= sin( fAngleY );
	vPlr.z -= cos( fAngleY );
	...

  Вот и все, что нужно для создания простенькой игры.
Статью написал faceH0r 9.12.2005
Используются технологии uCoz