# Bevy Example Docs Style
This is a working proposal document for an "Example docs" style that aims to produce short walkthroughs of what's going on in each example, ideally to be extracted and placed on each examples' page on the website, optimised for skim-reading.
## Style description
Gamedev details should aim to be beginner-explanatory, intermediate-noncondecending, expert-breadcrumbs. That is, some things should be explained so that someone new to games programming has the relationships between concepts briefly given context to, while more complicated bevy features and more complex use-cases should be lightly namedropped to act as a "mountain" for the user to "climb."
Experience with Rust should be assumed to be intermediate. If something complex is happening with Rust we shouldn't be afraid to explain it, but it should be brief and in the context of a specific bevy feature. Rust doesn't need to be over-explained.
There should also be some kind of narrative - we use X to achieve Y, or in order to do Y first we must do X. This isn't axiomatic or mechanical, that is we should not merely identify "X" and repeat that we're using them to achieve "Y". A subject should be identified for an example so that the narrative can be built around it. If I'm writing an explanation on an example that is only "Setting up the camera" then there's plenty of space to give to the details of setting up the camera and all the possible things one could draw on, but this can't be copied-and-pasted into another example. This also prevents "atomic" writing, to an extent.
We should not just give a blurb for every part of the engine and combine relevant blurbs together on each example page, that's best left for what the API docs do and eliminates the chance to explain context. Examples are an opportunity to show bevy-in-context, already proving itself by running in the browser with the code right next to it. "Example docs" are an opportunity to narrate that context and signpost related concepts.
Paragraphs should ideally cover 1 topic before being moved on from, and be pretty short. One of the cases I'm aiming to consider is skim-reading to look for specific concepts, then deeper reading to get their context.
Subjects of paragraphs should usually be namedropped at the beginning of those paragraphs, again this serves the purpose of skim-reading by looking for specific concepts then backreading their context.
Tone should adhere to the existing Bevy writing guidelines.
## Questions
- How granular should example explanations be?
- What is the assumed level of experience of the reader?
- Is an example explanation still making too many assumptions about what people know?
- Is there a lower bound to assuming information? If we go below it, are we being condecending to the reader or associating bevy with lack of skill?
## Assumptions
There is no linearity to how people come to the examples pages, people will look for what they need in the moment and then go to it. No page can assume that another page has been read first, or at least if it does it may need to link directly to that other page.
## Documentation rot
Bevy is young, and it changes at a fast rate. The intention for this example doc spec is that (at the very least until bevy reaches stability) the fruits of it are disposable. Through "wrong docs are worse than no docs" a catastrophically wrong example explanation (for instance, a massive change between versions with no capacity to address all changes in the docs) should be assumed to be better deleted than rewritten.
Catastrophically-wrong example explanations _should_ be pretty infrequent. If they're not, maybe this design needs revision. The splitting-up of concepts into individual skimmable paragraphs should lend itself to a not-overwhelming kind of rewriting, but an incremental one. That said, if the design fails it needs reconsideration.
# 2D Shapes (Medium explanation)
The "2D shapes" example isn't likely to be someone's first go at looking at bevy examples outside the fact it's currently the top example on the example page. The "subject" of this example explanation is the basics of primitives, materials, and meshes in a 2d context.
Basics used
- Camera setup
- this is trivial with required components now, so it's probably not worth covering?
Central concepts
- Primitive shapes
- meshes from primitive shapes
- meshes in a 2D context
- a basic color as a material
- wrapping handles in the newtypes
## Explanation
Here we use shape primitives to build meshes in a 2D rendering context, making each mesh a certain color by giving that mesh's entity a material based off a `Color`.
A shape primitive is a, it is not a mesh on its own. A circle can be defined with a radius, i.e. `Circle::new(50.0)`, but rendering tends to happen with triangles. So we need to turn shape descriptions into meshes.
Thankfully, we can add shape primitives directly to `Assets<Mesh>` because `Mesh` implements `From` for shape primitives and `Assets<T>::add` can be given any value that can be "turned into" `T`.
Meshes are better known for their use in 3D rendering, but we can use then in a 2D context too. Without a third dimension, the models we're building are flat shapes. These are still very useful for collision, "vector-style" graphics, or as a basis for where to apply a shader.
We apply a material to the shape by first making a `Color` then calling `Assets<ColorMaterial>::add` with that color as its argument, which will create a material from that color through the same process `Assets<Mesh>::add` can take a shape primitive.
Both the mesh and material need to be wrapped in respective "newtypes". The mesh and material are currently `Handle<Mesh>` and `Handle<ColorMaterial>` at the moment, which are not components. Handles are put behind "newtypes" to make it easier to them as required components or to give them new required components and side-step the orphan rule. All we need to do to make them components is wrap the mesh handle and the material handle in `Mesh2d` and `MeshMaterial2d` respectively.
# 3D scene (Big explanation)
The "basic 3d scene" is going to be visited largely with the purpose to understand the basics of bevy from an enthusiast perspective -- 3D is flashy, people want to work on 3D games. Some attention should be given to all covered items, including the basics of ECS, unless it gets too verbose. It's hard to contextualise so many fundamental parts of operating in Bevy without getting verbose, mind.
https://bevyengine.org/examples/3d-rendering/3d-scene/
Basics used (basics are the subject, so all should be covered to some extent.)
- Command spawning
- Resource access for meshes and materials
- Lights
- Camera setup
- Mesh instantiation
## Explanation
Here we're creating a basic bevy app that uses 3D graphics, lights, and shape primitives. To do this, we need to create a camera, a cube mesh, a flat circle mesh, and a light.
To create any of those objects, we need to use `Commands` to `spawn` entities. This is the canonical way of creating new entities in Bevy. Keep in mind spawning doesn't happen immediately! Commands are a "message" that Bevy holds on to until the end of each `Schedule` "phase."
`Commands` are accessed through a System, which in Bevy is just a function that takes specific kinds of arguments and gets manually "registered" so that Bevy knows we want to run it. We'll also want this system to run once at the beginning of the program in the `Startup` schedule label.
Cameras are necessary for rendering, and we want to be rendering in 3D so we will need to spawn a `Camera3D`. There's ways you can configure the camera for your specific needs, but for now we'll go for the default with `Camera3D::default()`.
We also want to place the camera away from the center of the 3D space looking at that center, so that we can spawn 3D objects close to (0, 0, 0) and know the camera will be looking at them. Creating a transform that's at a translation away from the center and then calling `Transform::looking_at` on that transform achieves this, and we add that transform alongside our `Camera3D` in a tuple using the `commands.spawn` method to attach both components to a new entity.
For spawning in 3D objects, at least ones generated from primitive shapes, we need access to how bevy stores meshes (the most common data for 3d objects) and materials (what colors, textures those objects have). We do this in bevy by getting Mutable access to Resources (`ResMut`) that store `Assets` that manage `Mesh` and `StandardMaterial` data, which are both Mesh Data and Material Data respectively.
`Assets<T>` is a way of processing and storing "asset"-like data. You "give" it data with the `.add` method and it gives you back a `Handle<T>`, this prevents storing duplicate copies of the same data and deletes any assets we're no longer using for us.
The only shapes we want in this basic scene are a `Cuboid` and a `Circle`. We can load both of these as assets by just calling `meshes.add` on them because `Assets<T>` handles anything that can be "converted" to `T`. There's an implementation for processing primitive shapes into meshes, so it does that for us. But `Handle<Mesh>` is not a component on its own, so in this circumstance we need to wrap it in a `Mesh3d`.
Applying a `Color` to a mesh is a similar story: we can create a new material by calling `materials.add` on a `Color`, which gets converted to a `StandardMaterial` because there's an implementation for converting `Color` to `StandardMaterial`. Again, `Handle<StandardMaterial>` is not a component so we need to wrap it in `MeshMaterial3d`.
It's dark, and we need a light. `PointLight` is a Light that behaves like it's coming from a Point -- think lightbulbs without a reflector. We need to make sure it's not "within" any of the meshes we've spawned because then the light will be blocked by those meshes, so we spawn it at a similar distance from the center of the scene as the camera, but in a different spot. We enable shadow shadows in the `PointLight`'s constructor and fill the rest with default values, one of the possible values you could choose is a different strength for the light.
# Game Menu ("Small"/presumptive explanation)
This is a moderately more specific example for which the bulk of the code is just about spawning heirarchies. Post-BSN-macro this will no doubt look more compact, but at this moment in time it's just a lot of code that uses basic UI principles. Most of what needs to be covered is heirarchies and `StateScoped`. This is also an example of the lack of connection between lines of code and needed documentation (though so is the 3D Scene).
Basic Concepts
- UI nodes
- Resources
Central Concepts
- UI Heirarchies
- Despawning entities
- Observer picking
- StateScoped
## Explanation
Many games need some kind of Main Menu to change some kind of settings. Here we're creating a menu navigate between and manipulate several options for a "game" that displays the options to us, with options represented in-engine with Resources. Switching between menu states involves using `StateScoped`.
Resources (`Res`/`ResMut`) will be used to store and manipulate game options here, as these are pieces of data that act as "global information" not tied to any single scoped state or entity.
`Node` is the foundational unit of UI in bevy, it acts a lot like an HTML tag with a `style` attribute. It has a lot of fields, but we can avoid having to declare all of them by defining the ones we're fine with being default with `..default()`.
UI Heirarchies are the central way of building UI in bevy. UI nodes can have child nodes, and those child nodes can also have child nodes etc. These relationships are constructed in this example with `Commands::with_child` and `Commands::with_children`. `Nodes` with `Node` children will use the layout information they're given (mostly in `Node`'s fields) to figure out how to look, but there's also separate styling for `Text`.
Switching between different options in the menu is done with `StateScoped`, which allows us to say "this entity only exists while we're in this state" and "this system only runs when we're in this state/the state has been entered/we've left this state." This kind of behaviour helps us separate information and game logic that depend on some basic context like "are we in a menu or in the game" or "are we in a loading screen or the final level."