Skip to content

Commit

Permalink
Add example guide
Browse files Browse the repository at this point in the history
  • Loading branch information
leudz committed Jul 9, 2024
1 parent eeddcc0 commit 6dae454
Show file tree
Hide file tree
Showing 10 changed files with 976 additions and 4 deletions.
7 changes: 7 additions & 0 deletions guide/master/src/SUMMARY.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
# Summary

[Welcome](./welcome.md)
- [Learn by example](./learn-by-example.md)
- [A lone square](./learn-by-example/a-lone-square.md)
- [Friends](./learn-by-example/friends.md)
- [Spark](./learn-by-example/spark.md)
- [Breather](./learn-by-example/breather.md)
- [Reign](./learn-by-example/reign.md)
- [True Viectory](./learn-by-example/true-victory.md)
- [Fundamentals](./fundamentals.md)
- [World](./fundamentals/world.md)
- [Add Entity](./fundamentals/add-entity.md)
Expand Down
3 changes: 3 additions & 0 deletions guide/master/src/fundamentals.md
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.
17 changes: 17 additions & 0 deletions guide/master/src/learn-by-example.md
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",
] }
```
88 changes: 88 additions & 0 deletions guide/master/src/learn-by-example/a-lone-square.md
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);
}
```
106 changes: 106 additions & 0 deletions guide/master/src/learn-by-example/breather.md
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);
}
```
Loading

0 comments on commit 6dae454

Please sign in to comment.