Код вертолета
Страница 1 из 1
Код вертолета
Хоть этот код не совершенен, вертолет неплохо летает, наклоняется и даже стреляет.
Важные ньюансы:
Для вертолета нужно создать физическую модель в которой будут четыре тела с названиями: helicopter (основное тело в которое пойдут меши корпуса вертолета), stabilizator (невидимое тело, которое должно располагаться над вертолетом, под ним будет висеть вертолет на специальном сочленении, у самого тела следует выключить параметр "Контактировать"), mainPropeller (тело с мешем основного винта), backPropeller (тело с мешем заднего винта). Также нужно три сочленения: два HingeJoint с именами suspensionJoint, соединяющий тело helicopter с телом mainPropeller и rotationJoint, соединяющий тело backPropeller с телом helicopter. Третье сочленение - UniversalJoint с именем stabilizeJoint соединяет тело stabilizator с телом helicopter. У этого сочленения должны быть включены ограничители на обеих осях. Направление одной оси - X, другой - Y. А также значения ограничителей должны стоять на 0. Еще нужны два мотора GearedMotor. Один с именем suspensionMotor должен крепиться на сочленении suspensionJoint, второй мотор с именем rotationMotor должен крепиться на сочленении rotationJoint.
В общем, образец готового вертолета я также прикреплю, разберетесь.
[Вы должны быть зарегистрированы и подключены, чтобы видеть эту ссылку]
Управление:
W -вперед
S - назад
A - поворот влево
D - поворот вправо
Q - движение левым боком
E - движение правым боком
Shift - вниз
Пробел - вверх
Это код класса вертолет
Класс GameControlKeys. Добавить две новые клавиши. Движение в правый бок и в левый бок. Назначение клавиши Use поменять
Класс PlayerIntellect. Найдите метод void ServerOrSingle_RestoreMainControlledUnit() и в нем Tank specific
Добавьте в условие этого метода ControlledObject is Helicopter
В классе ActionGameWindow, найдите метод void UpdateHUD(). В нем под Tank specific добавьте строки с Helicopter
А ниже в этом методе, под строкой Tank specific DrawTankGunTarget(renderer) добавьте аналогичные строки про Helicopter
Важные ньюансы:
Для вертолета нужно создать физическую модель в которой будут четыре тела с названиями: helicopter (основное тело в которое пойдут меши корпуса вертолета), stabilizator (невидимое тело, которое должно располагаться над вертолетом, под ним будет висеть вертолет на специальном сочленении, у самого тела следует выключить параметр "Контактировать"), mainPropeller (тело с мешем основного винта), backPropeller (тело с мешем заднего винта). Также нужно три сочленения: два HingeJoint с именами suspensionJoint, соединяющий тело helicopter с телом mainPropeller и rotationJoint, соединяющий тело backPropeller с телом helicopter. Третье сочленение - UniversalJoint с именем stabilizeJoint соединяет тело stabilizator с телом helicopter. У этого сочленения должны быть включены ограничители на обеих осях. Направление одной оси - X, другой - Y. А также значения ограничителей должны стоять на 0. Еще нужны два мотора GearedMotor. Один с именем suspensionMotor должен крепиться на сочленении suspensionJoint, второй мотор с именем rotationMotor должен крепиться на сочленении rotationJoint.
В общем, образец готового вертолета я также прикреплю, разберетесь.
[Вы должны быть зарегистрированы и подключены, чтобы видеть эту ссылку]
Управление:
W -вперед
S - назад
A - поворот влево
D - поворот вправо
Q - движение левым боком
E - движение правым боком
Shift - вниз
Пробел - вверх
Это код класса вертолет
- Код:
using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.Drawing.Design;
using Engine;
using Engine.EntitySystem;
using Engine.MapSystem;
using Engine.MathEx;
using Engine.PhysicsSystem;
using Engine.Renderer;
using Engine.SoundSystem;
using Engine.Utils;
using ProjectCommon;
using System.IO;
using Engine.FileSystem;
namespace ProjectEntities
{
public class HelicopterType : UnitType
{
[FieldSerialize]
private float maxSpeedUp = 40f;
[FieldSerialize]
private float speedRotations = 1f;
[FieldSerialize]
private float maxSpeedMove = 80f;
[FieldSerialize]
private float maxForce = 85000f;
[FieldSerialize]
private float force = 50000f;
[FieldSerialize]
Range optimalAttackDistanceRange;
[FieldSerialize]
Degree towerTurnSpeed = 90;
[FieldSerialize]
string soundOn;
[FieldSerialize]
string soundOff;
[FieldSerialize]
string soundGearUp;
[FieldSerialize]
string soundGearDown;
[FieldSerialize]
Range gunRotationAngleRange = new Range(-80, 20);
[FieldSerialize]
List<Gear> gears = new List<Gear>();
///////////////////////////////////////////
public class Gear
{
[FieldSerialize]
int number;
[FieldSerialize]
Range speedRange;
[FieldSerialize]
string soundMotor;
[FieldSerialize]
[DefaultValue(typeof(Range), "1 1.2")]
Range soundMotorPitchRange = new Range(1, 1.2f);
//
[DefaultValue(0)]
public int Number
{
get { return number; }
set { number = value; }
}
[DefaultValue(typeof(Range), "0 0")]
public Range SpeedRange
{
get { return speedRange; }
set { speedRange = value; }
}
[Editor(typeof(EditorSoundUITypeEditor), typeof(UITypeEditor))]
public string SoundMotor
{
get { return soundMotor; }
set { soundMotor = value; }
}
[DefaultValue(typeof(Range), "1 1.2")]
public Range SoundMotorPitchRange
{
get { return soundMotorPitchRange; }
set { soundMotorPitchRange = value; }
}
public override string ToString()
{
return string.Format("Gear {0}", number);
}
}
///////////////////////////////////////////
public float MaxSpeedUp
{
get { return maxSpeedUp; }
set { maxSpeedUp = value; }
}
public float SpeedRotations
{
get { return speedRotations; }
set { speedRotations = value; }
}
public float MaxSpeedMove
{
get { return maxSpeedMove; }
set { maxSpeedMove = value; }
}
public float MaxForce
{
get { return maxForce; }
set { maxForce = value; }
}
public float Force
{
get { return force; }
set { force = value; }
}
[Description("In degrees.")]
[DefaultValue(typeof(Range), "-80 20")]
public Range GunRotationAngleRange
{
get { return gunRotationAngleRange; }
set { gunRotationAngleRange = value; }
}
[DefaultValue(typeof(Range), "0 0")]
public Range OptimalAttackDistanceRange
{
get { return optimalAttackDistanceRange; }
set { optimalAttackDistanceRange = value; }
}
[Description("Degrees per second.")]
[DefaultValue(typeof(Degree), "90")]
public Degree TowerTurnSpeed
{
get { return towerTurnSpeed; }
set { towerTurnSpeed = value; }
}
[Editor(typeof(EditorSoundUITypeEditor), typeof(UITypeEditor))]
public string SoundOn
{
get { return soundOn; }
set { soundOn = value; }
}
[Editor(typeof(EditorSoundUITypeEditor), typeof(UITypeEditor))]
public string SoundOff
{
get { return soundOff; }
set { soundOff = value; }
}
public List<Gear> Gears
{
get { return gears; }
}
[Editor(typeof(EditorSoundUITypeEditor), typeof(UITypeEditor))]
public string SoundGearUp
{
get { return soundGearUp; }
set { soundGearUp = value; }
}
[Editor(typeof(EditorSoundUITypeEditor), typeof(UITypeEditor))]
public string SoundGearDown
{
get { return soundGearDown; }
set { soundGearDown = value; }
}
}
public class Helicopter : Unit
{
private HelicopterType _type = null;
public new HelicopterType Type
{
get { return _type; }
}
///////////////////////////////////////////
class Track
{
public float speed;
public float server_sentSpeed;
}
///////////////////////////////////////////
Body helicopterBody; //Это тело самого вертолета
Body stabilizatorBody; //Это тело стабилизатора. Небольшой куб, который надо расположить в редакторе физики над
//вертолетом, затем соединить его с телом вертолета при помощи сочленения UniversalJoint. Стабилизатор будет выравнивать
//тело вертолета, когда оно будет наклоняться. Тело стабилизатора должно быть над центром вертолета, чтобы тело вертолета
//висело ровно и не наклонялось само.
float Mass, suspensionForce;
GearedMotor suspensionMotor, rotationMotor;
HingeJoint suspensionJoint, rotationJoint;
UniversalJoint stabilizeJoint;
bool isWorking = false;
bool firstTick = true;
float RL = 0;
float FB1 = 0;
float FB2 = 0;
float RwLw1 = 0;
float RwLw2 = 0;
Body towerBody;
Vec3 towerBodyLocalPosition;
MapObjectAttachedMapObject mainGunAttachedObject;
Gun mainGun;
Vec3 mainGunOffsetPosition;
SphereDir towerLocalDirection;
SphereDir needTowerLocalDirection;
SphereDir server_sentTowerLocalDirection;
bool motorOn;
string currentMotorSoundName;
VirtualChannel motorSoundChannel;
HelicopterType.Gear currentGear;
Track leftTrack = new Track();
Track rightTrack = new Track();
protected override void OnPostCreate(bool loaded)
{
base.OnPostCreate(loaded);
if (EngineApp.Instance.ApplicationType == EngineApp.ApplicationTypes.Simulation)
GetPhysics();
{
if (EngineApp.Instance.ApplicationType != EngineApp.ApplicationTypes.ResourceEditor)
{
if (PhysicsModel == null)
{
Log.Error("Не добавлена физика вертолету. Класс Helicopter, экземпляр: " + Name);
return;
}
helicopterBody = PhysicsModel.GetBody("helicopter");
if (helicopterBody == null)
{
Log.Error("Тело 'helicopter' не найдено. Либо оно отсутствует, либо задано неправильное имя. Класс Helicopter, экземпляр: " + Name);
return;
}
towerBody = PhysicsModel.GetBody("tower");
stabilizatorBody = PhysicsModel.GetBody("stabilizator");
if (stabilizatorBody == null)
{
Log.Error("Тело 'stabilizator' не найдено. Либо оно отсутствует, либо задано неправильное имя. Класс Helicopter, экземпляр: " + Name);
return;
}
stabilizeJoint = PhysicsModel.GetJoint("stabilizeJoint") as UniversalJoint;
if (stabilizeJoint == null)
{
Log.Error("Сочленение 'stabilizeJoint' не найдено. Либо оно отсутствует, либо задано неправильное имя, либо сочленение не является UniversalJoint. Класс Helicopter, экземпляр: " + Name);
return;
}
}
//mainGun
foreach (MapObjectAttachedObject attachedObject in AttachedObjects)
{
MapObjectAttachedMapObject attachedMapObject = attachedObject as MapObjectAttachedMapObject;
if (attachedMapObject == null)
continue;
mainGun = attachedMapObject.MapObject as Gun;
if (mainGun != null)
{
mainGunAttachedObject = attachedMapObject;
mainGunOffsetPosition = attachedMapObject.PositionOffset;
break;
}
}
//towerBodyLocalPosition
if (towerBody != null)
towerBodyLocalPosition = PhysicsModel.ModelDeclaration.GetBody(towerBody.Name).Position;
//initialize currentGear
currentGear = Type.Gears.Find(delegate(HelicopterType.Gear gear)
{
return gear.Number == 0;
});
//disable contacts between chassisBody and towerBody
if (helicopterBody != null && towerBody != null)
{
foreach (Shape shape1 in helicopterBody.Shapes)
{
foreach (Shape shape2 in towerBody.Shapes)
{
PhysicsWorld.Instance.SetShapePairFlags(shape1, shape2,
ShapePairFlags.DisableContacts);
}
}
}
}
}
protected override void OnDestroy()
{
if (motorSoundChannel != null)
{
motorSoundChannel.Stop();
motorSoundChannel = null;
}
base.OnDestroy();
}
protected override void OnRender(Camera camera)
{
//not very true update in the OnRender.
//it is here because need update after all Ticks and before update attached objects.
UpdateTowerTransform();
base.OnRender(camera);
}
void TickTowerTurn()
{
//update direction
if (towerLocalDirection != needTowerLocalDirection)
{
Radian turnSpeed = Type.TowerTurnSpeed;
SphereDir needDirection = needTowerLocalDirection;
SphereDir direction = towerLocalDirection;
//update horizontal direction
float diffHorizontalAngle = needDirection.Horizontal - direction.Horizontal;
while (diffHorizontalAngle < -MathFunctions.PI)
diffHorizontalAngle += MathFunctions.PI * 2;
while (diffHorizontalAngle > MathFunctions.PI)
diffHorizontalAngle -= MathFunctions.PI * 2;
if (diffHorizontalAngle > 0)
{
if (direction.Horizontal > needDirection.Horizontal)
direction.Horizontal -= MathFunctions.PI * 2;
direction.Horizontal += turnSpeed * TickDelta;
if (direction.Horizontal > needDirection.Horizontal)
direction.Horizontal = needDirection.Horizontal;
}
else
{
if (direction.Horizontal < needDirection.Horizontal)
direction.Horizontal += MathFunctions.PI * 2;
direction.Horizontal -= turnSpeed * TickDelta;
if (direction.Horizontal < needDirection.Horizontal)
direction.Horizontal = needDirection.Horizontal;
}
//update vertical direction
if (direction.Vertical < needDirection.Vertical)
{
direction.Vertical += turnSpeed * TickDelta;
if (direction.Vertical > needDirection.Vertical)
direction.Vertical = needDirection.Vertical;
}
else
{
direction.Vertical -= turnSpeed * TickDelta;
if (direction.Vertical < needDirection.Vertical)
direction.Vertical = needDirection.Vertical;
}
if (direction.Equals(needTowerLocalDirection, .001f))
towerLocalDirection = direction;
towerLocalDirection = direction;
}
}
private void GetPhysics()
{
//Будьте внимательны при вводе имен тел, сочленений и моторов в редакторе ресурсов при создании физики.
//Обязательно соблюдайте регистр. По умолчанию имена принято писать с маленькой буквы
helicopterBody = PhysicsModel.GetBody("helicopter");
if (helicopterBody == null) Log.Error("{0} - Тело 'helicopter' не найдено. Либо оно отсутствует, либо задано неправильное имя. Класс Helicopter, экземпляр: " + Name, this);
stabilizatorBody = PhysicsModel.GetBody("stabilizator");
if (stabilizatorBody == null) Log.Error("{0} - Тело 'stabilizator' не найдено. Либо оно отсутствует, либо задано неправильное имя. Класс Helicopter, экземпляр: " + Name, this);
rotationJoint = PhysicsModel.GetJoint("rotationJoint") as HingeJoint;
rotationMotor = PhysicsModel.GetMotor("rotationMotor") as GearedMotor;
suspensionJoint = PhysicsModel.GetJoint("suspensionJoint") as HingeJoint;
suspensionMotor = PhysicsModel.GetMotor("suspensionMotor") as GearedMotor;
if (suspensionMotor == null) Log.Error("{0} - Мотор 'stabilizationMotor' не найден. Либо он отсутствует, либо задано неправильное имя, либо мотор не является GearedMotor. Класс Helicopter, экземпляр: " + Name, this);
if (suspensionJoint == null) Log.Error("{0} - Сочлинение 'suspensionJoint' не найдено. Либо оно отсутствует, либо задано неправильное имя, либо сочленение не является HingeJoint. Класс Helicopter, экземпляр: " + Name, this);
if (rotationJoint == null) Log.Error("{0} - Сочлинение 'rotationJoint' не найдено. Либо оно отсутствует, либо задано неправильное имя, либо сочленение не является HingeJoint. Класс Helicopter, экземпляр: " + Name, this);
if (rotationMotor == null) Log.Error("{0} - Мотор 'rotationMotor' не найден. Либо он отсутствует, либо задано неправильное имя, либо мотор не является GearedMotor. Класс Helicopter, экземпляр: " + Name, this);
foreach (Body b in PhysicsModel.Bodies) Mass += b.Mass;
suspensionForce = (-PhysicsWorld.Instance.MainScene.Gravity.Z * Mass) + Type.Force;
}
private void Starting()
{
if (suspensionJoint.Broken) return;
if (Intellect == null)
{
isWorking = false;
suspensionMotor.Throttle = 0;
rotationMotor.Throttle = 0;
}
else if (!isWorking && suspensionMotor.Throttle < 1)
{
suspensionMotor.Throttle += (TickDelta / 7);
rotationMotor.Throttle += (TickDelta / 7);
}
else
isWorking = true;
}
private void MoveUpDown()
{
Vec3 ForceVec = new Vec3(0, 0, suspensionForce);
if (Intellect.IsControlKeyPressed(GameControlKeys.Jump) && GetSpeed().Z < Type.MaxSpeedUp)
stabilizatorBody.AddForce(ForceType.GlobalAtLocalPos, TickDelta, ForceVec, Vec3.Zero);
else if (Intellect.IsControlKeyPressed(GameControlKeys.Run) && GetSpeed().Z > -Type.MaxSpeedUp)
stabilizatorBody.AddForce(ForceType.GlobalAtLocalPos, TickDelta, -ForceVec, Vec3.Zero);
}
private void MoveForwardBackward()
{
if (Intellect.IsControlKeyPressed(GameControlKeys.Forward))
{
if (GetSpeed().X < Type.MaxSpeedMove)
stabilizatorBody.AddForce(ForceType.LocalAtLocalPos, TickDelta, new Vec3(Type.Force, 0, 0), Vec3.Zero);
}
else if (Intellect.IsControlKeyPressed(GameControlKeys.Backward))
{
if (GetSpeed().X < Type.MaxSpeedMove)
stabilizatorBody.AddForce(ForceType.LocalAtLocalPos, TickDelta, new Vec3(-Type.Force, 0, 0), Vec3.Zero);
}
}
private void MoveLeftRight()
{
if (Intellect.IsControlKeyPressed(GameControlKeys.Rightward))
{
if (GetSpeed().X < Type.MaxSpeedMove)
stabilizatorBody.AddForce(ForceType.LocalAtLocalPos, TickDelta, new Vec3(0, -Type.Force, 0), Vec3.Zero);
}
else if (Intellect.IsControlKeyPressed(GameControlKeys.Leftward))
if (GetSpeed().X < Type.MaxSpeedMove)
stabilizatorBody.AddForce(ForceType.LocalAtLocalPos, TickDelta, new Vec3(0, Type.Force, 0), Vec3.Zero);
}
private void Rotate()
{
//Наклоны тела работают не совсем и не всегда корректно, нуждаются в доработке
//Тело наклоняется посредством изменения значения ограничителя в UniversalJoint, которое по умолчанию 0
//и не дает вертолету наклоняться
if (rotationJoint.Broken) return;
if (RL < 20)
RL += Intellect.GetControlKeyStrength(GameControlKeys.Left); //сила, с которой тело вертолета разворачивается
if (RL > -20)
RL -= Intellect.GetControlKeyStrength(GameControlKeys.Right);
if (FB1 < 30)
FB1 += Intellect.GetControlKeyStrength(GameControlKeys.Backward) * 2;
if (FB1 > 0 && FB1 < 30)
stabilizeJoint.Axis2.LimitHigh = FB1; //Наклоняет тело назад до 30 градусов
if (FB2 > -30)
FB2 -= Intellect.GetControlKeyStrength(GameControlKeys.Forward) * 2;
if (FB2 < 0 && FB2 > -30)
stabilizeJoint.Axis2.LimitLow = FB2; //Наклоняет тело вперед до 30 градусов
if (RwLw1 < 30)
RwLw1 += Intellect.GetControlKeyStrength(GameControlKeys.Leftward) * 2;
if (RwLw1 > 0 && RwLw1 < 30)
stabilizeJoint.Axis1.LimitHigh = RwLw1; //Наклоняет тело влево до 30 градусов
if (RwLw2 > -30)
RwLw2 -= Intellect.GetControlKeyStrength(GameControlKeys.Rightward) * 2;
if (RwLw2 < 0 && RwLw2 > -30)
stabilizeJoint.Axis1.LimitLow = RwLw2; //Наклоняет тело вправо до 30 градусов
stabilizatorBody.AngularVelocity = new Vec3(0, 0, RL * Type.SpeedRotations); //применение силы к телу для поворота
//по оси Z. Обратите внимание, что поворачиваться по оси Z должно не тело вертолета, а тело стабилизатора, которое
//плавно тянет за собой тело вертолета
}
private void Stabilization()
{
if (rotationJoint.Broken)
{
if (!suspensionJoint.Broken && suspensionMotor.Throttle != 0)
stabilizatorBody.AngularVelocity = new Vec3(0, 0, 3);
}
else stabilizatorBody.AddForce(ForceType.GlobalAtLocalPos, TickDelta,
-PhysicsWorld.Instance.MainScene.Gravity * Mass, Vec3.Zero);
//Автоматическое выравнивание вертолета
if (RL > 0) RL -= 0.1f;
if (RL < 0) RL += 0.1f;
if (FB1 > 0) FB1 -= 1f;
if (FB2 < 0) FB2 += 1f;
if (RwLw1 > 0) RwLw1 -= 1f;
if (RwLw2 < 0) RwLw2 += 1f;
}
//not ideal true
private Vec3 GetSpeed()
{
Vec3 v = Vec3.Zero;
Vec3 linearVelocity = stabilizatorBody.LinearVelocity;
Vec3 angularVelocity = stabilizatorBody.AngularVelocity;
//optimization
if (linearVelocity.Equals(Vec3.Zero, .2f) && angularVelocity.Equals(Vec3.Zero, .2f)) return v;
Vec3 localLinearVelocity = linearVelocity * stabilizatorBody.Rotation.GetInverse();
v.X = localLinearVelocity.X + Math.Abs(angularVelocity.X) * 2;
v.Y = localLinearVelocity.Y + Math.Abs(angularVelocity.Y) * 2;
v.Z = localLinearVelocity.Z + Math.Abs(angularVelocity.Z) * 2;
return v;
}
protected override void OnTick()
{
base.OnTick();
bool lastMotorOn = motorOn;
motorOn = Intellect != null && Intellect.IsActive();
if (motorOn != lastMotorOn)
{
if (motorOn)
SoundPlay3D(Type.SoundOn, .7f, true);
}
if (motorSoundChannel != null && !motorOn)
{
motorSoundChannel.Pause = true;
if (motorOn != lastMotorOn)
{
if (!motorOn)
SoundPlay3D(Type.SoundOff, .7f, true);
}
}
else if (motorSoundChannel != null && Intellect != null && isWorking == true)
motorSoundChannel.Pause = false;
TickTowerTurn();
firstTick = false;
Starting();
if (!isWorking)
return;
Stabilization();
if (!suspensionJoint.Broken)
{
MoveUpDown();
MoveForwardBackward();
MoveLeftRight();
Rotate();
}
else
isWorking = false;
TickMotorSound();
TickCurrentGear();
if (Intellect != null)
{
if (Intellect.IsControlKeyPressed(GameControlKeys.Fire1))
if (GunsTryFire(false))
if (Intellect.IsControlKeyPressed(GameControlKeys.Fire2))
GunsTryFire(true);
}
{
//send tower local direction to clients
if (EntitySystemWorld.Instance.IsServer())
Server_TickSendTowerLocalDirection();
//!!!!!should use for disabled renderer
if (EntitySystemWorld.Instance.IsDedicatedServer())
UpdateTowerTransform();
}
}
void Print(string Text)
{
//Метод для проверки работы кода.
//Чтобы его задействовать, впишите в нужный вам метод: Print("какой-то текст" + переменная, например Health);
//В игре в вызванной командной строке при помощи тильды "~" будет отображаться ваш текст
if (EngineConsole.Instance == null) return;
EngineConsole.Instance.Print(Text);
}
void TickMotorSound()
{
string needSoundName = null;
if (currentGear != null)
needSoundName = currentGear.SoundMotor;
if (needSoundName != currentMotorSoundName)
{
//change motor sound
currentMotorSoundName = needSoundName;
if (!string.IsNullOrEmpty(needSoundName))
{
Sound sound = SoundWorld.Instance.SoundCreate(
RelativePathUtils.ConvertToFullPath(Path.GetDirectoryName(Type.FilePath), needSoundName),
SoundMode.Mode3D | SoundMode.Loop);
if (sound != null)
{
motorSoundChannel = SoundWorld.Instance.SoundPlay(
sound, EngineApp.Instance.DefaultSoundChannelGroup, .3f, true);
motorSoundChannel.Position = Position;
switch (Type.SoundRolloffMode)
{
case DynamicType.SoundRolloffModes.Logarithmic:
motorSoundChannel.SetLogarithmicRolloff(Type.SoundMinDistance, Type.SoundMaxDistance,
Type.SoundRolloffLogarithmicFactor);
break;
case DynamicType.SoundRolloffModes.Linear:
motorSoundChannel.SetLinearRolloff(Type.SoundMinDistance, Type.SoundMaxDistance);
break;
}
motorSoundChannel.Pause = false;
}
}
}
//update motor channel position and pitch
if (motorSoundChannel != null)
{
Range speedRangeAbs = currentGear.SpeedRange;
if (speedRangeAbs.Minimum < 0 && speedRangeAbs.Maximum < 0)
speedRangeAbs = new Range(-speedRangeAbs.Maximum, -speedRangeAbs.Minimum);
Range pitchRange = currentGear.SoundMotorPitchRange;
float speedCoef = 0;
MathFunctions.Clamp(ref speedCoef, 0, 1);
//update channel
motorSoundChannel.Pitch = pitchRange.Minimum + speedCoef * pitchRange.Size();
motorSoundChannel.Position = Position;
}
}
protected override void Client_OnTick()
{
base.Client_OnTick();
TickCurrentGear();
TickMotorSound();
firstTick = false;
}
void TickCurrentGear()
{
//currently gears used only for sounds
if (currentGear == null)
return;
if (motorOn)
{
float speed = Math.Max(leftTrack.speed, rightTrack.speed);
HelicopterType.Gear newGear = null;
if (speed < currentGear.SpeedRange.Minimum || speed > currentGear.SpeedRange.Maximum)
{
//find new gear
newGear = Type.Gears.Find(delegate(HelicopterType.Gear gear)
{
return speed >= gear.SpeedRange.Minimum && speed <= gear.SpeedRange.Maximum;
});
}
if (newGear != null && currentGear != newGear)
{
//change gear
HelicopterType.Gear oldGear = currentGear;
OnGearChange(oldGear, newGear);
currentGear = newGear;
}
}
else
{
if (currentGear.Number != 0)
{
currentGear = Type.Gears.Find(delegate(HelicopterType.Gear gear)
{
return gear.Number == 0;
});
}
}
}
void OnGearChange(HelicopterType.Gear oldGear, HelicopterType.Gear newGear)
{
if (!firstTick && Health != 0)
{
bool up = Math.Abs(newGear.Number) > Math.Abs(oldGear.Number);
string soundName = up ? Type.SoundGearUp : Type.SoundGearDown;
SoundPlay3D(soundName, .7f, true);
}
}
[Browsable(false)]
public Gun MainGun
{
get { return mainGun; }
}
void UpdateTowerTransform()
{
if (towerBody == null || helicopterBody == null || mainGunAttachedObject == null)
return;
Radian horizontalAngle = towerLocalDirection.Horizontal;
Radian verticalAngle = towerLocalDirection.Vertical;
Range gunRotationRange = Type.GunRotationAngleRange * MathFunctions.PI / 180.0f;
if (verticalAngle < gunRotationRange.Minimum)
verticalAngle = gunRotationRange.Minimum;
if (verticalAngle > gunRotationRange.Maximum)
verticalAngle = gunRotationRange.Maximum;
//update tower body
towerBody.Position = GetInterpolatedPosition() +
GetInterpolatedRotation() * towerBodyLocalPosition;
towerBody.Rotation = GetInterpolatedRotation() *
new Angles(0, 0, -horizontalAngle.InDegrees()).ToQuat();
towerBody.Sleeping = true;
//update gun vertical rotation
Quat verticalRotation = new Angles(0, verticalAngle.InDegrees(), 0).ToQuat();
mainGunAttachedObject.RotationOffset = verticalRotation;
}
bool GunsTryFire(bool alternative)
{
bool fire = false;
foreach (MapObjectAttachedObject attachedObject in AttachedObjects)
{
MapObjectAttachedMapObject attachedMapObject = attachedObject as MapObjectAttachedMapObject;
if (attachedMapObject == null)
continue;
Gun gun = attachedMapObject.MapObject as Gun;
if (gun != null)
{
if (gun.TryFire(alternative))
fire = true;
}
}
return fire;
}
public void SetMomentaryTurnToPosition(Vec3 pos)
{
if (towerBody == null)
return;
Vec3 direction = pos - towerBody.Position;
towerLocalDirection = SphereDir.FromVector(Rotation.GetInverse() * direction);
needTowerLocalDirection = towerLocalDirection;
}
public void SetNeedTurnToPosition(Vec3 pos)
{
if (towerBody == null)
return;
if (Type.TowerTurnSpeed != 0)
{
Vec3 direction = pos - towerBody.Position;
needTowerLocalDirection = SphereDir.FromVector(Rotation.GetInverse() * direction);
}
else
SetMomentaryTurnToPosition(pos);
}
protected override void Server_OnClientConnectedAfterPostCreate(
RemoteEntityWorld remoteEntityWorld)
{
base.Server_OnClientConnectedAfterPostCreate(remoteEntityWorld);
RemoteEntityWorld[] worlds = new RemoteEntityWorld[] { remoteEntityWorld };
Server_SendTowerLocalDirectionToClients(worlds);
}
void Server_TickSendTowerLocalDirection()
{
float epsilon = new Degree(.5f).InRadians();
if (!towerLocalDirection.Equals(server_sentTowerLocalDirection, epsilon))
{
Server_SendTowerLocalDirectionToClients(EntitySystemWorld.Instance.RemoteEntityWorlds);
server_sentTowerLocalDirection = towerLocalDirection;
}
}
void Server_SendTowerLocalDirectionToClients(IList<RemoteEntityWorld> remoteEntityWorlds)
{
SendDataWriter writer = BeginNetworkMessage(remoteEntityWorlds, typeof(Helicopter),
(ushort)NetworkMessages.TowerLocalDirectionToClient);
writer.Write(towerLocalDirection);
EndNetworkMessage();
}
[NetworkReceive(NetworkDirections.ToClient, (ushort)NetworkMessages.TowerLocalDirectionToClient)]
void Client_ReceiveTowerLocalDirection(RemoteEntityWorld sender, ReceiveDataReader reader)
{
SphereDir value = reader.ReadSphereDir();
if (!reader.Complete())
return;
towerLocalDirection = value;
}
///////////////////////////////////////////
enum NetworkMessages
{
TowerLocalDirectionToClient,
TracksSpeedToClient,
}
///////////////////////////////////////////
}
}
Класс GameControlKeys. Добавить две новые клавиши. Движение в правый бок и в левый бок. Назначение клавиши Use поменять
- Код:
[DefaultKeyboardMouseValue( EKeys.F )]
Use,
[DefaultKeyboardMouseValue(EKeys.E)]
Rightward,
[DefaultKeyboardMouseValue(EKeys.Q)]
Leftward,
Класс PlayerIntellect. Найдите метод void ServerOrSingle_RestoreMainControlledUnit() и в нем Tank specific
- Код:
if( ControlledObject != null )
{
//Tank specific
if( ControlledObject is Tank || ControlledObject is Car )
Добавьте в условие этого метода ControlledObject is Helicopter
- Код:
if( ControlledObject != null )
{
//Tank specific
if( ControlledObject is Tank || ControlledObject is Car || ControlledObject is Helicopter )
В классе ActionGameWindow, найдите метод void UpdateHUD(). В нем под Tank specific добавьте строки с Helicopter
- Код:
//Tank specific
Tank tank = playerUnit as Tank;
if( tank != null )
weapon = tank.MainGun;
//Helicopter specific
Helicopter heli = playerUnit as Helicopter;
if (heli != null)
weapon = heli.MainGun;
А ниже в этом методе, под строкой Tank specific DrawTankGunTarget(renderer) добавьте аналогичные строки про Helicopter
- Код:
//Tank specific
DrawTankGunTarget( renderer );
//Helicopter specific
DrawHeliGunTarget(renderer);
Gedifilyte- Сообщения : 2
Рейтинг : 1724
Репутация : 0
Дата регистрации : 2019-08-12
Страница 1 из 1
Права доступа к этому форуму:
Вы не можете отвечать на сообщения
|
|
Пт Май 08, 2020 6:18 pm автор Gedifilyte
» Создание точки появления противников (Устаревшее)
Сб Дек 14, 2019 2:34 am автор Gedifilyte
» Создание инвентаря (устаревшее)
Пт Апр 13, 2018 7:43 pm автор Eris
» Программное создание Mesh
Пн Фев 05, 2018 12:05 am автор Eris
» Помогите !!! (вопросы, советы, обсуждения)
Вт Июн 06, 2017 11:39 am автор Zhuravlev Yuri
» Редакторы карт и ресурсов
Ср Май 24, 2017 10:23 pm автор Чумной Доктор
» Создание "Игрового типа" (GameType)
Ср Апр 05, 2017 2:19 am автор Filat
» Экспорт из 3ds Max
Сб Мар 11, 2017 12:22 pm автор Uggo
» Создание "Выбор персонажа"
Сб Фев 25, 2017 11:32 am автор Filat