Update Project
This commit is contained in:
+137
@@ -0,0 +1,137 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3d2bd141d86c3fb40a0a616c19e6de0c
|
||||
timeCreated: 1456620041
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using Random = UnityEngine.Random;
|
||||
|
||||
namespace Zenject.SpaceFighter
|
||||
{
|
||||
public class EnemyStateFollow : IEnemyState
|
||||
{
|
||||
readonly EnemyRotationHandler _rotationHandler;
|
||||
readonly EnemyCommonSettings _commonSettings;
|
||||
readonly Settings _settings;
|
||||
readonly EnemyTunables _tunables;
|
||||
readonly EnemyStateManager _stateManager;
|
||||
readonly EnemyView _view;
|
||||
readonly PlayerFacade _player;
|
||||
|
||||
bool _strafeRight;
|
||||
float _lastStrafeChangeTime;
|
||||
|
||||
public EnemyStateFollow(
|
||||
PlayerFacade player,
|
||||
EnemyView view,
|
||||
EnemyStateManager stateManager,
|
||||
EnemyTunables tunables,
|
||||
Settings settings,
|
||||
EnemyCommonSettings commonSettings,
|
||||
EnemyRotationHandler rotationHandler)
|
||||
{
|
||||
_rotationHandler = rotationHandler;
|
||||
_commonSettings = commonSettings;
|
||||
_settings = settings;
|
||||
_tunables = tunables;
|
||||
_stateManager = stateManager;
|
||||
_view = view;
|
||||
_player = player;
|
||||
}
|
||||
|
||||
public void EnterState()
|
||||
{
|
||||
_strafeRight = Random.Range(0, 1) == 0;
|
||||
_lastStrafeChangeTime = Time.realtimeSinceStartup;
|
||||
}
|
||||
|
||||
public void ExitState()
|
||||
{
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (_player.IsDead)
|
||||
{
|
||||
_stateManager.ChangeState(EnemyStates.Idle);
|
||||
return;
|
||||
}
|
||||
|
||||
var distanceToPlayer = (_player.Position - _view.Position).magnitude;
|
||||
|
||||
// Always look towards the player
|
||||
_rotationHandler.DesiredLookDir = (_player.Position - _view.Position).normalized;
|
||||
|
||||
// Strafe back and forth over the given interval
|
||||
// This helps avoiding being too easy a target
|
||||
if (Time.realtimeSinceStartup - _lastStrafeChangeTime > _settings.StrafeChangeInterval)
|
||||
{
|
||||
_lastStrafeChangeTime = Time.realtimeSinceStartup;
|
||||
_strafeRight = !_strafeRight;
|
||||
}
|
||||
|
||||
if (distanceToPlayer < _commonSettings.AttackDistance)
|
||||
{
|
||||
_stateManager.ChangeState(EnemyStates.Attack);
|
||||
}
|
||||
}
|
||||
|
||||
public void FixedUpdate()
|
||||
{
|
||||
MoveTowardsPlayer();
|
||||
Strafe();
|
||||
}
|
||||
|
||||
void Strafe()
|
||||
{
|
||||
// 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 MoveTowardsPlayer()
|
||||
{
|
||||
var playerDir = (_player.Position - _view.Position).normalized;
|
||||
|
||||
_view.AddForce(playerDir * _tunables.Speed);
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class Settings
|
||||
{
|
||||
public float StrafeMultiplier;
|
||||
public float StrafeChangeInterval;
|
||||
public float TeleportNewDistance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f6b8435c02df92747b53470f32656b93
|
||||
timeCreated: 1456620041
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using Random = UnityEngine.Random;
|
||||
|
||||
namespace Zenject.SpaceFighter
|
||||
{
|
||||
public class EnemyStateIdle : IEnemyState
|
||||
{
|
||||
readonly EnemyRotationHandler _rotationHandler;
|
||||
readonly Settings _settings;
|
||||
readonly EnemyView _view;
|
||||
|
||||
Vector3 _startPos;
|
||||
float _theta;
|
||||
Vector3 _startLookDir;
|
||||
|
||||
public EnemyStateIdle(
|
||||
EnemyView view, Settings settings,
|
||||
EnemyRotationHandler rotationHandler)
|
||||
{
|
||||
_rotationHandler = rotationHandler;
|
||||
_settings = settings;
|
||||
_view = view;
|
||||
}
|
||||
|
||||
public void EnterState()
|
||||
{
|
||||
_startPos = _view.Position;
|
||||
_theta = Random.Range(0, 2.0f * Mathf.PI);
|
||||
_startLookDir = _view.LookDir;
|
||||
}
|
||||
|
||||
public void ExitState()
|
||||
{
|
||||
}
|
||||
|
||||
// Just add a bit of subtle movement
|
||||
public void Update()
|
||||
{
|
||||
_theta += Time.deltaTime * _settings.Frequency;
|
||||
|
||||
_view.Position = _startPos + _view.RightDir * _settings.Amplitude * Mathf.Sin(_theta);
|
||||
|
||||
_rotationHandler.DesiredLookDir = _startLookDir;
|
||||
}
|
||||
|
||||
public void FixedUpdate()
|
||||
{
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class Settings
|
||||
{
|
||||
public float Amplitude;
|
||||
public float Frequency;
|
||||
}
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7a99ffa8c241c8a4e97392c7903712f0
|
||||
timeCreated: 1456618194
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user