Make a visual novel with Python
Bridge the gap between books and videogames by creating an interactive novel or choose-your-own-adventure with Python and pygame
Videogames have come a significant way since their early days, and in recent years it’s become even easier to tell a gripping and compelling story through the medium. A great way to tell a pure story is through the genre of visual novels. These interactive novels are extremely popular in Japan, though they’re gaining traction in the rest of the world, and usually have the player click through a story and make decisions as they go to experience different plot points and endings.
In Python, this is a relatively easy project to create, but with the addition of the pygame module we can make it easier still and more expandable for the future. Pygame adds better support for positioning images and text, creating display windows, using mouse and keyboard inputs, and simplifying the coding process. We’ll be coding this in Python 2, so make sure to run it in IDLE 2 and not IDLE 3 while writing and testing and coding.
1. Get pygame dependencies
The best way to install pygame for your system is to compile it. To do this you need to first install the right dependencies. Open up the terminal and install the following packages, which in Ubuntu looks like:
$ sudo apt-get install mercurial python-dev python-numpy libav-tools libsdl-image1.2-dev libsdl-mixer1.2-dev libsdl-ttf2.0-dev libsmpeg-dev libsdl1.2-dev libportmidi-dev libswscale-dev libavformat-dev libavcodec-dev
2. Get the pygame code
Next we need to download the code for pygame direct from the source. Still in the terminal, you can do this by typing in:
$ hg clone https://bitbucket.org/pygame/pygame
… which will download it to the folder pygame. Move to it using cd pygame in the terminal so we can continue building it.
3. Build the pygame module
To install it, we need to do it in two steps. First we need to prepare the code to install using the terminal with:
$ python setup.py build
One that’s finished, you can then actually install it with:
$ sudo python setup.py install
This won’t take too long.
4. Install in other ways
If the above steps don’t work for you (or if it seems a little bit daunting) you can check the pygame website for binary and executable files that will work on other operating systems and Linux distros. Head to http://pygame.org/download.shtml to get the files you need for your specific system, including Windows and OS X. The rest of the tutorial will work in any OS.
5. Get the visual novel files
We’ve uploaded the code to FileSilo, and here we’re going to walk you through what we’ve done to make it work. Download the files for the visual novel and unzip them. The two files we care about for the moment are the visualnovel.py and script.py python files – this is where all the important code is.
6. Understand the script file
For the moment the script file is small and literally just holds the script for the game. It’s made up of events for the visual novel to move between, line by line, by splitting it up into scenes. This includes the location of each line, the character, the actual line itself and information on how the game flows. These are all matrices that store the relevant information, and are completely customisable.
7. How the script relates
In our game, the code pulls in elements from the script file as it goes. We’ll explain how that works later, but this also allows us to implement decisions later on to change where the game might take you in a later part of the game.
8. Starting the main game
We don’t need many modules for the current state of our visual novel. Here we’ve imported the new pygame module, our script as a module and the time module for aesthetic reasons – we’re going to have the code pause in bits rather than just instantly change scenes to the next line. We also initialise pygame with a simple pygame.init().
9. Add variables and assets
We can now add the mixture of info that we need to run the novel. We define the size of the display screen to use (1000 pixels wide and 563 high), along with some RGB colours for the code to use. We’re also telling pygame which font to use, and how large for certain sections, and also loading images for the game.
10. Start the game
Create a display for the game. Pygame works by constantly updating the display with new information. To show how this works, the menu function adds elements to the display (which we’ve titled screen), such as filling it with colour, adding shapes and using blit to add images, or in this case text. Once you’ve created a buffer of changes to the screen, you update it with the flip() function.
11. See the mouse
As we’ve created the button as a rectangle and now an image on the menu, we need to know that the mouse is hovering over it to know when it’s clicked the button. First we have to use event.get() to see the mouse in general, then we look for the position with get_pos(). After that, we wait for it to click, see where it clicked (using the co-ordinates of the rectangle) and then make a decision after that.
12. Start the story
Our start_game function is called when the mouse clicks the right position and we prepare the game, getting the characters, locations and progression through the game script. The rest of this function uses this info to pull in data from the script to make the game flow properly.
13. First screen
The first screen is handled differently to the rest, and acts to get every element up on the interface before we start continuing – it makes the code take up a little less time to process as we begin. The getattr allows us to use the string/integer associated with our place in the story and call upon the relevant scene function from the script file. We then use an if statement with an iterative function to successively add screen elements, to give the illusion that it’s building up the first screen. We finish it by advancing the progression value.
14. Go to the next line
Similar to how our original startup code works, our next if statement and iteration checks to see what is different on the next line, and if it moves to a different scene function, and changes anything that is different without filling up the buffer any more than is needed. We’ve made it so no change is labelled with a 0 in the scripts.
15. The starting function
We finish our code bit with a simple function that starts off the entire game. This is just to encapsulate the entire code and allows us to add different ways of turning it off in the future. When running the file, IDLE will load everything up and then run the game() function at the end – this is similar to how you can add a __main__ function at the end that will start the code in the command line.
16. Expand your code
The code we’ve written is very expandable, enabling you to add decisions that are logged to take you to different scenes – or ‘routes’, in visual novel terminology – and make your game feel more interactive. This doesn’t require much more code to the if statements, and is also a good way to look into adding graphical buttons to click in order to use the collide function.
17. Move the assets
Currently, the code has the script-specific assets in the main visualnovel file. These can be moved to the script, allowing you to make the visualnovel file much more modular so that can you have multiple scripts with different assets to load at startup.