Platformer example started

This commit is contained in:
ThomasCharester committed 2026-02-22 13:59:04 +03:00
1 parent efcfaae647
commit 9f026b76d6
325 files changed
+23540 -270

No files matched your search

+4
View File
@@ -26,6 +26,10 @@ namespace Code.Debug
{
_stateMachine.SwitchState(AppStates.Gameplay).AllowStateTransition(AppStates.MainMenu);
}
public void SwitchPlatformer()
{
_stateMachine.SwitchState(AppStates.Platformer).AllowStateTransition(AppStates.MainMenu);
}
[SerializeField] private List<Button> buttons;
+3
View File
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 36ea829cf56649b4a025c709390a457c
timeCreated: 1770736333
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 95e867912f25463e8ae222819491ee0d
timeCreated: 1770905985
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 9df78f95b3ad416cb1a0a786f0b22365
timeCreated: 1771423438
@@ -0,0 +1,59 @@
using System;
using System.Collections.Generic;
using DG.Tweening;
using DG.Tweening.Core;
using DG.Tweening.Plugins.Options;
using UnityEngine;
namespace Code.Example.Platformer.Entity.Enemies
{
public class Bee : Entity
{
[SerializeField] private List<Transform> partolPoints;
private bool _onPatrol;
private bool _onPatrolMoveDamnit;
private int _currentPartolPoint;
private Transform _currentTarget;
private TweenerCore<Vector3, Vector3, VectorOptions> _patrolAction;
protected override void Move()
{
if (_onPatrol && !_onPatrolMoveDamnit)
{
_onPatrolMoveDamnit = true;
_patrolAction = transform.DOMove(partolPoints[_currentPartolPoint].position, 3f);
_patrolAction.onComplete += OnControlPointReached;
}
else
{
var direction = _currentTarget.position - transform.position;
direction.Normalize();
var targetPosition = _currentTarget.position + direction * -2f;
UnityEngine.Debug.DrawLine(transform.position, targetPosition, Color.red);
transform.DOMove(_currentTarget.position, 2f).onComplete += OnControlPointReached;
}
}
private void OnControlPointReached()
{
if (++_currentPartolPoint >= partolPoints.Count) _currentPartolPoint = 0;
_onPatrolMoveDamnit = false;
}
public void GotTarget(Transform other)
{
_onPatrol = false;
_currentTarget = other;
_patrolAction?.Complete();
}
public void LostTarget()
{
_onPatrol = true;
_currentTarget = null;
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 2abf74ae7a894c5abc850fe852fdf4e7
timeCreated: 1771433363
@@ -0,0 +1,14 @@
using System;
using UnityEngine;
namespace Code.Example.Platformer.Entity.Enemies
{
public class BeeRadar : MonoBehaviour
{
[SerializeField] private Bee bee;
private void OnTriggerEnter2D(Collider2D other) => bee.GotTarget(other.transform);
private void OnTriggerExit2D(Collider2D other) => bee.LostTarget();
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 582294c360404f6d952d9e28bde1fbea
timeCreated: 1771434696
@@ -0,0 +1,32 @@
using Code.Infrastructure.Configs;
using UnityEngine;
namespace Code.Example.Platformer.Entity.Enemies
{
public class Snail : Entity
{
[SerializeField] private Vector2 groundLeft;
[SerializeField] private Vector2 groundRight;
[SerializeField] private bool _directionRight;
protected override void Move()
{
CheckupDirection();
rigidbody2D.linearVelocityX = _directionRight ? 0.5f : -0.5f;
}
protected override void HandleFlipX() => spriteRenderer.flipX = rigidbody2D.linearVelocity.x > -0.01f;
private void CheckupDirection()
{
if (_directionRight)
{
if (!Physics2D.OverlapPoint((Vector2)transform.position + groundRight,
LayerMasks.Masks[LayerMaskType.PlatformerGround]))
_directionRight = false;
}
else if (!Physics2D.OverlapPoint((Vector2)transform.position + groundLeft,
LayerMasks.Masks[LayerMaskType.PlatformerGround]))
_directionRight = true;
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 4bb753139de944f69f426cbc1ec9ec92
timeCreated: 1771430576
@@ -0,0 +1,44 @@
using System;
using Code.Infrastructure.Configs;
using UnityEngine;
namespace Code.Example.Platformer.Entity
{
public abstract class Entity : MonoBehaviour
{
private static readonly int VelocityY = Animator.StringToHash("VelocityY");
private static readonly int VelocityX = Animator.StringToHash("VelocityX");
private static readonly int OnGround = Animator.StringToHash("OnGround");
[SerializeField] protected Rigidbody2D rigidbody2D;
[SerializeField] protected Animator animator;
[SerializeField] protected SpriteRenderer spriteRenderer;
[SerializeField] private Vector2 groundPoint;
protected bool onGround;
protected virtual void Update()
{
animator.SetFloat(VelocityX, rigidbody2D.linearVelocityX);
animator.SetFloat(VelocityY, rigidbody2D.linearVelocityY);
}
protected virtual void HandleFlipX() => spriteRenderer.flipX = rigidbody2D.linearVelocity.x < 0.01f;
protected virtual void FixedUpdate()
{
onGround = CheckGround();
animator.SetBool(OnGround, onGround);
Move();
if(rigidbody2D.linearVelocity.x is > 0.01f or < -0.01f) HandleFlipX();
}
protected virtual bool CheckGround()
{
UnityEngine.Debug.DrawLine(transform.position,(Vector2)transform.position + groundPoint, Color.green);
return Physics2D.OverlapPoint((Vector2)transform.position + groundPoint, LayerMasks.Masks[LayerMaskType.PlatformerGround]);
}
protected abstract void Move();
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f4b8cd0fdb9e4c258acd1f5898f193d1
timeCreated: 1770905992
@@ -0,0 +1,32 @@
using System;
using Code.Infrastructure.Generators;
using UnityEngine.AddressableAssets;
namespace Code.Example.Platformer.Entity
{
[Config("Configs/Gameplay/Platformer/EnemySettings", true)]
public class PlatformerEnemySettings
{
[ToConfig] public PlatformerEnemyData racerData;
[ToConfig] public AssetReference prefabReference;
}
[Serializable]
public struct PlatformerEnemyData
{
public string name;
public float speed;
public int damage;
public PlatformerEnemyType type;
}
public enum PlatformerEnemyType
{
Dummy
}
public class PlatformerEnemyFactory
{
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 49fd97d8a6464d3e86d6ea215949d1f5
timeCreated: 1771423258
@@ -0,0 +1,52 @@
using System;
using Code.Infrastructure.Input;
using Reflex.Attributes;
using UnityEngine;
using UnityEngine.InputSystem;
namespace Code.Example.Platformer.Entity
{
public class PlayerEntity : Entity
{
private IInputService _inputService;
[Inject]
private void Construct(IInputService inputService)
{
_inputService = inputService;
_inputService.BindActionPerformed((int)ActionMappings.Gameplay, (int)GameplayActions.Move,
MovementPerformed);
_inputService.BindActionCancelled((int)ActionMappings.Gameplay, (int)GameplayActions.Move,
MovementCancelled);
_inputService.BindActionPerformed((int)ActionMappings.Gameplay, (int)GameplayActions.Brake, JumpPerformed);
}
private void OnDestroy()
{
_inputService.UnbindActionPerformed((int)ActionMappings.Gameplay, (int)GameplayActions.Move,
MovementPerformed);
_inputService.UnbindActionCancelled((int)ActionMappings.Gameplay, (int)GameplayActions.Move,
MovementCancelled);
_inputService.UnbindActionPerformed((int)ActionMappings.Gameplay, (int)GameplayActions.Brake, JumpPerformed);
}
protected override void Move()
{
rigidbody2D.linearVelocityX = _moveDirection.x * 5f;
}
private Vector2 _moveDirection;
private void MovementPerformed(InputAction.CallbackContext callbackContext) =>
_moveDirection = callbackContext.ReadValue<Vector2>();
private void MovementCancelled(InputAction.CallbackContext callbackContext) =>
_moveDirection = Vector2.zero;
private void JumpPerformed(InputAction.CallbackContext callbackContext)
{
if (!onGround) return;
rigidbody2D.AddForceY(100f);
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6d5abb60d772491cbad21bb3a3689054
timeCreated: 1770908525
@@ -0,0 +1,16 @@
using UnityEngine;
namespace Code.Example.Platformer
{
public class PlatformerSceneData : MonoBehaviour
{
public Transform Player;
public LevelData levelData;
}
[System.Serializable]
public struct LevelData
{
// public List<Transform> enemyPoints;
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: fdfd83cbde8f4fbd97802ac19f2f32e5
timeCreated: 1771423037
@@ -0,0 +1,28 @@
using Code.Infrastructure.EventBus;
using Code.Infrastructure.SceneLoader;
using Reflex.Core;
using UnityEngine;
namespace Code.Example.Platformer
{
public class PlatformerSceneInstaller : MonoBehaviour, IInstaller
{
// [SerializeField] private PlatformerCanvas gameplayPlatformerCanvas;
public void InstallBindings(ContainerBuilder containerBuilder)
{
// containerBuilder.RegisterValue(gameplayPlatformerCanvas);
containerBuilder.OnContainerBuilt += OnContainerBuild;
}
private void OnContainerBuild(Container container)
{
// gameplayPlatformerCanvas.GameplayPlatformerCanvas.worldCamera =
// container.Resolve<CameraStateMachineContext>().cameraLoadedData.Camera;
//
container.Resolve<EventBus>()
.RaiseEvent<IOnPlatformerSceneLoadedHandler>(x => x.OnPlatformerSceneInitialized(container));
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 0aa23aea61d74467889be39a550c9922
timeCreated: 1770736749
@@ -0,0 +1,65 @@
using Code.Infrastructure.App;
using Code.Infrastructure.Camera;
using Code.Infrastructure.EventBus;
using Code.Infrastructure.Generators;
using Code.Infrastructure.Input;
using Code.Infrastructure.Loadings;
using Code.Infrastructure.SceneLoader;
using Code.Infrastructure.UI;
using Reflex.Core;
using Unity.Cinemachine;
using UnityEngine.SceneManagement;
namespace Code.Example.Platformer
{
[State(typeof(AppStates),typeof(AppStateMachineContext))]
[StateRaisingEvent]
public partial class PlatformerState : IOnPlatformerSceneLoadedHandler, ICinematicMachineHandle
{
public PlatformerState(AppStateMachineContext context, EventBus eventBus) : base(context, eventBus)
{
}
public override AppStates myState => AppStates.Platformer;
protected override void OnEnterState()
{
EventBus.Subscribe(this);
_loading = new(2, LoadingCompleted);
Context.UIService.OpenPanel(UIPanelType.Loading);
Context.SceneLoader.LoadSceneAsync(SceneId.Platformer, LoadSceneMode.Single).Forget();
Context.InputService.EnableMap(ActionMappings.Gameplay);
Context.CameraFactory.LoadCinemachineCamera(CameraMode.Platformer).Forget();
}
private Loading _loading;
private void LoadingCompleted()
{
Context.UIService.ClosePanel(UIPanelType.Loading);
}
protected override void OnExitState()
{
Context.CameraFactory.ReleaseCinemachineCamera(CameraMode.Platformer);
Context.InputService.DisableMap(ActionMappings.Gameplay);
EventBus.Unsubscribe(this);
}
public void OnPlatformerSceneLoaded()
{
}
public void OnPlatformerSceneInitialized(Container container)
{
_loading.DoProgress();
}
public void CinemachineLoaded(CinemachineCamera cinemachineCamera)
{
_loading.DoProgress();
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 823e3299b52c48a8869581e7c27ef9a8
timeCreated: 1770736342
+3
View File
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: b5da862624174a36ac3ace9058b79513
timeCreated: 1770737039
@@ -0,0 +1,10 @@
using UnityEngine;
namespace Code.Example.Platformer.UI
{
public class PlatformerCanvas : MonoBehaviour
{
[SerializeField] private Canvas gameplayPlatformerCanvas;
public Canvas GameplayPlatformerCanvas => gameplayPlatformerCanvas;
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 964ac33334f64f8d917b153e9890e155
timeCreated: 1770737062
@@ -0,0 +1,65 @@
using System;
using System.Collections.Generic;
using System.IO;
using Newtonsoft.Json;
using UnityEngine;
namespace Code.Example.Race
{
public class PlayerPrefsRacePoopshitter
{
private List<RaceData> _races = new();
public PlayerPrefsRacePoopshitter()
{
GetRaces();
}
public List<RaceData> GetRaces()
{
var path = Path.Combine(Application.persistentDataPath,"raceData.json");
using (StreamReader reader = new(path))
{
var json = reader.ReadToEnd();
_races = JsonConvert.DeserializeObject<List<RaceData>>(json);
}
// for (int i = 0; i < _raceCount; i++)
// races.Add(new(
// PlayerPrefs.GetFloat($"Race{i}"),
// PlayerPrefs.GetInt($"Place{i}")));
return _races;
}
public void AddRace(RaceData race)
{
// PlayerPrefs.SetFloat($"Race{_raceCount}", race.raceTimeSeconds);
// PlayerPrefs.SetInt($"Place{_raceCount}", race.place);
// PlayerPrefs.SetInt("RaceCount", ++_raceCount);
_races.Add(race);
var json = JsonConvert.SerializeObject(_races, Formatting.Indented);
var path = Path.Combine(Application.persistentDataPath,"raceData.json");
using (StreamWriter writer = new(path))
{
writer.Write(json);
}
}
}
[Serializable]
public struct RaceData
{
public float raceTimeSeconds;
public int place;
public RaceData(float raceTimeSeconds, int place)
{
this.raceTimeSeconds = raceTimeSeconds;
this.place = place;
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: e984eddc1697449487c9a790345dfb0b
timeCreated: 1770653240
+6 -1
View File
@@ -4,7 +4,8 @@ using System.Linq;
using Code.Example.Race.Racer;
using Code.Example.Race.Track;
using Code.Infrastructure.EventBus;
using Code.Infrastructure.Loadings;
using Code.Infrastructure.Loadings;
using UnityEngine;
namespace Code.Example.Race
{
@@ -28,8 +29,12 @@ namespace Code.Example.Race
RandomizeRacers(raceTrackData.trackData.RacerPoints.Count);
}
private float _timeStart;
public float RaceTime => Time.time - _timeStart;
public void StartRacers()
{
_timeStart = Time.time;
foreach (var racer in PlacedRacers)
{
racer.StartRacer();
@@ -8,5 +8,29 @@ namespace Code.Example.Race.Racer.AI
{
SteeringInput = steeringLinear;
}
protected override void Brake()
{
if (CarRb.linearVelocity.magnitude > 10f && (SteeringInput.y > CarRb.linearVelocity.y || SteeringInput.x > CarRb.linearVelocity.x))
{
foreach (var wheel in wheels)
{
wheel.wheelCollider.brakeTorque = 100 * racer.Data.brakeAcceleration * Time.fixedDeltaTime;
}
// carLights.isBackLightOn = true;
// carLights.OperateBackLights();
}
else
{
foreach (var wheel in wheels)
{
wheel.wheelCollider.brakeTorque = 0;
}
// carLights.isBackLightOn = false;
// carLights.OperateBackLights();
}
}
}
}
@@ -11,6 +11,7 @@ namespace Code.Example.Race.Racer.AI
{
[Inject] private EventBus _eventBus;
[SerializeField] private CarControllerRB carController;
public override void SetData(RacerData data)
{
Data = data;
@@ -10,7 +10,7 @@ namespace Code.Example.Race.Racer.AI.ID.Behaviours
steering.linear = transform.position - target.position;
steering.linear.Normalize();
steering.linear *= agent.Data.maxAcceleration;
// steering.linear *= agent.Data.maxAcceleration;
return steering;
}
}
@@ -0,0 +1,42 @@
using UnityEngine;
using System.Collections;
namespace Code.Example.Race.Racer.AI.ID.Behaviours
{
public class Pursue : Seek
{
public float maxPrediction;
private GameObject _targetAux;
private GameObject _target;
public void Awake()
{
_targetAux = _target;
_target = new GameObject();
}
void OnDestroy()
{
Destroy(_targetAux);
}
public override Steering GetSteering(Transform targetTransform)
{
var direction = _targetAux.transform.position - transform.position;
var distance = direction.magnitude;
var speed = agent.CarRigidbody.linearVelocity.magnitude;
float prediction;
if (speed <= distance / maxPrediction)
prediction = maxPrediction;
else
prediction = distance / speed;
_target.transform.position = _targetAux.transform.position;
// _target.transform.position += targetAgent.velocity * prediction;
return base.GetSteering(_target.transform);
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: c3a071d2cab443528dd16bdc044bab65
timeCreated: 1770998212
@@ -11,8 +11,7 @@ namespace Code.Example.Race.Racer.AI.ID.Behaviours
steering.linear = target.position - transform.position;
UnityEngine.Debug.DrawRay(transform.position, steering.linear, Color.yellow, 5f);
// steering.linear *= agent.Data.maxAcceleration;
steering.linear.Normalize();
UnityEngine.Debug.Log(steering.linear);
steering.linear.Normalize();
return steering;
}
}
@@ -34,7 +34,7 @@ namespace Code.Example.Race.Racer
public List<Wheel> wheels;
protected Rigidbody CarRb;
protected Rigidbody CarRb;
protected Vector2 SteeringInput = Vector2.zero;
public abstract void SetSteering(Vector2 steeringLinear);
@@ -16,9 +16,9 @@ namespace Code.Example.Race.Racer.Player
{
_inputService = inputService;
_inputService.BindActionPerformed((int)ActionMappings.Gameplay, (int)GameplayActions.Move, MovementPerformed);
_inputService.BindActionCancel((int)ActionMappings.Gameplay, (int)GameplayActions.Move, MovementEnded);
_inputService.BindActionCancelled((int)ActionMappings.Gameplay, (int)GameplayActions.Move, MovementEnded);
_inputService.BindActionPerformed((int)ActionMappings.Gameplay, (int)GameplayActions.Brake, BrakePerformed);
_inputService.BindActionCancel((int)ActionMappings.Gameplay, (int)GameplayActions.Brake, BrakeEnded);
_inputService.BindActionCancelled((int)ActionMappings.Gameplay, (int)GameplayActions.Brake, BrakeEnded);
}
private void MovementPerformed(InputAction.CallbackContext context) => MovementInput = context.ReadValue<Vector2>();
@@ -33,9 +33,9 @@ namespace Code.Example.Race.Racer.Player
{
if (_inputService == null) return;
_inputService.UnbindActionPerformed((int)ActionMappings.Gameplay, (int)GameplayActions.Move, MovementPerformed);
_inputService.UnbindActionCanceled((int)ActionMappings.Gameplay, (int)GameplayActions.Move, MovementEnded);
_inputService.UnbindActionCancelled((int)ActionMappings.Gameplay, (int)GameplayActions.Move, MovementEnded);
_inputService.UnbindActionPerformed((int)ActionMappings.Gameplay, (int)GameplayActions.Brake, BrakePerformed);
_inputService.UnbindActionCanceled((int)ActionMappings.Gameplay, (int)GameplayActions.Brake, BrakeEnded);
_inputService.UnbindActionCancelled((int)ActionMappings.Gameplay, (int)GameplayActions.Brake, BrakeEnded);
}
}
}
@@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using Code.Infrastructure.UI;
using DG.Tweening;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
namespace Code.Example.Race.UI
{
public class PlayerScores : UIPanel
{
[SerializeField] private Image image;
[SerializeField] private TMP_Text scoreText;
[SerializeField] private Color shownColor;
[SerializeField] private Color hiddenColor;
public void SetText(List<RaceData> scores)
{
scoreText.text = "";
foreach (var score in scores)
{
var t = TimeSpan.FromSeconds(score.raceTimeSeconds);
scoreText.text += $@"{score.place} место за {t:mm\:ss\:fff}\n";
}
}
public override void Open(Action callback = null)
{
image.DOColor(shownColor, 1f);
scoreText.DOColor(shownColor, 1f).onComplete = () => callback?.Invoke();
}
public override void Close(Action callback = null)
{
image.DOColor(hiddenColor, 1f);
scoreText.DOColor(hiddenColor, 1f).onComplete = () => callback?.Invoke();
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 250fd47281f3493e86590f89511bba17
timeCreated: 1770654299
+2 -2
View File
@@ -17,13 +17,13 @@ namespace Code.Example.Race.UI
public void SetText(string text) => winText.text = text;
public override void Open(Action callback = null)
{
image.DOColor(shownColor, 1f).onComplete = () => callback?.Invoke();
image.DOColor(shownColor, 1f);
winText.DOColor(shownColor, 1f).onComplete = () => callback?.Invoke();
}
public override void Close(Action callback = null)
{
image.DOColor(hiddenColor, 1f).onComplete = () => callback?.Invoke();
image.DOColor(hiddenColor, 1f);
winText.DOColor(hiddenColor, 1f).onComplete = () => callback?.Invoke();
}
}
@@ -10,7 +10,8 @@ namespace Code.Infrastructure.App
{
Bootstrap,
Gameplay,
MainMenu
MainMenu,
Platformer
}
public class AppStateMachineContext
@@ -9,6 +9,7 @@ using Code.Infrastructure.UI;
using Code.Infrastructure.Volume;
using Reflex.Core;
using Reflex.Enums;
using Reflex.Injectors;
using Unity.Cinemachine;
using UnityEngine;
using UnityEngine.Rendering.Universal;
@@ -26,7 +27,8 @@ namespace Code.Infrastructure.App
IVolumeLoaded,
IAudioSourcePoolInitializedHandle,
IAudioConfigsLoadedHandle,
ICinematicMachineHandle
ICinematicMachineHandle,
ILayerMasksInitializedHandle
{
public void InstallBindings(ContainerBuilder containerBuilder)
{
@@ -64,7 +66,6 @@ namespace Code.Infrastructure.App
Resolution.Eager);
containerBuilder.RegisterType(typeof(AudioService), new[] { typeof(IAudioService) }, Lifetime.Singleton,
Resolution.Eager);
}
private void InitLoadings()
@@ -79,8 +80,9 @@ namespace Code.Infrastructure.App
// Audio Factory
// Audio Pool
// Cinemachine Camera
_initialLoading = new Loading(10, () => EssentialLoadEnded(_thatRightContainer));
// Layer masks
_initialLoading = new Loading(11, () => EssentialLoadEnded(_thatRightContainer));
_ui2CamLoading = new Loading(2,
() =>
{
@@ -99,7 +101,9 @@ namespace Code.Infrastructure.App
_thatRightContainer = container;
container.Resolve<EventBus.EventBus>().Subscribe(this);
ConstructorInjector.Construct(typeof(LayerMasks), container);
var cameraFactory = container.Resolve<CameraFactory>();
cameraFactory.CreateCameraStateMachine(container.Resolve<CameraStateMachine>())
.Forget();
@@ -109,7 +113,8 @@ namespace Code.Infrastructure.App
{
container.Resolve<EventBus.EventBus>().Unsubscribe(this);
container.Resolve<AppStateMachine>().SwitchState(AppStates.Bootstrap)
.AllowStateTransition(AppStates.Gameplay);
.AllowStateTransition(AppStates.Gameplay)
.AllowStateTransition(AppStates.Platformer);
container.Resolve<AppStateMachineContext>().StateMachine = container.Resolve<AppStateMachine>();
}
@@ -127,7 +132,8 @@ namespace Code.Infrastructure.App
{
_thatRightContainer.Resolve<CameraStateMachineContext>().cameraLoadedData = data;
_thatRightContainer.Resolve<CameraStateMachine>().SwitchState(CameraMode.None)
.AllowStateTransition(CameraMode.ThirdPerson);
.AllowStateTransition(CameraMode.ThirdPerson)
.AllowStateTransition(CameraMode.Platformer);
data.Camera.GetUniversalAdditionalCameraData().renderPostProcessing = true;
@@ -198,5 +204,10 @@ namespace Code.Infrastructure.App
{
_initialLoading.DoProgress();
}
public void LayerMasksInitialized()
{
_initialLoading.DoProgress();
}
}
}
@@ -5,7 +5,6 @@ using Code.Infrastructure.SceneLoader;
using Reflex.Core;
using Reflex.Enums;
using UnityEngine;
using UnityEngine.Serialization;
using Resolution = Reflex.Enums.Resolution;
namespace Code.Infrastructure.App.SceneInstallers
@@ -23,6 +22,8 @@ namespace Code.Infrastructure.App.SceneInstallers
containerBuilder.RegisterValue(raceTrackData);
containerBuilder.RegisterType(typeof(RaceGame), Lifetime.Scoped,
Resolution.Lazy);
containerBuilder.RegisterType(typeof(PlayerPrefsRacePoopshitter), Lifetime.Scoped,
Resolution.Lazy);
containerBuilder.OnContainerBuilt += PostInstall;
}
@@ -48,11 +48,13 @@ namespace Code.Infrastructure.App.States
// Factory
// PlayerCounter
// WinScreen
// ScoreScreen
// CinemachineCamera
_gameplayLoading = new Loading(6, GameplayLoadingCompleted);
_gameplayLoading = new Loading(7, GameplayLoadingCompleted);
Context.UIService.TryLoadPanel(UIPanelType.PlayerScoreCounter);
Context.UIService.TryLoadPanel(UIPanelType.WinScreen);
Context.UIService.TryLoadPanel(UIPanelType.PlayerScores);
Context.SceneLoader.LoadSceneAsync(SceneId.Gameplay, LoadSceneMode.Single).Forget();
Context.InputService.EnableMap(ActionMappings.Gameplay);
Context.CameraFactory.LoadCinemachineCamera(CameraMode.ThirdPerson).Forget();
@@ -73,14 +75,15 @@ namespace Code.Infrastructure.App.States
_raceGame.PlacedRacers[0].gameObject.transform;
Context.UIService.ClosePanel(UIPanelType.Loading);
_raceGame.StartRacers();
}
protected override void OnExitState()
{
Context.InputService.DisableMap(ActionMappings.Gameplay);
{
Context.UIService.TryRemovePanel(UIPanelType.PlayerScoreCounter);
Context.UIService.TryRemovePanel(UIPanelType.WinScreen);
Context.UIService.TryRemovePanel(UIPanelType.PlayerScores);
Context.CameraFactory.ReleaseCinemachineCamera(CameraMode.ThirdPerson);
Context.InputService.DisableMap(ActionMappings.Gameplay);
@@ -125,9 +128,14 @@ namespace Code.Infrastructure.App.States
for (var i = 0; i < cachedScores.Count; i++)
if (cachedScores[i].Key.Data.type == RacerType.Player) id = i + 1;
UNTILTHEYFIXCONTAINERS.Resolve<PlayerPrefsRacePoopshitter>().AddRace(new(_raceGame.RaceTime, id));
var winText = $@"{id} МЕСТО\n";
winScreen.SetText(winText);
var getPanel = Context.UIService.TryGetPanel(UIPanelType.PlayerScores);
((PlayerScores)getPanel)
.SetText(UNTILTHEYFIXCONTAINERS.Resolve<PlayerPrefsRacePoopshitter>().GetRaces());
Context.UIService.ClosePanel(UIPanelType.PlayerScoreCounter);
Context.UIService.OpenPanel(UIPanelType.WinScreen);
@@ -137,7 +145,11 @@ namespace Code.Infrastructure.App.States
private async UniTaskVoid EndTheGame()
{
await UniTask.WaitForSeconds(3f);
Context.UIService.ClosePanel(UIPanelType.WinScreen);
Context.UIService.OpenPanel(UIPanelType.PlayerScores);
await UniTask.WaitForSeconds(5f);
Context.UIService.OpenPanel(UIPanelType.Loading);
Context.StateMachine.SwitchState(AppStates.MainMenu).AllowStateTransition(AppStates.Gameplay);
}
@@ -151,7 +163,7 @@ namespace Code.Infrastructure.App.States
public void UILoaded(UIPanelType uiPanelType)
{
if(uiPanelType == UIPanelType.WinScreen)
if(uiPanelType is UIPanelType.WinScreen or UIPanelType.PlayerScores)
{
_gameplayLoading.DoProgress();
return;
@@ -13,18 +13,16 @@ namespace Code.Infrastructure.App.States
[State(typeof(AppStates),typeof(AppStateMachineContext))]
[StateRaisingEvent]
public partial class MainMenuState : IUIPanelLoaded, IReadyToPlayHandle, IOnMainMenuSceneLoadedHandler
{
private EventBus.EventBus _eventBus;
{
public MainMenuState(AppStateMachineContext context, EventBus.EventBus eventBus) : base(context,eventBus)
{
_eventBus = eventBus;
{
}
public override AppStates myState => AppStates.MainMenu;
private Loading _loading;
protected override void OnEnterState()
{
_eventBus.Subscribe(this);
EventBus.Subscribe(this);
_loading = new Loading(2, LoadComplete);
@@ -38,7 +36,7 @@ namespace Code.Infrastructure.App.States
{
// Context.AudioFactory.ReleaseAudios(AudioNames.UISounds);
Context.UIService.TryRemovePanel(UIPanelType.DebugSceneChooser);
_eventBus.Unsubscribe(this);
EventBus.Unsubscribe(this);
}
public void UILoaded(UIPanelType uiPanelType)
@@ -10,7 +10,8 @@ namespace Code.Infrastructure.Camera
public enum CameraMode
{
None,
ThirdPerson
ThirdPerson,
Platformer
}
[Config("Configs/Camera/CameraConfig")]
@@ -6,29 +6,11 @@ namespace Code.Infrastructure.Camera.CameraStates
// [State(typeof(CameraMode),typeof(CameraStateMachineContext))]
public abstract class BaseCameraState : BaseState<CameraMode, CameraStateMachineContext>
{
protected EventBus.EventBus _eventBus;
// Трансформ объекта, за которым следует камера
protected Transform FollowTransform;
protected EventBus.EventBus EventBus;
// Позиция следования: текущая сглаженная позиция и горизонтальное направление камеры
protected Vector3 CurrentFollowPosition;
// Целевой вертикальный угол камеры (наклон вверх/вниз)
protected float TargetVerticalAngle;
// Текущая и целевая дистанция камеры от цели
protected float CurrentDistance, TargetDistance;
// Исходные значения дистанции для восстановления
protected float OriginalDefaultDistance, OriginalMinDistance, OriginalMaxDistance;
// Горизонтальное направление камеры (проекция forward на плоскость)
protected Vector3 PlanarDirection { get; set; }
protected BaseCameraState(CameraStateMachineContext context, EventBus.EventBus eventBus) : base(context, eventBus)
{
_eventBus = eventBus;
EventBus = eventBus;
}
// Основной метод обновления камеры, вызываемый извне каждый кадр
@@ -1,4 +1,5 @@
using Code.Infrastructure.Generators;
using Code.Infrastructure.Loadings;
using UnityEngine;
namespace Code.Infrastructure.Camera.CameraStates
@@ -6,6 +7,7 @@ namespace Code.Infrastructure.Camera.CameraStates
[State(typeof(CameraMode),typeof(CameraStateMachineContext), true)]
public partial class NoneCameraState : BaseCameraState
{
private Loading _loading;
public NoneCameraState(CameraStateMachineContext context, EventBus.EventBus eventBus) : base(context, eventBus)
{
}
@@ -0,0 +1,7 @@
namespace Code.Infrastructure.Configs
{
public enum LayerMaskType
{
PlatformerGround
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 0aab84d976cf4045b47f347ad8d77c79
timeCreated: 1770907660
@@ -0,0 +1,53 @@
using System.Collections.Generic;
using System.Linq;
using Code.Infrastructure.EventBus;
using Code.Infrastructure.Generators;
using Cysharp.Threading.Tasks;
using Reflex.Attributes;
using UnityEngine;
using UnityEngine.AddressableAssets;
namespace Code.Infrastructure.Configs
{
[Config("Configs/LayerMasksConfig", true)]
public struct LayerMasksConfig
{
[ToConfig] public LayerMask mask;
[ToConfig] public LayerMaskType type;
}
public class LayerMasks
{
public static Dictionary<LayerMaskType, LayerMask> Masks { get; } = new();
private static void SetMasks(IList<LayerMasksConfigConfig> configs)
{
foreach (var config in configs.Where(config => !Masks.ContainsKey(config.type)))
Masks.Add(config.type, config.mask);
}
public LayerMasks(IConfigLocator configLocator, EventBus.EventBus eventBus)
{
SetupMasks(configLocator, eventBus).Forget();
}
private async UniTaskVoid SetupMasks(IConfigLocator configLocator, EventBus.EventBus eventBus)
{
var handle =
Addressables.LoadAssetsAsync<LayerMasksConfigConfig>(
configLocator.TryGetManyConfigAssetReferences<LayerMasksConfigConfig>(), null, Addressables.MergeMode.Union);
await handle.ToUniTask();
SetMasks(handle.Result);
Addressables.Release(handle);
eventBus.RaiseEvent<ILayerMasksInitializedHandle>(x => x.LayerMasksInitialized());
}
}
public interface ILayerMasksInitializedHandle : IGlobalSubscriber
{
void LayerMasksInitialized();
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 2fe6e42771fc4a48a37acbe4fa992e4a
timeCreated: 1770906616
@@ -8,8 +8,8 @@ namespace Code.Infrastructure.Input
void EnableMap(ActionMappings actionMap);
void DisableMap(ActionMappings actionMap);
void BindActionPerformed(int mapId, int actionId, Action<InputAction.CallbackContext> action);
void BindActionCancel(int mapId, int actionId, Action<InputAction.CallbackContext> action);
void BindActionCancelled(int mapId, int actionId, Action<InputAction.CallbackContext> action);
void UnbindActionPerformed(int mapId, int actionId, Action<InputAction.CallbackContext> action);
void UnbindActionCanceled(int mapId, int actionId, Action<InputAction.CallbackContext> action);
void UnbindActionCancelled(int mapId, int actionId, Action<InputAction.CallbackContext> action);
}
}
@@ -43,14 +43,14 @@ namespace Code.Infrastructure.Input
public void BindActionPerformed(int mapId, int actionId, Action<InputAction.CallbackContext> action) => inputActionAsset
.actionMaps[mapId].actions[actionId].performed += action;
public void BindActionCancel(int mapId, int actionId, Action<InputAction.CallbackContext> action) => inputActionAsset
public void BindActionCancelled(int mapId, int actionId, Action<InputAction.CallbackContext> action) => inputActionAsset
.actionMaps[mapId].actions[actionId].canceled += action;
public void UnbindActionPerformed(int mapId, int actionId, Action<InputAction.CallbackContext> action) =>
inputActionAsset
.actionMaps[mapId].actions[actionId].performed -= action;
public void UnbindActionCanceled(int mapId, int actionId, Action<InputAction.CallbackContext> action) =>
public void UnbindActionCancelled(int mapId, int actionId, Action<InputAction.CallbackContext> action) =>
inputActionAsset
.actionMaps[mapId].actions[actionId].canceled -= action;
}
@@ -7,6 +7,7 @@ namespace Code.Infrastructure.SceneLoader
{
MainMenu,
Gameplay,
SoundTest
SoundTest,
Platformer
}
}
@@ -7,7 +7,7 @@ namespace Code.Infrastructure.UI.Panels
{
public class LoadingPanel : UIPanel
{
[SerializeField] private Image image;
[SerializeField] private RawImage image;
[SerializeField] private Color shownColor;
[SerializeField] private Color hiddenColor;
public override void Open(Action callback = null)
@@ -5,8 +5,11 @@ namespace Code.Infrastructure.UI
Logo,
Loading,
DebugSceneChooser,
// Race
PlayerScoreCounter,
WinScreen,
PlayerScores,
//
DebugMenu
}
}