Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ECS chapter for new book #182

Closed
wants to merge 146 commits into from
Closed
Show file tree
Hide file tree
Changes from 111 commits
Commits
Show all changes
146 commits
Select commit Hold shift + click to select a range
252325d
Book structure (#154)
alice-i-cecile Jun 2, 2021
8a3cf22
Overview of ECS
alice-i-cecile Jun 19, 2021
8f903e0
Added page on entities and components
alice-i-cecile Jun 19, 2021
4f0bc41
Editing cleanup
alice-i-cecile Jun 19, 2021
ac89c61
Basic page on queries
alice-i-cecile Jun 20, 2021
cee206b
Rust tips for Bevy
alice-i-cecile Jun 20, 2021
c69c59b
Resources page
alice-i-cecile Jun 20, 2021
c8ede28
Guessing game resource example
alice-i-cecile Jun 21, 2021
1e32b8f
Links should point to latest, not 0.5
alice-i-cecile Jun 21, 2021
b15e909
Improved clarity of guessing game example
alice-i-cecile Jun 21, 2021
1a145a8
Stub for commands
alice-i-cecile Jun 21, 2021
38c54c3
Spawning and despawning with Commands example
alice-i-cecile Jun 22, 2021
8574c9e
spawn_batch example
alice-i-cecile Jun 22, 2021
4c7e9fa
Added (buggy) insert / remove example
alice-i-cecile Jun 22, 2021
f91b0a2
Fixed add/remove components example
alice-i-cecile Jun 22, 2021
6a060a5
Linter plz
alice-i-cecile Jun 24, 2021
713a57f
Advice warning against use of type aliases
alice-i-cecile Jun 24, 2021
b054d15
Text body for query filters
alice-i-cecile Jun 28, 2021
b39bdd6
Section on optional resource types
alice-i-cecile Jun 28, 2021
815beb4
Explanatory note on missing mut
alice-i-cecile Jun 28, 2021
1152b21
Change detection explanation
alice-i-cecile Jun 28, 2021
d6cc1fe
Explanation of generic systems
alice-i-cecile Jun 29, 2021
38821f5
Text for exclusive world access page
alice-i-cecile Jun 29, 2021
607f71a
Explained how to control exclusive system insertion timing
alice-i-cecile Jun 29, 2021
98e46f4
Note on ordering exclusive systems
alice-i-cecile Jun 29, 2021
a812e4f
Corrected name of exclusive_system().at_end()
alice-i-cecile Jun 29, 2021
e3e927a
Typo fix
alice-i-cecile Jun 29, 2021
e158ab0
Clarity improvements to ECS chapter introduction
alice-i-cecile Jun 29, 2021
cb4cecb
Typo fix
alice-i-cecile Jun 29, 2021
b24a3a6
at_start is default behavior
alice-i-cecile Jun 29, 2021
aaf3e23
Option resources also work for NonSend
alice-i-cecile Jun 29, 2021
5cb00f0
Clarity edits on Query syntax
alice-i-cecile Jun 29, 2021
c9d7fe2
Clarified purpose of bundle field names
alice-i-cecile Jun 29, 2021
d0653de
Added query conflict error message
alice-i-cecile Jun 29, 2021
cddfea3
Removed long and complex example from entities and components page
alice-i-cecile Jun 29, 2021
5dad8ad
Accessing system parameters + manually running systems
alice-i-cecile Jun 29, 2021
3537668
Manually flushing commands
alice-i-cecile Jun 29, 2021
8a1e053
Updated notes on manually running systems from &mut World
alice-i-cecile Jun 30, 2021
8289828
Correctness nit
alice-i-cecile Jul 1, 2021
0b664f5
Typo fix
alice-i-cecile Jul 1, 2021
04a2d33
Corrected explanation of NonSend resource behavior
alice-i-cecile Aug 3, 2021
f4dff89
Added note on system parallelism + Without filters
alice-i-cecile Aug 3, 2021
8878e81
Require Component derive
alice-i-cecile Aug 3, 2021
01402b5
Shortened page names
alice-i-cecile Aug 3, 2021
3058e79
Moved tips and tricks to separate page
alice-i-cecile Aug 3, 2021
58d1b7c
Better scheduling explanation
alice-i-cecile Aug 3, 2021
4ed2ca5
Added high-level ECS example to start of chapter
alice-i-cecile Aug 4, 2021
d5636c8
High-level overview of commands in ECS intro
alice-i-cecile Aug 4, 2021
8352bd2
Added more explanation to the initial example
alice-i-cecile Aug 4, 2021
29eaf59
Added more clarifying links
alice-i-cecile Aug 4, 2021
16356d5
Added more technical details to ECS description
alice-i-cecile Aug 4, 2021
ed89be5
Swapped to much simpler falling example by @Nilirad
alice-i-cecile Aug 4, 2021
8f27ecd
Rewrote entities-components page to be more useful
alice-i-cecile Aug 5, 2021
20a2fb6
Reorganized chapter layout
alice-i-cecile Aug 5, 2021
80df83f
Polished page on resources
alice-i-cecile Aug 5, 2021
11260e7
Explained nested bundles
alice-i-cecile Aug 5, 2021
49eed9c
Completed page on Queries
alice-i-cecile Aug 5, 2021
0420c95
Cleaned up page on Systems
alice-i-cecile Aug 5, 2021
b05c7f5
Clarity improvements from @TypicalFork
alice-i-cecile Aug 5, 2021
3ae04bf
Completed change-detection page
alice-i-cecile Aug 6, 2021
cd44547
Fixed stale doc links
alice-i-cecile Aug 6, 2021
ebf131e
Added demonstration of how to manually run systems
alice-i-cecile Aug 6, 2021
31dd304
Exclusive system page editing pass
alice-i-cecile Aug 6, 2021
e99da61
Added exclusive system example from @JMS55
alice-i-cecile Aug 6, 2021
b0b671b
Moved custom commands to commands page
alice-i-cecile Aug 6, 2021
34f3198
Satisfy the gods of lint
alice-i-cecile Aug 6, 2021
6f5dff0
Custom commands example
alice-i-cecile Aug 6, 2021
e776c74
Added explanation of shared mutable access to World
alice-i-cecile Aug 6, 2021
9847aba
Command application order rules
alice-i-cecile Aug 6, 2021
f734bc5
Welcome blurb
alice-i-cecile Jun 14, 2021
528a91f
Community blurb
alice-i-cecile Jun 14, 2021
b35d0b8
Why not Bevy
alice-i-cecile Jun 14, 2021
8e7794c
Hello World
alice-i-cecile Jun 14, 2021
b0a7a0b
Quick draft on plugins
alice-i-cecile Jun 14, 2021
d82ee9b
Explain MinimalPlugins
alice-i-cecile Jun 14, 2021
9896278
Disabling plugins
alice-i-cecile Jun 14, 2021
1c28e56
Third-party plugins
alice-i-cecile Jun 14, 2021
62b998a
Removed Community page
alice-i-cecile Jun 16, 2021
07f4528
Content polish
alice-i-cecile Jun 16, 2021
50dbe1c
Link to documentation strategies
alice-i-cecile Jun 16, 2021
bef720e
Typo
alice-i-cecile Jun 16, 2021
a4ef5f8
Typo fix
alice-i-cecile Jun 16, 2021
a0b0363
Use link over embedding default plugins code
alice-i-cecile Jun 19, 2021
ab2410c
Better explained how plugins work
alice-i-cecile Jun 19, 2021
b6b0de4
Concrete example of a plugin before jumping to DefaultPlugins
alice-i-cecile Jun 19, 2021
0e9677d
Added page on App and AppBuilder
alice-i-cecile Jun 19, 2021
0b38fba
Fix hello_world code
alice-i-cecile Jun 19, 2021
138fa48
Swapped out Hello World example in Installation
alice-i-cecile Jun 19, 2021
70fbcb1
Condensed section on MinimalPlugins to link to code
alice-i-cecile Jun 19, 2021
c2f9070
Added advice on publishing 3rd party plugins
alice-i-cecile Jul 31, 2021
b2f30c1
Removed references to AppBuilder
alice-i-cecile Jul 31, 2021
a3a00ad
Encourage the reader to explore the reference docs more
alice-i-cecile Jul 31, 2021
3e370de
Introduction page optimism and clarity
alice-i-cecile Aug 1, 2021
190c6a2
Cleaned up game terminology
alice-i-cecile Aug 1, 2021
ec50cff
dbg -> info
alice-i-cecile Aug 1, 2021
f2799f5
Clarity improvements for Plugin page
alice-i-cecile Aug 2, 2021
fc9a7ad
Clarity improvements for `App` page
alice-i-cecile Aug 2, 2021
d8ebee3
Clarified that Bevy is both free and libre
alice-i-cecile Aug 2, 2021
4f169ab
Clarity improvements to Welcome page
alice-i-cecile Aug 2, 2021
ee2bfc3
Removed .system() call
alice-i-cecile Aug 6, 2021
4bd12cc
Typo fix
alice-i-cecile Aug 6, 2021
ce83f85
Style and phrasing tweaks
cart Aug 6, 2021
d9d038e
Wording fixes from @MinerSebas
alice-i-cecile Aug 7, 2021
f45037d
Yeet .system()
alice-i-cecile Aug 7, 2021
0bcb450
Improved clarity and flow of exclusive systems page
alice-i-cecile Aug 7, 2021
af47f49
Converted links and inline code-formatted names to short codes
alice-i-cecile Aug 9, 2021
34ef339
Expanded on explanation of query filters
alice-i-cecile Aug 12, 2021
1c2e1d8
Editing pass
alice-i-cecile Aug 12, 2021
83a7939
fix code highlighting after zola 0.14 (#191)
mockersf Jul 21, 2021
8a8731a
Fixed missing shortcodes
alice-i-cecile Aug 13, 2021
18cbae9
Added page on ECS internals for advanced users
alice-i-cecile Aug 13, 2021
5c6f450
Named queries
Nilirad Oct 3, 2021
86fa2ba
Ignore Zola-generated files
alice-i-cecile Oct 14, 2021
c62f9cb
Subtle but important mental model tweak on Queries
alice-i-cecile Oct 14, 2021
32ea535
Merge pull request #1 from Nilirad/named-queries
alice-i-cecile Oct 15, 2021
0328a1e
Fixed broken links (thanks to @sseemayer)
alice-i-cecile Nov 1, 2021
7690cc7
Minor edits
alice-i-cecile Nov 1, 2021
fdeab37
Edits from @tsoutsman
alice-i-cecile Nov 1, 2021
a03852c
Edits from @tsoutsman
alice-i-cecile Nov 1, 2021
137be61
Merge remote-tracking branch 'origin/book-ecs' into book-ecs
alice-i-cecile Nov 1, 2021
dc31a3a
Clarity improvements prompted by @mirkoRainer
alice-i-cecile Nov 3, 2021
8442122
Editing pass for clarity and polish
alice-i-cecile Nov 4, 2021
06d9aea
Wording workaround for #219
alice-i-cecile Nov 4, 2021
6f7a0c4
Mole game!
alice-i-cecile Nov 5, 2021
8e6f32f
Remove tabs in favor of spaces for better end result formatting
mirkoRainer Nov 5, 2021
d658883
Merge pull request #2 from mirkoRainer/mirko-converts-tabs-to-space-f…
alice-i-cecile Nov 5, 2021
5579722
Simplified / clarified 'static lifetime explanation
alice-i-cecile Dec 12, 2021
6712313
Use consistent spacing
sklum Jan 14, 2022
df9864e
Remove erroneous paren
sklum Jan 14, 2022
6cb86c9
Add missing paren
sklum Jan 14, 2022
9b0efb8
Use consistent function styling
sklum Jan 14, 2022
e3f41c3
Correct remove call
sklum Jan 14, 2022
c26a280
Use consistent function styling
sklum Jan 14, 2022
e4147f7
Add missing comma
sklum Jan 14, 2022
d562f22
Add missing comma
sklum Jan 14, 2022
f39156b
Use consistent spacing
sklum Jan 14, 2022
581ee6b
Add missing comma
sklum Jan 14, 2022
575af57
Merge pull request #3 from sklum/book-ecs
alice-i-cecile Jan 14, 2022
3206cae
Replace shortcodes
alice-i-cecile Feb 11, 2022
1bca9d8
Ignore generate-errors folder
alice-i-cecile Feb 11, 2022
1e9b8a6
Finish replacing shortcodes
alice-i-cecile Feb 11, 2022
ea4434c
Fix blog link
alice-i-cecile Feb 12, 2022
55beec6
Fix nits from Cart
alice-i-cecile Feb 12, 2022
1013543
Simplify Combatants example
alice-i-cecile Feb 12, 2022
9089603
Enable anchor links in ECS section
Feb 12, 2022
69e840b
Merge pull request #4 from KDecay/enable_anchor_links_ecs
alice-i-cecile Feb 12, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 0 additions & 21 deletions .github/workflows/ci.yml

This file was deleted.

25 changes: 0 additions & 25 deletions .github/workflows/deploy.yml

This file was deleted.

39 changes: 39 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# This is a basic workflow to help you get started with Actions

name: CI

# Controls when the action will run. Triggers the workflow on pushes to master
# or any pull request or pull request
on:
push:
branches: [master]
pull_request:

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
build:
runs-on: ubuntu-latest
if: github.ref != 'refs/heads/master' # Only on PRs, see also build_and_deploy below
steps:
- uses: actions/checkout@v2

- name: "Build website"
uses: shalzz/zola-deploy-action@master
env:
PAGES_BRANCH: gh-pages
BUILD_DIR: .
BUILD_ONLY: true
TOKEN: fake-secret

build_and_deploy:
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/master' # Only on a push to the master branch (like when PR's are merged)
steps:
- uses: actions/checkout@master

- name: "Build and deploy website"
uses: shalzz/zola-deploy-action@master
env:
PAGES_BRANCH: gh-pages
BUILD_DIR: .
TOKEN: ${{ secrets.CART_PAT }}
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
public
**/.DS_Store
.idea/
content/assets
11 changes: 6 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ The source files for https://bevyengine.org. This includes official Bevy news an

## Zola

The Bevy website is built using the Zola static site engine. In our experience, it is fast, flexible, and straightforward to use.
The Bevy website is built using the Zola static site engine. In our experience, it is fast, flexible, and straightforward to use. [Check it out here](https://www.getzola.org/)!

To check out any local changes you've made:
1. [Download Zola](https://www.getzola.org/).
2. Clone the Bevy Website git repo and enter that directory:
1. `git clone https://github.com/bevyengine/bevy-website.git`
2. `cd bevy-website`
1. Download Zola.
2. Clone the Bevy Website git repo and move to that directory:
1. `git clone https://github.com/bevyengine/bevy-website.git`
2. `cd bevy-website`
3. Start the Zola server with `zola serve`.

A local server should start and you should be able to access a local version of the website from there.

3 changes: 2 additions & 1 deletion config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ taxonomies = [
# Whether to do syntax highlighting
# Theme can be customised by setting the `highlight_theme` variable to a theme supported by Zola
highlight_code = true
highlight_theme = "css"
highlight_theme = "base16-ocean-dark"


[extra]
# Put all your custom variables here
146 changes: 145 additions & 1 deletion content/learn/book/ecs/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,148 @@ template = "book-section.html"
page_template = "book-section.html"
+++

TODO: high-level overview of how the ECS works
Bevy is fundamentally powered by its ECS (Entity Component System): almost all data is stored as components on entities, and all logic is executed by its systems.

As we [mentioned in the last chapter](../welcome/app/_index.md), all of our data is stored in a {{rust_type(type="struct" crate="bevy_ecs" name="World")}} on our {{rust_type(type="struct" crate="bevy" name="App")}}).
We can think of our **entity-component data storage** as a giant in-memory database:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not a fan of starting with a database analogy. It assumes the user understands databases (what is a row, column, cell, primary key, "ragged databases", tabular data storage, in-memory databases vs distributed databases, etc). Even I didn't know what "ragged" meant in a database context and I've clocked a ton of hours in the database world. Encouraging people to learn a niche term, how it relates to databases, then how that database concept relates to Bevy ECS feels pretty roundabout.

I think the analogy is helpful as either an aside that we link to, or as a one liner (to help people with the context to appreciate it). But I don't like that it is central to the initial framing. And it should probably be accompanied by a list of ways Bevy ECS isn't like a database (ex: sparse sets, the archetype abstraction, change detection, generational indices, etc).

I think it would be clearer (and more universally palatable) to introduce Bevy ECS concepts directly first, rather than via analogy. What role does each piece fill, how might you use each piece in practice, etc.


* each row is an **entity**, representing an object (perhaps a player, tile, or UI button) in our game
* each column is a type of **component**, storing data of a particular type (perhaps the sprite, team or life of a player entity) in an [efficient way](https://github.com/bevyengine/bevy/pull/1525) that keeps data of the same type tightly packed together
* each cell is a component of a particular entity, which has a concrete value we can look up and change
* we access data from this database using **queries**, which fetch entities with the specified components
* the primary key of this database is the {{rust_type(type="struct" crate="bevy_ecs" name="Entity")}} identifier, which can be used to look up specific entities using {{rust_type(type="struct" crate="bevy_ecs" name="Query" method = "get")}}

Of course, this database is [very ragged](https://www.transdatasolutions.com/what-is-ragged-data/): not all entities will have every component!
We can use this fact to specialize behavior between entities: systems only perform work on entities with the correct combination of components.
You don't want to apply gravity to entities without a position in your world, and you're only interested in using the UI layout algorithm to control the layout of UI entities!

When we want to go beyond this tabular data storage, we can use **resources**: global singletons which store data in monolithic blobs.
You might use resources to interface with other libraries, store unique bits of state like the game's score, or store secondary data structures like indexes to augment your use of entity-component data.

In order to manipulate and act on this data, we must use systems.
**Systems** are Rust functions that request specific data, such as resources and entities, from the {{rust_type(type="struct" crate="bevy_ecs" name="World")}}. They define a query in their parameters (arguments) that selects data with a particular combination of components.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I personally think that these "core concept" introductions would much more approachable if they followed a similar pattern to the current Bevy Book ECS intro:
image

The bullet points help visually break up the concepts. The simple examples isolated by concept help ground the concepts in reality (without burying them in a large blob of code).

I'm now realizing that I made the mistake of using Transform in the Query when I literally just introduced the Position component. And leaking the internals of Entity isn't particularly helpful as an introduction (especially when those leaked internals are incorrect!).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the bullet points a lot. I'm going to steal from this.

All of the rules and behaviours of our game are governed by systems.

Once the systems are added to our app the **runner** takes in this information and automatically runs our systems: typically once during each pass of the **game loop** according to the rules defined in their **schedule**.
Bevy's default execution strategy runs systems in parallel by default, without the need for any manual setup.
Because the **function signature** of each of our systems fully define the data it can access, we can ensure that only one system can change a piece of data at once (although any number can read from a piece of data at the same time).
Systems within the same **stage** are allowed to run in parallel with each other (as long as their data access does not conflict), and are assigned to a free thread as soon as one is free.

When we need to access data in complex, cross-cutting ways that are not cleanly modelled by our systems' function signatures, we can defer the work until we have exclusive access to the entire world's data: executing **commands** generated in earlier systems at the end of each stage or performing complex logic (like saving the entire game) in our own **exclusive systems**.
You will first encounter this when spawning and despawning entities: we have no way of knowing precisely which other components our entities might have, and so we are forced to wait until we can ensure that we can safely write to *all* component data at once.

## ECS by example

Before we dive into the details of each of these features, let's take a quick look at a simple game that you can run and play.
Unsurprisingly, the different parts of the ECS tend to be closely linked: components are not very useful without a way to spawn entities and systems that run our logic are very dull if we can't discuss the data they can access.
The details of each part are more easily grasped if you have a basic sense of the whole.

```rust
use bevy::app::AppExit;
use bevy::log::LogPlugin;
use bevy::prelude::*;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is ... a lot to take in all at once. I understand what you're going for (providing real context to ground concepts in reality before introducing them individually), but this might be peoples' first practical introduction to:

  1. Hashmaps
  2. iterators (let alone random iterators)
  3. The rand crate (what is Distribution, Uniform, and IteratorRandom?)
  4. Bevy ECS concepts: resources, systems, startup systems, components
  5. Rust concepts: (derives, pattern matching, etc)

I think its ok to assume some level of familiarity with Rust (as the goal here isn't to teach people rust), so to an extent (1) (2), and (5) are hard to avoid. But there will be a percentage of people who will ignore that advice, be new to both Bevy and Rust, find this code block as their first exposure to Bevy ECS and immediately think "wow thats a lot to take in". They might even close their tab and move on to something else.

I certainly don't want first time users' first experience with Bevy ECS to be:

// This is a fast but insecure HashMap (dictionary, for those coming from Python)
// implementation that Bevy re-exports for internal and external use
use bevy::utils::HashMap;

I personally like the narrative of feeding small, very scoped / bite-sized code blocks first. And each time having the user think "yeah ok that makes sense and doesnt scare me".

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, this example is way too complex for a new user.


// This component defines our entity's life total.
#[derive(Component)]
struct Life(f32);

// This component is used to mark if our entity is currently airborne.
#[derive(Component)]
struct Falling {
// The higher the initial height of falling, the higher the damage.
height: f32,
alice-i-cecile marked this conversation as resolved.
Show resolved Hide resolved
}

fn main() {
App::new()
// These plugins create the basic framework
.add_plugins(MinimalPlugins)
// This allows us to report player health using `info!`
.add_plugin(LogPlugin)
// Because we've added this system as a startup system,
// it runs exactly once before any ordinary system
.add_startup_system(spawn_player_system)
// Ordinary systems run once per frame (or pass of the game loop).
.add_system(gravity_system.label("gravity"))
// We need to make sure we report fall damage after gravity
// Otherwise it won't have been calculated yet
.add_system(fall_damage_system.after("gravity"))
.run();
}

// This system spawns the player at a fairly high elevation.
fn spawn_player_system(mut commands: Commands) {
const INITIAL_HEIGHT: f32 = 15.0;

// Entities must be spawned in a delayed fashion with commands.
commands
.spawn()
// We can add components to entities that we are spawning with the .insert()
.insert(Life(20.0))
// Transform is the standard position component in Bevy,
// controlling the translation, rotation and scale of entities
.insert(Transform::from_translation(Vec3::new(
0.0,
INITIAL_HEIGHT,
0.0,
)))
.insert(Falling {
height: INITIAL_HEIGHT,
});

// This expression creates a second entity, with a slightly different set of components
commands
.spawn()
// We can customize the starting values of our components
// by changing the data stored in the structs we pass in
.insert(Life(30.0))
// This player begins on the ground
// So we're not inserting the Falling component
.insert(Transform::from_translation(Vec3::new(0.0, 0.0, 0.0)));
}

// This system pulls down the entity towards the ground (at y = 0), at a constant velocity,
// only while it's falling.
// The With<Falling> filter ensures that only entities with the `Falling` component are affected
fn gravity_system(mut query: Query<&mut Transform, With<Falling>>) {
const FALL_RATE: f32 = 1.0;

// Performing the same operation on each entity returned by the query
// using a loop is a very common pattern
for mut transform in query.iter_mut() {
transform.translation.y = (transform.translation.y - FALL_RATE).max(0.0);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there could be a Name component and we could print the name with the current position here. This way the output could clearly show a component with a position changing and then a final print message with the damage. It could also just be another system.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A name might not be necessary if we want to keep it simple, but adding a simple log would help when running this example.

}
}

// This system deals damage to falling entities based on the height from which it fell
fn fall_damage_system(
mut commands: Commands,
// By adding `Entity` to our query, we can extract
// the unique identifier of the entity we're iterating over
mut query: Query<(Entity, &mut Life, &Falling, &mut Transform)>,
mut exit_events: EventWriter<AppExit>,
) {
// Each of the components in our query must be present
// on an entity for it to be returned in our query.
// This system will loop over the first entity spawned, but not the second.
for (entity, mut life, falling, mut transform) in query.iter_mut() {
// Our entity has touched the ground
if transform.translation.y <= 0.0 {
transform.translation.y = 0.0;
// We're using the `Entity` information from our query
// to ensure we're removing the `Falling` component from the correct entity
commands.entity(entity).remove::<Falling>();

// Falling from small heights shouldn't hurt players at all
let damage = (falling.height - 3.0).max(0.0);
// .0 accesses the first field of our Life(f32) tuple struct
life.0 = (life.0 - damage).max(0.0);
info!("Damage: {}", damage);
// End the game as soon as the first entity has collided with the ground
exit_events.send(AppExit);
}
}
}
```

If you'd like to see more tiny but cohesive examples like this, check out our [game examples](https://github.com/bevyengine/bevy/tree/latest/examples/game) on the Bevy GitHub repository.
Loading