Scripting as Part of Games Development

Scripting as Part of Games Development

·

7 min read

Introduction

Welcome to this blog post! In the previous post, which was about JSON files, I mentioned that I was going to be writing about scripting next. Well here we are! This blog is going to be covering what scripting languages are, how I have used them within the development of my engine so far, and how they could be used within a released games features.

Before I get to the discussion below, I’m gonna quickly mention that there is a newsletter subscription system. If you sign up to it then you will automatically get an email whenever I release a new post to this series. There is also a like button at the bottom of the page, which helps give me an indication of which topics I should focus on more in the future.

Onto scripts!

Scripts

The concept of scripts in games/software development is in some ways vastly different to the idea seen in other industries, such as film scripts. And in other ways very similar. Film scripts detail what each character says and does within a scene, along with giving other surrounding information. Programming scripts can, in some contexts, do the exact same thing - for example controlling NPC logic. And in other scenarios do vastly different things that are abstracted away from characters and game-play - an example being a number crunching script that calculates time consuming maths formulas.

But what are scripts?

In a programming context they are simply (relatively) small programs that are interpreted in real-time. Meaning that they are not compiled into a program, which is then run. Below is an example of a Python script which gets the user to input some text which it then repeats back out to them:

playerInput = input("Hello! Input some text!")
print(playerInput)
input("Waiting for input to close the program")

What may be immediately clear to anyone familiar with compiled languages, such as C++, is the lack of a main function. This wasn’t omitted for readability, it is simply not needed. (You can define one if you want to though). Another difference that may be clear is the lack of most of the syntax normally present in code files. Specifically semi-colons, data types and curly brackets {…}. How Python specifically handles these three is through: not having semi-colons be required to end lines, being a typeless language, and having scope be controlled through indentation instead of brackets.

Example Use Cases

The next question that arises from this idea of scripting is: why would anyone want to use something like this? This very much depends on their situation. Below is a short list of a couple of scripting languages and examples of when they could be used:

Python

Python is used for a vast number of different things. This ranges from simple console applications like the one shown earlier, to machine learning, to number processing, to just about anything else you could imagine. In my opinion it is vastly overused, but due to how easy it is to learn compared to other languages it has gained widespread adoption.

Another example use case for Python is as a tooling device. What I mean by this is that making tools using Python very easily. An example of this is how I have setup a shader compilation process for my engine. With the script I created I am able to visually select which shader I want to compile, and then the whole of the process is handled for me from there. This is done through a flow similar to below (some code has been omitted for length):

import subprocess
import os

import tkinter
from tkinter import filedialog

# Open a dialog box which allows the user to select a shader file
print("Select shader to compile")
tkinter.Tk().withdraw()
shaderPath = filedialog.askopenfilename()

# Determine what type of file this is based off of its extension (name.x)
# Do some internal processing based on the files contents

# Determine where the compiled shader is going to go (vertex shader example here)
compiledPath = shaderPathCropped + "/Compiled/Vertex/" + shaderName + "_vert" + ".spv"

# Call into the actual compiler to compile this shader 
# (".../glslc.exe" is an example placeholder path)
subprocess.run([".../glslc.exe", shaderPath, "-o", compiledPath])

# Write out reflection data based on the shader contents

I also created a ‘CompileAll.py‘ script which runs through every shader and compiles them using the script logic above. What is cool is that it actually calls into the individual compilation script using the subprocess system Python has.

import subprocess
import os
from pathlib import Path

def CompileAllInList(pathList):
    for path in pathlist:
        filepath = str(path)
        print(filepath)
        print("\n")
        subprocess.run(["python", "CompileSpecific.py", filepath])
        print("\n")

workingDir = os.getcwd()

print("\n--------------Vertex shaders--------------\n")
filePathToEncode = workingDir + "/Vertex/"
pathlist = Path(filePathToEncode).rglob('*.vert')

CompileAllInList(pathlist)

print("\n--------------Fragment shaders--------------\n")
filePathToEncode = workingDir + "/Fragment/"
pathlist = Path(filePathToEncode).rglob('*.frag')

CompileAllInList(pathlist)

print("\n--------------Compute shaders--------------\n")
filePathToEncode = workingDir + "/Compute/"
pathlist = Path(filePathToEncode).rglob('*.comp')

CompileAllInList(pathlist)

The aim of making these scripts was to simplify and speed up the process overall. As without them I would have had to manually run the compiler with the exact inputs typed by hand every time, and then create the reflection data by hand as well. (A further explanation of my shader reflection system is planned for a later blog post)

Lua

Well known for being the language that Roblox exposes for allowing its players to use for game creation, Lua is a fair bit different to Python.

The key part to Lua that I am aware of is its ability to call C functions in another program with very little setup required. Due to this it has the ability to drive NPC and intractable objects logic, as well as pre-determined flows, such as animations or cut-scenes. There are a couple of reasons behind why a scripting language would be used for flow control instead of a compiled language such as C++ or C. Firstly, it has a much lower programming skill-level required to start then compiled languages. So, peoples who’s job it is to create game-play and interactions (aka designers) will be able to do so without learning much new. Secondly, as the scripts are not compiled, they can be changed without re-building the project and relaunching to the same point in the game (which can take a looooooong time). They may even be able to be changed whilst the game is running for instant updates.

I have Lua integrated into my engine and have plans for creating a post detailing how the process works, as well as some examples of how I have used its power to control in-game events. (But before I can do that I need to actually use it to drive some events first :D )

Powershell

Powershell is Microsoft’s shell level scripting language. (Or at least it was, it is now open-source and cross-platform) Personally I have very little experience using it, and a very small fraction of that time was enjoyable. But, if you are familiar with Powershell, then it is a valid option for creating small scripts to aid in games development through tooling.

Here is an example of a basic powershell script to show the syntax differences (taken from the Microsoft docs):

$x = 2; $y = 3
Get-Power $x $y

function Get-Power([int]$x, [int]$y)
{
    if ($y -gt 0) { return $x * (Get-Power $x (--$y)) }
    else          { return 1 }
}

As you can see from the script, the syntax is a lot more intense than the previous languages. But it does provide the same functionality as Python, for example.

Conclusion

To conclude, this blog post has covered what scripting languages are and why they may be used within games development. It then went into detail on a couple of example languages, showing their differences to each other.

Thank you for reading this post! The next one is going to be going back to graphics programming and will be covering the stencil buffer in more detail than I have seen it usually covered. If you wish to be notified when I release the next one then feel free to subscribe to the mailing list. Till next week :D