Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/fireblade-engine/ecs
A dependency free, lightweight, fast Entity-Component System (ECS) implementation in Swift
https://github.com/fireblade-engine/ecs
ecs entity entity-component-system entitycomponentsystem fireblade-engine game-development game-engine gamedev ios linux macos spm swift swift-package-manager windows
Last synced: about 14 hours ago
JSON representation
A dependency free, lightweight, fast Entity-Component System (ECS) implementation in Swift
- Host: GitHub
- URL: https://github.com/fireblade-engine/ecs
- Owner: fireblade-engine
- License: mit
- Created: 2018-01-04T20:29:07.000Z (about 7 years ago)
- Default Branch: master
- Last Pushed: 2024-10-01T16:12:28.000Z (4 months ago)
- Last Synced: 2024-10-06T18:02:30.143Z (4 months ago)
- Topics: ecs, entity, entity-component-system, entitycomponentsystem, fireblade-engine, game-development, game-engine, gamedev, ios, linux, macos, spm, swift, swift-package-manager, windows
- Language: Swift
- Homepage:
- Size: 792 KB
- Stars: 109
- Watchers: 6
- Forks: 10
- Open Issues: 10
-
Metadata Files:
- Readme: README.md
- Contributing: CONTRIBUTING.md
- Funding: .github/FUNDING.yml
- License: LICENSE
- Code of conduct: CODE_OF_CONDUCT.md
- Codeowners: CODEOWNERS
Awesome Lists containing this project
README
# Fireblade ECS (Entity-Component System)
[![license](https://img.shields.io/badge/license-MIT-brightgreen.svg)](LICENSE)
[![macOS](https://github.com/fireblade-engine/ecs/actions/workflows/ci-macos.yml/badge.svg)](https://github.com/fireblade-engine/ecs/actions/workflows/ci-macos.yml)
[![Linux](https://github.com/fireblade-engine/ecs/actions/workflows/ci-linux.yml/badge.svg)](https://github.com/fireblade-engine/ecs/actions/workflows/ci-linux.yml)
[![Windows](https://github.com/fireblade-engine/ecs/actions/workflows/ci-windows.yml/badge.svg)](https://github.com/fireblade-engine/ecs/actions/workflows/ci-windows.yml)
[![WASM](https://github.com/fireblade-engine/ecs/actions/workflows/ci-wasm.yml/badge.svg)](https://github.com/fireblade-engine/ecs/actions/workflows/ci-wasm.yml)
[![documentation](https://github.com/fireblade-engine/ecs/workflows/Documentation/badge.svg)](https://github.com/fireblade-engine/ecs/wiki)
[![codecov](https://codecov.io/gh/fireblade-engine/ecs/branch/master/graph/badge.svg)](https://codecov.io/gh/fireblade-engine/ecs)
[![spi-swift-versions](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Ffireblade-engine%2Fecs%2Fbadge%3Ftype%3Dswift-versions)](https://swiftpackageindex.com/fireblade-engine/ecs)
[![spi-swift-platforms](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Ffireblade-engine%2Fecs%2Fbadge%3Ftype%3Dplatforms)](https://swiftpackageindex.com/fireblade-engine/ecs)This is a **dependency free**, **lightweight**, **fast** and **easy to use** [Entity-Component System](https://en.wikipedia.org/wiki/Entity_component_system) implementation in Swift. It is developed and maintained as part of the [Fireblade Game Engine project](https://github.com/fireblade-engine).
See the [Fireblade ECS Demo App](https://github.com/fireblade-engine/ecs-demo) or have a look at [documentation in the wiki](https://github.com/fireblade-engine/ecs/wiki) to get started.
## ๐ Getting Started
These instructions will get you a copy of the project up and running on your local machine and provide a code example.
### ๐ Prerequisites
* [Swift Package Manager (SPM)](https://github.com/apple/swift-package-manager)
* [Swiftlint](https://github.com/realm/SwiftLint) for linting - (optional)
* [SwiftEnv](https://swiftenv.fuller.li/) for Swift version management - (optional)### ๐ป Installing
Fireblade ECS is available for all platforms that support [Swift 5.8](https://swift.org/) and higher and the [Swift Package Manager (SPM)](https://github.com/apple/swift-package-manager).
Extend the following lines in your `Package.swift` file or use it to create a new project.
```swift
// swift-tools-version:5.8import PackageDescription
let package = Package(
name: "YourPackageName",
dependencies: [
.package(url: "https://github.com/fireblade-engine/ecs.git", from: "0.17.5")
],
targets: [
.target(
name: "YourTargetName",
dependencies: ["FirebladeECS"])
]
)```
## ๐ Code Example
### ๐๏ธ Nexus
The core element in the Fireblade-ECS is the [Nexus](https://en.wiktionary.org/wiki/nexus#Noun).
It acts as a centralized way to store, access and manage entities and their components.
A single `Nexus` may (theoretically) hold up to 4294967295 `Entities` at a time.
You may use more than one `Nexus` at a time.Initialize a `Nexus` with
```swift
let nexus = Nexus()
```### ๐ค Entities
then create entities by letting the `Nexus` generate them.
```swift
// an entity without components
let newEntity = nexus.createEntity()
```To define components, conform your class to the `Component` protocol
```swift
final class Position: Component {
var x: Int = 0
var y: Int = 0
}
```
and assign instances of it to an `Entity` with```swift
let position = Position(x: 1, y: 2)
entity.assign(position)
```You can be more efficient by assigning components while creating an entity.
```swift
// an entity with two components assigned.
nexus.createEntity {
Position(x: 1, y: 2)
Color(.red)
}// bulk create entities with multiple components assigned.
nexus.createEntities(count: 100) { _ in
Position()
Color()
}```
### ๐ช FamiliesThis ECS uses a grouping approach for entities with the same component types to optimize cache locality and ease up access to them.
Entities with the __same component types__ may belong to one `Family`.
A `Family` has entities as members and component types as family traits.Create a family by calling `.family` with a set of traits on the nexus.
A family that contains only entities with a `Movement` and `PlayerInput` component, but no `Texture` component is created by```swift
let family = nexus.family(requiresAll: Movement.self, PlayerInput.self,
excludesAll: Texture.self)
```These entities are cached in the nexus for efficient access and iteration.
Families conform to the [Sequence](https://developer.apple.com/documentation/swift/sequence) protocol so that members (components)
may be iterated and accessed like any other sequence in Swift.
Access a family's components directly on the family instance. To get family entities and access components at the same time call `family.entityAndComponents`.
If you are only interested in a family's entities call `family.entities`.```swift
class PlayerMovementSystem {
let family = nexus.family(requiresAll: Movement.self, PlayerInput.self,
excludesAll: Texture.self)func update() {
family
.forEach { (mov: Movement, input: PlayerInput) in
// position & velocity component for the current entity
// get properties
_ = mov.position
_ = mov.velocity
// set properties
mov.position.x = mov.position.x + 3.0
...
// current input command for the given entity
_ = input.command
...
}
}func update2() {
family
.entityAndComponents
.forEach { (entity: Entity, mov: Movement, input: PlayerInput) in
// the current entity instance
_ = entity// position & velocity component for the current entity
// get properties
_ = mov.position
_ = mov.velocity
}
}func update3() {
family
.entities
.forEach { (entity: Entity) in
// the current entity instance
_ = entity
}
}
}
```### ๐ง Singles
A `Single` on the other hand is a special kind of family that holds exactly **one** entity with exactly **one** component for the entire lifetime of the Nexus. This may come in handy if you have components that have a [Singleton](https://en.wikipedia.org/wiki/Singleton_(mathematics)) character. Single components must conform to the `SingleComponent` protocol and will not be available through regular family iteration.
```swift
final class GameState: SingleComponent {
var quitGame: Bool = false
}
class GameLogicSystem {
let gameState: Single
init(nexus: Nexus) {
gameState = nexus.single(GameState.self)
}
func update() {
// update your game sate here
gameState.component.quitGame = true
// entity access is provided as well
_ = gameState.entity
}
}```
### ๐ Serialization
To serialize/deserialize entities you must conform their assigned components to the `Codable` protocol.
Conforming components can then be serialized per family like this:```swift
// MyComponent and YourComponent both conform to Component and Codable protocols.
let nexus = Nexus()
let family = nexus.family(requiresAll: MyComponent.self, YourComponent.self)// JSON encode entities from given family.
var jsonEncoder = JSONEncoder()
let encodedData = try family.encodeMembers(using: &jsonEncoder)// Decode entities into given family from JSON.
// The decoded entities will be added to the nexus.
var jsonDecoder = JSONDecoder()
let newEntities = try family.decodeMembers(from: jsonData, using: &jsonDecoder)```
## ๐งช Demo
See the [Fireblade ECS Demo App](https://github.com/fireblade-engine/ecs-demo) to get started.
## ๐ Documentation
Consult the [online documentation](https://swiftpackageindex.com/fireblade-engine/ecs/documentation/FirebladeECS), or preview it locally:
- `make preview-docs`
## ๐ How to contribute
If you want to contribute please see the [CONTRIBUTION GUIDE](CONTRIBUTING.md) first.
To start your project contribution run these in your command line:
1. `git clone [email protected]:fireblade-engine/ecs.git fireblade-ecs`
2. `cd fireblade-ecs`
3. `make setupEnvironment`Before commiting code please ensure to run:
- `make precommit`
This project is currently maintained by [Christian Treffs](https://github.com/ctreffs).
See also the list of [contributors](https://github.com/fireblade-engine/ecs/contributors) who participated in this project.## ๐ License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details
## ๐ Acknowledgments
Inspired by
- [Ashley](https://github.com/libgdx/ashley)
- [Entitas](https://github.com/sschmid/Entitas-CSharp)
- [EntitasKit](https://github.com/mzaks/EntitasKit)