﻿@startuml



package AsteroidsEngine{

Class Engine{
    -Shader _shader
    #EntityCollection Entities
    -bool _waitRestart
    #Engine(int xres, int yres)
    #void OnLoad()
    #void SetupResources()
    #void OnUnload()
    #void OnResize()
    #void OnRenderFrame(FrameEventArgs e)
    #void OnUpdateFrame(FrameEventArgs e)
    #void OnKeyDown(KeyboardKeyEventArgs e)
    #void OnKeyUp(KeyboardKeyEventArgs e)
    -void RestartGame()
    +void GameOver()
}

 class Entity{
    -LinkedList<UpdateComponent> _updateComponents
    -ICollider _collider
    -RenderComponent _render
    -Matrix4 _transMatrix
    -Vector2 _position
    -float _scale
    -float _rotation
    +Vector2 Position
    +float Scale
    +float Rotation
    +Vector2 Velocity
    +bool Active
    +float Timer
    +string Tag
    +bool Visible
    +int ComponentsCount => _updateComponents.Count;
    +Entity(Vector2 position)
    -void UpdateMatrix()
    +void Update(float delta)
    +void Render()
    +void AddComponent(UpdateComponent component)
    +void SetRender(RenderComponent component)
    +void SetCollider(ICollider collider)
    +void Collide(Entity entity2)
}

Class EntityCollection{
    -LinkedList<Entity> _collection
    -Dictionary<string, ICollider> _colliders
    -Dictionary<string, UpdateComponent> _components
    -List<Entity> _newCollection
    -List<RenderComponent> _renders
    -string[] _renderTagOrder
    --
    +EntityCollection()
    -void FillColliders()
    +void AddRender(RenderComponent renderComponent)
    -void FillComponents()
    -void AddComponent(string name, UpdateComponent component)
    -UpdateComponent GetComponent(string name)
    -void AddCollider(string name, ICollider collider)
    -ICollider GetCollider(string name)
    -Entity ReuseOrCreate(string tag, int render)
    -Entity ReuseOrCreate(string tag)
    +void Update(float delta)
    +void Render()
    +void Collide(string tag1, string tag2)
    +void CleanUp()
    +Entity FindByTag(string tag)
    +RenderComponent GetRender(int num)
    ..
    +void CreatePlayer()
    +Entity CreateAsteroid()
    +void CreateBullet(Entity origin)
    +void CreateBanner()
    +void CreateLaser(Entity origin)
    +void CreateAsteroidSpawner()
    +Entity CreateUfo()
    +void CreateLaserCounter()
    +void CreateScoreUi()
}

Class GuiVariables{
    +int Score
    +int LaserCharges
    +bool GameOver
}

class RenderComponent{
    #int QuadNum
    +RenderComponent(int num)
    +Render()
}

class ServiceLocator{
    -{static} Shader _shader
    -{static} Engine _engine
    -{static} Controller _controller
    -{static} EntityCollection _entities
    -{static} GuiVariables _variables
    +{static} Shader GetShader()
    +{static} void SetShader(Shader shader)
    +{static} Engine GetEngine()
    +{static} void SetEngine(Engine engine)
    +{static} Controller GetController()
    +{static} void SetController(Controller controller)
    +{static} EntityCollection GetEntityCollection()
    +{static} void SetEntityCollection(EntityCollection collection)
    +{static} GuiVariables GetGuiVariables()
    +{static} void SetGuiVariables(GuiVariables variables)
}

class Controller{
    +int Rotation
    +bool Fire1
    +bool Fire2
    +bool Thrust
}

class Shader{
    -int _handle
    -Dictionary<string, int> _uniformLocations
    --
    +Shader(string vertexPath, string fragmentPath)
    +void Use()
    +int GetAttribLocation(string name)
    +void SetMatrix4(string name, Matrix4 data)
    ..
    -bool _disposedValue
    #void Dispose(bool disposing)
    +~Shader()
    +void Dispose()
}

abstract class UpdateComponent{
    +{abstract}void Update(Entity entity, float delta)
}

class AsteroidSpawnerComponent{
    -Random _rnd
    +void Update(Entity entity, float delta)
}

class DecayComponent{
    +void Update(Entity entity, float delta)
}

class GameOverComponent{
    +void Update(Entity entity, float delta)
}

class HyperDriveComponent{
    +void Update(Entity entity, float delta)
}

class LaserChargeComponent{
    +void Update(Entity entity, float delta)
}

class PlayerComponent{
    -const float LaserChargeTime
    -float _bulletCd;
    -float _laserCd;
    +void Update(Entity entity, float delta)
}

class ScoreDigitComponent{
    +void Update(Entity entity, float delta)
}

class UfoAiComponent{
    -Entity _target
    +void Update(Entity entity, float delta)
}

UpdateComponent <|-- AsteroidSpawnerComponent
UpdateComponent <|-- DecayComponent
UpdateComponent <|-- GameOverComponent
UpdateComponent <|-- HyperDriveComponent
UpdateComponent <|-- LaserChargeComponent
UpdateComponent <|-- PlayerComponent
UpdateComponent <|-- ScoreDigitComponent
UpdateComponent <|-- UfoAiComponent

EntityCollection *- Entity
EntityCollection *-- ICollider
EntityCollection *-- RenderComponent
EntityCollection *-- UpdateComponent

Engine *- EntityCollection
Engine *-- Shader

Entity o-- ICollider
Entity o- UpdateComponent
Entity o- RenderComponent

ServiceLocator o-- Engine
ServiceLocator o- GuiVariables
ServiceLocator o- EntityCollection
ServiceLocator o- Controller
ServiceLocator o- Shader



Interface ICollider{
    {abstract}+void OnCollide(Entity entity1, Entity entity2)
}



ICollider <|-- AsteroidCollider
ICollider <|-- BulletCollider
ICollider <|-- ShipCollider
ICollider <|-- UfoCollider

class AsteroidCollider{
    +void OnCollide(Entity entity1, Entity entity2)
}

class BulletCollider{
    +void OnCollide(Entity entity1, Entity entity2)
}

class ShipCollider{
    +void OnCollide(Entity entity1, Entity entity2)
}

class UfoCollider{
    +void OnCollide(Entity entity1, Entity entity2)
}
}

package AsteroidsApp{
    class PolyEngine{
        -Model _model
        -Texture _texture
        +bool SpriteMode
        #SetupResources()
        #void OnKeyDown(KeyboardKeyEventArgs e)
        -void SwitchMode()
        #void OnUnload(EventArgs e)       
    }
    
    class PolyRenderComponent{
        -Model _model
        -Texture _texture
        +PolyRenderComponent(int quadNum, Model model, Texture texture)
        +void Render()
        -void RenderSprite()
        -void RenderModel()
    }
    
    class Texture{
        -int _handle
        -List<string> _names
        #string Path
        -bool _disposedValue
        #int ElementBufferObject
        #uint[] Indices
        #int VertexArrayObject
        #int VertexBufferObject
        #float[] Vertices
        +Texture(string path)
        +int Length()
        +void GenIndices()
        +void InitBuffers()
        +void Use(TextureUnit unit)
        +void RenderQuad(string name)
        +void RenderQuad(int num)
        #void Dispose(bool disposing)
        +void Dispose()
        +~Texture()
    }
    
    class Model{
        +int[] _begin
        +int[] _lengths
        +Model(string path)
        +void GenIndices()
        +void RenderModel(int num)
    }
    
    class Program{
        -{static}void Main
    }
    
    Engine <|- PolyEngine
    RenderComponent <|-- PolyRenderComponent
    Texture <|- Model
    
    Program *- PolyEngine
    
    PolyEngine *-- Texture
    PolyEngine *- Model

    PolyRenderComponent o- Texture
    PolyRenderComponent o-- Model
}
@enduml