= Graphics
:icons: font
:source-highlighter: pygments
:source-language: rust
ifdef::env-github[:outfilesuffix: .adoc]

:rust: https://www.rust-lang.org/
:tcod-rs: https://github.com/tomassedovic/tcod-rs
:console: http://tomassedovic.github.io/tcod-rs/tcod/console/index.html
:colors: http://tomassedovic.github.io/tcod-rs/tcod/colors/index.html
:match: https://doc.rust-lang.org/book/ch06-02-match.html
:key: http://tomassedovic.github.io/tcod-rs/tcod/input/struct.Key.html

<<index#,Back to the index.>>

== Setting it up

=== Installing Rust

To install Rust, go to the {rust}[Rust homepage] and click the `Install` button.


=== Creating the roguelike project

Next we need to create the Rust project that will be our roguelike:

----
$ cargo new --bin roguelike
$ cd roguelike/
----

This will create two files: `Cargo.toml` and `main.rs` in the `src`
directory. `Cargo.toml` contains metadata for the project and any
dependencies you're going to need (such as libtcod).

`main.rs` is the file that contains your program. In it must be a
function called `main` which will be executed when you run your
program.

Cargo has automatically put a hello world program in your `main.rs` file.
It looks like this:

[source,rust]
----
fn main() {
    println!("Hello, world!");
}
----

You can run it by typing:

[source,bash]
----
cargo run --release
----

You will see something like this:

....
   Compiling roguelike v0.1.0 (file:///home/thomas/tmp/roguelike)
     Running `target/release/roguelike`
Hello, world!
....

Rust will first compile `main.rs` and any other files it needs (there
are none yet). The resulting binary program will be called `roguelike`
and placed in the `target/release` directory.

Cargo will then run the program which will print `Hello, world!`.

NOTE: Rust (and Cargo) can compile programs in two modes: _with
optimisations_ and _without_. Code compiled without optimisations is
*really slow*, but it's easier to work with under a debugger. We will
be using the optimised mode in the tutorial (with the `--release`
option), to make sure no one is making speed claims without
optimisations. If you do need the debug build for something, just drop
the `--release` flag.

=== Adding libtcod

You must then install the dependencies for {tcod-rs}[tcod] -- the
Rust bindings for libtcod.

Go to the following link and follow the instructions for your platform (Windows, Linux or Mac OS X):

https://github.com/tomassedovic/tcod-rs#how-to-use-this


=== Adding the font file

We will be using the font `arial10x10.png` that ships with libtcod.

You can download it from here:

https://github.com/tomassedovic/tcod-rs/raw/master/fonts/arial10x10.png

Feel free to check out the other fonts in there and pick the one you like.

Be sure to put it in your game directory -- next to `Cargo.toml`!


== Showing the @ on screen

To use any external library (i.e. code outside of your project) in
Rust, you need to have it in `Cargo.toml` under `[dependencies]`:

[source,toml]
----
[dependencies]
tcod = "0.15"
----

Rust libraries are called _crates_. Next, add some imports via the `use`
statements:

[source,rust]
----
tag::use_tcod[]
use tcod::colors::*;
use tcod::console::*;
end::use_tcod[]
----

Like in Python, Rust's code can be structured under modules. We could
always use the full path to a particular function or type (e.g.
``::tcod::console::Root``), but with the `use` statement, we can bring
it up to the current scope.

So `use tcod::console::Root` will let us type `Root` directly. Using
the asterisk (`*`) as the name means to import everything under
`tcod::console`. Which means `Root`, `FontType`,
`BackgroundFlag`, etc.


Now we'll add some constants so we don't end up littering the
source code with a bunch of opaque numbers:

[source,rust]
----
tag::consts[]
tag::screen_size[]
// actual size of the window
const SCREEN_WIDTH: i32 = 80;
const SCREEN_HEIGHT: i32 = 50;
end::screen_size[]

tag::limit_fps[]
const LIMIT_FPS: i32 = 20; // 20 frames-per-second maximum
end::limit_fps[]
end::consts[]
----

Just like in Python, constants are written using uppercase (as a
convention, not a hard rule). Unlike Python, the `const` keyword
guarantees that they will not be changed.

As you can see, constants need to have their type specified. In this
case it's `i32` or a 32-bit signed integer. Rust is able to infer most
types, but they do need to be explicitly mentioned in function
definitions and constants.

We will also encapsulate all of our libtcod-related values into a single Rust `struct`:

[source]
----
tag::tcod_root_struct[]
struct Tcod {
    root: Root,
}
end::tcod_root_struct[]
----

It only has a single value right now, but we'll add more later on.
Having all the tcod stuff in one place makes it easier to pass it
around to functions. And doing it now will save us from gnarly
refactors later. The Rust compiler would help us there, but it's still
an annoying chore we can avoid.

And now we can dive into the body of the `main` function and replace
the `println!` macro with code that sets up the libtcod window and
renders a character on it.

To create a window we call `Root::initializer(). ... .init()`.
In between go custom settings. Default values are going to be used for
any option that's not specified.

[source,rust]
----
tag::init[]
let root = Root::initializer()
    .font("arial10x10.png", FontLayout::Tcod)
    .font_type(FontType::Greyscale)
    .size(SCREEN_WIDTH, SCREEN_HEIGHT)
    .title("Rust/libtcod tutorial")
    .init();
end::init[]

tag::tcod_init[]
let mut tcod = Tcod { root };
end::tcod_init[]
----

A bunch of stuff is happening here so let's unpack this.

Rust uses `let` to create new variables, so `let root = <value>` will
create a new variable called `root`. Variables are immutable by
default (so they can't be changed accidentally), but we will want to
change the root console (e.g. by writing characters to it). To do
that, we need the `mut` keyword.

So `let mut tcod = <value>` means "create a variable called `tcod` that we
can change later". As you can see, we don't have to specify the type
of the variable -- Rust will figure it out. If we wanted, we could
type it explicitly, though:

[source,rust]
----
let root: Root = Root::initializer(). ... .init();
----

Now let's have a look at the window options we're passing in.

First, we're setting up a font. Libtcod uses bitmap fonts of various
formats. Calling the `font` methods lets us set our own font using a
file name and a font layout. `font_type` is another option for loading
a font.

The font must be in the root of your project, next to `Cargo.toml`. If you've
picked a different font than `arial10x10.png`, make sure to put the right
filename in your `font` method call.

Next we set the window dimensions (width and height in characters) and
the text displayed in the window's title bar.

Calling `init` will finalise the configuration and actually create the
window.


[source,rust]
----
tag::set_fps[]
tcod::system::set_fps(LIMIT_FPS);
end::set_fps[]
----

This line will limit the maximum number of frames per second libtcod
will issue. This is useful when you have a realtime game loop. If you
block for input (i.e. nothing happens until the player presses a key),
it will have no effect.

And speaking of game loops, now's the time to add one! Let's render a
white `@` on the screen until the libtcod window gets closed:

[source,rust]
----
tag::initial_game_loop[]
tag::initial_game_loop_header[]
tag::game_loop_while_header[]
while !tcod.root.window_closed() {
end::game_loop_while_header[]
    tcod.root.set_default_foreground(WHITE);
    tcod.root.clear();
end::initial_game_loop_header[]
    tcod.root.put_char(1, 1, '@', BackgroundFlag::None);
tag::root_flush[]
    tcod.root.flush();
end::root_flush[]
    tcod.root.wait_for_keypress(true);
}
end::initial_game_loop[]
----

Since we've set the FPS limit, this loop will be executed 20 times a
second, no more.

The `window_closed` method on the `root` console returns `true` if the
window was closed and `false` otherwise. We want to keep going while
it's open so we have to use `!` to negate the value.

The next line sets a default _foreground_ colour to white. This is the
colour everything will be drawn with unless specified otherwise.

The `tcod::colors` module contains values for common colours as well
as the `Color` struct that lets you use your own.

Then we `clear` the console of anything that we drew on the previous frame.

Next we draw the `@` character at the coordinates `1, 1` on the
screen. The `0, 0` coordinate is at the top left corner of the window.

Using `BackgroundFlag::None` says to ignore the default _background_
colour.

Calling `flush` will draw everything on the window at once.

And finally, we also need to call `wait_for_keypress` even though
we're not processing keyboard input yet. This is because libtcod
handles the window manager's events (including your request to close
the window) in the input processing code.

If we didn't call it, `window_close` would not work properly and the
game would crash or hang.


You can now run it with `cargo run --release` and bask in your
creation. It's almost a game now!

We will look at input next.

Here's link:part-1a-render.rs.txt[the complete code so far].

== Moving around

So that was cool. Now let's make our `@` move!

We'll need to keep track of the player's position. Let's create
variables for `x` and `y` and put them right before the game loop:

[source,rust]
----
tag::centre_player_position[]
let mut player_x = SCREEN_WIDTH / 2;
let mut player_y = SCREEN_HEIGHT / 2;
end::centre_player_position[]
----

They are mutable (we will change them when the player presses the
arrow keys) and initialised to the centre of the screen instead of the
top-left corner.

We will split the keyboard handling code into its own function to make
our game loop more readable. It will need the `root` console because
that's where we read the pressed keys from and also the player's
coordinates so we can change them based on the player's actions.

[source,rust]
----
tag::handle_keys_full[]
tag::handle_keys_header[]
fn handle_keys(tcod: &mut Tcod, player_x: &mut i32, player_y: &mut i32) -> bool {
end::handle_keys_header[]
    // todo: handle keys

tag::handle_keys_footer[]
    false
}
end::handle_keys_footer[]
end::handle_keys_full[]
----

A function signature in Rust is `fn function_name(parameter:
type, ...) -> return_type`. Here we call our function `handle_keys`;
it accepts three parameters -- the root console (of type
`tcod::console::Root`), the x coordinate and the y coordinate (of type
`i32`) -- and it returns a boolean value. `true` says "exit the game",
`false` means "keep going".

The `&mut` bits before the types are borrowing operators. You can read
about them (and the ownership they're strongly tied to) in the Rust
book:

https://doc.rust-lang.org/book/ch04-00-understanding-ownership.html

https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html

We must pass `root` as a borrowed value because it would be consumed
by the first call to `handle_keys` otherwise.

If we just passed `player_x` and `player_y` by value, `handle_keys`
could only read their values but it could not change them. Since we
want to update them based on the key the player pressed, we'll get
them as mutable references. Then we can assign a new value using the
dereference operator (e.g. `*player_x = 10`) and that will show up
back in the calling scope.

Right now, the function's body is empty, except that it always returns
`false` (which means, keep the game going). Let's add the keyboard
stuff.

We use the `wait_for_keypress` method to get the key and then update
the player's position if it's one of the arrow keys:

[source,rust]
----
tag::match_key_full[]
tag::match_key_header[]
let key = tcod.root.wait_for_keypress(true);
match key {
end::match_key_header[]
tag::movement_keys[]
    // movement keys
    Key { code: Up, .. } => *player_y -= 1,
    Key { code: Down, .. } => *player_y += 1,
    Key { code: Left, .. } => *player_x -= 1,
    Key { code: Right, .. } => *player_x += 1,
end::movement_keys[]

tag::match_key_footer[]
    _ => {}
}
end::match_key_footer[]
end::match_key_full[]
----

Instead of chaining a ton of `if/else` expressions together, we use
the `match` expression to specify the values we're interested in and
what to do with them.

The key returned by `wait_for_keypress` is of type `tcod::input::Key`
and {key}[has several fields we can look at]. Right now all we care
about is the `code`, which tells us the key that was pressed, but
there are others for `alt`, `ctrl`, etc.

The two dots at the end mean "I don't care about the other fields".
If it wasn't there, it would not compile until you specified values
for every field of the `Key` struct.

Rust requires that `match` arms are _exhaustive_. That means you have
to specify all the possible values. However, as we don't care about
the other keys the player could possibly press, we can use a special
value that matches _everything else_. That's what `_ => {}` at the end
does.

You can {match}[read more about match in the Rust book].

We could end here, but since we're doing keyboard stuff anyway, let's
add two more: `Alt+Enter` to toggle fullscreen mode and `Esc` to exit
the game.

Put these at the beginning of `match key`:

[source,rust]
----
tag::match_special_keys[]
Key {
    code: Enter,
    alt: true,
    ..
} => {
    // Alt+Enter: toggle fullscreen
    let fullscreen = tcod.root.is_fullscreen();
    tcod.root.set_fullscreen(!fullscreen);
}
Key { code: Escape, .. } => return true, // exit game
end::match_special_keys[]
----


And finally we need to `use` the keyboard input types we have in the
code:

[source,rust]
----
tag::use_input_key[]
use tcod::input::Key;
tag::use_input_keycode[]
use tcod::input::KeyCode::*;
end::use_input_keycode[]
end::use_input_key[]
----

Now, we could put it on top of the file next to the existing imports,
but Rust lets you place them in individual functions as well, which
will make them available only for that function. Since we'll contain
our keyboard-handling code in `handle_keys`, let's make it the first
thing there.

And finally, we just update the main loop to use our key handling and
draw at the player coordinates instead of `(1, 1)`. Put this at the
end of the `while` block:

[source,rust]
----
tag::handle_exit_keys[]
// handle keys and exit game if needed
let exit = handle_keys(&mut tcod, &mut player_x, &mut player_y);
tag::exit_game_loop[]
if exit {
    break;
}
end::exit_game_loop[]
end::handle_exit_keys[]
----

As you can see, we're passing `tcod` and the coordinates as mutable
references.


Now update our drawing function to use the player coordinates:

[source,rust]
----
tag::player_at_position[]
tcod.root
    .put_char(player_x, player_y, '@', BackgroundFlag::None);
end::player_at_position[]
----

Here's link:part-1b-movement.rs.txt[the complete code so far].

Continue to <<part-2-object-map#,the next part>>.
