mirror of
				https://github.com/MapMakersAndProgrammers/alternativa3d-archive.git
				synced 2025-10-30 17:05:17 -07:00 
			
		
		
		
	more versions added
This commit is contained in:
		| @@ -0,0 +1,508 @@ | ||||
| package alternativa.engine3d.controllers { | ||||
| 	import alternativa.engine3d.*; | ||||
| 	import alternativa.engine3d.core.Camera3D; | ||||
| 	import alternativa.engine3d.core.Mesh; | ||||
| 	import alternativa.engine3d.core.Object3D; | ||||
| 	import alternativa.engine3d.physics.Collision; | ||||
| 	import alternativa.types.Matrix3D; | ||||
| 	import alternativa.types.Point3D; | ||||
| 	import alternativa.utils.KeyboardUtils; | ||||
| 	import alternativa.utils.MathUtils; | ||||
| 	 | ||||
| 	import flash.display.DisplayObject; | ||||
| 	 | ||||
| 	use namespace alternativa3d; | ||||
| 	 | ||||
| 	/** | ||||
| 	 * Контроллер, реализующий управление движением объекта, находящегося в системе координат корневого объекта сцены.  | ||||
| 	 *  | ||||
| 	 * <p>Контроллер предоставляет два режима движения: режим ходьбы с учётом силы тяжести и режим полёта, в котором сила | ||||
| 	 * тяжести не учитывается. В обоих режимах может быть включена проверка столкновений с объектами сцены. Если проверка | ||||
| 	 * столкновений отключена, то в режиме ходьбы сила тяжести также игнорируется и дополнительно появляется возможность | ||||
| 	 * движения по вертикали. | ||||
| 	 *  | ||||
| 	 * <p>Для всех объектов, за исключением <code>Camera3D</code>, направлением "вперёд" считается направление его оси | ||||
| 	 * <code>Y</code>, направлением "вверх" — направление оси <code>Z</code>. Для объектов класса | ||||
| 	 * <code>Camera3D</code> направление "вперёд" совпадает с направлением локальной оси <code>Z</code>, а направление | ||||
| 	 * "вверх" противоположно направлению локальной оси <code>Y</code>. | ||||
| 	 *  | ||||
| 	 * <p>Вне зависимости от того, включена проверка столкновений или нет, координаты при перемещении расчитываются для | ||||
| 	 * эллипсоида, параметры которого устанавливаются через свойство <code>collider</code>. Координаты управляемого | ||||
| 	 * объекта вычисляются исходя из положения центра эллипсоида и положения объекта на вертикальной оси эллипсоида, | ||||
| 	 * задаваемого параметром <code>objectZPosition</code>. | ||||
| 	 *  | ||||
| 	 * <p>Команда <code>ACTION_UP</code> в режиме ходьбы при ненулевой гравитации вызывает прыжок, в остальных случаях | ||||
| 	 * происходит движение вверх. | ||||
| 	 */	 | ||||
| 	public class WalkController extends ObjectController { | ||||
| 		/** | ||||
| 		 * Величина ускорения свободного падения. При положительном значении сила тяжести направлена против оси Z, | ||||
| 		 * при отрицательном — по оси Z. | ||||
| 		 */ | ||||
| 		public var gravity:Number = 0; | ||||
| 		/** | ||||
| 		 * Вертикальная скорость прыжка. | ||||
| 		 */ | ||||
| 		public var jumpSpeed:Number = 0; | ||||
| 		/** | ||||
| 		 * Объект, на котором стоит эллипсоид при ненулевой гравитации. | ||||
| 		 */ | ||||
| 		private var _groundMesh:Mesh; | ||||
| 		/** | ||||
| 		 * Погрешность определения скорости. В режиме полёта или в режиме ходьбы при нахождении на поверхности | ||||
| 		 * скорость приравнивается к нулю, если её модуль не превышает заданного значения. | ||||
| 		 */ | ||||
| 		public var speedThreshold:Number = 1; | ||||
|  | ||||
| 		// Коэффициент эффективности управления перемещением при нахождении в воздухе в режиме ходьбы и нулевой гравитации. | ||||
| 		private var _airControlCoefficient:Number = 1; | ||||
|  | ||||
| 		private var _currentSpeed:Number = 0; | ||||
| 		 | ||||
| 		private var minGroundCos:Number = Math.cos(MathUtils.toRadian(70)); | ||||
| 		 | ||||
| 		private var destination:Point3D = new Point3D(); | ||||
| 		private var collision:Collision = new Collision(); | ||||
| 		 | ||||
| 		private var _objectZPosition:Number = 0.5; | ||||
| 		private var _flyMode:Boolean; | ||||
| 		private	var _onGround:Boolean; | ||||
| 		 | ||||
| 		private var velocity:Point3D = new Point3D(); | ||||
| 		private var tmpVelocity:Point3D = new Point3D(); | ||||
| 		 | ||||
| 		private var controlsActive:Boolean; | ||||
| 		 | ||||
| 		private var inJump:Boolean; | ||||
| 		private var startRotX:Number; | ||||
| 		private var startRotZ:Number; | ||||
|  | ||||
| 		// Координаты мышиного курсора в режиме mouse look в предыдущем кадре. | ||||
| 		private var prevMouseCoords:Point3D = new Point3D(); | ||||
| 		// Текущие координаты мышиного курсора в режиме mouse look. | ||||
| 		private var currentMouseCoords:Point3D = new Point3D(); | ||||
|  | ||||
| 		/** | ||||
| 		 * @inheritDoc | ||||
| 		 */ | ||||
| 		public function WalkController(eventSourceObject:DisplayObject) { | ||||
| 			super(eventSourceObject); | ||||
| 		} | ||||
| 		 | ||||
| 		/** | ||||
| 		 * Объект, на котором стоит эллипсоид при ненулевой гравитации. | ||||
| 		 */ | ||||
| 		public function get groundMesh():Mesh { | ||||
| 			return _groundMesh; | ||||
| 		} | ||||
| 		 | ||||
| 		/** | ||||
| 		 * Направление объекта на точку. В результате работы метода локальная ось объекта, соответствующая направлению "вперёд" | ||||
| 		 * будет направлена на указанную точку, а угол поворота вокруг этой оси будет равен нулю. | ||||
| 		 *  | ||||
| 		 * @param point координаты точки, на которую должен быть направлен объект | ||||
| 		 */ | ||||
| 		public function lookAt(point:Point3D):void { | ||||
| 			if (_object == null) { | ||||
| 				return; | ||||
| 			} | ||||
| 			var dx:Number = point.x - _object.x; | ||||
| 			var dy:Number = point.y - _object.y; | ||||
| 			var dz:Number = point.z - _object.z; | ||||
| 			_object.rotationX = Math.atan2(dz, Math.sqrt(dx * dx + dy * dy)) - (_object is Camera3D ? MathUtils.DEG90 : 0); | ||||
| 			_object.rotationY = 0; | ||||
| 			_object.rotationZ = -Math.atan2(dx, dy); | ||||
| 		} | ||||
| 		 | ||||
| 		/** | ||||
| 		 * Коэффициент эффективности управления перемещением в режиме ходьбы при нахождении в воздухе и ненулевой гравитации. | ||||
| 		 * Значение 0 обозначает полное отсутствие контроля, значение 1 указывает, что управление так же эффективно, как при | ||||
| 		 * нахождении на поверхности. | ||||
| 		 *  | ||||
| 		 * @default 1 | ||||
| 		 */ | ||||
| 		public function get airControlCoefficient():Number { | ||||
| 			return _airControlCoefficient; | ||||
| 		} | ||||
|  | ||||
| 		/** | ||||
| 		 * @private | ||||
| 		 */ | ||||
| 		public function set airControlCoefficient(value:Number):void { | ||||
| 			_airControlCoefficient = value > 0 ? value : -value; | ||||
| 		} | ||||
| 		 | ||||
| 		/** | ||||
| 		 * Максимальный угол наклона поверхности в радианах, на которой возможен прыжок и на которой объект стоит на месте | ||||
| 		 * в отсутствие управляющих воздействий. Если угол наклона поверхности превышает заданное значение, свойство | ||||
| 		 * <code>onGround</code> будет иметь значение <code>false</code>. | ||||
| 		 *  | ||||
| 		 * @see #onGround | ||||
| 		 */ | ||||
| 		public function get maxGroundAngle():Number { | ||||
| 			return Math.acos(minGroundCos);  | ||||
| 		} | ||||
| 			 | ||||
| 		/** | ||||
| 		 * @private | ||||
| 		 */ | ||||
| 		public function set maxGroundAngle(value:Number):void { | ||||
| 			minGroundCos = Math.cos(value); | ||||
| 		} | ||||
| 		 | ||||
| 		/** | ||||
| 		 * Положение управляемого объекта на оси Z эллипсоида. Значение 0 указывает положение в нижней точке эллипсоида, | ||||
| 		 * значение 1 -- положение в верхней точке эллипсоида. | ||||
| 		 */		 | ||||
| 		public function get objectZPosition():Number { | ||||
| 			return _objectZPosition; | ||||
| 		} | ||||
|  | ||||
| 		/** | ||||
| 		 * @private | ||||
| 		 */		 | ||||
| 		public function set objectZPosition(value:Number):void { | ||||
| 			_objectZPosition = value; | ||||
| 			setObjectCoords(); | ||||
| 		} | ||||
| 		 | ||||
| 		/** | ||||
| 		 * Включене и выключение режима полёта. | ||||
| 		 *  | ||||
| 		 * @default false | ||||
| 		 */		 | ||||
| 		public function get flyMode():Boolean { | ||||
| 			return _flyMode; | ||||
| 		} | ||||
|  | ||||
| 		/** | ||||
| 		 * @private | ||||
| 		 */		 | ||||
| 		public function set flyMode(value:Boolean):void { | ||||
| 			_flyMode = value; | ||||
| 		} | ||||
| 		 | ||||
| 		/** | ||||
| 		 * Индикатор положения эллипсоида на поверхности в режиме ходьбы. Считается, что эллипсоид находится на поверхности, | ||||
| 		 * если угол наклона поверхности под ним не превышает заданного свойством <code>maxGroundAngle</code> значения. | ||||
| 		 *  | ||||
| 		 * @see #maxGroundAngle  | ||||
| 		 */ | ||||
| 		public function get onGround():Boolean { | ||||
| 			return _onGround; | ||||
| 		} | ||||
|  | ||||
| 		/** | ||||
| 		 * Модуль текущей скорости. | ||||
| 		 */ | ||||
| 		public function get currentSpeed():Number { | ||||
| 			return _currentSpeed; | ||||
| 		} | ||||
| 		 | ||||
| 		/** | ||||
| 		 * Установка привязки клавиш по умолчанию. Данный метод очищает все существующие привязки клавиш и устанавливает следующие: | ||||
| 		 * <table border="1" style="border-collapse: collapse"> | ||||
| 		 * <tr><th>Клавиша</th><th>Действие</th></tr> | ||||
| 		 * <tr><td>W</td><td>ACTION_FORWARD</td></tr> | ||||
| 		 * <tr><td>S</td><td>ACTION_BACK</td></tr> | ||||
| 		 * <tr><td>A</td><td>ACTION_LEFT</td></tr> | ||||
| 		 * <tr><td>D</td><td>ACTION_RIGHT</td></tr> | ||||
| 		 * <tr><td>SPACE</td><td>ACTION_UP</td></tr> | ||||
| 		 * <tr><td>CONTROL</td><td>ACTION_DOWN</td></tr> | ||||
| 		 * <tr><td>SHIFT</td><td>ACTION_ACCELERATE</td></tr> | ||||
| 		 * <tr><td>UP</td><td>ACTION_PITCH_UP</td></tr> | ||||
| 		 * <tr><td>DOWN</td><td>ACTION_PITCH_DOWN</td></tr> | ||||
| 		 * <tr><td>LEFT</td><td>ACTION_YAW_LEFT</td></tr> | ||||
| 		 * <tr><td>RIGHT</td><td>ACTION_YAW_RIGHT</td></tr> | ||||
| 		 * <tr><td>M</td><td>ACTION_MOUSE_LOOK</td></tr> | ||||
| 		 * </table> | ||||
| 		 */ | ||||
| 		override public function setDefaultBindings():void { | ||||
| 			unbindAll(); | ||||
| 			bindKey(KeyboardUtils.W, ACTION_FORWARD); | ||||
| 			bindKey(KeyboardUtils.S, ACTION_BACK); | ||||
| 			bindKey(KeyboardUtils.A, ACTION_LEFT); | ||||
| 			bindKey(KeyboardUtils.D, ACTION_RIGHT); | ||||
| 			bindKey(KeyboardUtils.SPACE, ACTION_UP); | ||||
| 			bindKey(KeyboardUtils.CONTROL, ACTION_DOWN); | ||||
| 			bindKey(KeyboardUtils.UP, ACTION_PITCH_UP); | ||||
| 			bindKey(KeyboardUtils.DOWN, ACTION_PITCH_DOWN); | ||||
| 			bindKey(KeyboardUtils.LEFT, ACTION_YAW_LEFT); | ||||
| 			bindKey(KeyboardUtils.RIGHT, ACTION_YAW_RIGHT); | ||||
| 			bindKey(KeyboardUtils.SHIFT, ACTION_ACCELERATE); | ||||
| 			bindKey(KeyboardUtils.M, ACTION_MOUSE_LOOK); | ||||
| 		} | ||||
| 		 | ||||
| 		/** | ||||
| 		 * Метод выполняет поворот объекта в соответствии с имеющимися воздействиями. Взгляд вверх и вниз ограничен | ||||
| 		 * отклонением в 90 градусов от горизонтали. | ||||
| 		 *  | ||||
| 		 * @param frameTime длительность текущего кадра в секундах  | ||||
| 		 */ | ||||
| 		override protected function rotateObject(frameTime:Number):void { | ||||
| 			// Mouse look | ||||
| 			var rotX:Number; | ||||
| 			if (_mouseLookActive) { | ||||
| 				prevMouseCoords.copy(currentMouseCoords); | ||||
| 				currentMouseCoords.x = _eventsSource.stage.mouseX; | ||||
| 				currentMouseCoords.y = _eventsSource.stage.mouseY; | ||||
| 				if (!prevMouseCoords.equals(currentMouseCoords)) { | ||||
| 					_object.rotationZ = startRotZ + (startMouseCoords.x - currentMouseCoords.x) * _mouseCoefficientX; | ||||
| 					rotX = startRotX + (startMouseCoords.y - currentMouseCoords.y) * _mouseCoefficientY; | ||||
| 					if (_object is Camera3D) { | ||||
| 						// Коррекция поворота для камеры | ||||
| 						_object.rotationX = (rotX > MathUtils.DEG90) ? 0 : (rotX < -MathUtils.DEG90) ? -Math.PI : rotX - MathUtils.DEG90; | ||||
| 					} else { | ||||
| 						_object.rotationX = (rotX > MathUtils.DEG90) ? MathUtils.DEG90 : (rotX < -MathUtils.DEG90) ? -MathUtils.DEG90 : rotX; | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 			 | ||||
| 			// Повороты влево-вправо | ||||
| 			if (_yawLeft) { | ||||
| 				_object.rotationZ += _yawSpeed * frameTime; | ||||
| 			} else if (_yawRight) { | ||||
| 				_object.rotationZ -= _yawSpeed * frameTime; | ||||
| 			} | ||||
| 			// Взгляд вверх-вниз | ||||
| 			rotX = NaN; | ||||
| 			if (_pitchUp) { | ||||
| 				rotX = _object.rotationX + _pitchSpeed * frameTime; | ||||
| 			} else if (_pitchDown) { | ||||
| 				rotX = _object.rotationX - _pitchSpeed * frameTime; | ||||
| 			} | ||||
| 			if (!isNaN(rotX)) { | ||||
| 				if (_object is Camera3D) { | ||||
| 					// Коррекция поворота для камеры | ||||
| 					_object.rotationX = (rotX > 0) ? 0 : (rotX < -Math.PI) ? -Math.PI : rotX; | ||||
| 				} else { | ||||
| 					_object.rotationX = (rotX > MathUtils.DEG90) ? MathUtils.DEG90 : (rotX < -MathUtils.DEG90) ? -MathUtils.DEG90 : rotX; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		 | ||||
| 		/** | ||||
| 		 * Метод вычисляет вектор потенциального смещения эллипсоида, учитывая режим перемещения, команды перемещения и силу тяжести. | ||||
| 		 *  | ||||
| 		 * @param frameTime длительность текущего кадра в секундах  | ||||
| 		 * @param displacement в эту переменную записывается вычисленное потенциальное смещение объекта | ||||
| 		 */ | ||||
| 		override protected function getDisplacement(frameTime:Number, displacement:Point3D):void { | ||||
| 			var cos:Number = 0; | ||||
| 			if (checkCollisions && !_flyMode) { | ||||
| 				// Проверка наличия под ногами поверхности | ||||
| 				displacement.x = 0; | ||||
| 				displacement.y = 0; | ||||
| 				displacement.z = - 0.5 * gravity * frameTime * frameTime; | ||||
| 				if (_collider.getCollision(_coords, displacement, collision)) { | ||||
| 					cos = collision.normal.z; | ||||
| 					_groundMesh = collision.face._mesh; | ||||
| 				} else { | ||||
| 					_groundMesh = null; | ||||
| 				} | ||||
| 			} | ||||
| 			_onGround = cos > minGroundCos; | ||||
| 			 | ||||
| 			if (_onGround && inJump) { | ||||
| 				inJump = false; | ||||
| 			} | ||||
| 			 | ||||
| 			var len:Number; | ||||
| 			var x:Number; | ||||
| 			var y:Number; | ||||
| 			var z:Number; | ||||
|  | ||||
| 			// При наличии управляющих воздействий расчитывается приращение скорости  | ||||
| 			controlsActive = _forward || _back || _right || _left || _up || _down; | ||||
| 			if (controlsActive) { | ||||
| 				if (_flyMode) { | ||||
| 					tmpVelocity.x = 0; | ||||
| 					tmpVelocity.y = 0; | ||||
| 					tmpVelocity.z = 0; | ||||
| 					// Режим полёта, ускорения направлены вдоль локальных осей | ||||
| 					// Ускорение вперёд-назад | ||||
| 					if (_forward) { | ||||
| 						tmpVelocity.y = 1; | ||||
| 					} else if (_back) { | ||||
| 						tmpVelocity.y = -1; | ||||
| 					} | ||||
| 					// Ускорение влево-вправо | ||||
| 					if (_right) { | ||||
| 						tmpVelocity.x = 1; | ||||
| 					} else if (_left) { | ||||
| 						tmpVelocity.x = -1; | ||||
| 					} | ||||
| 					// Ускорение вверх-вниз | ||||
| 					if (_up) { | ||||
| 						tmpVelocity.z = 1; | ||||
| 					} else if (_down) { | ||||
| 						tmpVelocity.z = -1; | ||||
| 					} | ||||
| 					var matrix:Matrix3D = _object.transformation; | ||||
| 					x = tmpVelocity.x; | ||||
| 					if (_object is Camera3D) { | ||||
| 						y = -tmpVelocity.z; | ||||
| 						z = tmpVelocity.y; | ||||
| 					} else { | ||||
| 						y = tmpVelocity.y; | ||||
| 						z = tmpVelocity.z; | ||||
| 					} | ||||
| 					// Поворот вектора из локальной системы координат объекта в глобальную | ||||
| 					velocity.x += (x * matrix.a + y * matrix.b + z * matrix.c) * _speed; | ||||
| 					velocity.y += (x * matrix.e + y * matrix.f + z * matrix.g) * _speed; | ||||
| 					velocity.z += (x * matrix.i + y * matrix.j + z * matrix.k) * _speed; | ||||
| 				} else { | ||||
| 					 | ||||
| 					// Режим хождения, ускорения вперёд-назад-влево-вправо лежат в глобальной плоскости XY, вверх-вниз направлены вдоль глобальной оси Z | ||||
| 					var heading:Number = _object.rotationZ; | ||||
| 					var headingCos:Number = Math.cos(heading); | ||||
| 					var headingSin:Number = Math.sin(heading); | ||||
| 					 | ||||
| 					var spd:Number = _speed; | ||||
| 					if (gravity != 0 && !_onGround) { | ||||
| 						spd *= _airControlCoefficient; | ||||
| 					} | ||||
| 					 | ||||
| 					// Вперёд-назад | ||||
| 					if (_forward) { | ||||
| 						velocity.x -= spd * headingSin; | ||||
| 						velocity.y += spd * headingCos; | ||||
| 					} else if (_back) { | ||||
| 						velocity.x += spd * headingSin; | ||||
| 						velocity.y -= spd * headingCos; | ||||
| 					} | ||||
| 					// Влево-вправо | ||||
| 					if (_right) { | ||||
| 						velocity.x += spd * headingCos; | ||||
| 						velocity.y += spd * headingSin; | ||||
| 					} else if (_left) { | ||||
| 						velocity.x -= spd * headingCos; | ||||
| 						velocity.y -= spd * headingSin; | ||||
| 					} | ||||
| 					if (gravity == 0) { | ||||
| 						// Ускорение вверх-вниз | ||||
| 						if (_up) { | ||||
| 							velocity.z += _speed; | ||||
| 						} else if (_down) { | ||||
| 							velocity.z -= _speed; | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
| 			} else { | ||||
| 				// Управление неактивно, замедление движения | ||||
| 				len = 1 / Math.pow(3, frameTime * 10); | ||||
| 				if (_flyMode || gravity == 0) { | ||||
| 					velocity.x *= len; | ||||
| 					velocity.y *= len; | ||||
| 					velocity.z *= len; | ||||
| 				} else { | ||||
| 					if (_onGround) { | ||||
| 						velocity.x *= len; | ||||
| 						velocity.y *= len; | ||||
| 						if (velocity.z < 0) { | ||||
| 							velocity.z *= len; | ||||
| 						} | ||||
| 					} else { | ||||
| 						if (cos > 0 && velocity.z > 0) { | ||||
| 							velocity.z = 0; | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 			// Прыжок | ||||
| 			if (_onGround && _up && !inJump) { | ||||
| 				velocity.z = jumpSpeed; | ||||
| 				inJump = true; | ||||
| 				_onGround = false; | ||||
| 				cos = 0; | ||||
| 			} | ||||
| 			// В режиме ходьбы добавляется ускорение свободного падения, если находимся не на ровной поверхности | ||||
| 			if (!(_flyMode || _onGround)) { | ||||
| 				velocity.z -= gravity * frameTime; | ||||
| 			} | ||||
| 			 | ||||
| 			// Ограничение скорости | ||||
| 			var max:Number = _accelerate ? _speed * _speedMultiplier : _speed; | ||||
| 			if (_flyMode || gravity == 0) { | ||||
| 				len = velocity.length; | ||||
| 				if (len > max) { | ||||
| 					velocity.length = max; | ||||
| 				} | ||||
| 			} else { | ||||
| 				len = Math.sqrt(velocity.x * velocity.x + velocity.y * velocity.y); | ||||
| 				if (len > max) { | ||||
| 					velocity.x *= max / len; | ||||
| 					velocity.y *= max / len; | ||||
| 				} | ||||
| 				if (cos > 0 && velocity.z > 0) { | ||||
| 					velocity.z = 0; | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			// Cмещение за кадр | ||||
| 			displacement.x = velocity.x * frameTime; | ||||
| 			displacement.y = velocity.y * frameTime; | ||||
| 			displacement.z = velocity.z * frameTime; | ||||
| 		} | ||||
| 		 | ||||
| 		/** | ||||
| 		 * Метод применяет потенциальный вектор смещения к эллипсоиду с учётом столкновений с геометрией сцены, если включён | ||||
| 		 * соотвествующий режим. | ||||
| 		 *    | ||||
| 		 * @param frameTime время кадра в секундах | ||||
| 		 * @param displacement векотр потенциального смещения эллипсоида | ||||
| 		 */ | ||||
| 		override protected function applyDisplacement(frameTime:Number, displacement:Point3D):void { | ||||
| 			if (checkCollisions) { | ||||
| 				_collider.calculateDestination(_coords, displacement, destination); | ||||
|  | ||||
| 				displacement.x = destination.x - _coords.x; | ||||
| 				displacement.y = destination.y - _coords.y; | ||||
| 				displacement.z = destination.z - _coords.z; | ||||
| 			} else { | ||||
| 				destination.x = _coords.x + displacement.x; | ||||
| 				destination.y = _coords.y + displacement.y; | ||||
| 				destination.z = _coords.z + displacement.z; | ||||
| 			} | ||||
|  | ||||
| 			velocity.x = displacement.x / frameTime; | ||||
| 			velocity.y = displacement.y / frameTime; | ||||
| 			velocity.z = displacement.z / frameTime; | ||||
|  | ||||
| 			_coords.x = destination.x; | ||||
| 			_coords.y = destination.y; | ||||
| 			_coords.z = destination.z; | ||||
| 			setObjectCoords(); | ||||
| 			 | ||||
| 			var len:Number = Math.sqrt(velocity.x * velocity.x + velocity.y * velocity.y + velocity.z * velocity.z); | ||||
| 			if (len < speedThreshold) { | ||||
| 				velocity.x = 0; | ||||
| 				velocity.y = 0; | ||||
| 				velocity.z = 0; | ||||
| 				_currentSpeed = 0; | ||||
| 			} else { | ||||
| 				_currentSpeed = len; | ||||
| 			} | ||||
| 		} | ||||
| 		 | ||||
| 		/** | ||||
| 		 * Метод устанавливает координаты управляемого объекта в зависимости от параметра <code>objectZPosition</code>. | ||||
| 		 *  | ||||
| 		 * @see #objectZPosition | ||||
| 		 */ | ||||
| 		override protected function setObjectCoords():void { | ||||
| 			_object.x = _coords.x; | ||||
| 			_object.y = _coords.y; | ||||
| 			_object.z = _coords.z + (2 * _objectZPosition - 1) * _collider.radiusZ; | ||||
| 		} | ||||
| 		 | ||||
| 		/** | ||||
| 		 * Метод выполняет необходимые действия при включении вращения объекта мышью. | ||||
| 		 */		 | ||||
| 		override protected function startMouseLook():void { | ||||
| 			super.startMouseLook(); | ||||
| 			startRotX = _object is Camera3D ? _object.rotationX + MathUtils.DEG90 : _object.rotationX; | ||||
| 			startRotZ = _object.rotationZ; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 Tubix
					Tubix