Files
dungeons/Assets/Plugins/Zenject/OptionalExtras/SampleGame2 (Advanced)/Scripts/Enemy/States/EnemyStateAttack.cs

138 lines
4.3 KiB
C#

using System;
using UnityEngine;
using Random = UnityEngine.Random;
namespace Zenject.SpaceFighter
{
public class EnemyStateAttack : IEnemyState
{
readonly EnemyRotationHandler _rotationHandler;
readonly EnemyCommonSettings _commonSettings;
readonly AudioPlayer _audioPlayer;
readonly EnemyTunables _tunables;
readonly EnemyStateManager _stateManager;
readonly PlayerFacade _player;
readonly Settings _settings;
readonly EnemyView _view;
readonly Bullet.Factory _bulletFactory;
float _lastShootTime;
bool _strafeRight;
float _lastStrafeChangeTime;
public EnemyStateAttack(
Bullet.Factory bulletFactory,
EnemyView view,
Settings settings,
PlayerFacade player,
EnemyStateManager stateManager,
EnemyTunables tunables,
AudioPlayer audioPlayer,
EnemyCommonSettings commonSettings,
EnemyRotationHandler rotationHandler)
{
_rotationHandler = rotationHandler;
_commonSettings = commonSettings;
_audioPlayer = audioPlayer;
_tunables = tunables;
_stateManager = stateManager;
_player = player;
_settings = settings;
_view = view;
_bulletFactory = bulletFactory;
_strafeRight = Random.Range(0.0f, 1.0f) < 0.5f;
}
public void EnterState()
{
}
public void ExitState()
{
}
public void Update()
{
if (_player.IsDead)
{
_stateManager.ChangeState(EnemyStates.Idle);
return;
}
_rotationHandler.DesiredLookDir = (_player.Position - _view.Position).normalized;
// Strafe back and forth over the given interval
if (Time.realtimeSinceStartup - _lastStrafeChangeTime > _settings.StrafeChangeInterval)
{
_lastStrafeChangeTime = Time.realtimeSinceStartup;
_strafeRight = !_strafeRight;
}
// Shoot every X seconds
if (Time.realtimeSinceStartup - _lastShootTime > _settings.ShootInterval)
{
_lastShootTime = Time.realtimeSinceStartup;
Fire();
}
// If the player runs away then chase them
if ((_player.Position - _view.Position).magnitude > _commonSettings.AttackDistance + _settings.AttackRangeBuffer)
{
_stateManager.ChangeState(EnemyStates.Follow);
}
}
public void FixedUpdate()
{
// Strafe to avoid getting hit too easily
if (_strafeRight)
{
_view.AddForce(_view.RightDir * _settings.StrafeMultiplier * _tunables.Speed);
}
else
{
_view.AddForce(-_view.RightDir * _settings.StrafeMultiplier * _tunables.Speed);
}
}
void Fire()
{
var bullet = _bulletFactory.Create(
_settings.BulletSpeed, _settings.BulletLifetime, BulletTypes.FromEnemy);
// Randomize our aim a bit
var accuracy = Mathf.Clamp(_tunables.Accuracy, 0, 1);
var maxError = 1.0f - accuracy;
var error = Random.Range(0, maxError);
if (Random.Range(0.0f, 1.0f) < 0.5f)
{
error *= -1;
}
var thetaError = error * _settings.ErrorRangeTheta;
bullet.transform.position = _view.Position + _view.LookDir * _settings.BulletOffsetDistance;
bullet.transform.rotation = Quaternion.AngleAxis(thetaError, Vector3.forward) * _view.Rotation;
_audioPlayer.Play(_settings.ShootSound, _settings.ShootSoundVolume);
}
[Serializable]
public class Settings
{
public AudioClip ShootSound;
public float ShootSoundVolume = 1.0f;
public float BulletLifetime;
public float BulletSpeed;
public float BulletOffsetDistance;
public float ShootInterval;
public float ErrorRangeTheta;
public float AttackRangeBuffer;
public float StrafeMultiplier;
public float StrafeChangeInterval;
}
}
}