My First Rust Project
Tigley, Micah
My First Rust Project: Creating a Roguelike with Amethyst by Micah Tigley One of the biggest challenges to learning Rust is finding a project to continuously practice that newfound knowledge on. As someone with a background in front-end web development, the world of Rust was new and exciting to someone with limited systems programming experience. There were a number of open-source projects to choose from and so many areas to explore, it was a bit intimidating. I finally settled on Rust's game development community. This talk looks at my journey diving into game development with Rust by building my first roguelike game with the Amethyst game engine.
 Hey everyone, my name is Mika and my pronouns are she and her. Today I'm going to talk about my beginnings with game development using the Amethyst game engine. When I first decided to do this talk, I had intended to share a full 2D roguelike game, but I found that my focus was in other areas of game development that I found more interesting to explore. Learning game development and Rust has always been an on and off learning endeavor of mine and I'm excited to share some of those learnings with you today. I'm just a developer looking to talk about one of her many in progress projects. So when I decided to learn a new programming language, I tried to identify criteria outlining some of the things I'd like to get out of it. And since my development experience was primarily in front end web development, I wanted to try picking up another language that was considered low level or whose use cases were designed to work closer to the hardware. Another was documentation. I think most people will appreciate that in any area of software development. And being someone who likes to do independent reading and research on a topic at my own pace, it really helps to have accessible documentation to refer to. And finally, having a welcome community helps lower the barrier to learning. This was actually one of the biggest reasons that got me interested in Rust since the community surrounding it is dedicated to making it a fun and safe place to be. So in general, I was looking to learn a new language that presented not only a challenge, but also a history that emphasized open collaboration. And that's how I arrived at Rust. And it also helps that the language's mascot is pretty cute. So I think like most people who are getting it started with Rust, one of the first things I did to jumpstart my learning was a combination of reading the Rust programming language and trying out some of the concepts in the Rust playground. And this was a good way for me to get a bit of a foundation before jumping into actual Rust projects. And once I felt like I had some of the basics of Rust, I decided to contribute to a few open source projects. One of the first things I did was update the standard library documentation for the string slice type. And later on, I made some contributions to the Servo web browser engine project where I implemented a few of the missing attributes on the mouse event interface. And unfortunately, I haven't been able to contribute to other open source projects this year, but hopefully I can find some time in the future. But of course, there's just so much to know about Rust and so much to learn about it. And it's hard to keep track of what I've learned. And while I was writing this talk, it was actually already difficult to get a grasp of where I wanted to begin and eventually lead into what I've learned about game development. The amount of things to do can get pretty overwhelming. So to help with this, I had to choose an area I was interested in. And so I began my search. And to no one's surprise, I arrived at game development. Video games have always been an important part of my life, and it felt natural to choose this area of software development to sink my teeth into. I wasn't looking to create the next big indie title, but rather just create a few projects that I could lightly work on. And some experimentation had me interested in developing a roguelike. There's a couple good tutorials on how to create your own, and while I was working on my first game, I found that I was actually more interested in creating a 2D rendered game. And I wanted to do this in Rust. And so one of the first places I went to get some information was checking out the Are We Game Yet? website. I thought this was a good place to get some ideas of what I might need to build a 2D game using Rust. But of course, the game development space can be pretty intimidating in itself. And as someone with basic knowledge of computer graphics, amongst other things, it was difficult knowing where to start. I was also interested in drawing some 2D sprites to the screen more so, and so I needed a library that would do most of the heavy lifting for me. And luckily, that is what game engines are for. So when looking for a game engine to use, I was more concerned about finding one that provided accessible documentation and hands-on learning and some examples to help demonstrate certain concepts. And from the Are We Game Yet? website, I was able to find the Amethyst game engine. This is a screenshot of the project's landing page at amethyst.rs. As I researched the project, I found that it checked off everything I was looking for in a game development written in Rust. And the documentation for Amethyst was easily available through the project's website. I never really felt the resources they provided were scattered, which is a huge plus for me. And some of the things I found really nice is that Amethyst provides a book that entails not only how to use the engine, but also talks a little bit about ECS, which is a topic I will talk about later. It also provides links to its communities, online API reference, and also to their examples. And the book also has a section where you can build a Pong clone using Amethyst. This was a really nice hands-on project to help understand the basics of using the engine. And I also felt that it was enough to start experimenting with my own projects once I was finished with it. And finally, there were many implementation examples showing what Amethyst can do. And these examples were readily compilable and were easy to experiment with. Another nice thing about this project was that there are a few games available on its blog that showcase the game engine's features. And after doing some learning and experimentation with Rust, I decided to take what I learned and apply it to what I wanted to make in the first place, which was simply drawing 2D sprites to the screen. I wanted to break down this section into three parts, explaining what ECS is, showing how I went about implementing a 2D sprite animation using this framework, and finally, I'll extend on this by explaining how I went about implementing a camera follow system for the player. So what exactly is ECS? ECS stands for Entity Component System, where an entity in your game represents a single object. An entity often represented with a single ID can be composed of a number of components where a component acts like a container for data that can describe an aspect of an object. And finally, a system is a piece of logic that can operate on one or more entities in the game. ECS is a common pattern used in game development, and it makes it easy to compose objects since components can be arbitrarily added to entities. And so there's that piece of theory. When I first read about ECS, I needed some time to build a simple mental model of what it could look like in practice. And so let's shift into something that's more fun to talk about while also trying to build on this mental model. Let's talk about Animal Crossing New Horizons on the Switch. Animal Crossing is a cute laid back game where you get to build an island society of cute anthropomorphic animals. And in this image and the game in general, we can probably apply some of the ideas of ECS to help build our understanding of it. And there's a lot of things on the island that we can identify as objects, which are represented by entities in the world of Animal Crossing New Horizons. For example, the player character is an entity, Isabella is an entity, Timmy and Tommy are entities, and even this tree is an entity. You get the point. But it feels wrong to describe our island residents as just entities. After all, an entity is usually represented by a single ID that has a number of components associated with it. We need to be able to associate some data with them. And to keep things simple, I wanted to focus on describing data for the villagers in Animal Crossing. For some context, villagers are non-playable characters that can move to your island by either randomly moving there or finding them on another island the player is exploring. And they become residents of the little town you've created. They can also do activities similar to the player, such as fishing, gardening and exploring. And the player can interact with these villagers and even develop friendships with them. And this being my first Animal Crossing game, I thought what made a villager special is that they added more characters to the island by well being cute. And though I've learned recently that each villager shares attributes that are unique to each of them that actually influence how they interact with other villagers on the island. And so here's one of the first villagers that moved to my island. Her name is Flurry and she's a hamster. And the moment I found her while exploring another island, I just had to take her home with me. I just love how she has those cute little blue eyebrows and paws and red t-shirt and she's just the cutest thing ever. Anyway, there are specific attributes villagers have. And I didn't list all of them here since I wanted to keep this simple. Attributes that specifically describe a villager will be its species, personality and hobby. These attributes will be contained by what I will call a villager component. And you'll notice that the name and birth the attributes weren't included because I think these attributes should be included in a separate component, which we will talk about later. So with amethyst, declaring components requires us to define the data being described. And in this example, we declare a villager struct, which contains information about that components, species, personality and hobby types. And once the underlying data for the component is defined, we then have to implement the component trait for the villager. The storage type determines how the component will be stored. And in this example, the dense vector storage type, which is where elements are stored in a contiguous vector, it allows for lower use memory usage and it also like and for also dealing with larger components. And this diagram is to help visualize how the villager component is added to an entity in the game. In amethyst, whenever a new component is created, it's added to a storage responsible for storing components of a specific type. And in this diagram, we can create a number of villager components and add them to specific entities. Here we can see that the entity zero is associated with the villager component that describes flurry and this is similarly done for the other entities representing villagers. And so to do this with amethyst, we have to get a reference to the world, which acts as a container for resources in your game. To create a new entity in the game, we first need to import the builder trait, which allows us to create the entity builder using create entity. Using the entity builder, we can add component to that entity. And in this example, we add the villager component we defined earlier. Finally, we can finish building and get the actual entity by calling built. Now we can extend this by using the name and birthday attributes in another component. I decided to call it the resident component since it generically describes any character on the island. And in this example, I've added another entity, entity three, meant to represent the player character. And since villagers also have names and birthdays, the resident component can also be reused and attached to entities with the villager component. So now let's move into the section on getting a simple sprite cheat animation working using amethyst. But before we get started, I wanted to explain that a sprite cheat animation is simply taking a sprite cheat and changing what sprite image or frame is drawn to the screen in rapid succession. This gives the illusion of movement, much like how one would see with a flip book. So the first thing we should do is describe the relevant components for the sprite cheat animation. The first is the animation component, which has attributes frames, frame duration and index. Frames describe the number of sprite images for one animation cycle. Frame duration describes how long each image should be shown for. An index indicates where in the sprite sheet the first image of the animation is. And the second component is provided by animate amethyst. It's responsible for containing data about the sprite sheet and which image from the sheet to draw to the screen. The data used to describe this is a sprite sheet. And this is a reference to the sprite sheet asset. And in amethyst, these references to texture assets are known as handles, and sprite number is the location of the sprite image in the sprite sheet. Now associating a component with an entity doesn't do much on its own. Our animation needs a way to manipulate what sprite image is drawn to the screen during each game cycle. And this is where implementation of an animation system comes in. In this diagram, we implement an animation system with amethyst by having that system read or write data for different component storages during each iteration of the game loop. This example shows that the animation system being implemented will read from the time resource. Resources in amethyst are containers of data that are not associated with an entity. And then the animation system reads from the animation component storage. And finally, the animation system will write to an entity's sprite render component, in particular, the sprite render sprite number value will be modified to tell amethyst to draw the next image in the animation sequence to the screen. And this is what the animation system would look like using amethyst. Implementing a system involves implementing the system trait on a struct. And this system is then executed during each iteration of the game loop. And when we define the system, amethyst requires us to define a type called system data, which tells the system what data from the engine it should expect to get and how it should be interacting with it. Some of the system data types amethyst provides are read storage, which gives the system an immutable reference to the entire storage containing the animation components. On the flip side, there is also the write storage data type, which gives us a mutable reference to the entire storage containing the sprite render components. And then there's the read data type. And this gives us an immutable reference to the time resource. And now the next step is to implement the systems run method. In our animation systems run method, we get all entities with an associated animation and sprite render component. This is done using join. And this allows for the joining of components for iteration over entities with specific components. And now that we have that entity, we need to find which frame to use for the sprite render's number value, depending on the game's elapsed time. And finally, we can modify the entity sprite render to draw the new sprite image. And here's the final result of an idle animation for the wizard sprite. However, it would be much more interesting if the player could move around some sort of environment. To do this, we can design another system that is responsible for moving the player around. And for this system, our game will read from the input handler resource provided by Amethyst and will also be writing to an entity's transform component storage. The transform component storage is available through Amethyst, and it's a common component to use. This is because transform can describe an entity's position, rotation, scale, and much more. And for this game, we're really only concerned about modifying an entity's position and rotation in response to user input. And now that a system is in place for the player to move around, it might be nice to have another system that consists of a camera that tracks the player's movement within the environment. And at the time of writing this, I found that simply attaching subject tags to particular entities made implementing the system straightforward. In particular, I created a player subject component that I associated with an entity designated as a player. The camera subject component is also associated with an entity designed as the camera view. And the camera follow system would then modify the associated transform component for both the player and camera entities. And the result would then look something like this. Here I have the same wizard sprite moving through the game's environment with a camera following their movements. And there's also a few things I wanted to say about this demo. Earlier in this talk, I mentioned how I dabbled a bit developing a simple roguelike. And one thing that I became particularly interested in is being able to generate a random tile map that would act as the environment the player could move around in. And so as another mini side project that was separate from my project that used Amethyst, I played around with developing a tile map generator that I could use potentially in my game. And the image I have here is a generated background image used in the demo. And for this small project, I used a create called image to extract pixel data from a source sprite sheet and had it put into an image buffer. And this image buffer would then be outputted as a PNG image local to the project directory. The generated map images aren't perfect, but it was a fun way to learn and see different layouts for the game environment. And since these are only images, I'd have to still extend my game and develop some sort of collision system so that the player cannot move through tiles that are considered walls. So as you can see, I wasn't able to complete a full game yet, but being able to complete a small project like this has made the process much more enjoyable. And the biggest takeaway from my learnings was that it's okay to iterate on project ideas. Do it at your own pace and also have fun. And besides coding, another way to keep myself motivated was to document some of what I learned. I did this by writing a blog post as soon as I finished one section of my project. And not only did it help retain my knowledge over time, but it also challenged me to think about how I can communicate what I learned in a way that was helpful not only for myself, but also others. Prior to this talk, I actually wrote a blog post documenting how I implemented 2D sprite animations using Amethyst. And one of the things I really appreciated my past self for doing was taking the time to establish context and also outline her thought process throughout. And this was the most difficult part and also the most time consuming part of writing this other way short blog post because I really wanted to find a perfect balance between providing enough context while also being forthright in my content. And if anyone's interested, the link to this specific blog post is available at mtiggly.dev. And I wanted to touch on writing with the intent to teach someone. Like it's very useful, even if it's just for yourself, because it will help really ease doubts you have about your knowledge. And one way to do this is to keep a series of blog posts and over time you'll have created your own repository of knowledge. And who knows, maybe someone will find what you wrote about really useful. And so that's the end of my talk. I wanted to thank everyone who came to listen and thank you everyone who made this talk possible. And hopefully anyone who is interested in either Rust or game development will be inspired to build something.
 Hey everyone, my name is Mika and my pronouns are she and her.  Today I'm going to talk about my beginnings with game development using the Amethyst game  engine.  When I first decided to do this talk, I had intended to share a full 2D roguelike game,  but I found that my focus was in other areas of game development that I found more interesting  to explore.  Learning game development and Rust has always been an on and off learning endeavor of mine  and I'm excited to share some of those learnings with you today.  I'm just a developer looking to talk about one of her many in progress projects.  So when I decided to learn a new programming language, I tried to identify criteria outlining  some of the things I'd like to get out of it.  And since my development experience was primarily in front end web development, I wanted to  try picking up another language that was considered low level or whose use cases were designed  to work closer to the hardware.  Another was documentation.  I think most people will appreciate that in any area of software development.  And being someone who likes to do independent reading and research on a topic at my own  pace, it really helps to have accessible documentation to refer to.  And finally, having a welcome community helps lower the barrier to learning.  This was actually one of the biggest reasons that got me interested in Rust since the community  surrounding it is dedicated to making it a fun and safe place to be.  So in general, I was looking to learn a new language that presented not only a challenge,  but also a history that emphasized open collaboration.  And that's how I arrived at Rust.  And it also helps that the language's mascot is pretty cute.  So I think like most people who are getting it started with Rust, one of the first things  I did to jumpstart my learning was a combination of reading the Rust programming language and  trying out some of the concepts in the Rust playground.  And this was a good way for me to get a bit of a foundation before jumping into actual  Rust projects.  And once I felt like I had some of the basics of Rust, I decided to contribute to a few  open source projects.  One of the first things I did was update the standard library documentation for the string  slice type.  And later on, I made some contributions to the Servo web browser engine project where  I implemented a few of the missing attributes on the mouse event interface.  And unfortunately, I haven't been able to contribute to other open source projects this  year, but hopefully I can find some time in the future.  But of course, there's just so much to know about Rust and so much to learn about it.  And it's hard to keep track of what I've learned.  And while I was writing this talk, it was actually already difficult to get a grasp  of where I wanted to begin and eventually lead into what I've learned about game development.  The amount of things to do can get pretty overwhelming.  So to help with this, I had to choose an area I was interested in.  And so I began my search.  And to no one's surprise, I arrived at game development.  Video games have always been an important part of my life, and it felt natural to choose  this area of software development to sink my teeth into.  I wasn't looking to create the next big indie title, but rather just create a few projects  that I could lightly work on.  And some experimentation had me interested in developing a roguelike.  There's a couple good tutorials on how to create your own, and while I was working on  my first game, I found that I was actually more interested in creating a 2D rendered  game.  And I wanted to do this in Rust.  And so one of the first places I went to get some information was checking out the Are  We Game Yet?  website.  I thought this was a good place to get some ideas of what I might need to build a 2D game  using Rust.  But of course, the game development space can be pretty intimidating in itself.  And as someone with basic knowledge of computer graphics, amongst other things, it was difficult  knowing where to start.  I was also interested in drawing some 2D sprites to the screen more so, and so I needed a library  that would do most of the heavy lifting for me.  And luckily, that is what game engines are for.  So when looking for a game engine to use, I was more concerned about finding one that  provided accessible documentation and hands-on learning and some examples to help demonstrate  certain concepts.  And from the Are We Game Yet?  website, I was able to find the Amethyst game engine.  This is a screenshot of the project's landing page at amethyst.rs.  As I researched the project, I found that it checked off everything I was looking for  in a game development written in Rust.  And the documentation for Amethyst was easily available through the project's website.  I never really felt the resources they provided were scattered, which is a huge plus for me.  And some of the things I found really nice is that Amethyst provides a book that entails  not only how to use the engine, but also talks a little bit about ECS, which is a topic I  will talk about later.  It also provides links to its communities, online API reference, and also to their examples.  And the book also has a section where you can build a Pong clone using Amethyst.  This was a really nice hands-on project to help understand the basics of using the engine.  And I also felt that it was enough to start experimenting with my own projects once I  was finished with it.  And finally, there were many implementation examples showing what Amethyst can do.  And these examples were readily compilable and were easy to experiment with.  Another nice thing about this project was that there are a few games available on its  blog that showcase the game engine's features.  And after doing some learning and experimentation with Rust, I decided to take what I learned  and apply it to what I wanted to make in the first place, which was simply drawing 2D sprites  to the screen.  I wanted to break down this section into three parts, explaining what ECS is, showing how  I went about implementing a 2D sprite animation using this framework, and finally, I'll extend  on this by explaining how I went about implementing a camera follow system for the player.  So what exactly is ECS?  ECS stands for Entity Component System, where an entity in your game represents a single  object.  An entity often represented with a single ID can be composed of a number of components  where a component acts like a container for data that can describe an aspect of an object.  And finally, a system is a piece of logic that can operate on one or more entities in  the game.  ECS is a common pattern used in game development, and it makes it easy to compose objects since  components can be arbitrarily added to entities.  And so there's that piece of theory.  When I first read about ECS, I needed some time to build a simple mental model of what  it could look like in practice.  And so let's shift into something that's more fun to talk about while also trying to  build on this mental model.  Let's talk about Animal Crossing New Horizons on the Switch.  Animal Crossing is a cute laid back game where you get to build an island society of cute  anthropomorphic animals.  And in this image and the game in general, we can probably apply some of the ideas of  ECS to help build our understanding of it.  And there's a lot of things on the island that we can identify as objects, which are  represented by entities in the world of Animal Crossing New Horizons.  For example, the player character is an entity, Isabella is an entity, Timmy and Tommy are  entities, and even this tree is an entity.  You get the point.  But it feels wrong to describe our island residents as just entities.  After all, an entity is usually represented by a single ID that has a number of components  associated with it.  We need to be able to associate some data with them.  And to keep things simple, I wanted to focus on describing data for the villagers in Animal  Crossing.  For some context, villagers are non-playable characters that can move to your island by  either randomly moving there or finding them on another island the player is exploring.  And they become residents of the little town you've created.  They can also do activities similar to the player, such as fishing, gardening and exploring.  And the player can interact with these villagers and even develop friendships with them.  And this being my first Animal Crossing game, I thought what made a villager special is that  they added more characters to the island by well being cute.  And though I've learned recently that each villager shares attributes that are unique  to each of them that actually influence how they interact with other villagers on the  island.  And so here's one of the first villagers that moved to my island.  Her name is Flurry and she's a hamster.  And the moment I found her while exploring another island, I just had to take her home  with me.  I just love how she has those cute little blue eyebrows and paws and red t-shirt and  she's just the cutest thing ever.  Anyway, there are specific attributes villagers have.  And I didn't list all of them here since I wanted to keep this simple.  Attributes that specifically describe a villager will be its species, personality and hobby.  These attributes will be contained by what I will call a villager component.  And you'll notice that the name and birth the attributes weren't included because I  think these attributes should be included in a separate component, which we will talk  about later.  So with amethyst, declaring components requires us to define the data being described.  And in this example, we declare a villager struct, which contains information about that  components, species, personality and hobby types.  And once the underlying data for the component is defined, we then have to implement the  component trait for the villager.  The storage type determines how the component will be stored.  And in this example, the dense vector storage type, which is where elements are stored in  a contiguous vector, it allows for lower use memory usage and it also like and for also  dealing with larger components.  And this diagram is to help visualize how the villager component is added to an entity  in the game.  In amethyst, whenever a new component is created, it's added to a storage responsible for storing  components of a specific type.  And in this diagram, we can create a number of villager components and add them to specific  entities.  Here we can see that the entity zero is associated with the villager component that describes  flurry and this is similarly done for the other entities representing villagers.  And so to do this with amethyst, we have to get a reference to the world, which acts as  a container for resources in your game.  To create a new entity in the game, we first need to import the builder trait, which allows  us to create the entity builder using create entity.  Using the entity builder, we can add component to that entity.  And in this example, we add the villager component we defined earlier.  Finally, we can finish building and get the actual entity by calling built.  Now we can extend this by using the name and birthday attributes in another component.  I decided to call it the resident component since it generically describes any character  on the island.  And in this example, I've added another entity, entity three, meant to represent the player  character.  And since villagers also have names and birthdays, the resident component can also be reused  and attached to entities with the villager component.  So now let's move into the section on getting a simple sprite cheat animation working using  amethyst.  But before we get started, I wanted to explain that a sprite cheat animation is simply taking  a sprite cheat and changing what sprite image or frame is drawn to the screen in rapid succession.  This gives the illusion of movement, much like how one would see with a flip book.  So the first thing we should do is describe the relevant components for the sprite cheat  animation.  The first is the animation component, which has attributes frames, frame duration and  index.  Frames describe the number of sprite images for one animation cycle.  Frame duration describes how long each image should be shown for.  An index indicates where in the sprite sheet the first image of the animation is.  And the second component is provided by animate amethyst.  It's responsible for containing data about the sprite sheet and which image from the sheet  to draw to the screen.  The data used to describe this is a sprite sheet.  And this is a reference to the sprite sheet asset.  And in amethyst, these references to texture assets are known as handles, and sprite number  is the location of the sprite image in the sprite sheet.  Now associating a component with an entity doesn't do much on its own.  Our animation needs a way to manipulate what sprite image is drawn to the screen during  each game cycle.  And this is where implementation of an animation system comes in.  In this diagram, we implement an animation system with amethyst by having that system  read or write data for different component storages during each iteration of the game loop.  This example shows that the animation system being implemented will read from the time  resource.  Resources in amethyst are containers of data that are not associated with an entity.  And then the animation system reads from the animation component storage.  And finally, the animation system will write to an entity's sprite render component, in  particular, the sprite render sprite number value will be modified to tell amethyst to  draw the next image in the animation sequence to the screen.  And this is what the animation system would look like using amethyst.  Implementing a system involves implementing the system trait on a struct.  And this system is then executed during each iteration of the game loop.  And when we define the system, amethyst requires us to define a type called system data, which  tells the system what data from the engine it should expect to get and how it should  be interacting with it.  Some of the system data types amethyst provides are read storage, which gives the system an  immutable reference to the entire storage containing the animation components.  On the flip side, there is also the write storage data type, which gives us a mutable  reference to the entire storage containing the sprite render components.  And then there's the read data type.  And this gives us an immutable reference to the time resource.  And now the next step is to implement the systems run method.  In our animation systems run method, we get all entities with an associated animation  and sprite render component.  This is done using join.  And this allows for the joining of components for iteration over entities with specific  components.  And now that we have that entity, we need to find which frame to use for the sprite  render's number value, depending on the game's elapsed time.  And finally, we can modify the entity sprite render to draw the new sprite image.  And here's the final result of an idle animation for the wizard sprite.  However, it would be much more interesting if the player could move around some sort  of environment.  To do this, we can design another system that is responsible for moving the player around.  And for this system, our game will read from the input handler resource provided by Amethyst  and will also be writing to an entity's transform component storage.  The transform component storage is available through Amethyst, and it's a common component  to use.  This is because transform can describe an entity's position, rotation, scale, and much  more.  And for this game, we're really only concerned about modifying an entity's position and  rotation in response to user input.  And now that a system is in place for the player to move around, it might be nice to  have another system that consists of a camera that tracks the player's movement within the  environment.  And at the time of writing this, I found that simply attaching subject tags to particular  entities made implementing the system straightforward.  In particular, I created a player subject component that I associated with an entity  designated as a player.  The camera subject component is also associated with an entity designed as the camera view.  And the camera follow system would then modify the associated transform component for both  the player and camera entities.  And the result would then look something like this.  Here I have the same wizard sprite moving through the game's environment with a camera  following their movements.  And there's also a few things I wanted to say about this demo.  Earlier in this talk, I mentioned how I dabbled a bit developing a simple roguelike.  And one thing that I became particularly interested in is being able to generate a random tile  map that would act as the environment the player could move around in.  And so as another mini side project that was separate from my project that used Amethyst,  I played around with developing a tile map generator that I could use potentially in  my game.  And the image I have here is a generated background image used in the demo.  And for this small project, I used a create called image to extract pixel data from a  source sprite sheet and had it put into an image buffer.  And this image buffer would then be outputted as a PNG image local to the project directory.  The generated map images aren't perfect, but it was a fun way to learn and see different  layouts for the game environment.  And since these are only images, I'd have to still extend my game and develop some sort  of collision system so that the player cannot move through tiles that are considered walls.  So as you can see, I wasn't able to complete a full game yet, but being able to complete  a small project like this has made the process much more enjoyable.  And the biggest takeaway from my learnings was that it's okay to iterate on project  ideas.  Do it at your own pace and also have fun.  And besides coding, another way to keep myself motivated was to document some of what I learned.  I did this by writing a blog post as soon as I finished one section of my project.  And not only did it help retain my knowledge over time, but it also challenged me to think  about how I can communicate what I learned in a way that was helpful not only for myself,  but also others.  Prior to this talk, I actually wrote a blog post documenting how I implemented 2D sprite  animations using Amethyst.  And one of the things I really appreciated my past self for doing was taking the time  to establish context and also outline her thought process throughout.  And this was the most difficult part and also the most time consuming part of writing this  other way short blog post because I really wanted to find a perfect balance between  providing enough context while also being forthright in my content.  And if anyone's interested, the link to this specific blog post is available at mtiggly.dev.  And I wanted to touch on writing with the intent to teach someone.  Like it's very useful, even if it's just for yourself, because it will help really ease  doubts you have about your knowledge.  And one way to do this is to keep a series of blog posts and over time you'll have created  your own repository of knowledge.  And who knows, maybe someone will find what you wrote about really useful.  And so that's the end of my talk.  I wanted to thank everyone who came to listen and thank you everyone who made this talk  possible.  And hopefully anyone who is interested in either Rust or game development will be inspired  to build something.
RustConf_2020_-_My_First_Rust_Project__Creating_a__GFi_EdS_s_c_0_107.png RustConf_2020_-_My_First_Rust_Project__Creating_a__GFi_EdS_s_c_108_407.png RustConf_2020_-_My_First_Rust_Project__Creating_a__GFi_EdS_s_c_408_4691.png RustConf_2020_-_My_First_Rust_Project__Creating_a__GFi_EdS_s_c_4692_7043.png RustConf_2020_-_My_First_Rust_Project__Creating_a__GFi_EdS_s_c_7044_9059.png RustConf_2020_-_My_First_Rust_Project__Creating_a__GFi_EdS_s_c_9060_9575.png RustConf_2020_-_My_First_Rust_Project__Creating_a__GFi_EdS_s_c_9576_10343.png RustConf_2020_-_My_First_Rust_Project__Creating_a__GFi_EdS_s_c_10344_14615.png RustConf_2020_-_My_First_Rust_Project__Creating_a__GFi_EdS_s_c_14616_17927.png RustConf_2020_-_My_First_Rust_Project__Creating_a__GFi_EdS_s_c_17928_22703.png RustConf_2020_-_My_First_Rust_Project__Creating_a__GFi_EdS_s_c_22704_26063.png RustConf_2020_-_My_First_Rust_Project__Creating_a__GFi_EdS_s_c_26064_26279.png RustConf_2020_-_My_First_Rust_Project__Creating_a__GFi_EdS_s_c_26280_27599.png RustConf_2020_-_My_First_Rust_Project__Creating_a__GFi_EdS_s_c_27600_28511.png RustConf_2020_-_My_First_Rust_Project__Creating_a__GFi_EdS_s_c_28512_28799.png RustConf_2020_-_My_First_Rust_Project__Creating_a__GFi_EdS_s_c_28800_28919.png RustConf_2020_-_My_First_Rust_Project__Creating_a__GFi_EdS_s_c_28920_29315.png RustConf_2020_-_My_First_Rust_Project__Creating_a__GFi_EdS_s_c_29316_31211.png RustConf_2020_-_My_First_Rust_Project__Creating_a__GFi_EdS_s_c_31212_31307.png RustConf_2020_-_My_First_Rust_Project__Creating_a__GFi_EdS_s_c_31308_31595.png RustConf_2020_-_My_First_Rust_Project__Creating_a__GFi_EdS_s_c_31596_31691.png RustConf_2020_-_My_First_Rust_Project__Creating_a__GFi_EdS_s_c_31692_31775.png RustConf_2020_-_My_First_Rust_Project__Creating_a__GFi_EdS_s_c_31776_31967.png RustConf_2020_-_My_First_Rust_Project__Creating_a__GFi_EdS_s_c_31968_32051.png RustConf_2020_-_My_First_Rust_Project__Creating_a__GFi_EdS_s_c_32052_32387.png RustConf_2020_-_My_First_Rust_Project__Creating_a__GFi_EdS_s_c_32388_32447.png RustConf_2020_-_My_First_Rust_Project__Creating_a__GFi_EdS_s_c_32448_33860.png
Hey everyone, my name is Mika and my pronouns are she and her. Today I'm going to talk about my beginnings with game development using the Amethyst game engine. When I first decided to do this talk, I had intended to share a full 2D roguelike game, but I found that my focus was in other areas of game development that I found more interesting to explore. Learning game development and Rust has always been an on and off learning endeavor of mine and I'm excited to share some of those learnings with you today. I'm just a developer looking to talk about one of her many in progress projects. So when I decided to learn a new programming language, I tried to identify criteria outlining some of the things I'd like to get out of it. And since my development experience was primarily in front end web development, I wanted to try picking up another language that was considered low level or whose use cases were designed to work closer to the hardware. Another was documentation. I think most people will appreciate that in any area of software development. And being someone who likes to do independent reading and research on a topic at my own pace, it really helps to have accessible documentation to refer to. And finally, having a welcome community helps lower the barrier to learning. This was actually one of the biggest reasons that got me interested in Rust since the community surrounding it is dedicated to making it a fun and safe place to be. So in general, I was looking to learn a new language that presented not only a challenge, but also a history that emphasized open collaboration. And that's how I arrived at Rust. And it also helps that the language's mascot is pretty cute. So I think like most people who are getting it started with Rust, one of the first things I did to jumpstart my learning was a combination of reading the Rust programming language and trying out some of the concepts in the Rust playground. And this was a good way for me to get a bit of a foundation before jumping into actual Rust projects. And once I felt like I had some of the basics of Rust, I decided to contribute to a few open source projects. One of the first things I did was update the standard library documentation for the string slice type. And later on, I made some contributions to the Servo web browser engine project where I implemented a few of the missing attributes on the mouse event interface. And unfortunately, I haven't been able to contribute to other open source projects this year, but hopefully I can find some time in the future. But of course, there's just so much to know about Rust and so much to learn about it. And it's hard to keep track of what I've learned. And while I was writing this talk, it was actually already difficult to get a grasp of where I wanted to begin and eventually lead into what I've learned about game development. The amount of things to do can get pretty overwhelming. So to help with this, I had to choose an area I was interested in. And so I began my search. And to no one's surprise, I arrived at game development. Video games have always been an important part of my life, and it felt natural to choose this area of software development to sink my teeth into. I wasn't looking to create the next big indie title, but rather just create a few projects that I could lightly work on. And some experimentation had me interested in developing a roguelike. There's a couple good tutorials on how to create your own, and while I was working on my first game, I found that I was actually more interested in creating a 2D rendered game. And I wanted to do this in Rust. And so one of the first places I went to get some information was checking out the Are We Game Yet? website. I thought this was a good place to get some ideas of what I might need to build a 2D game using Rust. But of course, the game development space can be pretty intimidating in itself. And as someone with basic knowledge of computer graphics, amongst other things, it was difficult knowing where to start. I was also interested in drawing some 2D sprites to the screen more so, and so I needed a library that would do most of the heavy lifting for me. And luckily, that is what game engines are for. So when looking for a game engine to use, I was more concerned about finding one that provided accessible documentation and hands-on learning and some examples to help demonstrate certain concepts. And from the Are We Game Yet? website, I was able to find the Amethyst game engine. This is a screenshot of the project's landing page at amethyst.rs. As I researched the project, I found that it checked off everything I was looking for in a game development written in Rust. And the documentation for Amethyst was easily available through the project's website. I never really felt the resources they provided were scattered, which is a huge plus for me. And some of the things I found really nice is that Amethyst provides a book that entails not only how to use the engine, but also talks a little bit about ECS, which is a topic I will talk about later. It also provides links to its communities, online API reference, and also to their examples. And the book also has a section where you can build a Pong clone using Amethyst. This was a really nice hands-on project to help understand the basics of using the engine. And I also felt that it was enough to start experimenting with my own projects once I was finished with it. And finally, there were many implementation examples showing what Amethyst can do. And these examples were readily compilable and were easy to experiment with. Another nice thing about this project was that there are a few games available on its blog that showcase the game engine's features. And after doing some learning and experimentation with Rust, I decided to take what I learned and apply it to what I wanted to make in the first place, which was simply drawing 2D sprites to the screen. I wanted to break down this section into three parts, explaining what ECS is, showing how I went about implementing a 2D sprite animation using this framework, and finally, I'll extend on this by explaining how I went about implementing a camera follow system for the player. So what exactly is ECS? ECS stands for Entity Component System, where an entity in your game represents a single object. An entity often represented with a single ID can be composed of a number of components where a component acts like a container for data that can describe an aspect of an object. And finally, a system is a piece of logic that can operate on one or more entities in the game. ECS is a common pattern used in game development, and it makes it easy to compose objects since components can be arbitrarily added to entities. And so there's that piece of theory. When I first read about ECS, I needed some time to build a simple mental model of what it could look like in practice. And so let's shift into something that's more fun to talk about while also trying to build on this mental model. Let's talk about Animal Crossing New Horizons on the Switch. Animal Crossing is a cute laid back game where you get to build an island society of cute anthropomorphic animals. And in this image and the game in general, we can probably apply some of the ideas of ECS to help build our understanding of it. And there's a lot of things on the island that we can identify as objects, which are represented by entities in the world of Animal Crossing New Horizons. For example, the player character is an entity, Isabella is an entity, Timmy and Tommy are entities, and even this tree is an entity. You get the point. But it feels wrong to describe our island residents as just entities. After all, an entity is usually represented by a single ID that has a number of components associated with it. We need to be able to associate some data with them. And to keep things simple, I wanted to focus on describing data for the villagers in Animal Crossing. For some context, villagers are non-playable characters that can move to your island by either randomly moving there or finding them on another island the player is exploring. And they become residents of the little town you've created. They can also do activities similar to the player, such as fishing, gardening and exploring. And the player can interact with these villagers and even develop friendships with them. And this being my first Animal Crossing game, I thought what made a villager special is that they added more characters to the island by well being cute. And though I've learned recently that each villager shares attributes that are unique to each of them that actually influence how they interact with other villagers on the island. And so here's one of the first villagers that moved to my island. Her name is Flurry and she's a hamster. And the moment I found her while exploring another island, I just had to take her home with me. I just love how she has those cute little blue eyebrows and paws and red t-shirt and she's just the cutest thing ever. Anyway, there are specific attributes villagers have. And I didn't list all of them here since I wanted to keep this simple. Attributes that specifically describe a villager will be its species, personality and hobby. These attributes will be contained by what I will call a villager component. And you'll notice that the name and birth the attributes weren't included because I think these attributes should be included in a separate component, which we will talk about later. So with amethyst, declaring components requires us to define the data being described. And in this example, we declare a villager struct, which contains information about that components, species, personality and hobby types. And once the underlying data for the component is defined, we then have to implement the component trait for the villager. The storage type determines how the component will be stored. And in this example, the dense vector storage type, which is where elements are stored in a contiguous vector, it allows for lower use memory usage and it also like and for also dealing with larger components. And this diagram is to help visualize how the villager component is added to an entity in the game. In amethyst, whenever a new component is created, it's added to a storage responsible for storing components of a specific type. And in this diagram, we can create a number of villager components and add them to specific entities. Here we can see that the entity zero is associated with the villager component that describes flurry and this is similarly done for the other entities representing villagers. And so to do this with amethyst, we have to get a reference to the world, which acts as a container for resources in your game. To create a new entity in the game, we first need to import the builder trait, which allows us to create the entity builder using create entity. Using the entity builder, we can add component to that entity. And in this example, we add the villager component we defined earlier. Finally, we can finish building and get the actual entity by calling built. Now we can extend this by using the name and birthday attributes in another component. I decided to call it the resident component since it generically describes any character on the island. And in this example, I've added another entity, entity three, meant to represent the player character. And since villagers also have names and birthdays, the resident component can also be reused and attached to entities with the villager component. So now let's move into the section on getting a simple sprite cheat animation working using amethyst. But before we get started, I wanted to explain that a sprite cheat animation is simply taking a sprite cheat and changing what sprite image or frame is drawn to the screen in rapid succession. This gives the illusion of movement, much like how one would see with a flip book. So the first thing we should do is describe the relevant components for the sprite cheat animation. The first is the animation component, which has attributes frames, frame duration and index. Frames describe the number of sprite images for one animation cycle. Frame duration describes how long each image should be shown for. An index indicates where in the sprite sheet the first image of the animation is. And the second component is provided by animate amethyst. It's responsible for containing data about the sprite sheet and which image from the sheet to draw to the screen. The data used to describe this is a sprite sheet. And this is a reference to the sprite sheet asset. And in amethyst, these references to texture assets are known as handles, and sprite number is the location of the sprite image in the sprite sheet. Now associating a component with an entity doesn't do much on its own. Our animation needs a way to manipulate what sprite image is drawn to the screen during each game cycle. And this is where implementation of an animation system comes in. In this diagram, we implement an animation system with amethyst by having that system read or write data for different component storages during each iteration of the game loop. This example shows that the animation system being implemented will read from the time resource. Resources in amethyst are containers of data that are not associated with an entity. And then the animation system reads from the animation component storage. And finally, the animation system will write to an entity's sprite render component, in particular, the sprite render sprite number value will be modified to tell amethyst to draw the next image in the animation sequence to the screen. And this is what the animation system would look like using amethyst. Implementing a system involves implementing the system trait on a struct. And this system is then executed during each iteration of the game loop. And when we define the system, amethyst requires us to define a type called system data, which tells the system what data from the engine it should expect to get and how it should be interacting with it. Some of the system data types amethyst provides are read storage, which gives the system an immutable reference to the entire storage containing the animation components. On the flip side, there is also the write storage data type, which gives us a mutable reference to the entire storage containing the sprite render components. And then there's the read data type. And this gives us an immutable reference to the time resource. And now the next step is to implement the systems run method. In our animation systems run method, we get all entities with an associated animation and sprite render component. This is done using join. And this allows for the joining of components for iteration over entities with specific components. And now that we have that entity, we need to find which frame to use for the sprite render's number value, depending on the game's elapsed time. And finally, we can modify the entity sprite render to draw the new sprite image. And here's the final result of an idle animation for the wizard sprite. However, it would be much more interesting if the player could move around some sort of environment. To do this, we can design another system that is responsible for moving the player around. And for this system, our game will read from the input handler resource provided by Amethyst and will also be writing to an entity's transform component storage. The transform component storage is available through Amethyst, and it's a common component to use. This is because transform can describe an entity's position, rotation, scale, and much more. And for this game, we're really only concerned about modifying an entity's position and rotation in response to user input. And now that a system is in place for the player to move around, it might be nice to have another system that consists of a camera that tracks the player's movement within the environment. And at the time of writing this, I found that simply attaching subject tags to particular entities made implementing the system straightforward. In particular, I created a player subject component that I associated with an entity designated as a player. The camera subject component is also associated with an entity designed as the camera view. And the camera follow system would then modify the associated transform component for both the player and camera entities. And the result would then look something like this. Here I have the same wizard sprite moving through the game's environment with a camera following their movements. And there's also a few things I wanted to say about this demo. Earlier in this talk, I mentioned how I dabbled a bit developing a simple roguelike. And one thing that I became particularly interested in is being able to generate a random tile map that would act as the environment the player could move around in. And so as another mini side project that was separate from my project that used Amethyst, I played around with developing a tile map generator that I could use potentially in my game. And the image I have here is a generated background image used in the demo. And for this small project, I used a create called image to extract pixel data from a source sprite sheet and had it put into an image buffer. And this image buffer would then be outputted as a PNG image local to the project directory. The generated map images aren't perfect, but it was a fun way to learn and see different layouts for the game environment. And since these are only images, I'd have to still extend my game and develop some sort of collision system so that the player cannot move through tiles that are considered walls. So as you can see, I wasn't able to complete a full game yet, but being able to complete a small project like this has made the process much more enjoyable. And the biggest takeaway from my learnings was that it's okay to iterate on project ideas. Do it at your own pace and also have fun. And besides coding, another way to keep myself motivated was to document some of what I learned. I did this by writing a blog post as soon as I finished one section of my project. And not only did it help retain my knowledge over time, but it also challenged me to think about how I can communicate what I learned in a way that was helpful not only for myself, but also others. Prior to this talk, I actually wrote a blog post documenting how I implemented 2D sprite animations using Amethyst. And one of the things I really appreciated my past self for doing was taking the time to establish context and also outline her thought process throughout. And this was the most difficult part and also the most time consuming part of writing this other way short blog post because I really wanted to find a perfect balance between providing enough context while also being forthright in my content. And if anyone's interested, the link to this specific blog post is available at mtiggly.dev. And I wanted to touch on writing with the intent to teach someone. Like it's very useful, even if it's just for yourself, because it will help really ease doubts you have about your knowledge. And one way to do this is to keep a series of blog posts and over time you'll have created your own repository of knowledge. And who knows, maybe someone will find what you wrote about really useful. And so that's the end of my talk. I wanted to thank everyone who came to listen and thank you everyone who made this talk possible. And hopefully anyone who is interested in either Rust or game development will be inspired to build something.
roguelike game, but I found that my focus was in interesting to explore. Learning game development a new programming language, I tried to identify experience was primarily in front end web the barrier to learning. This was actually one of Rust since the community surrounding it is your own, and while I was working on my first in itself. And as someone with basic knowledge of I was able to find the Amethyst game engine. This is a screenshot of the project's landing page at amethyst.rs. As I researched the project, I found finally, there were many implementation examples has a number of components associated with it. We And the biggest takeaway from my learnings was useful. And so that's the end of my talk. I