Introduction Welcome Getting Started My First Program     Troubleshooting and Distributing Transforming Data Interactive Programs     Programming Exercises     Making Games
Documentation Declarations     Procedures     Variables Statements     Flow Control Expressions Libraries     Print     IO     Random     Game Engine
Tutorials Complete Tutorials     Introduction to Programming     Quick Start     Programming Exercises     Programming Games


Let's apply all that you learned to program awesome video games!

About the Tutorials

The Game Programming tutorials were created to take all that your learned to the next level, by applying your knowledge in game development! Games are one of the most complex types of software to create, but also one of the most rewarding. Seeing your code come alive with moving images, sounds, particles and much more; while the user interacts with this imaginary world is just amazing.

The tutorials were created in a sequence, where it starts off by teaching you the fundamentals of game programming, taking you to the different challenges you will face while creating these interactive worlds, all the way polishing the games and adding professional-quality techniques to your games.

To help you in this incredible journey, we have created a Game Engine library to make your game-programming learning path super productive. You can read all about the Game Engine in this page.
To get started, all you need to do is download Vizzcode and select the tutorials in the Welcome Screen.
Here is how each tutorial is structure:

In the Invaders: Basic tutorial you will create a simple shoot'em'up game. You will be able to use that knowledge to make your own game ideas come to life! Making games can be hard, so you should already be familiar with programming in Vizzcode, at least up until Loops. You can always review previous tutorials and come back here later.

Then comes the Tappy Plane: Basic tutorial, where we will build on the foundations learned in the previous game tutorial and create a new game - Tappy Plane.
You will learn more about gameplay programming and organizing your program to create more complicated behaviors!

The Tic Tac Toe: Basic tutorial will take your gameplay programming skills to the next level by teaching you how to program the gameplay entirely on your own, without relying on the game engine. We will only use the Game Engine to display the images and play the audio.
It will be a great opportunity to learn a lot more about game logic and data transformation!

When you get comfortable with your new skills, the Shooting Gallery: Basic tutorial comes to show you an entirely different world: programming a custom object system! You will specify the object's data, animate objects, learn about an important interpolation equation and more!
In the end you will have the base of a Shooting Gallery game and the knowledge to expand it and create more complex games with custom objects.

At last, comes the final tutorial in this series: the Invaders: Advanced. You will learn how to program some more advanced elements in your games to take them to the next level.
In this tutorial, you will create enemy ships that shoot back, improve the player's movement, add parallax effects to the background, display the score with a custom font, implement advanced sound effects and more!

The next sections of this page will serve as a companion in your journey with these tutorials: you will follow the tutorial inside Vizzcode, then you can come here to be directed to specific parts of the documentation that mentions what you are programming in more detail.
What are you waiting for? Let's go!

Invaders: Basic

Learn the basics about making games! All you need to do is select the tutorial from Vizzcode's Welcome Screen!

Invaders: Basic - Gameplay screenshot

Introduction and what we will build
This page sets up the stage to start creating amazing video games.
Move on to get started!

How Games are Programmed
The topics discussed in this page will be presented throughout all the game programming tutorials.
It's important to keep them in mind, but don't worry too much if you are a bit overwhelmed.
If you need, re-read the tutorial page or head on over to the Making Games documentation page and specifically the How Games Are Programmed section.

After that, the page starts using the Game Engine library to setup a basic Game Loop in the game. You can read a section on how to use the library if you want more examples.
You can read more about the game_is_running procedure here. It will always be used when making games in Vizzcode.
You can download the assets you need to create this project here, as well as learn more about distributing your game here.

Programming the player's ship
Be sure to test your game in every step of tutorial. Don't wait for a bunch of new things to appear before checking it out!
You can check out more information on drawing images with draw_bitmap here.
If you don't see the image, make sure the path you inserted leads correctly to a PNG image from the executable. For example, if we ask to draw the file assets/background.png, starting from where the executable is located (inside the project folder) the program will move inside the assets folder and open background.png. Make sure your path is correct!
If you want to know more about how the object system of the Game Engine library works, you can head over to its API specification here and read the description and examples of every procedure used in this tutorial page. But don't worry too much about every detail yet; the more you program using these elements the more you will understand how they work.

Making the Player Shoot
This pages uses that you learned in the previous page along to spawn objects dynamically.
If you need to, go back and review the previous page or re-read this page carefully.
It's important that you are following each step of the way.
You can always use the Game Engine's API reference to learn more about certain procedures the game is using, for example the button_pressed or the get_first_instance procedures.
Another great way to help your understanding is to play around with your code. Don't be afraid to break it! Try setting different values and changing the structure of the program. The more you program, the more you will understand!
Also read each of the procedure's name, parameters and return values. They can really help you know how it's meant to fit together.

Creating the Asteroids
This page introduces you to a very important tool in game-making: timers.
The idea is very simple, we have a variable that is incrementing its value as the time passes (asteroid_timer += get_delta_seconds). With the timer value incrementing, we can work with it as if it were a chronometer, and test if its time is greater than some value (if asteroid_timer > .5). If it is, we must reset the timer by moving back it back to the amount we want (asteroid_timer -= .5).

The final part of this page shows you how to calculate the direction vector between the asteroid and the player. It will help us find the direction we should "push" the asteroid so that it moves straight to the player (using the set_instance_velocity procedure).
I suggest you really play around with the code - changing the values and the nodes before moving on. It will really make sure you grasps how the entire system is working before adding new elements. You can always go back and re-read the page more carefully.

Game Over
There is a nice description of how the objects_collided procedure works in the engine's API spec.
The state system that the tutorial introduces you to in this page is a very useful tool in game programming, and one that we will use and expand on in the next tutorials as well.
The idea is very simple: if game over is true, we will execute some code, if it's not, we will execute another part of the code. We have been using this base idea for a long time now, the only difference is that now we've applied it in the game loop - that is constantly being evaluated.
Try to keep in mind the value of the variables at every time when you are testing the game. If you need to, use the technique we've discussed in the help section of the Introduction to Programming series to manually execute the code. You can learn all about that here.

Destroy the Asteroid and Earn Points
As usual, this page builds on what you learned previously. So if you need, go back and re-read parts of the tutorial to make sure you understand the base system before expanding on it.
It's important to be familiar with Vizzcode's features such as multiple return values and compound declarations.
The score system is very easy, it's just a variable that increments on a certain condition! Remember to "run the program in your head" to make sure you know how its behaving at every point.

Polish: Music, Sound Effects and Particles
This page introduces very important concepts of game development. Good player feedback (also referred to as game feel or game juice) is one of the key differences between amateur and profession-level games.
One of the great things about game feel is that you can learn by playing and analysing other games, make you you think about every thing that happens when you shoot a gun in your favorite shooter game. Is there a powerful sound effect? A quick animation? Does the screen shake? Is there a particle effect? What other elements did you notice in the key actions you take when playing your favorite games?
With that in mind, you are introduced to several procedures available in the Game Engine library all of which are detailed in the complete API page. Just search for the name of the procedure you wish to know more in there!
Remember to experiment with different values - if you have an idea, try it! See how you can change the way the game plays based on what you learned in this page.

Extra Challenges
This is the end of the first game tutorial!
I hope you learned a lot with it!
You are in control of your learning journey, so if you need, don't be afraid to start over the tutorial and redo every step of the way. I assure you it gets easier every time!
If you feel up to the challenge, try solving the proposed challenges in the tutorial. They start off very simple - something you can do with what you have been learning so far, and keep increasing the complexity!
  • Implement a high score system: Below the score, there is the high score, that shows the greatest score the player achieved in this run of the game;
  • Increasing difficulty: The higher the score, the more difficult the game gets (faster and more frequent meteors, for example);
  • Hold to shoot: Make it possible for the player to hold a button to shoot. Remember not to directly add every frame, but to add a timer, like the asteroid spawner;
  • More lives: Make it so the players have three lives, when they collide with the asteroid, they lose one life and the game is only over when all lives are lost;
  • Play and improve: Play the game continuously and write down all the things you can do to improve what is already there or new ideas to expand it. Then tackle these problems just like you did the Programming Exercises!
  • Experiment with the procedures: The Game Engine library has dozens of procedures to create interesting things in your games. Don't be afraid to experiment with them and searching about the ones you didn't figure out how they work;
  • New games: Create new games from scratch! It can be very valuable to just start playing around with the features you have learned with an open-goal: let the game idea emerge while you are programming, play around with crazy things you come up with and polish it to make it as engaging as possible.
After you are confident with everything you learned in this tutorial, and challenged yourself with the proposed exercises, move on to the next tutorial!

Tappy Plane: Basic

Let's create another game!
This tutorial will reinforce what you learned in the previous tutorial and expand on some very cool new elements to create a more elaborate game!
So start Vizzcode and choose this tutorial in the Welcome Screen!

Tappy Plane: Basic - Gameplay screenshot

Introduction and What we Will Build
Get ready for another learning bomb!
Remember to go to the Game Engine documentation page whenever you want to know more about a certain procedure or system inside the game engine! You should also download the assets with this link and extract them in your project folder. Let's go!

Player Movement
This pages starts doing the same steps you have done in the previous tutorial: creating the game loop, drawing the background, and creating and spawning the player. You can go back to the tutorial and review these elements if you need.
The new elements introduced are simply new procedures in the game engine. You can search their name in the Game Engine API page and read all about them there.
A small note on the acceleration vs velocity system. Because the acceleration is a derivative of the velocity, it simply changes the velocity of the object! That's why when you set the velocity to a certain value, all the momentum built by the acceleration is gone, because the velocity was set to a specific value!

if you Fall, Get Back Up
In the previous tutorial, we used the objects_collided procedure to check the collision in our game.
We are going to start this game by doing a collision test by hand: check the position of the object against an infinite horizontal line, at the y position -35.
Because it's a very simple behavior (checking if the position is below a certain line), we can easily do it ourselves and change the game accordingly. In this game, we'll set the game_over variable. Like we have done before, this variable will be the base of the state system of the game (is the game over or is it playing?) and be used to drive certain interaction options for the player or visual elements on the screen.
Read and analyze the tutorial's code to make sure yours is similar and that you understand it.

This page combines two different systems we created in the previous tutorial: the score system (a variable that increments on certain conditions) and a timer (a variable that increments continuously as time goes by and when it gets to a certain point, some action is taken).
Read carefully the explanation in the page and see how the problem is broken down into the tasks: Creating the variables, Implementing the timer and the score, Resetting the score and Drawing the score.
If you need, you can go back and re-read the specific tutorial pages on timers and the score.

Rocky Obstacles
This page explains and implements has several steps to result on the obstacle system in the game.
It's important to read the entire page very carefully because each paragraphs builds on the previous.
You already know about creating and spawning obstacles from the previous pages and tutorials (like this one) and collision as well (like this one).
An interesting point taught in this page is the use of procedures to refactor the code. There is an entire tutorial on procedures in case you are not very familiar with them. You can access it here.
The more complex the program gets (and we are starting to create some complex programs) the more important it is to be able to move code around and you learn more about the program. Whenever you are creating a non-trivial program, you have some idea of where you are going but the details of implementing what you want are often obscures. That's why it's very valuable to be able to experiment creating a solution (like simply implementing the player death) and when you see an opportunity to organize your code better based on the way it's shaping up, you can then refactor the code - organizing it in a more optimal way. Another way to think about this process is that once you understand better what the code means, you change it to a better representation of that meaning: what the code does is the same, but it does it in a better way now that you have expanded it further and learned more about the details of your solution. Because of this, this process is also known as semantic compression
This pages also goes deeper on the scene system of the game engine. The best way to learn about it is accessing the Game Engine API and reading the description and the examples of the scene-system procedures.

Unlimited Rocks
This page challenges you to create a timer (like we have done before) to make the rocks spawn continuously.
The rest of the page discussing testing the game for bugs and solving them.
In the documentation we have already discussed fixing compiler error but program bugs are a different beast.
You must really understand the program and what it's doing to be able to realize why a certain unexpected behavior is happening and fix it. The more complicated the program, the more difficult it is finding bugs, that's why good testings is very valuable. The test works best when it's able to reproduce a bug with a simple series of steps. If you know what are the steps you take to see the bug, you can then analyse the code and understand the state of the program at that point (you may even execute the program in a piece of paper (or even in your head), like we discussed here).
Another very interesting way you can use to track down bugs and understand each value of the program is to draw key variables to the screen, so you can check their values against your assumptions. You can use all the drawing procedures in the game engine to help you with that.

Music, Sound FX and Particles
This tutorial simply uses what you learned before to give the game the finishing touches.
If you are uncertain about how a certain procedure works, just look it up in the Game Engine's API reference.
You can also go back to the previous tutorial where we talked about polishing the game.

Start Screen
This pages takes an incremental approach in programming a new functionality.
Firstly, we discuss the possibilities for implementing the start screen, then we choose one of the possible approaches.
Once the basic idea is implemented, we test the game and look for ways to implement, then we improve it. After that, we test again and look for more ways, and so on...
This iterative approach is very valuable when you are programming new functionalities, discovering new ways to implement solutions that you are not used to.
Make sure you read each paragraph carefully and implement it accordingly. Each functionality will built on the previous.
You can also try to implement the solution in different ways, on your own. That's very valuable for your learning journey.

Try taking this approach to the game itself. What do you want to improve on it? Test it, find out how you can make it better, then research how you can implement that improvement.
If the program is getting a bit out of hand because of its complexity, start a new project; one that's very small, so you can manage its complexity and learn along the way. The ability to manage the complexity of the program is a skill that can developed just like any other. So practice, practice, practice! :)

When you feel like taking on more information, move on to the next tutorial.

Tic Tac Toe: Basic

In this new tutorial, you will learn a lot about game logic and how to structure it. You will learn different ways to transform data and program the gameplay code.
All you need to get started is open Vizzcode and click on this tutorial!

Tic Tac Toe: Basic - Gameplay screenshot

Introduction and What we Will Build
The Tic-Tac-Toe game we will create may seem simple, but that's the beauty of making games: you can start with the simplest of systems and explore it in interesting ways; in terms or programming, design, art, sound or any other discipline involved. We will focus on creating the game logic and using the game engine just to display images and play sounds.

The Board in-memory vs the Visual Board
Just like before, you can download the assets here and extract them in the project folder.
In order to successfully solve a problem, we must understand the tools we have and choose them accordingly. If you solved the last array Programming Exercise you already used an array data structure to represent a 2D grid. If you haven't, I highly recommend you stop this tutorial and try to solve that exercise. The hints there will also help you to understand the data structure we will use to store and operate on the board in this game.
If you solve the exercise and re-read the page and are still not sure how the system will work, just go through the next few pages and it will start to make sense. Then, you can come back and analyse the base explanation after seeing how it works in practice.

Drawing the Board
This page shows the very useful method of writing the usage code first.
When you solve a problem like this, you will create a nice interface between the code that wants a certain functionality and the code that implements it. There is quite a bit of thinking involved in solving these problems, so make sure you know the tools you have at your disposal. For example, if you are not very confident using procedures, you can check out the documentation or even the entire introduction tutorial.
The last array Programming Exercise also helps consolidation some of the more practical problems in this page.
The images are there to help you, take some time to understand each image well. If you need, write down some other examples or transformations that are taking place between the different elements of the image. Like: how would these diagrams work in a 4x5 grid. Try solving this problem slowly and you will gain a lot more understanding.

Transforming the Mouse Click
This page focuses on the transformation back to the index format.
if you get stuck on certain parts of the explanation, try going back a few paragraphs and testing with different values, like a 4x5 grid.
It could be very useful to draw a board and play around with its values to make sure the formula work and you understand it.
This method of using an int where each number means something (like an error code) is a very common method and you might see that a lot when using other people's code. It's important to get used to this more abstract way of referring to data.

Turn Based Logic
Similarly to what we have done, you can create variables to store information about the state of the game (like "Which player should be placing marks now?"). These variables can then drive certain parts of the code or simply be used directly as a value.
Again, the incremental approach of solving problems is present, where you implement a simple solution and evaluate the resolve, improving it until it's complete.

Victory Condition
In this page we create a procedure to test the board. It reinforces the uses of global variables and integer as states. In this case, we specified the meaning of the value (1 for player 1 wins, 2 for player 2 wins, 3 for a draw, and 0 to continue playing) to make it easier for us to program. For example, we don't need to know what player won: if the mark is not empty and is equal on an entire row, column or diagonal, we simple return the value of the board tile because it will coincide with our return value's data (1 for player 1 wins and 2 for player 2 wins).
The tests themselves are probably easier than what you though! Most time the simplest solution is the best one: just test each row, column and diagonal!
Then, using the return value as a state for game should be very familiar by now.

Polishing and Distributing
This page invites you to add a bunch of nice feedback effects, like we have seen before. You are also welcome to explore the Game Engine docs to discover new interesting ways to improve the game.
Making the marks highlight the row, column or diagonal that won is easier than you might think. All you need to do is create another possible state for the board tile (like 3 = highlight X, 4 = highlight O) and when you test the row, column or diagonal, you also change their value!
The IA (Artificial Intelligence) for the game might start out really simple, just selecting a random available mark. That would be mostly about structuring the code to make only the player interact with the game and the "other player" be simply a procedure that decides where the AI's mark should be.
Lastly, you can distribute the games on the internet! You might even publish it on a game store so that other players find your game and maybe even get you some money!
Remember to take some time to put those new skills into practice. A good technique might be to go back and skim through the previous game tutorials looking for opportunities to improve the game and the code.
Afterwards, there will be another tutorial waiting for you to expand your knowledge!

Shooting Gallery: Basic

So far, we either have been using the Game Engine's object system (like in the Invaders and Tappy Plane games) or none at all (like the Tic Tac Toe game). In this tutorial, you will learn how to create a custom object system. This will expand the possibilities of the games you can make dramatically. You will specify what data each object will hold and how it will use it during the simulation part of the game. You will also learn cool ways to animate an object and render multi-part objects!
All you need to get started is download Vizzcode and select this tutorial in the Welcome Screen!

Shooting Gallery: Basic - Gameplay screenshot

Introduction and What we Will Build
This page reviews important concepts we learned a while back about the Input->Simulate->Render as well as using parallel arrays to store multiple different data of a single "object".
If you need it, you can review this Making Games page to remember the fundamental structure of games in code.
The parallel arrays concept was introduced in the part 8 of the Introduction to Programming tutorial series (which you can review here) and solidified in several of the array Programming Exercises.
Make sure you are very confident with these concepts before jumping in.
Download the assets here, extract them on your project folder, and move on!

Creating the Object System
Just like last time, we start off by creating a data structure for the data of the game. But this time, because we need several variables for several different objects, we created different arrays: one for each data element of the entire object.
It's important to analyse the diagrams carefully to understand the data layout. You can also review the arrays tutorial in which there are examples of using multiple arrays that refer to the same data object. In the Programming Exercises there are numerous examples of using parallel arrays to solve problems. Each of these exercises has several hints that explain further the concept.
If you had a hard time understanding it in this tutorial, try spending some time studying the other ones and implementing it here will become a breeze.
Of course, you can also choose to move on. As the results start appearing, it's easier to understand some of the decisions.

Animating the Targets
Some areas of game programming can get a little mathy.
You can choose to try and understand every aspect of it, probably by searching online for more details on the linear interpolation function. You can also focus on understanding how to use that in practice.
At any rate, it's fundamental to know the programming features necessary to implement the lerp (linear interpolate) in Vizzcode, such as arithmetic expressions and procedures.
The diagrams in the page explain how the function works in the code, so pay very close attention to them.
You can also experiment with the function after copying it from the tutorial to see the results in practice, try setting up a simple example with a single draw_rectangle call in which the x position is set by a lerp function. Try calling the lerp with t = 0, t = 1, and with values in-between. Then (like in the tutorial), add a timer to it and try to control it further.

The Target's Lifetime Behavior
Previously, we have been using a bool or an int variable to set some state. Based on their value, we would run some code.
In this case, we do the exact same thing, but using a float variable. So, we will add conditions to operate parts of the code (for example, setting the render_y variable) to work a certain way if the timer is between some values or work another way if its in another range.
Understanding it and being able to manipulate the timer is very important.
To help you visualize it, you could try calling draw_float and draw_text so you know the value of the timer as well as what is executing in the program. The best way to understand it is reading the tutorial page very attentively and experiment changing the values and playing with the code in every step of the way.

Making the Player Shoot the Target
We have already used the objects_collided procedure that the Game Engine offers as well as implemented a simple point vs line collision.
In this page, this knowledge is expanded further when we implement a point vs circle collision.
The idea is simple, we need to know if the user clicked on the target. The mouse cursor is a point in the world, the target is a circle. We need to see if the point is inside the target when the user clicked the left mouse button.
To do this, we must check the distance between the point and the center of the sphere and check if it's smaller than the radius.
Like with other math-heavier programming problems, you can choose to focus on just applying the math in your program or you can go the next level and try and understand the why it works the way it does.
The diagrams were made to help you, just make sure you are following what is going on in every paragraph.
You can also just copy the code and apply it in a simpler program just to play around and understand this one thing. Simplifying to gain understanding is always a great way to learn!

Player Objective
One of the most incredible things about programming is that it allows us to quickly experiment with crazy ideas and test the results for real. In other areas, for example, a great deal of planning is required and you can't iterate very much. For example, after building a house, you can't turn it 45 degrees to have a better sun position without redoing the whole thing! Programming is much more flexible than that, and it allows us to experiment with ideas and see the results to evaluate them. A lot of game designers (especially on smaller teams) have this experimental approach. Even in larger teams, programmers can always experiment on the problems they need to solve and go back or redo the solution if needed.
This page encourages you to experiment with different player objects in this game, while showing how to create a simple score system.

Polishing the Game
You should be used to adding these kinds of finishing touches on your games by now. It's only a matter of knowing what procedures are at our disposal when using the Game Engine library and using them in creative ways. Accessing the engine API is a great way to learn that, but playing around and trying whacky ideas is the best way to discover cool effects and results!

With what you learned so far you are certainly capable of creating tons of cool and interesting games! You can also polish them to a nice level and publish them!
Remember that the more games you release, the better you'll get at making them! So start simple and create often.
When you are ready to take another leap in your game development knowledge, check out the last tutorial!

Invaders: Advanced

This tutorial will show you how to take your games to the next level.
You will learn more about game feel, organizing your code, programming gameplay elements, optimizing the game, making it sound and look better and more!
You should be comfortable with all the programming features as well as the techniques you learned in the previous tutorials.
Ready? Go!

Invaders: Advancedo - Gameplay screenshot

Introduction and What we Will Build
It's very important to celebrate your progress, especially if you are doing something as difficult as programming games!
You should already have the Invaders: Basic code working. So just copy it to the new project (you should also copy the assets, or download them again here).

Adding the Enemy Ship
This page really shows the essence of programming now that you are past the basics: combining what you already know in interesting ways to create unique results.
This page uses objects, collision, semantic compression, timers and countless other elements.
That's why it's important to go back to tutorials you didn't understand correctly so you take away all the knowledge at your disposal.
The "new" elements introduced are simply specific procedures or parameters of the Game Engine library you haven't used before. If you explore its documentation page, you will find several other tools you can use, and your creativity will combine them with what you already know to create cool behaviors.
If the amount of things becomes too much for you, remember to break down your problem into smaller problems until they are easy enough for you to solve them. There is a documentation section to help you getting into a problem solving mindset here.

Movement and Code Cleanup
"Just as we build, so must we clean", an ancient philosopher said... I think....
The key takeaway here is that the more functionality we add, the more opportunities we have to improve the code and solve bugs. A common error among programmers is to just keep building and building and building until their programs are so huge not even them can understand or work on them. They become riddled with bugs and the maintenance cost is huge. They're so interconnected in complex ways that you can't even refactor them at that point.
This might sound absurd, but it's very common!
Small things such as removing duplicate code, reviewing how you solved a problem after solving it correctly and fixing bugs are crucial to create complex but healthy systems. Always evaluate your code and your understanding of it!

Destroy the Offscreen Objects
Another great benefit of understand how your program works in a deep level is that you know the optimization opportunities.
Even though computer are crazy fast, you have probably become frustrated with programs that seemed to that forever to do something. More than likely, it's because their programmers didn't have a deep understanding of their programs, just a superficial one.
For example, in the case of our game, we were spawning objects endlessly, and even though we reset the scene (deleting all objects) when the player restarts the game, during gameplay the objects keep piling up, even though they are not needed anymore.
With that in mind, we created an invisible object (setting its color alpha (opacity) value to zero) and destroying the instances that collide with it.

Parallax Background
This page introduces a concept you will most definitely see in professional games: secondary animations. They help give life to the game world and immerse players in them.
Using the same point vs line collision system we learned a while back, we implemented an endless cycle of moving planets on the background, with several random elements to avoid looking repetitive.
If you need, you can always create an empty project and create this functionality with nothing else polluting the game's code. It will help you play around with it and understand how the system works completely.

Custom Font Rendering
Another important aspect you will see in professional-quality games is a visual coherency.
This means that they won't use a random font to display the score just because it happens to be the font the game engine displays ints with. They will consider the most adequate font to immerse the player in the world they are creating and how it can be used to leverage the feel and the immersion.
A great technique to use when improving some element in the program is to avoid changing the API (or the interface between the code that uses a functionality and the code that implements it).
For example, we don't know how the draw_int procedure works but we know we call it by passing the value to draw and the x and y positions. So if we create another procedure that has the same interface, we don't have to change the calling code at all - just the name of the procedure it's calling!

With that in mind, the challenge becomes implementing the new routine.
If you have taken the Input, Processing, Output exercises in the Programming Exercises page, specifically the Seconds and Minutes and the Days, Hours, Seconds and Minutes exercises, you already used the division and modulo operators to decompose a number.
That's precisely what is going on here.
If you need, you can create a simple console program and print the result of the operations to make sure you know what is going on. You can also read more about the arithmetic expressions and specifically the modulo operator.

Advanced Sound Design
You already know how to play a sound and you have used it effectively to make the game feel better.
But you can always go fancier!

As you can see the base elements used in creating this nice effects are now new or crazy (even though we have been using button_pressed, button_is_down right next to it in the documentation ;) )
The interesting thing is they way they were used: by creating an if statement with all the possible keys the player can press to move the ship, we create a body of code that gets executed only when the player is moving around. And, as we learned, adding feedback to make the players' perception more connected to their actions is a great way to make the game feel better.
Saving the sound id and changing its volume is easy once you use what you know to create a nice structure of code.

Final Polish
Again, using what you already creatively can result in interesting elements in the game!
Calling spawn_particles every frame created a very cool effect that reinforces the sound effect we just added, when you understand its pitfalls (like being framerate-dependent) is even better, because you can consciously use it in a way that will make the game better and avoid using it where it could present problems.
There are several hidden treasures in the Game Engine API such as set_object_particle_trail and set_window_options procedure, so make sure to spend some time there or even experiment trying to call these procedures in a test game project!

Celebrate and Continue Your Journey
Congrats! It's really cool that you finished these tutorials and hopefully you are really enjoying your new super powers! :)
The great thing about your programming super powers is that the more you use them, the more powerful they get! Then, you will be able to create better and better projects!
The suggestions I gave in this page are great points to continue your journey, whenever you feel lost in your programming journey, start a new project you are excited about and let the ideas evolve while you develop the program!
Well, that's it! See you later!