-
Notifications
You must be signed in to change notification settings - Fork 46
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
976 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,6 @@ | ||
# Fundamentals | ||
|
||
This section is about learning all basic ECS operations. | ||
|
||
It also acts as a reference that you can come back to.\ | ||
So even if you've just finished building the square eater game, this section can be useful to get a more condensed version. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# Learn by example | ||
|
||
In this section you'll learn how to use shipyard by building a small game. | ||
|
||
<iframe src="https://leudz.github.io/shipyard/square_eater" width="645" height="360" title="Square Eater game" scrolling="no"></iframe> | ||
|
||
## Dependencies | ||
|
||
We'll only use two dependencies, let's add them to `Cargo.toml`. | ||
|
||
```toml | ||
macroquad = "0.4.8" | ||
shipyard = { git = "https://github.com/leudz/shipyard", default-features = false, features = [ | ||
"proc", | ||
"std", | ||
] } | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
# A lone square | ||
|
||
Let's start with a blank window. | ||
|
||
```rust,noplaypen | ||
use macroquad::prelude::*; | ||
#[macroquad::main("Square Eater")] | ||
async fn main() { | ||
loop { | ||
next_frame().await | ||
} | ||
} | ||
``` | ||
|
||
Then let's add the player. This game is all about squares so naturally the player is one. | ||
|
||
```rust,noplaypen | ||
struct Square { | ||
x: f32, | ||
y: f32, | ||
size: f32, | ||
} | ||
struct Player { | ||
square: Square, | ||
} | ||
``` | ||
|
||
We can now it add the scene. | ||
|
||
```rust,noplaypen | ||
#[macroquad::main("Square Eater")] | ||
async fn main() { | ||
let x = screen_width() / 2.0; | ||
let y = screen_height() / 2.0; | ||
let player = Player { | ||
square: Square { x, y, size: 15.0 }, | ||
}; | ||
loop { | ||
clear_background(WHITE); | ||
render(&player); | ||
next_frame().await | ||
} | ||
} | ||
impl Square { | ||
fn render(&self, color: Color) { | ||
draw_rectangle(self.x, self.y, self.size, self.size, color); | ||
} | ||
} | ||
fn render(player: &Player) { | ||
player.square.render(BLUE); | ||
} | ||
``` | ||
|
||
Our player looks a bit stiff, we can fix that. | ||
|
||
```rust,noplaypen | ||
async fn main() { | ||
// -- SNIP -- | ||
let mut player = Player { | ||
square: Square { x, y, size: 15.0 }, | ||
}; | ||
loop { | ||
clear_background(WHITE); | ||
move_player(&mut player); | ||
render(&player); | ||
next_frame().await | ||
} | ||
} | ||
fn move_player(player: &mut Player) { | ||
let width = screen_width(); | ||
let height = screen_height(); | ||
let (x, y) = mouse_position(); | ||
player.square.x = x.clamp(0.0, width - player.square.size); | ||
player.square.y = y.clamp(0.0, height - player.square.size); | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
# Breather | ||
|
||
Let's refactor a little to give us time to process this betrayal and think of a way to get our revenge.\ | ||
You can move things around and maybe create modules. | ||
|
||
We're using an initial size in a few spots, we can abstract it. | ||
|
||
```rust,noplaypen | ||
const INIT_SIZE: f32 = 5.0; | ||
async fn main() { | ||
// -- SNIP -- | ||
let player = Player { | ||
square: Square { | ||
x, | ||
y, | ||
size: INIT_SIZE * 3.0, | ||
}, | ||
}; | ||
// -- SNIP -- | ||
} | ||
impl Friend { | ||
fn new() -> Friend { | ||
// -- SNIP -- | ||
Friend(Square { | ||
x: gen_range(0.0, width - INIT_SIZE), | ||
y: gen_range(0.0, height - INIT_SIZE), | ||
size: INIT_SIZE, | ||
}) | ||
} | ||
} | ||
fn collision(mut player: UniqueViewMut<Player>, v_friend: View<Friend>) { | ||
for friend in v_friend.iter() { | ||
if friend.0.size == MAX_SIZE && friend.0.collide(&player.square) { | ||
player.square.size -= INIT_SIZE / 2.; | ||
if player.square.size < INIT_SIZE { | ||
panic!("Murder"); | ||
} | ||
} | ||
} | ||
} | ||
``` | ||
|
||
We can also handle the game over a little cleaner. | ||
|
||
```rust,noplaypen | ||
enum GameOver { | ||
Defeat, | ||
} | ||
async fn main() { | ||
// -- SNIP -- | ||
loop { | ||
// -- SNIP -- | ||
if world.run(collision).is_err() { | ||
panic!("Murder"); | ||
} | ||
// -- SNIP -- | ||
} | ||
} | ||
fn collision(mut player: UniqueViewMut<Player>, v_friend: View<Friend>) -> Result<(), GameOver> { | ||
for friend in v_friend.iter() { | ||
if friend.0.size == MAX_SIZE && friend.0.collide(&player.square) { | ||
player.square.size -= INIT_SIZE / 2.; | ||
if player.square.size < INIT_SIZE { | ||
return Err(GameOver::Defeat); | ||
} | ||
} | ||
} | ||
Ok(()) | ||
} | ||
``` | ||
|
||
Systems can return any type, [`World::run`](https://docs.rs/shipyard/latest/shipyard/struct.World.html#method.run) then returns when the function returns.\ | ||
Moving the panic to `main` isn't a big change but it allows a better control of what happens which will be useful later on. | ||
|
||
To finish this chapter we can better show the duplicity of the "`Friend`s". | ||
|
||
```rust,noplaypen | ||
fn render(player: UniqueView<Player>, v_friend: View<Friend>) { | ||
for friend in v_friend.iter() { | ||
if friend.0.size == MAX_SIZE { | ||
friend.0.render(RED); | ||
} else if friend.0.size > player.square.size { | ||
friend.0.render(GRAY); | ||
} else { | ||
friend.0.render(GREEN); | ||
} | ||
} | ||
player.square.render(BLUE); | ||
} | ||
``` |
Oops, something went wrong.