Let's write Snake game!
This is a modal window.
The media could not be loaded, either because the server or network failed or because the format is not supported.
Formal Metadata
Title |
| |
Subtitle |
| |
Title of Series | ||
Number of Parts | 542 | |
Author | ||
License | CC Attribution 2.0 Belgium: You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal purpose as long as the work is attributed to the author in the manner specified by the author or licensor. | |
Identifiers | 10.5446/61637 (DOI) | |
Publisher | ||
Release Date | ||
Language |
Content Metadata
Subject Area | |
Genre |
FOSDEM 2023276 / 542
2
5
10
14
15
16
22
24
27
29
31
36
43
48
56
63
74
78
83
87
89
95
96
99
104
106
107
117
119
121
122
125
126
128
130
132
134
135
136
141
143
146
148
152
155
157
159
161
165
166
168
170
173
176
180
181
185
191
194
196
197
198
199
206
207
209
210
211
212
216
219
220
227
228
229
231
232
233
236
250
252
256
258
260
263
264
267
271
273
275
276
278
282
286
292
293
298
299
300
302
312
316
321
322
324
339
341
342
343
344
351
352
354
355
356
357
359
369
370
372
373
376
378
379
380
382
383
387
390
394
395
401
405
406
410
411
413
415
416
421
426
430
437
438
440
441
443
444
445
446
448
449
450
451
458
464
468
472
475
476
479
481
493
494
498
499
502
509
513
516
517
520
522
524
525
531
534
535
537
538
541
00:00
Game theoryActive contour modelActive contour modelModule (mathematics)Game theoryComputer animation
00:43
Java appletClient (computing)Computing platformLemma (mathematics)Scripting languageBinary fileElectronic mailing listConstraint (mathematics)Game theoryImplementationWordCore dumpSemiconductor memoryGame theoryWeb 2.0MereologyActive contour modelIntegrated development environmentSoftwareImplementationPhysical systemOrder (biology)Wrapper (data mining)Constraint (mathematics)Binary codeCodeData structureLogicEnumerated typeType theoryMetreVirtual machineWeb applicationAssembly languageBlock (periodic table)Limit (category theory)IntegerEvent horizonComputing platformArmAttribute grammarSimilarity (geometry)Formal languageDifferent (Kate Ryan album)Context awarenessWeb browserComputer animation
06:35
Active contour modelImplementationGame theoryParsingString (computer science)OvalEvent horizonStrutData conversionDirection (geometry)Game theoryPoint (geometry)Active contour model1 (number)Level (video gaming)Position operatorCodeFrequencyDemo (music)Exterior algebraProper mapModule (mathematics)Plug-in (computing)Projective planeCoprocessorCompilation albumUser interfaceOrder (biology)Multiplication signInteractive televisionDifferent (Kate Ryan album)CASE <Informatik>Frame problemRight angleComputer animation
12:26
Well-formed formulaComputer fileUniform resource locatorGoogolActive contour modelHill differential equationPrice indexBoom (sailing)Software frameworkGame theoryCodeKey (cryptography)Point (geometry)Expert systemComputer animation
13:52
File formatBinary fileEuclidean vectorPhysical systemEvent horizonSoftware bugGame theoryActive contour modelConstraint (mathematics)Multiplication signWeb 2.0Exterior algebraComputing platformGoodness of fitGame theoryPhysical systemConnectivity (graph theory)Pattern languageMereologyDemo (music)MathematicsEvent horizonFrequencySoftware testingFrame problemParameter (computer programming)CodeObject (grammar)Functional (mathematics)TouchscreenInstance (computer science)Active contour modelComputer animation
19:33
Computer iconDirectory serviceFunction (mathematics)Error messageDefault (computer science)GEDCOMLimit (category theory)Game theoryState of matterWindowTable (information)Active contour model
20:41
9 (number)ResultantGame theoryKey (cryptography)State of matterNumberPosition operatorDifferent (Kate Ryan album)Focus (optics)CodePhysical system2 (number)Active contour modelFunctional (mathematics)Parallel portEvent horizonRepresentation (politics)Direction (geometry)Function (mathematics)Computer animation
23:49
Arrow of timeAsynchronous Transfer ModeWeb pageCodePoint (geometry)Line (geometry)View (database)Computer animation
25:05
Gamma functionVideo game consoleError messageNetwork topologyDew pointGraphic designComputer clusterActive contour modelOrdinary differential equationDegree (graph theory)Core dumpDirection (geometry)Different (Kate Ryan album)ImplementationMereologyActive contour modelWrapper (data mining)TrailTranslation (relic)Front and back endsWeb applicationUniform resource locatorMessage passingSource code
27:33
Fibonacci numberPhysical systemRepository (publishing)Web 2.0Computer animation
28:11
Computer fileActive contour modelFile formatWeb 2.0Thread (computing)MereologyLimit (category theory)Computer animation
30:24
Computer animationProgram flowchart
Transcript: English(auto-generated)
00:14
So now we've got Tommaso, he's going to tell us how to build a Snake game, and we're going to build it together.
00:21
Hopefully. Hi all. Today we are here to talk about Snake, obviously, Rust and Wasm. In particular we will see how to build a Snake game written in Rust and ship it as a Wasm module.
00:41
Before doing that, I would like to introduce myself. Hi, I'm Tommaso, I have two cats. And commonly I used to be a software architect in a web application environment. So probably the games are not my best stuff I can build, but I try.
01:04
So let's start to talk about what Wasm is. Wasm, more or less, is a stack-based virtual machine that allows to be portable. So we can build applications and bring where you want, mostly.
01:26
And the main target is web, but not linked to the web only.
01:40
We will see later. So we have four concepts, efficient and fast, memory safety, open the debugable, and part of the web platform. For this reason, we have four parts. The core one, JavaScript API that allows us to interact with JavaScript words like browser notes and so on.
02:08
Web API that allows us to interact with DOM events and so on. And Wasm, this is an acronym that stands for Web Assembly System Integration, if I remember correctly.
02:23
It allows us to interact with the system, networking, and so on. Obviously, Wasm is not allowed in browser context for some reason. So how we can write a Wasm module?
02:44
Wasm actually supports two kind of formats, text and binary. But probably you don't want to write directly into Wasm. For example, assembly, probably in this year no one writes in assembly directly.
03:03
But if you want, you can do that. But probably you want leverage on different languages. For example, CC++, Rust, Go, and so on. But if you remember the previous slide, we talked about the memory safeness of the Web Assembly.
03:27
And which is the other language that remember has a similar capability? Rust. Because Rust guarantees memory safety. And this is why we are here to talk about Rust plus Web Assembly.
03:46
So which is the constraint we have for building Wasm in Rust? Unfortunately, we are not so free to use what we want. We need to put an attribute, Wasm.gen, in all types exported.
04:04
So structure and arms and so on. But not linked to that. Also, the implementation block we need to treat like that. So put the same attribute on top of the implementation block.
04:23
And unfortunately, Wasm doesn't understand all the types available in Rust. So bytes, array, integer, but not all the integers are supported. We have some limitation about that.
04:42
As consequence, for example, enumeration needs to be treated as 80. And all returned values from meters need to be casted to some Wasm types.
05:04
Or return a Wasm.gen structure. So we are here to talk about Snake. Who play at least one Snake?
05:22
At least one. Okay. Okay. For the other, Snake is the simplest game to grid. There is a two-dimension grid. And your aim is to win. For winning, avoiding go through walls and eat yourself.
05:46
You are able to eat foods that give you scores and so on. Your aim is to drive the Snake through walls and try to eat the food, more or less.
06:00
Anyway, we will see later. So our code is here. Is a cargo workspace with three members. The first one is just plain Rust implementation of game logic. Without Wasm stuff. Without any other part.
06:22
The second one is handmade Snake that is just a wrapper on the previous one. In order to let a JavaScript world to import it and use it. So we implement the web interface manually. So JavaScript and the DOMs.
06:42
And the last is Bevy plugin that allows us to create a proficiency. More proficiency than manual ones. A game. The last two members use the first one.
07:01
And we will see how. So conceptually we have a bunch of stuff. A direction that allows us to describe which is the direction the Snake have. The point because we live inside a grid.
07:21
So we have to somehow describe the points. The game itself. Private stuff. Skip it. But mainly we have two members. Tic and get last snapshot. Tic allows us to move the Snake in the direction specified there.
07:45
And the last snapshot allows us to know what happened in the last tic. For example I eat food. I go through the wall which is my score.
08:01
Which is the position. And last but not least the period duration. Because you know in the game the interval between the tics change accordingly with your score. So the game more gone than the period decrease.
08:24
So how we can use... Hopefully you read the code. Because the finger anyway. I describe it. We have a level. Describe it as a simple way through a string.
08:45
We can parse it creating a game. We invoke a tic method on the game describing which is the direction we want to use. Get last snapshot.
09:02
Check status. For example in this case I eat food because the age goes on the food. We are not yet on the wall and the game over is none.
09:21
Instead the code below goes through the wall so on wall is true and the game over is some with the reason. And finally we have two public levels. Snake one and snake two.
09:41
The difference probably you know but for repeating the difference is the frame. So in snake one we have a frame with all the walls. Instead snake two is more like a toroid so you can go left and appear on the right and up and bound.
10:06
So how we can use this? We have a snake core. Again without any dependency. We need to wrap it because we already seen.
10:22
We have some deficit about that. We have some custom JavaScript code that interacts with DOM in order to update the UI. This is more like what happened.
10:42
And a compilation time after the compilation actually. We have a processor for compilation the Rust code into a Wasm. And this compilation generates two artifacts actually. The Wasm itself and an auto generated JavaScript module that allows us to simplify the interaction with the Wasm module.
11:05
After that the same JavaScript code and the same DOM. So more or less what we have is Wasm and auto generated JavaScript. That allows a lot.
11:21
So shortly we need to wrap all the stuff. All the stuff. So the direction, the point, the game, the snapshot and so on. So definitely we are not able to do that for a large project. Obviously this works for a little ones like snake.
11:43
But if you want to build a bigger one probably is not the best solution. But if you want instead create a cryptographic library, hashing library, something like that. This is really amazing. This is sufficient.
12:01
But for the gaming probably not so much. So before seeing which is our alternative we have I have prepared a demo that obviously you can find in the code.
12:21
So let's see if it works properly. Obviously yes. Here. Okay. So because I haven't the framework that helped me to build a better user UI, I choose this one.
12:53
Sorry, I'm not a UI expert. So for our purpose is sufficient.
13:01
As you can see here there is some bootstrap, webpack, blah, blah, blah. We don't care at all. But at that point we download the Wasm. Wasm is a few kilobytes, so not so big. The user is able to choose which game he would like to play, click on here and move with the arrow key.
13:28
Not whoa, but why not whoa? Thanks. Okay. Obviously when I go through the wall the game is put on wall.
13:45
Again, not the best user experience we have, but sorry. So we will see the code together in the final Q&A session. So sorry. Time constraints.
14:02
So which is our alternative? Our alternative, there are many alternatives obviously. I choose Bevy engine because I like it. I didn't find, again, I'm a web developer, so for gaming stuff I don't understand nothing.
14:26
But Bevy engine allow me to put something in short time, so good stuff, guys. Good stuff, team. And support across platform as well.
14:42
Windows, Mac, Windows, and obviously web. The pattern used is ACS, Entity Component System. Entity is just an ID that you can put on the world. And the component is a tag, something you can attach to an entity like image, like a position, like something like that.
15:06
And system is a function that work on those stuff. Can add entity, remove add component, remove a component, move existing component, and so on. So more or less how Bevy works.
15:25
Each frame invokes, Bevy runs our function called system that change add, remove components and entities that allow us to change our worlds.
15:47
And finally, Bevy render some of them obviously on the screen. So conceptually, this what I understand in two years, at night obviously, is not my job again.
16:06
So it's almost simplest to understand. Last stuff to introduce of Bevy, we have two another concept I need to introduce. The resource event is a plain rest object that allow us to be fired and to be listened.
16:29
So we can inform other function, other systems that something happens. And the resources is just a global instance because system is allowed to access only on the world, not our custom objects.
16:47
So you need to put your resources on the world and fetch it inside the system. And a nice feature, Bevy tracks when a resource change.
17:02
We will see later. So how can you use them? A system, for example, firing events that is listened by system two that on that event change accordingly a resource A. And system three more or less react on that change.
17:22
For example, moving the snake. So let's have a look to a more detailed example on the code. Skipping the arguments because it's not important to understand better what I would like to show.
17:45
Firstly, because systems runs every frame, we don't want to tick on every frame. We want to wait the time. So, you know, also for test proposing, this is nice.
18:06
So we need to wait the tick event. So only when the tick event is fired, we call tick method on game. Game is on the third arguments that the game resources obviously is the game we saw before.
18:28
After that we get the snapshot, check if the game over is we are in game over. If yes, we send, we fire a game over event.
18:43
After that we update the snake position, update the resource score, update the food and the duration of the timer. Because, you know, the period can change. A nice stuff to be focused on is the if because we don't want to change if the real value is changed.
19:08
Bevy leverage on the ref mute. So it is important to not the ref mute before the real change.
19:21
So have a look at a quick demo. After the demo we can see the code, I promise. So, again, the demo. The demo I propose you to show the native part.
19:44
So, cargo run, blah, blah, blah. Okay. This is our windows that is created natively. Okay. Again, I can choose snake one as the shoe with button this time.
20:02
Thanks. And, again, it's not my job, but I this is what I implemented. So, as you can see, under the hood there is some locks. And in front of you should be at least the snake that runs through the table.
20:28
And this is the way I handle the game over. So, and obviously quit close the windows.
20:41
So, we have three different states in our game. And in our code I track these in three different packages, sub packages. Choose game, play game, and game over. And as you probably understand, we can leverage on event system to bring the user from one state to another one.
21:10
Also because it's written there. So, let's focus on the play state because probably is the most important one. So, what we need to do in the play state?
21:21
And probably we need to surely when we enter in that state, we create the resource, the dedicated resource, and make the initial draw. After that, we already saw we need to wait the tick key event called tick game methods.
21:41
Update the position, update the food position and the score number. And surely we don't forget them handling the press key and the fire the game tick. So, these are the last slides.
22:04
After that we can run in we will see the output and the code. So, the graphical representation. We have in red the system, so the function. HandleKeyBotInput that update the direction resource.
22:21
We will see it before. When I press the key, the direction resource change. SendGameTick is the function that wait x seconds. So, after x seconds sends game tick event, listen and buy tick system.
22:46
That update after calling tick method on the game, all the resources. Because the resource change, I can update accordingly the score, the snake and the food.
23:04
Why I started like that? Because the last three systems I mentioned, updateScore, updateSnake, updateFoods, can be paralyzed by Bevy. Bevy has a parallelization system that allows you to automatically parallelize the system.
23:27
If he understood that is parallelizable. For example, doesn't access a mutable way on the same stuff. So, show me the code, but probably show me the result also.
23:45
If you want. You want? Okay. Okay. So, I built it in release mode and this is important.
24:05
Refresh the page. Okay. As you can see here, we have 60 megabytes, not kilo, mega. But not in release mode, this heavier to up to 70 mega, if I remember correctly.
24:21
So, crazy. Snake1 obviously are the same user experience, the same user experience.
24:41
And as you can see here, there is the logs also. Nice feature is that he also linked to the particular lines. And this is amazing, at least from my point of view.
25:01
So, let's dig into the code. So, we have time. Apparently, yes. So, here we have the handmade snake.
25:21
I remember that this is just a wrapper around our core implementation. As you can see here, there is JSys that is JavaScript API from the WebAssembly package we described before. The other part is just merely the tracing, for example, a different location.
25:46
The second dependency allows us to print a message on panic, for example. And the first is the wasbingen. So, because I don't lie, not now at least, here we have all the bingen attributes with all the enumeration, the structures, and so on.
26:16
And here under this folder, we have the classic Webpack, the Webpack frontend stuff.
26:30
I really don't know what is this. For building it, I use Waspack that allows us to translate Rust in Wasm.
26:45
And I use it in the handmade package. Instead, baby snake is built using track that allows us to somehow transform all the Rust plus index.html into a web application directly.
27:14
And if you are questioning how it works, why we made handmade snake and baby snake, which is the main difference under the hood,
27:32
the answer is this.
27:42
This is the public repository on GitHub. And here, as you can see, there is a web system. There's another API that allows us to interact with DOM world. So, at Rust side, we can change the canvas because under the hood, there is the canvas.
28:05
It's displayed inside the canvas. So, more or less, I have done. Thank you. If there is any questions, I will be happy.
28:24
Be kind. So we have about five minutes for questions. Be kind. We have a show of hands for questions.
28:49
Have you ever played around with much more entities in Bevy, like 100,000 or 1 million entities? Good question.
29:01
No, I didn't. I know that the limitation here is the thread number, obviously. We have in JavaScript, we have in browser. If you don't use Web Worker, for example, you don't able to scale on this part.
29:20
Bevy is not using Web Worker, at least for the time being. So he is not able to parallelize. And for this reason, probably you can find a limitation. There is no internet, but in the Bevy engine website, there is a dedicated example.
29:52
Also, Shipe has Wasmu. So you can find it and give me the answer, please.
30:12
Thanks. Thank you very much.