riversong code showcase
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace DanieleMarotta.RiversongCodeShowcase
|
||||
{
|
||||
[CreateAssetMenu(fileName = "CritterDefinition", menuName = "Riversong Code Showcase/Critter Definition")]
|
||||
public class CritterDefinition : GameDataAsset
|
||||
{
|
||||
public AgentDefinition AgentDefinition;
|
||||
|
||||
public int MinCritterCount = 5;
|
||||
|
||||
public int MaxCritterCount = 15;
|
||||
|
||||
public float MinSpawningInterval = 10;
|
||||
|
||||
public float MaxSpawningInterval = 15;
|
||||
|
||||
public ProductDefinition Product;
|
||||
|
||||
public int MinProductAmount = 3;
|
||||
|
||||
public int MaxProductAmount = 5;
|
||||
}
|
||||
}
|
||||
24
Source/Riversong/Game/World/Agents/Critters/CritterHerd.cs
Normal file
24
Source/Riversong/Game/World/Agents/Critters/CritterHerd.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using Unity.Mathematics;
|
||||
|
||||
namespace DanieleMarotta.RiversongCodeShowcase
|
||||
{
|
||||
public class CritterHerd : Entity, IAgentSourceEntity
|
||||
{
|
||||
private AgentSourceState _agentsState;
|
||||
|
||||
public CritterDefinition CritterDefinition { get; set; }
|
||||
|
||||
public int2 Center { get; set; }
|
||||
|
||||
public int MaxCritterCount { get; set; }
|
||||
|
||||
public float SpawnTimer { get; set; }
|
||||
|
||||
public float SpawnCooldown => 0;
|
||||
|
||||
public ref AgentSourceState GetAgentSourceStateRW()
|
||||
{
|
||||
return ref _agentsState;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using Random = UnityEngine.Random;
|
||||
|
||||
namespace DanieleMarotta.RiversongCodeShowcase
|
||||
{
|
||||
[GameSystemGroup(typeof(DefaultAgentsSystemGroup))]
|
||||
public class CritterHerdMoveCenterSystem : GameSystem, IUpdatable
|
||||
{
|
||||
[InjectService]
|
||||
private IEntityCollection _entityCollection;
|
||||
|
||||
[InjectService]
|
||||
private World _world;
|
||||
|
||||
[InjectService]
|
||||
private ISignalBus _signalBus;
|
||||
|
||||
public CritterHerdMoveCenterSystem(IServiceLocator serviceLocator) : base(serviceLocator)
|
||||
{
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
foreach (CritterHerd herd in _entityCollection.GetInternalEntityList(typeof(CritterHerd)))
|
||||
{
|
||||
if (!_world.BlockMap.IsBlocked(herd.Center, BlockReason.BlocksAgents)) continue;
|
||||
|
||||
var oldCenter = herd.Center;
|
||||
var moveDirection = ((Directions)Random.Range(0, 8)).ToVector();
|
||||
var center = oldCenter + 4 * moveDirection;
|
||||
|
||||
if (!_world.Contains(center) || _world.BlockMap.IsBlocked(center, BlockReason.BlocksAgents)) continue;
|
||||
|
||||
herd.Center = center;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
using Unity.Mathematics;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Pool;
|
||||
using Random = UnityEngine.Random;
|
||||
|
||||
namespace DanieleMarotta.RiversongCodeShowcase
|
||||
{
|
||||
[GameSystemGroup(typeof(EarlyAgentsSystemGroup))]
|
||||
public class CritterSpawnSystem : GameSystem, IUpdatable
|
||||
{
|
||||
[InjectService]
|
||||
private World _world;
|
||||
|
||||
[InjectService]
|
||||
private IEntityCollection _entityCollection;
|
||||
|
||||
[InjectService]
|
||||
private IAgentFactory _agentFactory;
|
||||
|
||||
[InjectService]
|
||||
private ITileSpace _tileSpace;
|
||||
|
||||
public CritterSpawnSystem(IServiceLocator serviceLocator) : base(serviceLocator)
|
||||
{
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
foreach (CritterHerd herd in _entityCollection.GetInternalEntityList(typeof(CritterHerd)))
|
||||
{
|
||||
ref var agentSourceState = ref herd.GetAgentSourceStateRW();
|
||||
|
||||
if (agentSourceState.AgentCount[(int)AgentJob.None] >= herd.MaxCritterCount)
|
||||
{
|
||||
herd.SpawnTimer = float.MinValue;
|
||||
continue;
|
||||
}
|
||||
|
||||
var critterDefinition = herd.CritterDefinition;
|
||||
|
||||
if (herd.SpawnTimer < 0) herd.SpawnTimer = Random.Range(critterDefinition.MinSpawningInterval, critterDefinition.MaxSpawningInterval);
|
||||
|
||||
herd.SpawnTimer -= Time.deltaTime;
|
||||
if (herd.SpawnTimer <= 0)
|
||||
{
|
||||
herd.SpawnTimer = float.MinValue;
|
||||
|
||||
var wanderingRadius = critterDefinition.AgentDefinition.WanderingRadius;
|
||||
if (!TryFindRandomFreeTile(herd.Center - wanderingRadius, herd.Center + wanderingRadius, out var tile)) continue;
|
||||
|
||||
var position = _tileSpace.TileToWorld(tile);
|
||||
var critter = _agentFactory.CreateCritter(critterDefinition, herd, position);
|
||||
critter.WanderingCenter = tile;
|
||||
|
||||
ref var intentQueue = ref critter.GetIntentQueueRW();
|
||||
intentQueue.EnqueueIntent(AgentIntent.MakeLive());
|
||||
IntentQueue.LoopWandering(ref intentQueue, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool TryFindRandomFreeTile(int2 min, int2 max, out int2 tile)
|
||||
{
|
||||
using var candidatesScope = ListPool<int2>.Get(out var candidates);
|
||||
|
||||
foreach (var candidate in TileRange.From(min, max))
|
||||
if (!_world.BlockMap.IsBlocked(candidate, BlockReason.BlocksAgents))
|
||||
candidates.Add(candidate);
|
||||
|
||||
if (candidates.Count == 0)
|
||||
{
|
||||
tile = int2.zero;
|
||||
return false;
|
||||
}
|
||||
|
||||
tile = candidates[Random.Range(0, candidates.Count)];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Source/Riversong/Game/World/Agents/Critters/CritterState.cs
Normal file
11
Source/Riversong/Game/World/Agents/Critters/CritterState.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
namespace DanieleMarotta.RiversongCodeShowcase
|
||||
{
|
||||
public struct CritterState
|
||||
{
|
||||
public bool IsCritter;
|
||||
|
||||
public int CritterDefinitionId;
|
||||
|
||||
public int LockId;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace DanieleMarotta.RiversongCodeShowcase
|
||||
{
|
||||
[GameSystemGroup(typeof(DefaultAgentsSystemGroup))]
|
||||
[UpdateAfter(typeof(AgentManagerSystem))]
|
||||
[UpdateBefore(typeof(AgentsCleanUpSystem))]
|
||||
public class SpawnProductStackAfterCritterDeathSystem : GameSystem, IUpdatable
|
||||
{
|
||||
[InjectService]
|
||||
private IEntityCollection _entityCollection;
|
||||
|
||||
[InjectService]
|
||||
private ITileSpace _tileSpace;
|
||||
|
||||
[InjectService]
|
||||
private IProductStackFactory _productStackFactory;
|
||||
|
||||
[InjectService]
|
||||
private World _world;
|
||||
|
||||
public SpawnProductStackAfterCritterDeathSystem(IServiceLocator serviceLocator) : base(serviceLocator)
|
||||
{
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
foreach (CritterHerd herd in _entityCollection.GetInternalEntityList(typeof(CritterHerd)))
|
||||
{
|
||||
ref var agentSourceState = ref herd.GetAgentSourceStateRW();
|
||||
|
||||
foreach (var critterId in agentSourceState.AgentIds)
|
||||
{
|
||||
var critter = _entityCollection.Get<Agent>(critterId);
|
||||
if (critter.LifecycleState != AgentLifecycleState.DeSpawning) continue;
|
||||
|
||||
var tile = _tileSpace.WorldToTile(critter.Position);
|
||||
if (_world.BlockMap.IsBlocked(tile, BlockReason.BlocksAgents)) continue;
|
||||
|
||||
var product = herd.CritterDefinition.Product;
|
||||
var amount = Random.Range(herd.CritterDefinition.MinProductAmount, herd.CritterDefinition.MaxProductAmount + 1);
|
||||
|
||||
_productStackFactory.CreateOrMerge(tile, product, amount);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace DanieleMarotta.RiversongCodeShowcase
|
||||
{
|
||||
[GameSystemGroup(typeof(DefaultAgentsSystemGroup))]
|
||||
public class UnlockCrittersSystem : GameSystem, IUpdatable
|
||||
{
|
||||
[InjectService]
|
||||
private IEntityCache _entityCache;
|
||||
|
||||
[InjectService]
|
||||
private IEntityCollection _entityCollection;
|
||||
|
||||
[InjectService]
|
||||
private IIntentLogicExecutor _intentLogicExecutor;
|
||||
|
||||
public UnlockCrittersSystem(IServiceLocator serviceLocator) : base(serviceLocator)
|
||||
{
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
foreach (var critter in _entityCache.GetCritterAgents())
|
||||
{
|
||||
ref var critterState = ref critter.GetCritterStateRW();
|
||||
if (critterState.LockId == Entity.InvalidId || _entityCollection.Exists(critterState.LockId)) continue;
|
||||
|
||||
Debug.LogError($"Invalid lock id {critterState.LockId} on critter {critter.Id}");
|
||||
|
||||
critterState.LockId = Entity.InvalidId;
|
||||
|
||||
ref var intentQueue = ref _intentLogicExecutor.CancelRemainingIntents(critter);
|
||||
IntentQueue.LoopWandering(ref intentQueue, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using System.Collections.Generic;
|
||||
using Unity.Mathematics;
|
||||
|
||||
namespace DanieleMarotta.RiversongCodeShowcase
|
||||
{
|
||||
public class WorldCritterHerdsState
|
||||
{
|
||||
public List<int2> EligibleCenters { get; } = new();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user