Documentation ¶
Overview ¶
Package model provides a wrapper around the Arche ECS world that helps with rapid prototyping and model development.
Example ¶
package main import ( "github.com/mlange-42/arche-model/model" "github.com/mlange-42/arche-model/system" ) func main() { // Create a new, seeded model. m := model.New().Seed(123) // Add systems. m.AddSystem(&system.FixedTermination{ Steps: 100, }) // Run the simulation. m.Run() }
Output:
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Model ¶
type Model struct { Systems // Systems manager and scheduler World ecs.World // The ECS world // contains filtered or unexported fields }
Model is the top-level ECS entrypoint.
Model provides access to the ECS world, and manages the scheduling of System and UISystem instances via Systems. System instances are updated with a frequency given by TPS. UISystem instances are updated independently of normal systems, with a frequency given by FPS.
The Systems scheduler, the model's resource.Tick, resource.Termination and a central resource.Rand PRNG source can be accessed by systems as resources.
Example ¶
package main import ( "github.com/mlange-42/arche-model/model" "github.com/mlange-42/arche-model/system" ) func main() { // Create a new, seeded model. m := model.New().Seed(123) // Add systems. m.AddSystem(&system.FixedTermination{ Steps: 100, }) // Run the simulation. m.Run() }
Output:
Example (ManualUpdate) ¶
package main import ( "github.com/mlange-42/arche-model/model" "github.com/mlange-42/arche-model/system" ) func main() { // Create a new, seeded model. m := model.New().Seed(123) // Add systems. m.AddSystem(&system.FixedTermination{ Steps: 100, }) // Run the simulation manually. m.Initialize() for m.Update() { m.UpdateUI() } m.Finalize() }
Output:
func (*Model) Reset ¶
func (m *Model) Reset()
Reset resets the world and removes all systems.
Can be used to run systematic simulations without the need to re-allocate memory for each run. Accelerates re-populating the world by a factor of 2-3.
Example ¶
package main import ( "github.com/mlange-42/arche-model/model" "github.com/mlange-42/arche-model/system" ) func main() { // Create a new model. m := model.New() // Do many model runs. for i := 0; i < 10; i++ { // Reset the model to clear entities, systems etc. before the run. m.Reset() // Seed the model for the run. m.Seed(uint64(i)) // Add systems. m.AddSystem(&system.FixedTermination{ Steps: 100, }) // Run the simulation. m.Run() } }
Output:
func (*Model) Run ¶
func (m *Model) Run()
Run the model, updating systems and ui systems according to Model.TPS and Model.FPS, respectively. Initializes the model if it is not already initialized. Finalizes the model after the run.
Runs until Terminate in the resource resource.Termination is set to true (see resource.Termination).
To perform updates manually, see Model.Update and Model.UpdateUI, as well as Model.Initialize and Model.Finalize.
func (*Model) Seed ¶
Seed sets the random seed of the model's resource.Rand. Call without an argument to seed from the current time.
Systems should always use the Rand resource for PRNGs.
func (*Model) Update ¶ added in v0.7.0
Update the model's systems. Return whether the run should continue.
Ignores Model.TPS.
Panics if Model.Initialize was not called.
func (*Model) UpdateUI ¶ added in v0.7.0
func (m *Model) UpdateUI()
UpdateUI the model's UI systems.
Ignores Model.FPS.
Panics if Model.Initialize was not called.
type System ¶
type System interface { Initialize(w *ecs.World) // Initialize the system. Update(w *ecs.World) // Update the system. Finalize(w *ecs.World) // Finalize the system. }
System is the interface for ECS systems.
See also UISystem for systems with an independent graphics step.
Example ¶
package main import ( "fmt" "github.com/mlange-42/arche-model/model" "github.com/mlange-42/arche-model/resource" "github.com/mlange-42/arche-model/system" "github.com/mlange-42/arche/ecs" "github.com/mlange-42/arche/generic" ) // TestSystem is an example for implementing [System]. type TestSystem struct { timeRes generic.Resource[resource.Tick] } // Initialize the system. func (s *TestSystem) Initialize(w *ecs.World) { s.timeRes = generic.NewResource[resource.Tick](w) } // Update the system. func (s *TestSystem) Update(w *ecs.World) { time := s.timeRes.Get() fmt.Println(time.Tick) } // Finalize the system. func (s *TestSystem) Finalize(w *ecs.World) {} func main() { // Create a new model. m := model.New() // Add the test system. m.AddSystem(&TestSystem{}) // Add a termination system that ends the simulation. m.AddSystem(&system.FixedTermination{Steps: 30}) // Run the simulation. m.Run() }
Output:
type Systems ¶
type Systems struct { // Ticks per second for normal systems. // Values <= 0 (the default) mean as fast as possible. TPS float64 // Frames per second for UI systems. // A zero/unset value defaults to 30 FPS. Values < 0 sync FPS with TPS. // With fast movement, a value of 60 may be required for fluent graphics. FPS float64 // Whether the simulation is currently paused. // When paused, only UI updates but no normal updates are performed. Paused bool // contains filtered or unexported fields }
Systems manages and schedules ECS System and UISystem instances.
System instances are updated with a frequency given by TPS (ticks per second). UISystem instances are updated independently of normal systems, with a frequency given by FPS (frames per second).
Systems is an embed in Model and it's methods are usually only used through a Model instance. By also being a resource of each Model, however, systems can access it and e.g. remove themselves from a model.
Example ¶
package main import ( "github.com/mlange-42/arche-model/model" "github.com/mlange-42/arche-model/system" "github.com/mlange-42/arche/ecs" ) func main() { // Create a new model. m := model.New() // The model contains Systems as an embed, TPS and FPS are accessible through the model directly. m.TPS = 1000 m.FPS = 60 // Create a system sys := system.FixedTermination{ Steps: 10, } // Add the system the usual way, through the model. // The model contains Systems as an embed, so actually [Systems.AddSystem] is called. m.AddSystem(&sys) // Inside systems, [Systems] can be accessed as a resource. systems := ecs.GetResource[model.Systems](&m.World) // Pause the simulation, e.g. based on user input. systems.Paused = true // Remove the system using the resource. systems.RemoveSystem(&sys) }
Output:
func (*Systems) AddSystem ¶
AddSystem adds a System to the model.
Panics if the system is also a UISystem. To add systems that implement both System and UISystem, use Systems.AddUISystem
func (*Systems) AddUISystem ¶
AddUISystem adds an UISystem to the model.
Adds the UISystem also as a normal System if it implements the interface.
func (*Systems) RemoveSystem ¶
RemoveSystem removes a system from the model.
Systems can also be removed during a model run. However, this will take effect only after the end of the full model step.
func (*Systems) RemoveUISystem ¶
RemoveUISystem removes an UI system from the model.
Systems can also be removed during a model run. However, this will take effect only after the end of the full model step.
type UISystem ¶
type UISystem interface { InitializeUI(w *ecs.World) // InitializeUI the system. UpdateUI(w *ecs.World) // UpdateUI/update the system. PostUpdateUI(w *ecs.World) // PostUpdateUI does the final part of updating, e.g. update the GL window. FinalizeUI(w *ecs.World) // FinalizeUI the system. }
UISystem is the interface for ECS systems that display UI in an independent graphics step.
See also System for normal systems.
Example ¶
package main import ( "fmt" "github.com/mlange-42/arche-model/model" "github.com/mlange-42/arche-model/resource" "github.com/mlange-42/arche-model/system" "github.com/mlange-42/arche/ecs" "github.com/mlange-42/arche/generic" ) // TestUISystem is an example for implementing [UISystem]. type TestUISystem struct { timeRes generic.Resource[resource.Tick] } // Initialize the system. func (s *TestUISystem) InitializeUI(w *ecs.World) { s.timeRes = generic.NewResource[resource.Tick](w) } // Update the system. func (s *TestUISystem) UpdateUI(w *ecs.World) { time := s.timeRes.Get() fmt.Println(time.Tick) } // PostUpdate the system. func (s *TestUISystem) PostUpdateUI(w *ecs.World) {} // Finalize the system. func (s *TestUISystem) FinalizeUI(w *ecs.World) {} func main() { // Create a new model. m := model.New() // Add the test ui system. m.AddUISystem(&TestUISystem{}) // Add a termination system that ends the simulation. m.AddSystem(&system.FixedTermination{Steps: 30}) // Run the simulation. m.Run() }
Output: