Missed part 1? read it here first: https://chequered.ink/the-making-of-gamedevdan-vs-life-part-1/
Making The Launcher
The launcher itself is pretty simple – much simpler than I expected when I started. It’s essentially just an empty husk that performs a few basic functions: display a list of games, sort the games in an order chosen by the user, launch the selected game. The information for these games is not stored in the launcher’s GameMaker project at all, but in separate text files. The reason for this is simple: each time a new game is added to the pack all we have to do is dump it in the same folder as the launcher and edit the text file. If the information for each and every game was stored in the launcher project itself, we’d have to create a new build of the launcher every time we wanted to update the information for a single game!
So how does it work? First the launcher creates a ds_grid in which it will store all of the information for each game in the pack. Each horizontal row will represent a game, each column represents some piece of information about the game (its title, the relative file path to the executable, a description, etc).
To populate this ds_grid with information, the launcher then needs to read information from the text files stored in the pack. One text file contains just the names of each game in a vertical list, like this:
Antibody Blast Antibody Blast 2 Antibody Blast 3 Antibody Blast: Go Balloon Festival Ballooning Over The Ocean etc.
The launcher counts how many games there are by reading the text file (using the functions file_text_readln and file_text_eof) and resizes the ds_grid to give it the right amount of rows. The first column of the ds_grid is then populated with the name of each game in the list. If you can picture it in your head the ds_grid will now be a large table with a list of games in the first column, and empty space for more information in the other columns, like this:
|Antibody Blast 2|
|Antibody Blast 3|
|Antibody Blast: Go|
|Ballooning Over The Ocean|
The second text file is an ini file which contains more detail about each game. The ini file is formatted as shown below. Each section of the ini file is marked by the title of the game exactly as it appears in the other text file and surrounded by two square brackets. Each key of the ini file represents a piece of information the launcher needs to know about each game, for example: where to find the executable it needs to launch.
[Game Name] exe=”Relative\Path\To\Executable\Game.exe” sprite=”Relative\Path\To\Game\Icon\Sprite.png” releasedate=”20160905” description=”this is a very fun game” [Game Name 2] exe=”Relative\Path\To\Executable\Game2.exe” sprite=”Relative\Path\To\Game\Icon\Sprite2.png” releasedate=”20170515” description=”this is also a very fun game, but quite different from the one above”
The launcher reads this information for each game (using the ini_* functions) and populates the rest of the columns in the ds_grid with the appropriate information, so that it looks something like this:
|Antibody Blast 2||\Games\AntibodyBlast2\Play.exe||\Sprites\AB2.png||20161206|
|Antibody Blast 3||\Games\AntibodyBlast3\Play.exe||\Sprites\AB3.png||20170315|
So the launcher now has a ds_grid containing all the information it needs to display all of the games on the screen and launch a game the user has selected. To display each game the launcher simply loops through the table drawing each game icon and title on the screen. The end result is something like this:
I could go into more detail about using “for” loops to draw the grid, how the information on the right-hand panel is shown by reading the ds_grid, and so on, but if you’re clued up on both of those things you probably already know how I did it, and if you’re not it’d be wise to learn those skills on a smaller scale first!
Finally, there is one piece of the puzzle missing. How do we launch the .exe files when the player selects a game? In older versions of GameMaker we could simply have used the functions execute_shell or execute_program, but these were removed from GameMaker: Studio for a number of reasons. As such, these functions need to be added back in with an extension. A few examples of such an extension are, at time of writing, available on the GameMaker Marketplace, but could be easily created with a little bit of research or commissioned explicitly for a specific project.
When the user selects a game, the launcher runs the .exe file listed in the ds_grid for that game. It also exits fullscreen and displays a “launching” message instead of the game grid. This prevents the launcher from hogging the screen, stops the player launching more than one game, and also provides some user feedback while the game window inevitably takes a few seconds to appear.
That’s it really, that’s how the Launcher works. It does have other features I’ve not mentioned yet. It can sort the games in order of name or release date (using GameMaker’s built-in “sort” functions for data structures) and it can read and display a list of credits from an external text file, but those are a nice bonuses rather than core features.
One thing you may have realised already is that, in theory, end users can add new games to the pack on their own if they want to simply by editing the text files. In fact, with a bit of tweaking GameDevDan vs Life could be turned into a launcher for any game, similar to the GameGo launcher from Kenney. I wouldn’t recommend it, there are better ways of doing it than tinkering with the folders in GameDevDan vs Life, but it could be done.
Next time, in the final part, we’ll see a little bit about the process of updating old GameMaker games to work on new PCs. Be sure to keep an eye out for part 3!