diff options
Diffstat (limited to 'source/game/systems')
| -rw-r--r-- | source/game/systems/CameraRenderSystem.cs | 43 | ||||
| -rw-r--r-- | source/game/systems/CameraSystem.cs | 39 | ||||
| -rw-r--r-- | source/game/systems/ChunkMapRenderSystem.cs | 63 | ||||
| -rw-r--r-- | source/game/systems/EntityDebugSystem.cs | 44 | ||||
| -rw-r--r-- | source/game/systems/LightingSystem.cs | 100 | ||||
| -rw-r--r-- | source/game/systems/LocalPlayerSystem.cs | 246 | ||||
| -rw-r--r-- | source/game/systems/TargetPositionSystem.cs | 37 | ||||
| -rw-r--r-- | source/game/systems/mainmenu/MainMenuBackgroundSystem.cs | 33 | ||||
| -rw-r--r-- | source/game/systems/mainmenu/MainMenuRenderSystem.cs | 43 | ||||
| -rw-r--r-- | source/game/systems/physics/PhysicsCollisionDebugSystem.cs | 61 | ||||
| -rw-r--r-- | source/game/systems/physics/PhysicsSystem.cs | 42 | ||||
| -rw-r--r-- | source/game/systems/physics/PhysicsWorldCollisionSystem.cs | 83 | ||||
| -rw-r--r-- | source/game/systems/ui/GameGUIDrawSystem.cs | 12 |
13 files changed, 846 insertions, 0 deletions
diff --git a/source/game/systems/CameraRenderSystem.cs b/source/game/systems/CameraRenderSystem.cs new file mode 100644 index 0000000..2846fa7 --- /dev/null +++ b/source/game/systems/CameraRenderSystem.cs @@ -0,0 +1,43 @@ +using Celesteia.Graphics; +using Celesteia.Resources.Sprites; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using MonoGame.Extended; +using MonoGame.Extended.Entities; +using MonoGame.Extended.Entities.Systems; + +namespace Celesteia.Game.Systems { + public class CameraRenderSystem : EntityDrawSystem + { + private readonly Camera2D _camera; + private readonly SpriteBatch _spriteBatch; + + private ComponentMapper<Transform2> transformMapper; + private ComponentMapper<EntityFrames> entityFramesMapper; + + public CameraRenderSystem(Camera2D camera, SpriteBatch spriteBatch) : base(Aspect.All(typeof(Transform2), typeof(EntityFrames))) { + _camera = camera; + _spriteBatch = spriteBatch; + } + + public override void Initialize(IComponentMapperService mapperService) + { + transformMapper = mapperService.GetMapper<Transform2>(); + entityFramesMapper = mapperService.GetMapper<EntityFrames>(); + } + + public override void Draw(GameTime gameTime) + { + _spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, SamplerState.PointClamp, null, null, null, _camera.GetViewMatrix()); + + foreach (int entityId in ActiveEntities) { + Transform2 transform = transformMapper.Get(entityId); + EntityFrames entityFrames = entityFramesMapper.Get(entityId); + + entityFrames.Draw(0, _spriteBatch, transform.Position, transform.Scale, Color.White); + } + + _spriteBatch.End(); + } + } +}
\ No newline at end of file diff --git a/source/game/systems/CameraSystem.cs b/source/game/systems/CameraSystem.cs new file mode 100644 index 0000000..be121a5 --- /dev/null +++ b/source/game/systems/CameraSystem.cs @@ -0,0 +1,39 @@ +using System; +using Celesteia.Game.Components; +using Celesteia.Game.Input; +using Celesteia.Graphics; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Input; +using MonoGame.Extended; +using MonoGame.Extended.Entities; +using MonoGame.Extended.Entities.Systems; + +namespace Celesteia.Game.Systems { + public class CameraSystem : EntityUpdateSystem + { + private Camera2D _camera; + private float smoothing = 128f; + + private ComponentMapper<Transform2> transformMapper; + + public CameraSystem(Camera2D camera) : base(Aspect.All(typeof(Transform2), typeof(CameraFollow))) + => _camera = camera; + + public override void Initialize(IComponentMapperService mapperService) + => transformMapper = mapperService.GetMapper<Transform2>(); + + Vector2 pos; + public override void Update(GameTime gameTime) + { + foreach (int entityId in ActiveEntities) { + pos = transformMapper.Get(entityId).Position * smoothing; + pos.X = MathF.Round(pos.X) / smoothing; + pos.Y = MathF.Round(pos.Y) / smoothing; + _camera.Center = pos; + break; + } + + if (KeyboardHelper.IsDown(Keys.LeftControl)) _camera.Zoom += (int) Math.Clamp(MouseHelper.ScrollDelta, -1f, 1f); + } + } +}
\ No newline at end of file diff --git a/source/game/systems/ChunkMapRenderSystem.cs b/source/game/systems/ChunkMapRenderSystem.cs new file mode 100644 index 0000000..afb867c --- /dev/null +++ b/source/game/systems/ChunkMapRenderSystem.cs @@ -0,0 +1,63 @@ +using System.Collections.Generic; +using Celesteia.Game.Planets; +using Celesteia.Graphics; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using MonoGame.Extended.Entities.Systems; + +namespace Celesteia.Game.Systems { + public class ChunkMapRenderSystem : IUpdateSystem, IDrawSystem + { + private readonly Camera2D _camera; + private readonly SpriteBatch _spriteBatch; + private ChunkVector _lastChunkPos; + private ChunkVector _pivotChunkPos => ChunkVector.FromVector2(_camera.Center); + public int RenderDistance = 4; + private ChunkMap _chunkMap; + + public ChunkMapRenderSystem(Camera2D camera, SpriteBatch spriteBatch, ChunkMap chunkMap) { + _camera = camera; + _spriteBatch = spriteBatch; + _chunkMap = chunkMap; + } + + public void Initialize(MonoGame.Extended.Entities.World world) {} + + private ChunkVector _v; + private List<ChunkVector> activeChunks = new List<ChunkVector>(); + public void Update(GameTime gameTime) + { + if (_lastChunkPos != _pivotChunkPos) { + activeChunks.Clear(); + for (int i = -RenderDistance; i <= RenderDistance; i++) { + _v.X = _pivotChunkPos.X + i; + for (int j = -RenderDistance; j <= RenderDistance; j++) { + _v.Y = _pivotChunkPos.Y + j; + + if (!_chunkMap.ChunkIsInMap(_v)) continue; + activeChunks.Add(_v); + } + } + + _lastChunkPos = _pivotChunkPos; + } + } + + public void Draw(GameTime gameTime) { + _spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, SamplerState.PointWrap, null, null, null, _camera.GetViewMatrix()); + + // Draw every chunk in view. + foreach (ChunkVector cv in activeChunks) DrawChunk(cv, gameTime, _spriteBatch); + + _spriteBatch.End(); + } + + private void DrawChunk(ChunkVector cv, GameTime gameTime, SpriteBatch spriteBatch) { + Chunk c = _chunkMap.GetChunk(cv); + + if (c != null) c.Draw(gameTime, spriteBatch); + } + + public void Dispose() {} + } +}
\ No newline at end of file diff --git a/source/game/systems/EntityDebugSystem.cs b/source/game/systems/EntityDebugSystem.cs new file mode 100644 index 0000000..9b7914a --- /dev/null +++ b/source/game/systems/EntityDebugSystem.cs @@ -0,0 +1,44 @@ +using Celesteia.Graphics; +using Celesteia.Resources; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using MonoGame.Extended; +using MonoGame.Extended.Entities; +using MonoGame.Extended.Entities.Systems; + +namespace Celesteia.Game.Systems { + public class EntityDebugSystem : EntityDrawSystem + { + private readonly Camera2D _camera; + private readonly SpriteBatch _spriteBatch; + + private ComponentMapper<Transform2> transformMapper; + + private SpriteFont _font; + + public EntityDebugSystem(Camera2D camera, SpriteBatch spriteBatch) : base(Aspect.All(typeof(Transform2))) { + _camera = camera; + _spriteBatch = spriteBatch; + } + + public override void Initialize(IComponentMapperService mapperService) + { + transformMapper = mapperService.GetMapper<Transform2>(); + + _font = ResourceManager.Fonts.GetFontType("Hobo").Font; + } + + public override void Draw(GameTime gameTime) + { + _spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Additive, SamplerState.PointClamp, null, null, null, _camera.GetViewMatrix()); + + foreach (int entityId in ActiveEntities) { + Transform2 transform = transformMapper.Get(entityId); + + _spriteBatch.DrawString(_font, transform.Position.ToString(), transform.Position, Color.White, 0f, new Vector2(0.5f, 0.5f), .12f, SpriteEffects.None, 0f); + } + + _spriteBatch.End(); + } + } +}
\ No newline at end of file diff --git a/source/game/systems/LightingSystem.cs b/source/game/systems/LightingSystem.cs new file mode 100644 index 0000000..73c6cf8 --- /dev/null +++ b/source/game/systems/LightingSystem.cs @@ -0,0 +1,100 @@ +using Celesteia.Graphics; +using Celesteia.Graphics.Lighting; +using Celesteia.Resources; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using MonoGame.Extended.Entities.Systems; +using Celesteia.Resources.Types; +using Celesteia.Game.Planets; +using System.Threading.Tasks; +using System.Collections.Generic; + +namespace Celesteia.Game.Systems { + public class LightingSystem : IUpdateSystem, IDrawSystem + { + private readonly Camera2D _camera; + private readonly SpriteBatch _spriteBatch; + private readonly ChunkMap _chunkMap; + + public LightingSystem(Camera2D camera, SpriteBatch spriteBatch, ChunkMap chunkMap) { + _camera = camera; + _spriteBatch = spriteBatch; + _chunkMap = chunkMap; + } + public void Dispose() { } + + private int _lightRenderDistance = 5; + + private Dictionary<byte, BlockLightProperties> lightingDictionary; + public void Initialize(MonoGame.Extended.Entities.World world) { + int _size = 2 * _lightRenderDistance * Chunk.CHUNK_SIZE; + + _lightMap = new LightMap(_size, _size); + _texture = new Texture2D(_spriteBatch.GraphicsDevice, _size, _size); + + lightingDictionary = new Dictionary<byte, BlockLightProperties>(); + } + + private LightMap _lightMap; + private Texture2D _texture; + + private bool drawTexture = false; + private Task _lightUpdate; + public void Update(GameTime gameTime) + { + if (_lightUpdate == null || (_lightUpdate != null && _lightUpdate.IsCompleted)) + _lightUpdate = Task.Factory.StartNew(() => UpdateLight()); + + if (drawTexture) UpdateTexture(); + } + + private Point _position; + private void UpdatePosition() { + _position = ChunkVector.FromVector2(_camera.Center).Resolve() - new Point(_lightRenderDistance * Chunk.CHUNK_SIZE); + } + + private void UpdateTexture() { + _drawPosition = _position.ToVector2(); + _texture.SetData<Color>(_lightMap.GetColors(), 0, _lightMap.GetColorCount()); + drawTexture = false; + } + + private void UpdateLight() { + UpdatePosition(); + + UpdateEmission(); + _lightMap.Propagate(); + _lightMap.CreateColorMap(); + + drawTexture = true; + } + + private BlockState _block; + private void UpdateEmission() { + for (int i = 0; i < _lightMap.Width; i++) { + for (int j = 0; j < _lightMap.Height; j++) { + if (!(_block = _chunkMap.GetForeground(i + _position.X, j + _position.Y)).Empty && _lightMap.AddForeground(i, j, _block.Type.Light)) continue; + if (!(_block = _chunkMap.GetBackground(i + _position.X, j + _position.Y)).Empty && _lightMap.AddBackground(i, j, _block.Type.Light)) continue; + + _lightMap.AddLight(i, j, true, LightColor.ambient, 4); + } + } + } + + private BlendState multiply = new BlendState() { + ColorBlendFunction = BlendFunction.Add, + ColorSourceBlend = Blend.DestinationColor, + ColorDestinationBlend = Blend.Zero, + }; + + private Vector2 _drawPosition; + public void Draw(GameTime gameTime) + { + _spriteBatch.Begin(SpriteSortMode.Immediate, multiply, SamplerState.LinearClamp, null, null, null, _camera.GetViewMatrix()); + + _spriteBatch.Draw(_texture, _drawPosition, Color.White); + + _spriteBatch.End(); + } + } +}
\ No newline at end of file diff --git a/source/game/systems/LocalPlayerSystem.cs b/source/game/systems/LocalPlayerSystem.cs new file mode 100644 index 0000000..5c17cb4 --- /dev/null +++ b/source/game/systems/LocalPlayerSystem.cs @@ -0,0 +1,246 @@ +using System; +using System.Collections.Generic; +using Celesteia.Game.Components; +using Celesteia.Game.Components.Items; +using Celesteia.Game.Components.Physics; +using Celesteia.Game.Components.Player; +using Celesteia.Game.Input; +using Celesteia.Game.Items; +using Celesteia.Game.Planets; +using Celesteia.Graphics; +using Celesteia.GUIs.Game; +using Celesteia.Resources; +using Celesteia.Resources.Sprites; +using Celesteia.Resources.Types; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework.Input; +using MonoGame.Extended; +using MonoGame.Extended.Entities; +using MonoGame.Extended.Entities.Systems; + +namespace Celesteia.Game.Systems { + public class LocalPlayerSystem : UpdateSystem, IDrawSystem + { + private GameInstance _game; + private GameGUI _gameGui; + private Camera2D _camera; + private ChunkMap _chunkMap; + + private Entity _player; + public Entity Player { + get => _player; + set { + _player = value; + + localPlayer = _player.Get<LocalPlayer>(); + targetPosition = _player.Get<TargetPosition>(); + physicsEntity = _player.Get<PhysicsEntity>(); + frames = _player.Get<EntityFrames>(); + attributes = _player.Get<EntityAttributes>(); + input = _player.Get<PlayerInput>(); + inventory = _player.Get<Inventory>(); + } + } + private LocalPlayer localPlayer; + private PlayerInput input; + private PhysicsEntity physicsEntity; + private EntityFrames frames; + private EntityAttributes attributes; + private TargetPosition targetPosition; + private Inventory inventory; + + private SpriteBatch _spriteBatch; + + private BlockFrame _selectionSprite; + + public LocalPlayerSystem(GameInstance game, ChunkMap chunkMap, Camera2D camera, SpriteBatch spriteBatch, GameGUI gameGui) { + _game = game; + _chunkMap = chunkMap; + _camera = camera; + _gameGui = gameGui; + _spriteBatch = spriteBatch; + + _selectionSprite = ResourceManager.Blocks.Selection.GetFrame(0); + } + + private bool IsGameActive => !_gameGui.Paused && (int)_gameGui.State < 1 && _game.IsActive; + + public override void Update(GameTime gameTime) + { + if (_player == null) return; + + bool clicked = false; + UpdateGUI(gameTime, input, out clicked); + + if (IsGameActive) { + UpdateSelectedItem(); + + UpdateMouse(gameTime, input); + UpdateMovement(gameTime, input, physicsEntity, frames, attributes.Attributes, targetPosition); + UpdateJump(gameTime, localPlayer, input, physicsEntity, attributes.Attributes); + + if (!clicked) UpdateClick(gameTime, input); + } else SelectionColor = Color.Transparent; + } + + private static Dictionary<int, int> hotbarMappings = new Dictionary<int, int>() { + { (int)Keys.D1, 0 }, + { (int)Keys.D2, 1 }, + { (int)Keys.D3, 2 }, + { (int)Keys.D4, 3 }, + { (int)Keys.D5, 4 }, + { (int)Keys.D6, 5 }, + { (int)Keys.D7, 6 }, + { (int)Keys.D8, 7 }, + { (int)Keys.D9, 8 } + }; + + private void UpdateSelectedItem() { + foreach (int keys in hotbarMappings.Keys) { + if (KeyboardHelper.Pressed((Keys) keys)) { + _gameGui.HotbarSelection = hotbarMappings[keys]; + } + } + + if (!KeyboardHelper.IsDown(Keys.LeftControl) && MouseHelper.ScrollDelta != 0f) { + int change = (int) -Math.Clamp(MouseHelper.ScrollDelta, -1f, 1f); + int selection = _gameGui.HotbarSelection; + + selection += change; + + if (selection < 0) selection = _gameGui.HotbarSlots - 1; + if (selection >= _gameGui.HotbarSlots) selection = 0; + + _gameGui.HotbarSelection = selection; + } + } + + bool _inventoryPress; + bool _craftingPress; + bool _pausePress; + private void UpdateGUI(GameTime gameTime, PlayerInput input, out bool clicked) { + _inventoryPress = input.Inventory.Poll(); + _craftingPress = input.Crafting.Poll(); + _pausePress = input.Pause.Poll(); + + if (_inventoryPress || _craftingPress || _pausePress) { + switch (_gameGui.State) { + case InventoryScreenState.Closed: + if (_craftingPress) _gameGui.State = InventoryScreenState.Crafting; + else if (_inventoryPress) _gameGui.State = InventoryScreenState.Inventory; + else if (_pausePress) _gameGui.TogglePause(); + break; + case InventoryScreenState.Inventory: + if (_craftingPress) _gameGui.State = InventoryScreenState.Crafting; + else _gameGui.State = InventoryScreenState.Closed; + break; + case InventoryScreenState.Crafting: + _gameGui.State = InventoryScreenState.Closed; + break; + default: break; + } + } + + _gameGui.Update(gameTime, out clicked); + } + + float h; + private bool _moving; + private double _startedMoving; + private void UpdateMovement(GameTime gameTime, PlayerInput input, PhysicsEntity physicsEntity, EntityFrames frames, EntityAttributes.EntityAttributeMap attributes, TargetPosition targetPosition) { + h = input.Horizontal.Poll(); + + if (h != 0f) { + // Player has started moving, animate. + if (!_moving) _startedMoving = gameTime.TotalGameTime.TotalSeconds; + + // Flip sprite according to horizontal movement float. + frames.Effects = h < 0f ? SpriteEffects.None : SpriteEffects.FlipHorizontally; + } + + _moving = h != 0f; + + // If the player is moving, change the frame every .25 seconds, else return the standing frame. + frames.Frame = _moving ? (int)((gameTime.TotalGameTime.TotalSeconds - _startedMoving) / 0.25) : 0; + + if (h == 0f) return; + + h *= 1f + (input.Run.Poll() ? 1.5f : 0); + h *= attributes.Get(EntityAttribute.MovementSpeed); + h *= gameTime.GetElapsedSeconds(); + + targetPosition.Target.X += h; + } + + private void UpdateJump(GameTime gameTime, LocalPlayer localPlayer, PlayerInput input, PhysicsEntity physicsEntity, EntityAttributes.EntityAttributeMap attributes) + { + if (localPlayer.JumpRemaining > 0f) { + if (input.Jump.Poll()) { + physicsEntity.SetVelocity(physicsEntity.Velocity.X, -attributes.Get(EntityAttribute.JumpForce)); + localPlayer.JumpRemaining -= gameTime.GetElapsedSeconds(); + } + } else if (physicsEntity.CollidingDown) localPlayer.JumpRemaining = attributes.Get(EntityAttribute.JumpFuel); + } + + private Point? Selection; + private BlockState SelectedBlock; + private Color SelectionColor; + public void SetSelection(Point? selection) { + if (selection == Selection) return; + + Selection = selection; + if (!selection.HasValue) { + SelectionColor = Color.Transparent; + return; + } + + SelectedBlock = _chunkMap.GetForeground(Selection.Value); + if (!SelectedBlock.Draw) SelectedBlock = _chunkMap.GetBackground(Selection.Value); + + SelectionColor = (SelectedBlock.Type.Strength >= 0 ? Color.White : Color.Black); + } + + Vector2 pointV = Vector2.Zero; + Point point = Point.Zero; + private void UpdateMouse(GameTime gameTime, PlayerInput input) { + pointV = _camera.ScreenToWorld(MouseHelper.Position); + pointV.Floor(); + point = pointV.ToPoint(); + + SetSelection(point); + } + + + bool success = false; + ItemStack stack = null; + IItemActions actions = null; + private void UpdateClick(GameTime gameTime, PlayerInput input) { + if (!input.PrimaryUse.Poll() && !input.SecondaryUse.Poll()) return; + if (_gameGui.GetSelectedItem() == null) return; + + stack = _gameGui.GetSelectedItem(); + if(stack.Type == null || stack.Type.Actions == null) return; + + actions = stack.Type.Actions; + + if (input.PrimaryUse.Poll()) success = actions.Primary(gameTime, _chunkMap, point, _player); + if (input.SecondaryUse.Poll()) success = stack.Type.Actions.Secondary(gameTime, _chunkMap, point, _player); + + if (success && stack.Type.ConsumeOnUse) stack.Amount -= 1; + + inventory.AssertAmounts(); + } + + public void Draw(GameTime gameTime) + { + if (!UIReferences.GUIEnabled) return; + + _spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, SamplerState.PointClamp, null, null, null, _camera.GetViewMatrix()); + + _selectionSprite.Draw(0, _spriteBatch, pointV, SelectionColor); + + _spriteBatch.End(); + } + } +}
\ No newline at end of file diff --git a/source/game/systems/TargetPositionSystem.cs b/source/game/systems/TargetPositionSystem.cs new file mode 100644 index 0000000..7089bc1 --- /dev/null +++ b/source/game/systems/TargetPositionSystem.cs @@ -0,0 +1,37 @@ +using Celesteia.Game.Components; +using Celesteia.Game.Planets; +using Microsoft.Xna.Framework; +using MonoGame.Extended; +using MonoGame.Extended.Entities; +using MonoGame.Extended.Entities.Systems; + +namespace Celesteia.Game.Systems { + public class TargetPositionSystem : EntityUpdateSystem { + private ChunkMap _chunkMap; + + private ComponentMapper<Transform2> transformMapper; + private ComponentMapper<TargetPosition> targetPositionMapper; + + public TargetPositionSystem(ChunkMap chunkMap) : base(Aspect.All(typeof(Transform2), typeof(TargetPosition))) + => _chunkMap = chunkMap; + + public override void Initialize(IComponentMapperService mapperService) + { + transformMapper = mapperService.GetMapper<Transform2>(); + targetPositionMapper = mapperService.GetMapper<TargetPosition>(); + } + + public override void Update(GameTime gameTime) + { + foreach (int entityId in ActiveEntities) { + TargetPosition targetPosition = targetPositionMapper.Get(entityId); + Transform2 transform = transformMapper.Get(entityId); + + if (targetPosition.Target.X < 0 || targetPosition.Target.X > _chunkMap.BlockWidth) + targetPosition.Target.X = MathHelper.Clamp(targetPosition.Target.X, 0f, _chunkMap.BlockWidth); + + transform.Position = targetPosition.Target; + } + } + } +}
\ No newline at end of file diff --git a/source/game/systems/mainmenu/MainMenuBackgroundSystem.cs b/source/game/systems/mainmenu/MainMenuBackgroundSystem.cs new file mode 100644 index 0000000..e4d5e28 --- /dev/null +++ b/source/game/systems/mainmenu/MainMenuBackgroundSystem.cs @@ -0,0 +1,33 @@ +using Celesteia.Game.Components.Skybox; +using Microsoft.Xna.Framework; +using MonoGame.Extended; +using MonoGame.Extended.Entities; +using MonoGame.Extended.Entities.Systems; + +namespace Celesteia.Game.Systems.MainMenu { + public class MainMenuBackgroundSystem : EntityUpdateSystem + { + private ComponentMapper<Transform2> transformMapper; + private ComponentMapper<SkyboxRotateZ> rotatorMapper; + + public MainMenuBackgroundSystem() : base(Aspect.All(typeof(Transform2), typeof(SkyboxRotateZ))) {} + + public override void Initialize(IComponentMapperService mapperService) + { + transformMapper = mapperService.GetMapper<Transform2>(); + rotatorMapper = mapperService.GetMapper<SkyboxRotateZ>(); + } + + public override void Update(GameTime gameTime) + { + foreach (int entityId in ActiveEntities) { + SkyboxRotateZ rotator = rotatorMapper.Get(entityId); + Transform2 transform = transformMapper.Get(entityId); + + rotator.Current += rotator.Magnitude * (gameTime.GetElapsedSeconds() / 1000f) * 20f; + + transform.Rotation = rotator.Current; + } + } + } +}
\ No newline at end of file diff --git a/source/game/systems/mainmenu/MainMenuRenderSystem.cs b/source/game/systems/mainmenu/MainMenuRenderSystem.cs new file mode 100644 index 0000000..ada6a77 --- /dev/null +++ b/source/game/systems/mainmenu/MainMenuRenderSystem.cs @@ -0,0 +1,43 @@ +using Celesteia.Graphics; +using Celesteia.Resources.Sprites; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using MonoGame.Extended; +using MonoGame.Extended.Entities; +using MonoGame.Extended.Entities.Systems; + +namespace Celesteia.Game.Systems.MainMenu { + public class MainMenuRenderSystem : EntityDrawSystem + { + private ComponentMapper<Transform2> transformMapper; + private ComponentMapper<SkyboxPortionFrames> framesMapper; + + private Camera2D _camera; + private SpriteBatch _spriteBatch; + + public MainMenuRenderSystem(Camera2D camera, SpriteBatch spriteBatch) : base(Aspect.All(typeof(Transform2), typeof(SkyboxPortionFrames))) { + _camera = camera; + _spriteBatch = spriteBatch; + } + + public override void Initialize(IComponentMapperService mapperService) + { + transformMapper = mapperService.GetMapper<Transform2>(); + framesMapper = mapperService.GetMapper<SkyboxPortionFrames>(); + } + + public override void Draw(GameTime gameTime) + { + _spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.NonPremultiplied, SamplerState.PointClamp, null, RasterizerState.CullNone, null, _camera.GetViewMatrix()); + + foreach (int entityId in ActiveEntities) { + SkyboxPortionFrames frames = framesMapper.Get(entityId); + Transform2 transform = transformMapper.Get(entityId); + + frames.Draw(0, _spriteBatch, transform.Position, transform.Rotation, transform.Scale); + } + + _spriteBatch.End(); + } + } +}
\ No newline at end of file diff --git a/source/game/systems/physics/PhysicsCollisionDebugSystem.cs b/source/game/systems/physics/PhysicsCollisionDebugSystem.cs new file mode 100644 index 0000000..f605c30 --- /dev/null +++ b/source/game/systems/physics/PhysicsCollisionDebugSystem.cs @@ -0,0 +1,61 @@ +using Celesteia.Game.Components.Physics; +using Celesteia.Game.Planets; +using Celesteia.Graphics; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using MonoGame.Extended; +using MonoGame.Extended.Entities; +using MonoGame.Extended.Entities.Systems; + +namespace Celesteia.Game.Systems.Physics { + public class PhysicsCollisionDebugSystem : EntityDrawSystem + { + private readonly Camera2D _camera; + private readonly SpriteBatch _spriteBatch; + private readonly ChunkMap _chunkMap; + + private ComponentMapper<Transform2> transformMapper; + private ComponentMapper<CollisionBox> collisionBoxMapper; + + public PhysicsCollisionDebugSystem(Camera2D camera, SpriteBatch spriteBatch, ChunkMap chunkMap) : base(Aspect.All(typeof(Transform2), typeof(CollisionBox))) { + _camera = camera; + _spriteBatch = spriteBatch; + _chunkMap = chunkMap; + } + + public override void Initialize(IComponentMapperService mapperService) + { + transformMapper = mapperService.GetMapper<Transform2>(); + collisionBoxMapper = mapperService.GetMapper<CollisionBox>(); + } + + public override void Draw(GameTime gameTime) + { + if (!GameInstance.DebugMode) return; + + _spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Additive, SamplerState.PointClamp, null, null, null, _camera.GetViewMatrix()); + + foreach (int entityId in ActiveEntities) { + Rectangle box = collisionBoxMapper.Get(entityId).Rounded; + + int minX = box.X; + int maxX = box.X + box.Width; + + int minY = box.Y; + int maxY = box.Y + box.Height; + + for (int i = minX; i < maxX; i++) + for (int j = minY; j < maxY; j++) { + RectangleF? blockBox = _chunkMap.TestBoundingBox(i, j); + if (blockBox.HasValue) { + _spriteBatch.DrawRectangle(new RectangleF(i, j, blockBox.Value.Width, blockBox.Value.Height), Color.Red, .05f, 0f); + } else { + _spriteBatch.DrawRectangle(new RectangleF(i, j, 1f, 1f), Color.Green, .05f, 0f); + } + } + } + + _spriteBatch.End(); + } + } +}
\ No newline at end of file diff --git a/source/game/systems/physics/PhysicsSystem.cs b/source/game/systems/physics/PhysicsSystem.cs new file mode 100644 index 0000000..3963cc1 --- /dev/null +++ b/source/game/systems/physics/PhysicsSystem.cs @@ -0,0 +1,42 @@ +using Celesteia.Game.Components; +using Celesteia.Game.Components.Physics; +using Microsoft.Xna.Framework; +using MonoGame.Extended; +using MonoGame.Extended.Entities; +using MonoGame.Extended.Entities.Systems; + +namespace Celesteia.Game.Systems.Physics { + public class PhysicsSystem : EntityUpdateSystem { + public const float GRAVITY_CONSTANT = 9.7f; + + public PhysicsSystem() : base(Aspect.All(typeof(PhysicsEntity), typeof(TargetPosition))) {} + + private ComponentMapper<TargetPosition> targetPositionMapper; + private ComponentMapper<PhysicsEntity> physicsEntityMapper; + + public override void Initialize(IComponentMapperService mapperService) + { + targetPositionMapper = mapperService.GetMapper<TargetPosition>(); + physicsEntityMapper = mapperService.GetMapper<PhysicsEntity>(); + } + + public override void Update(GameTime gameTime) + { + foreach (int entityId in ActiveEntities) { + TargetPosition targetPosition = targetPositionMapper.Get(entityId); + PhysicsEntity physicsEntity = physicsEntityMapper.Get(entityId); + + // Apply gravity if applicable + if (physicsEntity.Gravity) { + if (physicsEntity.CollidingDown && physicsEntity.Velocity.Y > 0f) { + physicsEntity.SetVelocity(physicsEntity.Velocity.X, 0.1f); + } + + physicsEntity.AddVelocity(0f, physicsEntity.Mass * PhysicsSystem.GRAVITY_CONSTANT * gameTime.GetElapsedSeconds()); + } + + targetPosition.Target += physicsEntity.Velocity * gameTime.GetElapsedSeconds(); + } + } + } +}
\ No newline at end of file diff --git a/source/game/systems/physics/PhysicsWorldCollisionSystem.cs b/source/game/systems/physics/PhysicsWorldCollisionSystem.cs new file mode 100644 index 0000000..ba8da22 --- /dev/null +++ b/source/game/systems/physics/PhysicsWorldCollisionSystem.cs @@ -0,0 +1,83 @@ +using System; +using Celesteia.Game.Components; +using Celesteia.Game.Components.Physics; +using Celesteia.Game.Planets; +using Microsoft.Xna.Framework; +using MonoGame.Extended; +using MonoGame.Extended.Entities; +using MonoGame.Extended.Entities.Systems; + +namespace Celesteia.Game.Systems.Physics { + public class PhysicsWorldCollisionSystem : EntityUpdateSystem { + private ChunkMap _chunkMap; + + public PhysicsWorldCollisionSystem(ChunkMap chunkMap) : base(Aspect.All(typeof(TargetPosition), typeof(PhysicsEntity), typeof(CollisionBox))) { + _chunkMap = chunkMap; + } + + private ComponentMapper<Transform2> transformMapper; + private ComponentMapper<TargetPosition> targetPositionMapper; + private ComponentMapper<PhysicsEntity> physicsEntityMapper; + private ComponentMapper<CollisionBox> collisionBoxMapper; + + public override void Initialize(IComponentMapperService mapperService) + { + transformMapper = mapperService.GetMapper<Transform2>(); + targetPositionMapper = mapperService.GetMapper<TargetPosition>(); + physicsEntityMapper = mapperService.GetMapper<PhysicsEntity>(); + collisionBoxMapper = mapperService.GetMapper<CollisionBox>(); + } + + public override void Update(GameTime gameTime) + { + foreach (int entityId in ActiveEntities) { + Transform2 transform = transformMapper.Get(entityId); + TargetPosition targetPosition = targetPositionMapper.Get(entityId); + PhysicsEntity physicsEntity = physicsEntityMapper.Get(entityId); + CollisionBox collisionBox = collisionBoxMapper.Get(entityId); + + collisionBox.Update(targetPosition.Target); + + int minX = (int)MathF.Floor(collisionBox.Bounds.Center.X - (collisionBox.Bounds.Width / 2f)); + int maxX = (int)MathF.Ceiling(collisionBox.Bounds.Center.X + (collisionBox.Bounds.Width / 2f)); + + int minY = (int)MathF.Floor(collisionBox.Bounds.Center.Y - (collisionBox.Bounds.Height / 2f)); + int maxY = (int)MathF.Ceiling(collisionBox.Bounds.Center.Y + (collisionBox.Bounds.Height / 2f)); + + bool collLeft = false; + bool collRight = false; + bool collUp = false; + bool collDown = false; + + for (int i = minX; i < maxX; i++) + for (int j = minY; j < maxY; j++) { + RectangleF? blockBox = _chunkMap.TestBoundingBox(i, j); + if (blockBox.HasValue) { + RectangleF inter = RectangleF.Intersection(collisionBox.Bounds, blockBox.Value); + + if (inter.IsEmpty) continue; + + if (inter.Width < inter.Height) { + collLeft = blockBox.Value.Center.X < collisionBox.Bounds.Center.X; + collRight = blockBox.Value.Center.X > collisionBox.Bounds.Center.X; + + targetPosition.Target += new Vector2(blockBox.Value.Center.X < collisionBox.Bounds.Center.X ? inter.Width : -inter.Width, 0f); + } else { + collUp = blockBox.Value.Center.Y < collisionBox.Bounds.Center.Y; + collDown = blockBox.Value.Center.Y > collisionBox.Bounds.Center.Y; + + targetPosition.Target += new Vector2(0f, blockBox.Value.Center.Y < collisionBox.Bounds.Center.Y ? inter.Height : -inter.Height); + } + + collisionBox.Update(targetPosition.Target); + } + } + + physicsEntity.CollidingDown = collDown; + physicsEntity.CollidingUp = collUp; + physicsEntity.CollidingLeft = collLeft; + physicsEntity.CollidingRight = collRight; + } + } + } +}
\ No newline at end of file diff --git a/source/game/systems/ui/GameGUIDrawSystem.cs b/source/game/systems/ui/GameGUIDrawSystem.cs new file mode 100644 index 0000000..0140786 --- /dev/null +++ b/source/game/systems/ui/GameGUIDrawSystem.cs @@ -0,0 +1,12 @@ +using Celesteia.GUIs.Game; +using Microsoft.Xna.Framework; +using MonoGame.Extended.Entities.Systems; + +namespace Celesteia.Game.Systems.UI { + public class GameGUIDrawSystem : DrawSystem { + private GameGUI _gui; + + public GameGUIDrawSystem(GameGUI gui) => _gui = gui; + public override void Draw(GameTime gameTime) => _gui.Draw(gameTime); + } +}
\ No newline at end of file |
