You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardexpand all lines: docs/faq.md
+4-4
Original file line number
Diff line number
Diff line change
@@ -14,7 +14,7 @@ It's possible to have your project automatically compile SDL2 from source as par
14
14
15
15
```toml
16
16
[dependencies.tetra]
17
-
version = "0.7"
17
+
version = "0.8"
18
18
features = ["sdl2_bundled"]
19
19
```
20
20
@@ -26,7 +26,7 @@ If you want to avoid your users having to install SDL2 themselves (or you having
26
26
27
27
```toml
28
28
[dependencies.tetra]
29
-
version = "0.7"
29
+
version = "0.8"
30
30
features = ["sdl2_static_link"]
31
31
```
32
32
@@ -50,11 +50,11 @@ Yes - since 0.5.8, `Mesh` has constructors for basic shapes and there is a `Geom
50
50
51
51
Note that primitive shape drawing currently isn't batched, so drawing too many generated shapes at once may be slow.
52
52
53
-
If that's all too complicated and you just want to draw simple rectangles, you could also [create a solid colored `Texture`](https://docs.rs/tetra/0.7.0/tetra/graphics/struct.Texture.html#method.from_data) and then draw that. If you create a 1x1 solid white texture, you can use the `scale` and `color``DrawParams` to draw multiple rectangles of varying sizes/colors/transparencies in a single draw call.
53
+
If that's all too complicated and you just want to draw simple rectangles, you could also [create a solid colored `Texture`](https://docs.rs/tetra/0.8/tetra/graphics/struct.Texture.html#method.from_data) and then draw that. If you create a 1x1 solid white texture, you can use the `scale` and `color``DrawParams` to draw multiple rectangles of varying sizes/colors/transparencies in a single draw call.
54
54
55
55
### Does Tetra support high-DPI rendering?
56
56
57
-
Tetra added basic support for high-DPI rendering in 0.5.4, which can be enabled via [`ContextBuilder::high_dpi`](https://docs.rs/tetra/0.7/tetra/struct.ContextBuilder.html#method.high_dpi). You may also need some platform-specific configuration/packaging - see the docs for `ContextBuilder::high_dpi` for more info.
57
+
Tetra added basic support for high-DPI rendering in 0.5.4, which can be enabled via [`ContextBuilder::high_dpi`](https://docs.rs/tetra/0.8/tetra/struct.ContextBuilder.html#method.high_dpi). You may also need some platform-specific configuration/packaging - see the docs for `ContextBuilder::high_dpi` for more info.
Copy file name to clipboardexpand all lines: docs/tutorial/01-creating-a-project.md
+11-11
Original file line number
Diff line number
Diff line change
@@ -19,7 +19,7 @@ Next, add Tetra as a dependency in the newly-generated `Cargo.toml`:
19
19
20
20
```toml
21
21
[dependencies]
22
-
tetra = "0.7"
22
+
tetra = "0.8"
23
23
```
24
24
25
25
> [!WARNING]
@@ -38,9 +38,9 @@ With that, we're ready to start developing our game! Let's take a closer look at
38
38
39
39
## Creating a Context
40
40
41
-
[`Context`](https://docs.rs/tetra/0.7/tetra/struct.Context.html) is a struct that holds all of the 'global' state managed by the framework, such as window settings and connections to the graphics/audio/input hardware. Any function in Tetra's API that requires access to this state will take a reference to a `Context` as the first parameter, so you won't get very far without one!
41
+
[`Context`](https://docs.rs/tetra/0.8/tetra/struct.Context.html) is a struct that holds all of the 'global' state managed by the framework, such as window settings and connections to the graphics/audio/input hardware. Any function in Tetra's API that requires access to this state will take a reference to a `Context` as the first parameter, so you won't get very far without one!
42
42
43
-
To build our game's `Context`, we can use the descriptively-named [`ContextBuilder`](https://docs.rs/tetra/0.7/tetra/struct.ContextBuilder.html) struct:
43
+
To build our game's `Context`, we can use the descriptively-named [`ContextBuilder`](https://docs.rs/tetra/0.8/tetra/struct.ContextBuilder.html) struct:
44
44
45
45
```rust
46
46
fnmain() {
@@ -52,18 +52,18 @@ fn main() {
52
52
53
53
This creates a `Context` that is configured to display a window with the title 'Pong', sized at 640 by 480 pixels, which will automatically close when the player presses the escape key.
54
54
55
-
> [!INFO]
56
-
> To see what other options can be set on a `Context`, and what the default settings are, take a look at the API documentation for [`ContextBuilder`](https://docs.rs/tetra/0.7/tetra/struct.ContextBuilder.html).
55
+
> [!NOTE]
56
+
> To see what other options can be set on a `Context`, and what the default settings are, take a look at the API documentation for [`ContextBuilder`](https://docs.rs/tetra/0.8/tetra/struct.ContextBuilder.html).
57
57
58
58
If you `cargo run` your project from the command line now, you may be confused, as nothing will appear to happen. This is because we're not actually starting a game loop yet - `main` just returns straight away after the `Context` is created!
59
59
60
60
To fix this, we'll need to implement `State`.
61
61
62
62
## Defining Some State
63
63
64
-
[`State`](https://docs.rs/tetra/0.7/tetra/trait.State.html) is a trait exposed by Tetra, which is implemented for the type that stores your game's state. It exposes various methods that will be called during the game loop, and you can override these in order to define your game's behaviour.
64
+
[`State`](https://docs.rs/tetra/0.8/tetra/trait.State.html) is a trait exposed by Tetra, which is implemented for the type that stores your game's state. It exposes various methods that will be called during the game loop, and you can override these in order to define your game's behaviour.
65
65
66
-
> [!INFO]
66
+
> [!NOTE]
67
67
> This trait fulfils a similar purpose to the `Game` base class in XNA, or the `ApplicationListener` interface in LibGDX.
68
68
69
69
For now, we don't need to store data or override any of the default behaviour, so we can just use an empty struct and implementation:
@@ -76,7 +76,7 @@ impl State for GameState {}
76
76
77
77
## Running the Game Loop
78
78
79
-
Now that we have a `State`, we're ready to start the game loop! To do this, call the [`run`](https://docs.rs/tetra/0.7/tetra/struct.Context.html#method.run) method on `Context`, passing in a closure that constructs your `State` struct:
79
+
Now that we have a `State`, we're ready to start the game loop! To do this, call the [`run`](https://docs.rs/tetra/0.8/tetra/struct.Context.html#method.run) method on `Context`, passing in a closure that constructs your `State` struct:
80
80
81
81
```rust
82
82
fnmain() ->tetra::Result {
@@ -89,13 +89,13 @@ fn main() -> tetra::Result {
89
89
90
90
There's a few things you should pay attention to here:
91
91
92
-
- The return type of `main` has been changed to [`tetra::Result`](https://docs.rs/tetra/0.7/tetra/error/type.Result.html).
92
+
- The return type of `main` has been changed to [`tetra::Result`](https://docs.rs/tetra/0.8/tetra/error/type.Result.html).
93
93
- A [`?` operator](https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html#a-shortcut-for-propagating-errors-the--operator) has been added to the end of `build`.
94
94
- There is no semi-colon after `run`, so its output will be returned from `main`.
95
95
96
96
`build` will return an error if the context fails to be constructed, and `run` will return any errors you throw during the game loop. By using the `?` operator, we can propagate these errors up and out of `main`. Rust will then automatically print out the error message to the terminal, which is handy when debugging.
97
97
98
-
> [!INFO]
98
+
> [!NOTE]
99
99
> Returning `Result` from `main` is nice for prototyping, but doesn't give you much control over how the error gets reported. If you want to customize this, you can always `match` on the result of `build` and/or `run`.
100
100
101
101
You may also notice that the closure takes a parameter, which we're currently ignoring - we'll look at what that's for next chapter.
@@ -106,7 +106,7 @@ If you run `cargo run` from your terminal now, you should finally see a window
106
106
107
107
Our goal for this chapter was to set up our project, and we've done that! A black window isn't very interesting, though, so let's finish by changing the background color to something a bit more inspiring.
108
108
109
-
To do this, we'll implement one of the `State` trait methods. [`draw`](https://docs.rs/tetra/0.7/tetra/trait.State.html#method.draw) is called by Tetra whenever it is time for the engine to draw a new frame. We can call [`tetra::graphics::clear`](https://docs.rs/tetra/0.7/tetra/graphics/fn.clear.html) inside this method to clear the window to a plain color:
109
+
To do this, we'll implement one of the `State` trait methods. [`draw`](https://docs.rs/tetra/0.8/tetra/trait.State.html#method.draw) is called by Tetra whenever it is time for the engine to draw a new frame. We can call [`tetra::graphics::clear`](https://docs.rs/tetra/0.8/tetra/graphics/fn.clear.html) inside this method to clear the window to a plain color:
Copy file name to clipboardexpand all lines: docs/tutorial/02-adding-the-paddles.md
+13-13
Original file line number
Diff line number
Diff line change
@@ -19,10 +19,10 @@ Create a folder called `resources` in your project directory, and save this imag
19
19
20
20

21
21
22
-
> [!INFO]
22
+
> [!NOTE]
23
23
> The naming of this folder isn't something that's enforced by Tetra - structure your projects however you'd like!
24
24
25
-
To add this image to our game, we can use our first new type of the chapter: [`Texture`](https://docs.rs/tetra/0.7/tetra/graphics/struct.Texture.html). This represents a piece of image data that has been loaded into graphics memory.
25
+
To add this image to our game, we can use our first new type of the chapter: [`Texture`](https://docs.rs/tetra/0.8/tetra/graphics/struct.Texture.html). This represents a piece of image data that has been loaded into graphics memory.
26
26
27
27
Since we want our texture to stay loaded until the game closes, let's add it as a field in our `GameState` struct:
28
28
@@ -32,7 +32,7 @@ struct GameState {
32
32
}
33
33
```
34
34
35
-
We can then use [`Texture::new`](https://docs.rs/tetra/0.7/tetra/graphics/struct.Texture.html#method.new) to load the sprite and populate that field:
35
+
We can then use [`Texture::new`](https://docs.rs/tetra/0.8/tetra/graphics/struct.Texture.html#method.new) to load the sprite and populate that field:
36
36
37
37
```rust
38
38
fnmain() ->tetra::Result {
@@ -50,7 +50,7 @@ Notice that we're now using the previously unnamed parameter that's passed to th
50
50
51
51
Try running the game now - if all is well, it should start up just like it did last chapter. If you get an error message, check that you've entered the image's path correctly!
52
52
53
-
> [!INFO]
53
+
> [!NOTE]
54
54
> A `Texture` is effectively just an ID number under the hood. This means that they are very lightweight and cheap to clone - don't tie yourself in knots trying to pass references to them around your application!
55
55
>
56
56
> The same is true for quite a few other types in Tetra - check the API documentation for more info.
@@ -106,7 +106,7 @@ fn main() -> tetra::Result {
106
106
}
107
107
```
108
108
109
-
> [!INFO]
109
+
> [!NOTE]
110
110
> The `i32` casts look a bit silly, but for most of the places we'll be using the constants, it'll be easier to have them as floating point numbers.
111
111
112
112
With that bit of housekeeping out of the way, let's finally draw something!
This will draw the texture to the screen at position `16.0, 16.0`.
131
131
132
-
> [!INFO]
133
-
> If you look at the docs for [`Texture::draw`](https://docs.rs/tetra/0.7/tetra/graphics/struct.Texture.html#method.draw), you'll notice that the type of the second parameter is actually `Into<DrawParams>`, not `Vec2`.
132
+
> [!NOTE]
133
+
> If you look at the docs for [`Texture::draw`](https://docs.rs/tetra/0.8/tetra/graphics/struct.Texture.html#method.draw), you'll notice that the type of the second parameter is actually `Into<DrawParams>`, not `Vec2`.
134
134
>
135
-
> When you pass in a `Vec2`, it is automatically converted into a [`DrawParams`](https://docs.rs/tetra/0.7/tetra/graphics/struct.DrawParams.html) struct with the `position` parameter set. If you want to change other parameters, such as the rotation, color or scale, you can construct your own `DrawParams` instead, using `DrawParams::new`.
135
+
> When you pass in a `Vec2`, it is automatically converted into a [`DrawParams`](https://docs.rs/tetra/0.8/tetra/graphics/struct.DrawParams.html) struct with the `position` parameter set. If you want to change other parameters, such as the rotation, color or scale, you can construct your own `DrawParams` instead, using `DrawParams::new`.
136
136
137
137
## Reacting to Input
138
138
@@ -187,14 +187,14 @@ While we _could_ do this in our `draw` method, this is a bad idea for several re
187
187
- Mixing up our game logic and our rendering logic isn't great seperation of concerns.
188
188
- The `draw` method does not get called at a consistent rate - the timing can fluctuate depending on the speed of the system the game is being run on, leading to subtle differences in behaviour. This is fine for drawing, but definitely not for physics!
189
189
190
-
Instead, it's time for us to add another method to our [`State`](https://docs.rs/tetra/0.7/tetra/trait.State.html) implementation. The [`update`](https://docs.rs/tetra/0.7/tetra/trait.State.html#method.update) method is called 60 times a second, regardless of how fast the game as a whole is running. This means that even if rendering slows to a crawl, you can still be confident that the code in that method is deterministic.
190
+
Instead, it's time for us to add another method to our [`State`](https://docs.rs/tetra/0.8/tetra/trait.State.html) implementation. The [`update`](https://docs.rs/tetra/0.8/tetra/trait.State.html#method.update) method is called 60 times a second, regardless of how fast the game as a whole is running. This means that even if rendering slows to a crawl, you can still be confident that the code in that method is deterministic.
191
191
192
-
> [!INFO]
192
+
> [!NOTE]
193
193
> This 'fixed-rate update, variable-rate rendering' style of game loop is best explained by Glenn Fiedler's classic '[Fix Your Timestep](https://gafferongames.com/post/fix_your_timestep/)' blog post. If you've used the `FixedUpdate` method in Unity, this should feel pretty familiar!
194
194
>
195
-
> If you want to change the rate at which updates happen, or switch to a more traditional 'lockstep' game loop, you can do this via the [`timestep` parameter on `ContextBuilder`](https://docs.rs/tetra/0.7/tetra/struct.ContextBuilder.html#method.timestep).
195
+
> If you want to change the rate at which updates happen, or switch to a more traditional 'lockstep' game loop, you can do this via the [`timestep` parameter on `ContextBuilder`](https://docs.rs/tetra/0.8/tetra/struct.ContextBuilder.html#method.timestep).
196
196
197
-
Inside the `update` method, we can use the functions exposed by the [`input`](https://docs.rs/tetra/0.7/tetra/input/index.html) module in order to check the state of the keyboard:
197
+
Inside the `update` method, we can use the functions exposed by the [`input`](https://docs.rs/tetra/0.8/tetra/input/index.html) module in order to check the state of the keyboard:
198
198
199
199
```rust
200
200
// Inside `impl State for GameState`:
@@ -237,7 +237,7 @@ impl Entity {
237
237
}
238
238
```
239
239
240
-
> [!INFO]
240
+
> [!NOTE]
241
241
> It's worth mentioning at this point: this isn't the only way of structuring a game in Rust!
242
242
>
243
243
> The language lends itself very well to 'data-driven' design patterns, such as [entity component systems](https://en.wikipedia.org/wiki/Entity_component_system), and you'll definitely want to investigate these concepts if you start writing a bigger game. For now though, let's keep things as simple as possible!
Copy file name to clipboardexpand all lines: docs/tutorial/03-adding-a-ball.md
+2-2
Original file line number
Diff line number
Diff line change
@@ -157,7 +157,7 @@ if paddle_hit.is_some() {
157
157
}
158
158
```
159
159
160
-
> [!INFO]
160
+
> [!NOTE]
161
161
> Storing the identity of the paddle that got hit is redundant right now, but we'll use it later!
162
162
163
163
> [!WARNING]
@@ -210,7 +210,7 @@ if let Some(paddle) = paddle_hit {
210
210
}
211
211
```
212
212
213
-
> [!INFO]
213
+
> [!NOTE]
214
214
> I'll admit, it's a little bit wasteful to calculate the X center as well, but I'm aiming for code clarity over maximum efficiency. Besides, it's a Pong clone, not Crysis!
215
215
216
216
Now the player has some agency over where the ball goes - too much agency, as it turns out, as they can just send it flying off the top of the screen! A little bit more code at the end of `update` will fix that:
0 commit comments