BACHELOR THESIS

Andrej Ciˇzm´arikˇ

Framework for Development of -like Games

Department of Software and Computer Science Education

Supervisor of the bachelor thesis: Mgr. Jakub Gemrot Study programme: Computer Science Study branch: Programming and Software Systems

Prague 2017 I declare that I carried out this bachelor thesis independently, and only with the cited sources, literature and other professional sources. I understand that my work relates to the rights and obligations under the Act No. 121/2000 Sb., the Copyright Act, as amended, in particular the fact that the Charles University has the right to conclude a license agreement on the use of this work as a school work pursuant to Section 60 subsection 1 of the Copyright Act.

In ...... date ...... signature of the author

i N´azevpr´ace:Framework pro tvorbu her typu tower defense

Autor: Andrej Ciˇzm´arikˇ

Katedra: Katedra softwaru a v´yukyinformatiky

Vedouc´ı bakal´aˇrsk´epr´ace: Mgr. Jakub Gemrot, Katedra softwaru a v´yuky informatiky

Abstrakt: Tower Defense hry s´upopul´arnym subˇz´anromreal-time strategick´ych hier, kde hr´aˇc chr´ani str´aˇzen´y objekt obrann´ymi veˇzami pred n´ajazdmi nepriatel’ov. S´uˇcasn´e Tower Defense hry s´uvˇsak uzavret´e, ˇc´ım znemoˇzˇnuj´u ak´ukol’vek rozˇs´ıritel’nost’ a sk´umaniezdrojov´ehok´odu. Ciel’om pr´aceje preto vytvorit’ multiplatformov´yframework pre tvorbu hier typu Tower Defense spolu s ilustraˇcnouimplement´aciouhry v tomto frameworku. Framework podporuje potrebn´e hern´e objekty: veˇze, jednotky, ako aj interakcie medzi nimi – vˇsetko skriptovatel’n´ev jazyku LUA. Dalejˇ podporuje manipul´acius text´urami, anim´aciami,zvukov´ymiefektami a hern´ymimapami vytvoren´ymiv dostupnom grafickom editore. Uˇz´ıvatel’sk´erozhranie sa navrhuje v deklarat´ıvnom jazyku XAML. Ciel’ pr´acesa podarilo naplnit’ – pomocou vytvoren´ehoframeworku je moˇzn´evyv´ıjat’ Tower Defense hry na platforme Windows a Android.

Kl´ıˇcov´aslova: framework, v´yvoj poˇc´ıtaˇcov´ych her, Tower Defense

Title: Framework for Development of Tower Defense-like Games

Author: Andrej Ciˇzm´arikˇ

Department: Department of Software and Computer Science Education

Supervisor: Mgr. Jakub Gemrot, Department of Software and Computer Science Education

Abstract: Tower Defense is a popular subgenre or real-time strategy, where the player guards an object by building defending towers against raiding enemy units. Current Tower Defense games have, however, closed source code which completely prevents any possibility to extend these games or study their code. Due to this fact the aim of this thesis is to develop a multi-platform framework for development of Tower Defense games together with an illustrative example game created using the framework. Framework supports game objects: towers, units and interactions between them – all scriptable in scripting language LUA. Framework also supports textures, animations, sound effects and game maps created using an available graphical editor. User interface is designed using declarative language XAML. In the result we fulfilled the aim of the thesis – using the created framework users can develop Tower Defense games for platforms Windows and Android.

Keywords: framework, video games development, Tower Defense

ii I would like to thank my supervisor, Mgr. Jakub Gemrot, for his patient guidance and valuable advice he has provided during my work on this thesis. I am also very grateful for the support my family provided not only during the work on this thesis but throughout my whole bachelor studies.

iii Contents

Introduction 3

1 Problem analysis 5 1.1 Tower Defense definition ...... 5 1.2 Game mechanics in Tower Defense ...... 6 1.3 Our definition for Tower Defense-like ...... 8 1.3.1 Supported mechanics ...... 8 1.4 User interface layouts ...... 9 1.5 Creating and representing maps ...... 9 1.6 Framework requirements ...... 10 1.6.1 Pluggable design ...... 10 1.6.2 Target platforms ...... 10 1.6.3 Third party libraries ...... 11 1.6.4 Graphics library ...... 11 1.6.5 User interface library ...... 12 1.6.6 LUA interpretter library ...... 13 1.7 Supported features ...... 13

2 User documentation 15 2.1 Target audience ...... 15 2.2 Creating a new game ...... 15 2.3 Content Pipeline ...... 17 2.4 Adding graphics and sounds ...... 18 2.5 Adding unit animations ...... 18 2.6 Adding visual effects ...... 19 2.7 Adding units ...... 19 2.8 Adding towers ...... 20 2.9 Adding game actions ...... 21 2.10 Scripting support ...... 22 2.10.1 Debugging embedded scripts ...... 22 2.11 Scripting game entities ...... 23 2.12 Scripting units ...... 25 2.13 Scripting towers ...... 28 2.14 Scripting game actions ...... 30 2.15 Registering for scripting ...... 31 2.16 Adding upgrades ...... 32 2.17 Adding maps ...... 32 2.18 Adding levels ...... 34 2.19 Adding sounds ...... 36 2.20 Adding custom fonts ...... 36 2.21 Adding user interface screens ...... 37 2.21.1 Visual Studio designer tool ...... 39 2.22 Example game ...... 39 2.22.1 User interface in the example game ...... 41

1 3 Development documentation 43 3.1 Development tools ...... 43 3.2 Top-down solution design ...... 43 3.2.1 Solution structure ...... 43 3.2.2 Model-view-viewmodel pattern ...... 44 3.3 Overview of the solution architecture ...... 44 3.4 Game real-time progression ...... 45 3.4.1 Timestep modes in MonoGame ...... 45 3.4.2 Game loop in MonoGame ...... 46 3.5 Framework initialization phase ...... 47 3.6 Framework gameplay phase ...... 48 3.7 The main framework projects ...... 49 3.7.1 Game objects component ...... 50 3.7.2 Input/Output component ...... 52 3.7.3 Data and Persistent storage component ...... 54 3.7.4 Sound system component ...... 54 3.7.5 Spritesheet packing component ...... 55 3.7.6 Level state, Game events and World component ...... 55 3.7.7 User interface and other framework components ...... 57 3.7.8 Custom file format ...... 58 3.7.9 Scripting environment ...... 59 3.8 UserInterface.csproj ...... 60 3.9 GameUILibrary.csproj ...... 60 3.10 MapDataExtractor utility ...... 62 3.11 Expanding the project ...... 63

Conclusion 65

Bibliography 67

List of Figures 70

Attachments 71 A Framework solution and documentation ...... 71 B MapDataExtractor utility solution ...... 71 C Compiling and running framework ...... 71 D Licenses ...... 71

2 Introduction

Tower Defense (TD) is a popular real-time strategy game subgenre, focusing on correct tower positioning and resource management. The main objective is to defend an object against raiding enemy units. TD games are played on maps with one or more paths leading to the guarded object. Players can then build defending towers alongside the paths to destroy and obstruct enemy units from reaching the object. TD games are usually level-based, meaning that players need to successfully finish previous levels in order to unlock harder ones. While TD games have been quite popular over the past years, there are rarely seen solutions which present tools specifically designed to simplify the development of TD games. There are some open-source real-time strategy games [1], however, these games do not serve as a tool and thus can not be directly used to create new games. Even though many successful implementations of TD games already exist, for instance, Kingdom Rush [2], Bloons TD [3] or Plants vs Zombies [4] their source code is closed. This fact completely prevents the possibility of code studying or extending these games. Majority of current game frameworks (e.g., [5], MonoGame [6], Unreal Engine 4 [7] present complex solutions containing many unnecessary features for the development of TD games. Furthermore, many subsystems and game objects, which are actually needed for the development, are not implemented. As a result of mentioned reasons, the goal of this thesis is to design and implement a 2D framework for the development of TD-like games. An integral part of the thesis is implementation of an illustrative game created using the framework as a proof of concept. The framework together with the game provide a decent starting point for creating an easily extendable and multi-platform game.

Project goals

In this section we will list our goals that we aim to fulfill in this thesis.

(G1) Easy way of defining game objects and adding content By simple to use, we mean the user is not required to be a programmer. Game objects should be defined by modifying game files, instead of writing source code.

(G2) Maps The project should support an intuitive way of creating game maps. By intuitive we mean making use of a graphical editor, rather than forcing the user to define complex maps using text files.

(G3) Pluggable design In order to avoid recompiling whole project every time something is changed, we intend to provide a solution relying on the pluggability.

3 (G4) Support for replays The players should be offered with an option to save the replay of the current level. This feature simplifies the process of generating gameplay videos.

(G5) Multi-platform By multi-platform we mean that the project should support development for at least two different platforms.

(G6) Tutorials Publishing a framework without illustrative tutorials may result in discouraging many potential users. Therefore, this thesis should provide easy-to-follow tutorials, showing users how to create their own games.

(G7) Example game As a proof of concept, but also to showcase the features of the framework, a simple TD game should be implemented.

Structure of this thesis

In the first chapter we will analyze the TD genre, focusing on the key concepts and game mechanics found in some popular TD games. We analyze possible approaches for implementation of our framework and establish more specific goals which have to be met during the development. User documentation, consisting mainly of illustrative tutorials is contained in the second chapter. This serves as the starting point for users that want to create their own TD game mostly by modifying the example game. The tutorials illustrate how to configure our framework in order to create games. The third chapter is dedicated to the development documentation of our framework – this part is about implementation in C# programming language. The documentation provides information about the solution design, its architecture and description of the key components with their implementation. Finally we discuss the results of the thesis and mention possible options for future work.

4 1. Problem analysis

We start this chapter by further describing TD genre together with game mechanics in some popular TD games. From this summary we continue by defining what has to be supported in our framework. Later on we discuss different possibilities of designing and implementing some parts of the framework.

1.1 Tower Defense definition

TD as a subgenre of real-time strategy, usually does not progress in turns. This means that continuous time progression is an important aspect of many TD games. TD games are played on maps with one or multiple paths as well as some places to build towers. Enemy units use these paths in order to reach the guarded object. An example of a non-trivial system of paths can be seen in the Figure 1.1.

First path

End of paths

Level status

Second path

Towers

Friendly units

Special powers

Map entrance with enemy units

Figure 1.1: One of levels from Kingdom Rush. Enemy units are raiding from the entrance at the bottom of the screen, trying to reach the path’s end at the top. Source: https:// www.kingdomrush.com/

The most essential part in TD games is building defending towers. Players can usually choose from multiple types of towers to build, where each of them

5 can be better for a different situation. While some towers are totally ineffective against some units, they can be really strong against others. This fact enforces the use of appropriate towers for a given situation as well as taking an advantage of correct tower positioning. The main objective in TD games is then to eliminate all units or, in case of an infinite level, withstand as long as possible. Level-based design ofmostTD games provide further possibilities to present more features, such as upgrades persistent through levels or integrating a storyline.

1.2 Game mechanics in Tower Defense

For this analysis we decided to choose some of the popular TD games, based on the total number of downloads on Store [8]. We decided to choose following games: Kingdom Rush, Plants vs Zombies and Bloons TD. Each of the chosen games, at the time of writing this thesis, has at least one million down- loads.

Health points: When players are unable to stop an unit from reaching the guarded object, some of the health points are lost. This mechanic was present in every analyzed game for tracking the win-condition.

Resources: In all analyzed games the resources can be used to perform var- ious tasks, for example, building a tower, upgrading a tower or using a special power. Players gain resources after destroying an enemy unit. The amount of gained resources corresponds to the enemy difficulty. Additionally, Plants vs Zombies offers towers which generate resources over time.

Unit types: The games deploy various unit types. Besides graphical appear- ance, units may differ in their properties but also perform different actions. This ensures that the game is not monotonous and requires different strategies based on currently attacking units.

Tower types: Similarly, having various unit types, the games provide differ- ent towers as well. Towers are used for automatically attacking raiding enemy units. However, they can perform other actions, such as applying various effects, or generating resources.

Tower upgrades: Whenever players build a basic tower, they might be of- fered with an option to upgrade it. These upgrades are active only for the duration of the current level. This can be seen in Kingdom Rush and Bloons TD.

Persistent upgrades: Persistent upgrades after purchasing usually remain active for the rest of the game, which means they are active for more than a single level. The games we analyzed implement upgrades as technology trees [9].

Tower placement: Some TD games are played on a grid-based map, as seen in the Figure 1.2. This means that each map is divided into tiles where players

6 Towers

Resources Obstacles

Enemy units

Figure 1.2: An example of a grid-based TD game - Plants vs Zombies. The game map is divided into tiles on which can be built towers. The players are able to build certain towers which serve as obstacles. The enemy units are then forced to destroy them as they are blocking their path. Source: http:// www.popcap.com/ build their towers. Other TD games are played on maps with no particular struc- turing and players can place towers only on few designated places. This can be seen in Figure 1.1.

Waves of enemies: Waves serve as an abstraction for multiple enemy units attacking at once. Waves tend to get stronger over time, which is generally achieved by deploying stronger units and attacking from multiple paths.

Friendly units: Concept of friendly units, as seen in Kingdom Rush, turned out to be quite popular. By this mechanic we understand placement of friendly units on a path providing additional obstructions for enemy units. Whenever enemy units get into the range of friendly units they engage in combat.

Time controlling: When designing levels, it is sometimes necessary to leave a brief moment for a player between waves to prepare for upcoming attacks. As we believe that being forced to wait for a game to spawn next wave can be con- sidered annoying, players should be provided with an option to skip this time.

Obstacles: In certain TD games it is possible to place towers in such a way that they create obstacles for enemy unit. This usually results in the enemy units

7 being forced to either destroy the tower, as seen in Plants vs Zombies, or to take detours. This kind of TD games are usually played on grid-based maps.

Paths: Some TD games contain maps having only one path. Other TD games like Kingdom Rush provide multiple entrances and paths for enemy units to choose from. These paths at some point usually join into one path which con- tains defending object at its end.

Special powers: In some TD games players can further interact with the world by using special powers. The special powers can be various actions and spells for players to use on either friendly or enemy entities. This mechanic can be seen in multiple TD games, for example, in Kingdom Rush and Bloons TD.

1.3 Our definition for Tower Defense-like

To describe what should be supported in our framework, we are going to evaluate the described game mechanics. This will give us a better example on what should be supported regarding the TD genre.

1.3.1 Supported mechanics To create a good TD framework, it would be very convenient to support all mechanics found in popular TD games. However, this decision would result in our topic being too broad to reasonably cover in this thesis. Therefore, according to the previous game mechanics descriptions, we are setting the requirements on our framework as follows:

Health points and resources: Our framework has support for health points to track win-condition. It also supports at least one basic resource.

Unit and tower types: Our framework has an easy-to-use option to define new game objects including units and towers.

Tower and persistent upgrades: Similarly, to defining new objects, users can define upgrades of towers. Our framework provides support for persistent upgrades between levels.

Tower placement and paths: Our framework supports maps with multiple paths, entrances and exits. Towers can be placed only on designated places.

Special powers and friendly units: Our framework supports associating actions with user interface controls, this can be used to implement special pow- ers. Friendly units can be spawned by towers, behaving as described in section 1.2.

Waves of enemies: Our framework has an option when defining levels to split events into waves.

8 Time controlling: Our framework has an option to skip to next event or wave.

Obstacles, in a way they are described, will not be supported by our framework. All paths are static and do not change during any level.

1.4 User interface layouts

Based on characteristics of TD games, we are going to describe possible user interface layouts. The aim of this analysis is to provide better API to interact with user interface and integrate these constructs into the example game.

Main menu: Almost every game requires at least a simple main menu. These screens usually contain multiple buttons – each of them can take us to a different screen or perform certain actions.

Level selection: We already mentioned that majority of TD games are level- based. Therefore our framework should provide API to support operations, such as mark a level, show next or show previous levels.

Heads-up display: During a level players should be able to access most of the user interface controls from the same screen they are playing on. This requires the framework to be able to show user interface screens as an overlay over the actual game.

In-game menu: An useful construct for creating, for example, a pause menu can be an in-game menu. This can be either fully visible menu or hidden until a specific event occurs.

1.5 Creating and representing maps

We already defined that games created using our framework are played on maps with no particular partitioning. Therefore there may be multiple roads, each having its own entrance and exit. Towers can be placed only on designated places and may spawn additional friendly units.

Paths: Each path can be represented as an ordered list of waypoints, where each waypoint is a point in two-dimensional space. Starting from the entrance in a way that each two points with neighbouring indexes form an edge in the path.

Towers The places designated to build towers on as well as spawnpoints can be represented as points in two-dimensional space. The connection between a spawnpoint and a tower can be represented as an edge between these points.

From this analysis we can clearly see that the map representation is really simple. To keep the creation process of maps simple as well, we can let users draw maps – to embed the data directly into map textures.

9 We still need to solve the transformation process into the described representation. This might be hard to achieve if we allowed users to use raster graphics. However vector graphics seems to be a suitable solution because the map data can be easily extracted when using one of the popular formats, for example SVG [10]. As stated in goal (G2) we need to provide a graphical editor and since we want vector graphics we could generally use any editor capable to work with vector graphics. However we believe that InkScape [11] is one of the most popular editors and therefore the users might be familiar with this software. Users can then draw paths, places to build towers and spawnpoints using certain primitives provided by InkScape. Our framework should provide a simple tool which is responsible of transforming the data from vector graphics into the described representation.

1.6 Framework requirements

In this section, we will discuss third party libraries, which we need for certain tasks during framework implementation. Regarding graphics capabilities of our framework, we are only going to implement support for 2D graphics. Creating 3D models and textures requires additional tools and certainly more time compared to 2D graphics. To keep the framework simple to use, we are going to be working with 2D graphics only.

1.6.1 Pluggable design We need to represent behaviors of entities and actions between them. Furthermore, apart from the correct representation, we need to make this plugable so that when altering behaviors we do not need to recompile the whole project. For this type of behavior representation we considered two following options:

• Behavior definition in a markup language [12]

• Integrating scripting language [13]

As we intend to provide more flexible solution, where the user is not limited by given document structure, we decided to integrate an existing scripting language. Using this solution the user is able to store object states as well as use advanced flow control structures. We decided to choose LUA [14] because we believe it’s one of the most used scripting languages for game development. Therefore this approach should be appealing for many game developers.

1.6.2 Target platforms We decided to support development for platforms Windows and Android. While Windows being the most popular platform on desktops and Android the most popular platform for mobile devices, we believe that this way our framework can target most of the current devices.

10 1.6.3 Third party libraries The next thing we need to do is to choose additional third party libraries. As implementing various technical solutions, e.g., graphics and sound libraries, UI library and LUA scripts interpreter, would be topic on their own. Due to this fact we need to choose libraries for the following aspects:

• Displaying of real-time 2D graphics and sound playback capabilities

• Creation and integrating of user interface

• LUA scripts interpreter

In addition, each chosen library needs to be multi-platform so that games created by our framework will not be limited to a single platform as well. The minimum requirement is that they support at least development for Windows and Android.

1.6.4 Graphics library The first step is to find a graphical library. This decision is going to narrowour options regarding other libraries and tools used during the development. Apart from already mentioned requirements we also need:

• Game loop [15] support

• Sprite batch operations support

• User interface support

• Good documentation and tutorials available

SharpDX [16] is an open-source MIT licensed .NET wrapper of DirectX [17]. This library provides low-level API for development on platforms with DirectX support. This fact is quite limiting because Android does not support DirectX.

OpenTK [18] is an open-source MIT/X11 licensed .NET wrapper of OpenGL [19]. Similarly to SharpDX this library provides low-level API for development on platforms with OpenGL support. In addition this library provides support for game window, which implements game loop pattern and few other useful features for game development.

MonoGame is an open-source Microsoft Public licensed game framework. This library serves as a wrapper under the same API for both DirectX and OpenGL [19] – thus gaining the ability to switch the underlaying technology at any time based on the targeted platform. The framework implements inter- face of discontinued framework XNA [20] which makes it possible to also use some tutorials and examples created for XNA. The support for game development is broader compared to the libraries above, for example, support for fonts, media player and a tool for managing content.

11 Unity is a proprietary licensed . Similarly to other game engines (e.g., Unreal Engine 4, Wave Engine [21]), Unity provides a complex solution with various tools, features and editors. Despite the many advantages of game engines, using any of them would result in unnecessarily complicated and bloated solution which is not intended, as we are creating a rather simple framework.

SharpDX OpenTK MonoGame Unity Sprite batch operations Audio support Game loop support User interface - - - Pluggable design - - - - Documentation, examples Limited Limited Windows platform Android platform - License MIT MIT/X11 MS Public Proprietary

Even though Unity seems to fit our requirements better than other described alternatives, its license is rather limiting for us – the terms of use may possibly change during the development and its source code is closed. Therefore the use of this library could have a negative impact on our framework. Due to these reasons we decided to choose MonoGame library. The decision determined us to use .NET framework for the further development, more specifically we are going to implement the framework in C# programming language. We can still ensure Android support using Xamarin’s Mono compiler [22]. In the following two sections we will describe possible additional libraries to provide the support for user interface and pluggable design because these two features are not supported by MonoGame itself.

1.6.5 User interface library Choosing a library for user interface turned out to be quite challenging. Due to the fact that there are few libraries suitable for our framework we could not meet all our requirements. Let us list the requirements first:

• Support for controls needed in game development (image button, heads up display etc..)

• Support for scaling according to device’s DPI [23]

• Good documentation and tutorials available

GeonBit.UI [24] is an open-source MIT licensed library. The library provides an interesting solution for creating user interface together with an illustrative tu- torial on how to use the library. However, at the time of writing this thesis, there is not an official support for Android or touch-screen devices in general.

EmptyKeys [25] is a MIT licensed library with some parts being open-source. The library supports development for multiple platforms including Windows and

12 Android. User interface is written in XAML [26] without code-behind support and thus relying on MVVM pattern [27]. Being heavily inspired by WPF, many constructs and components are implemented in a similar manner. However, the library lacks more advanced tutorials and examples on how to properly use the library. Despite the disadvantage, at the time of writing this thesis, EmptyKeys was certainly the best available library for this task.

1.6.6 LUA interpretter library In this section we will briefly discuss options for LUA scripts interpretter on .NET platform. Our requirements on this library are as follows: • Support for most LUA constructs • Possibility to debug embedded scripts in our framework • Good documentation and tutorials available NLua [28] is an MIT licensed library. Even though the library seems to provide working solution for our framework, there is only one available tutorial on how to use it. API for debugging of embedded scripts is present, however it seems to be very limited – certainly not providing an out-of-box working solution.

MoonSharp [29] is an open-source BSD licensed library. This library tries to provide almost the same support as defined in LUA 5.2 language definition [30]. Together with numerous tutorials found on the website and possibility to debug embedded scripts using installed addon to Visual Studio Code [31], this library fits our requirements.

1.7 Supported features

This section provides an overview of the high-level features which will be sup- ported by our framework. This overview had later an impact on the architecture of our project as well as on its implementation. Having already established our project goals, we will link the goals (G1) to (G5) with their realization in our framework.

(S1) Easy way of defining game objects: From the goal (G1), we know that an easy way to define game objects is required. All game objects are defined using textual game data files. (S2) Adding content: Content supported by MonoGame is managed using its utility called Pipeline tool. (S3) Editor for maps: To fulfill the goal (G2), maps for our framework can be created using a third party software called InkScape. The program is a freeware distributed under the GNU General Public License. Users can define paths, places to build towers and spawnpoints for friendly units using only the basic primitives. For better maintenance of the map data files, it is possible to split the map definition into multiple files.

13 (S4) Scripting support: Pluggable design as defined in the goal (G3) is achieved with scripting. Our framework provides scripting interfaces with high-level API for easier implementation of the behaviors for units, towers and game actions.

(S5) Sounds support: From within the scripting environment it is possible to play sound effects. Our framework implements a sound system capable of tracking information about played sounds.

(S6) Spritesheets packing: To ensure better performance for drawing, all graphics content needed for the current level is packed into one or multiple bigger textures.

(S7) Animations support: Our framework supports animating units. Anima- tions support can be significantly extended with visual effects which provide more advanced API for animations. Games created using our framework are graphical 2D games represented using bitmaps. Because of this fact we use spritesheets for animations. Spine animations are not supported because we neither have many nor complex animations. One of the reasons is also the fact that good spine animation tools are generally not distributed under a free license.

(S8) Visual effects support: Visual effects are basically more advanced animations, providing the feature to fix to a game entity. The animation is then drawn over the game entity and it changes its drawing position according to the position of the game entity.

(S9) Persistent upgrades: Users are able to define persistent upgrades similar to other game objects. Combined with the replays feature we also need to track used upgrades for each replay in order to be able to display the saved gameplay correctly.

(S10) Graphical user interface support: Users are able to create graphical user interface for our framework to be able to interact with players.

(S11) Support for replays: Replays are required by the goal (G4) to provide an easier way to generate gameplay videos.

(S12) Development for Android and Windows: We know that according to the goal (G5) our framework needs to support the development for at least two different platforms. As we already mentioned our framework supports building games for both Windows and Android platform.

14 2. User documentation

This chapter is mostly dedicated to tutorials on how to correctly use our framework. The tutorials are illustrated on the example game created as a part of this thesis.

2.1 Target audience

We expect the users, in order to be able to fully use our framework, to be familiar with following tasks:

• Working with textual files – editing using pre-defined templates

• Working with bitmap and vector graphics

• Scripting in LUA

• optional: Programming using C#

While programming in C# is not required, it is certainly helpful to understand at least basic concepts as the scripting API as well as our framework is implemented in this language.

2.2 Creating a new game

The architecture of our framework expects the user to copy the whole solution inside his workspace before starting to work on a new game . Information about the solution can be found in the attachment A. This section is then going to serve as a guide providing information on how to configure the framework in order to create a new game.

Now let us have a look at the Figure 1.1 from the first chapter again. Using the same figure, which displays a level from the game Kingdom Rush, weare going to illustrate the motivation for individual tutorials in this chapter. It is also important to mention that the tutorials were inspired by the same game. The process itself can be split into a few tasks. While it is generally possible to perform these tasks in an arbitrary order, it is necessary to reference only already defined and added game objects. Referencing undefined or not correctly added objects will result in errors. We are also going to link the high-level features defined in the section 1.7 with their corresponding tutorials, which describe how to use these features.

Adding units and towers: Each unit and tower after their successful definition can be used repeatedly in every level. The exact approach onhow to define them can be seen in the section 2.7 for units and in the section 2.8for towers. In the tutorials above we cover the process of adding certain game objects in a way described in the framework’s feature (S1). However, this also applies for

15 other game objects like levels, game actions, visual effects and upgrades which will be covered in other tutorials.

Adding maps: Each map consists of two files – one of the files is the actual texture we want to draw on the screen, while the other file contains information about paths, places to build towers and spawnpoints. In the section 2.17 we can see the step-by-step solution on how to create maps. Exactly as defined in the feature (S3) our framework expects the maps tobe created using an editor with graphical user interface called Inkscape.

Adding levels: Each level must have its associated definition file which defines various information about the level. However, the most important part is its list of timed events, which are executed on their time of occurrence. A tutorial dedicated to creating levels with an example can be found in the section 2.18. Based on the information provided about each level, our framework builds spritesheets out of required textures. This is an automatic process which ensures better performance of graphics card and covers the framework’s feature (S6).

Adding game actions: Game actions can be added in a way described in the section 2.9. They provide a way to define various interactions between mul- tiple game entities or player and game entities.

Scripting: To implement new game mechanics and behaviors for game entities we use scripting. Scripting API overview for game entities can be seen in section 2.11. More specific API with scripts examples can be seen in section 2.12 for units and in section 2.13 for towers. Regarding scripting for game actions we can refer to the section 2.14. In the tutorials mentioned above we covered the framework’s feature (S4) about scripting support. Some additional information is also provided in the next part about registering certain objects for scripting.

Registering for scripting: This is an important but very straight-forward process of making game objects, sounds and visual effects available for the script- ing environment. The exact steps can be found in the section 2.15.

Adding graphics, sounds and fonts: All graphics, sounds and fonts are managed by the Pipeline tool provided by MonoGame framework.. An exact approach on how to correctly add content to our framework is documented in section 2.4. Moreover for performance reasons MonoGame requires additional information about fonts which can be generated as seen in section 2.20. These tutorials cover the feature (S2) about adding content, as well as the feature (S5) about the sound support. API regarding the sound support is cov- ered in tutorials about scripting.

Adding animations and visual effects: Each animation is only a sequence of frames. Visual effect is then more advanced animation, which provides additional API for scripting – like timing or fixing on a position. Adding this into framework is described in the section 2.5 for animations and in the section

16 2.6 for visual effects. Therefore this covers the feature (S7) about bitmap animations for game enti- ties and the feature (S8), which requires visual effects with broader options than basic animations.

Adding upgrades: Upgrades are basically binary flags. Their state is accessible within the scripting interface which makes it possible to use upgrades when writing behaviors for game entities. The process of working with upgrades is described in the section 2.16. As upgrades are ensured by our framework to be persistent, this tutorial cov- ers the feature (S9) about persistent upgrades.

Creating user interface: Users can create user interface screens using the Designer tool provided by Visual Studio. The process of their implementation is described in the section 2.21. This basically covers the framework’s feature (S10) regarding graphical user interface support.

Replays are handled automatically – framework tracks needed events and saves them on player’s demand. GameService implements all necessary methods to provide view-model with capabilities to work with replays. This covers the framework’s feature (S11). When the game is ready to be built, as stated in the feature (S12), we can build the game for both platforms Windows and Android. The exact approach on how to compile solution and build for both mentioned platforms is covered in the attachment C of this thesis.

2.3 Content Pipeline

For managing content we use a tool provided by MonoGame framework - Pipeline tool. Added content must follow the predefined folder structure. This means that all graphics content is in the folder sprites, all fonts are in the folder fonts and all audio is in the folder sounds. Pipeline tool then compiles all the content into the custom XNB format [32]. Built content can be referenced in our framework. These are currently supported file formats for building:

• Graphics: .bmp, .dds, .dib, .hdr, .jpg, .pfm, .png, .ppm, .tga

• Audio: .xap, .wma, .mp3, .wav

• Fonts: .spritefont

If the supported formats are for some reason not satisfiable, there is an option to implement custom content processors to expand the Pipeline tool. However, it is advised to primarily use lossless file formats to avoid possible artefacts which may arise during the build process.

17 2.4 Adding graphics and sounds

Graphics and sounds are added into our framework using the previously described Pipeline tool. After the content is either copied or linked to Pipeline tool, we choose the Build option from the menu. After the build process is finished the content is ready to use in our framework.

2.5 Adding unit animations

Animations are added to framework as separate frames in the same way as any other graphics content. Frames of an animation, in order to be identified, need to have consistent filenames. Filenames of the frames have to consist ofa prefix which is common for all frames and an index number. The index numberis a formatted integer to 4 digits with leading zeros. The first frame has the index number equal to 0 and is growing with more frames. An example of adding a new animation can be seen in the Figure 2.1.

# ------# This file contains definition for animations | # (name) - [string] unit name | # (animation_type) - [string] animation type | # (frames_prefix) - [string] common prefix for all frames | # (frames_count) - [integer] count of all frames | # | # Template for definition: | # (name);(animation_type);(frames_prefix);(frames_count) | # ------knight;GOING_UP;knight_run_n;8

Figure 2.1: Example of file animations.tas

In the presented example we can see the definition of an animation for the unit with name knight. The animation type is set to GOING UP. Common prefix for filenames of frames is knight run n and the total count of all frames is 8. The filenames which match the definition from the example are following: knight run n0000, knight run n0001, knight run n0002, knight run n0003, knight run n0004, knight run n0005, knight run n0006, knight run n0007

Framework has some hard-coded animation types, which are automatically switched based on given context. This does not affect, however, visual effects which are basically unlimited. The supported animation types for units are the following ones:

GOING UP, GOING DOWN, GOING LEFT, GOING RIGHT CASTING UP, CASTING DOWN, CASTING LEFT, CASTING RIGHT

18 ATTACKING UP, ATTACKING DOWN, ATTACKING LEFT, ATTACKING RIGHT

2.6 Adding visual effects

Visual effects are added in a similar way compared to the animations. Toadd a visual effects for later use in our framework, we need to add their definition to the file effects.tas, one visual effect per line. An example of the file can beseen in the Figure 2.2.

# ------# This file contains definition for effects | # (name) - [string] unique name of the effect | # (frames_prefix) - [string] common prefix for all frames | # (frames_count) - [int] count of frames | # | # Template for definition: | # (name);(frame_prefix);(frame_count) | # ------fxFireball;fireball;20

Figure 2.2: Example of file effects.tas

In this example we can see the definition of a new effect with name fxFireball. Filenames of frames have the same common prefix of fireball with the total count of 20 frames. The process of fixing on a game entity and modifying timing is resolved within the scripting environment which is covered in tutorials about scripting.

2.7 Adding units

For the framework to know which units are present in the game, we need to define them first. Units are defined in thefile troops.tas, one unit per line. An example of the file with a unit definition can be seen in the Figure 2.3. In the presented example we defined a new unit with name knight. This unit has 20 hitpoints and can travel at the speed of 15 pixels a second – this is mea- sured in the rendering resolution because in the result everything is scaled based on the actual presentation resolution. When this unit is killed players receives 10 resources. This unit is down-scaled to 0.6 of its original size.

The next step is to associate our unit with graphics content. To achieve this we add animations for the new unit as we previously described. Every unit does not need to have associated all animation types, only those which are later used in its script.

The last step to create an unit is to write its LUA script. The name of the script is same as unit’s name. The exact approach on how to write scripts will

19 # ------# This file contains definition and basic attributes for units | # (name) - [string] unique name of the unit | # (hitpoints) - [integer] representing health of the unit | # (speed) - [integer] determines speed of the unit | # (reward) - [integer] reward for killing unit | # (size) - [float] scale of units (default = 1.0) | # (party) - [string] affiliation: FRIENDLY or ENEMY | # | # Template for definition: | # (name);(hitpoints);(speed);(reward);(size);(party) | # ------knight;20;15;10;0.6;ENEMY

Figure 2.3: Example of file troop.tas be described in the section 2.11.

2.8 Adding towers

All towers in order to be registered by our framework need to be first defined in the file towers.tas, one tower per line. An example of the file with definitions of two towers can be seen in the Figure 2.4.

# ------# This file contains definition for all towers | # (name) - [string] unique name of the tower | # (cost) - [integer] price of the tower | # (proj) - [string] name of a defined projectile | # (dmg) - [integer] damage dealth by the projectile | # (speed) - [float] speed of the projectile | # (range) - [integer] range at which tower is able to attack | # (cd) - [integer] projectile cooldown in milliseconds | # (upg) - [string] name of a defined tower or NULL | # (ucost) - [integer] cost of the upgrade | # | # Template for definition: | # (name);(cost);(proj);(dmg);(speed);(range);(cd);(upg);(ucost) | # ------tower_1;50;projectile_1;3;400;110;800;tower_2;100 tower_2;250;projectile_1;10;400;150;600;NULL;0

Figure 2.4: Example of file towers.tas

In the presented example we can observe the definition of a tower with name tower 1 which costs 50 resources. Projectile used by the tower is called projectile 1, which deals 3 damage and firing at the speed of 400 pixels per second.

20 The tower can target all enemies in radius of 110 pixels but fire only once per 800 milliseconds. Once again mentioned speed and radius is measured in the rendering resolutions. On the actual device everything is scaled accordingly. This tower can be upgraded to a tower with name tower 2 after supplying 100 resources. In the definition of the tower with name tower 2 we can see that this tower has enhanced some of its properties and can not be further upgraded.

Next thing we need to do is to define projectiles used by the towers and associate the towers and projectiles with graphics content. This is achieved by altering the file staticAssets.tas. An example of this file can be seen on the example in the Figure 2.5. # ------# This file contains information about static assets | # (name) - [string] unique name of the tower | # (tTexture) - [string] filename with tower texture | # (pTexture) - [string] filename with projectile texture | # | # Template for definition: | # (name);(tTexture);(pTexture) | # ------tower_1;towerTexture;projectileTexture

Figure 2.5: Example of file staticAssets.tas

In the example we can see the association of the tower with name tower 1 and a texture with filename towerTexture. As for the displaying of its projectiles, a texture with projectileTexture will be used.

The last step we need to make is to implement LUA script which contains behavior for this tower. The filename of the script is same as the tower’s name. The exact approach on ho to write scripts for game entities will be described in section 2.11.

2.9 Adding game actions

All game action in order to be recognized by our framework need to be first defined in the file actions.tas. An example of this file with definitions of three game actions can be seen in the Figure 2.6. In the presented example we can see the definition of three game actions. We will now further describe the definitions in the example: The first game action with name heal has cooldown time equal to 1500 milliseconds, casting time time equal to 750 milliseconds, can be casted at range 150 pixels. It targets a single unit which needs to be friendly to the game entity casting the spell. In case the game action is used as a special power, the targeted game entity is friendly to the player. The second game action has name fireball. Its cooldown time is 20000 milliseconds and casting time 0 milliseconds. This game action targets multiple

21 # ------# This file contains definition for all actions | # (name) - [string] unique name of the action | # (cd) - [integer] cooldown of the action | # (cast_time) - [integer] time required to perform the action | # (range) - [integer] maximum range to find target of action | # (targetCount) - [string] targets: SINGLE/MULTIPLE/NONE | # (affilation) - [string] who to target: ENEMY/FRIENDLY/NA | # | # (name);(cast_time)(cd);(range);(targetting);(affilation) | # ------heal;1500;750;150;SINGLE;FRIENDLY fireball;20000;0;80;MULTIPLE;ENEMY spawn_guardian;20000;0;0;NONE;NA

Figure 2.6: Example of file action.tas enemy units in radius of 80 points. The last game action has name spawn guardian. Its cooldown time is once again 20000 milliseconds and casting time 0 milliseconds. This game action does not require a target, and therefore has zero range.

Similarly to game units, every game action needs to have its corresponding script. The filename has to be same as the game action name. We will further discuss how to write scripts for game actions in the section 2.14.

2.10 Scripting support

The file globals.lua serves as the main LUA module for scripting. As we previously mentioned, the file contains unique integer addresses for all game objects and sounds. More about this is discussed in the section 2.15. The module can be used in every script created and therefore can be particularly useful for implementing some functions which might be used by multiple scripts. In order to be recognized by our framework, scripts must obey the exact folder structure. All LUA scripts and modules are placed inside the folder scripts. This folder further contains three subfolders troops – where unit scripts are placed, towers – where tower scripts are placed and actions – where game action scripts are placed.

2.10.1 Debugging embedded scripts Embedded LUA scripts can be debugged. However, this feature is only available for platform Windows and the DEBUG directive needs to be defined. To start debugging we need to start Visual Studio Code, which have already installed the addon for debugging as described in the section 3.1. When the framework is running we can attach Visual Studio Code’s remote debugger to our process, which is a feature handled by the installed addon.

22 The remote debugger offers various commands to use when debugging. For the full list of supported commands, see the official page of the addon [31]. We will show the two most important commands. The first is !list which lists all available scripts – an index number and the name of the script on each line. The second is !switch index which sets the current debugged scripts based on the index numbers provided by the first command. Remote debugging supports common debugging tools, for example, break- points, conditional breakpoints, values of local variables and watches.

2.11 Scripting game entities

Our framework requires that scripts for game entities implement three func- tions. The functions have a single argument expecting an IDynamic instance:

OnInit(entity): This function is called only once, exactly when the game entity is about to enter the world. Therefore, this is an useful place to perform initialization of the game entity.

OnUpdate(entity): This function is called everytime the entity is updated by our framework. Due to this fact it is necessary to keep the update function simple, the use of extensive loops and performing unnecessary operations is highly unadvised.

OnDying(entity): This function is necessary for units only. It is called only once, exactly when our framework discovers the unit has died. After this func- tion, the unit is no longer updated.

Now we will discuss common scripting interface for all entities. These meth- ods are implemented by towers as well as units.

To provide support for storing entity’s state, game entities have overloaded operator [], called indexer. To check whether an entity has initialized a variable, we use method HasVariable which return true if the variable was initialized. Even though LUA does not require from programmers to initialize variables, our framework throws a ScriptingException to avoid errors when implementing scripts. DynValue this[int id] { get; set; } bool HasVariable(int id); Variables storage API for game entities Some mechanics may require time measuring. To support timers, our framework implements following methods. SetTimer creates a new timer, StartTimer starts the countdown, IsTimeUp checks whether the time is up and finally ResetTimer resets the timer. void SetTimer(int id, int milliseconds); void StartTimer(int id);

23 bool IsTimeUp(int id); void ResetTimer(int id); Variables storage API for game entities Registering delayed callbacks is also supported by our framework. Using the method AddEvent, it is possible to register an event to an entity’s schedule. When delayed time is over the callback is executed. void AddEvent(int milliseconds, DynValue function, IDynamic target) Delayed callbacks API for game entities For the sounds support, our framework implements following methods. PlaySound tries to play a sound and returns true, if the operation was successful. StopAll stops all sounds on a given level and does not preserve any state of the sounds. PauseAll pauses all sounds on a given level and preserves their state. ContinueAll continues all previously paused sounds on a given level. bool PlaySound(int id, int level); void StopAll(int level); void PauseAll(int level); void ContinueAll(int level); Delayed callbacks API for game entities To check game entity’s state, our framework implements following methods. CanExecute returns true if the game action with provided id can be executed. IsExecuting returns true if a game action is currently being executed. bool CanExecute(int actionId); bool IsExecuting(); Entity state checking API for game entities For executing game actions, we use the method ExecuteAction. void ExecuteAction(int actionId); Game action execution API for game entities To remove all previously targeted entities, we use the method RemoveTargets. void RemoveTargets(); Target removing API for game entities To access information about active upgrades, we use the method IsUpgrade- Active. bool IsUpgradeActive(int upgradeId); API for checking state of upgrades for game entities For visual effects support, our framework implements following methods. ApplyVisualEffectActionTarget and ApplyVisualEffectActionTargets apply the effect either on a single entity targeted by action or multiple entities. ApplyVisualEffectThis applies the visual effect on current entity. The effect then lasts during the given interval in milliseconds.

24 void ApplyVisualEffectActionTarget(int id, int duration ); void ApplyVisualEffectActionTargets(int id, int duration ); void ApplyVisualEffectThis(int id, int duration); Target removing API for game entities Additional displaying options for game entities are implemented using methods SetTransparency and RemoveTransparency affecting the transparency of the entity. void SetTransparency(float value); void RemoveTransparency(); Additional displaying API for game entities Specific scripting interfaces for units and towers together with examples can be seen in corresponding sections, for units in the section 2.12 and for towers in the section 2.13.

2.12 Scripting units

In this section we will describe API for implementing behaviors for units which we will then illustrate on examples.

To control the movement of units, we have two basic methods. ContinueWalk- ing, in case of an enemy unit, makes the unit to follow its path and for friendly units it makes the unit to walk to the spawnpoint. StopWalking makes the unit to stop moving and stays at the current position. void ContinueWalking(); void StopWalking(); Movement API for units To check unit’s state we can use four methods. IsInCombat return true is the unit is in combat with a different unit. CanCombatStrike return true if the unit can strike its combat target. IsPlayers return true if the unit is friendly. bool IsInCombat(); bool CanCombatStrike(int id); bool IsPlayers(); API for checking unit’s state Targetting other units is handled using a few methods. Target method tries to find a single unit based on supplied parameters. TargetAll method is used to target all units in a given range. All targeting methods return true, if at least one suitable target exists. bool Target(int actionId, TargettingModifier modifier); bool TargetAll(int actionId, int maxTargets = int.MaxValue); Targeting API for units

25 To handle unit’s combat, we can use two basic methods. InitiateCombat sets targeted entity as combat target. If the new combat target was not in combat, its combat target is set too. CombatStrike then attacks the combat target. void InitiateCombat(int id); void CombatStrike(int id); Combat API for units Additional unit displaying options are provided by some advanced meth- ods. SpeedUpAnimationSpeed, SlowDownAnimationSpeed and SetDefaultAnima- tionSpeed provide an option to alter the frame rate of animations for the unity. void SpeedUpAnimationSpeed(float multiplier); void SlowDownAnimationSpeed(float multiplier); void SetDefaultAnimationSpeed(); Advanced displaying API for units Additional method for units regarding visual effects support – ApplyVisual- EffectCombatTarget applies visual effect on its combat target. void ApplyVisualEffectCombatTarget(int id, int duration ); Visual effects API for units In the example below, we can see the implementation of an unit. This example can serve as a basic enemy unit’s behavior. local _table = require’globals.lua’; local variables = _table.variables; local actions = _table.actions; local sounds = _table.sounds; function OnInit(entity) end; function OnUpdate(entity) if (entity.IsInCombat()) then entity.StopWalking(); if entity.CanCombatStrike(actions.attack_slow) then entity.PlaySound(sounds.sword_slash, 1); entity.CombatStrike(actions.attack_slow); end; return; end; entity.ContinueWalking(); end; function OnDying(entity) entity.PlaySound(sounds.dying_enemy, 1); end; Example of an enemy unit behavior implementation

26 In the presented example, we can see a slightly modified implementation of an enemy unit called knight from the example game. Its update function consists of checking if the unit is in combat – if yes, it tries to strike its combat target. If the unit is not in combat they follow the path. When the unit dies it plays a sound signalizing its death. local _table = require’globals.lua’; local variables = _table.variables; local actions = _table.actions; local sounds = _table.sounds; function OnInit(entity) end; function OnUpdate(entity) if (entity.IsInCombat()) then if entity.CanCombatStrike(actions.attack_fast) then entity.PlaySound(sounds.axe_slash, 1); entity.CombatStrike(actions.attack_fast); end; return; end; obj.ContinueWalking(); if (entity.CanExecute(actions.eagle_eye)) then if (entity.Target(actions.eagle_eye, targettingModifier.Closest, false)) then entity.InitiateCombat(actions.attack_fast); return; end; end; end; function OnDying(entity) entity.PlaySound(sounds.dying_friendly, 1); end; Example of a friendly unit behavior implementation In the second presented example we can see the behavior of a friendly unit called axeman from the example game. Whenever in combat, this unit tries to strike its combat target with the game action called attack fast. Its method ContinueWalking is overriden to go to the spawnpoint but, in case of combat, it walks towards the combat target. The friendly unit tries to find the closest target for combat using the game action called eagle eye. After a suitable combat target is found it initiates the combat with the game action called attack fast. If this unit dies it plays dying friendly sound.

27 2.13 Scripting towers

Behaviors for towers are implemented in a similar way, compared to units. Once again, we will first describe available API for scripting and then present some examples. Targeting support is a bit different compared to units. Towers have different methods to target units for basic shooting – Target and TargetAll. Methods for targeting regarding game actions – TargetAction and TargetActionAll. All targeting methods return true, if at least one suitable target exists. bool Target(TargettingModifier modifier = TargettingModifier.NA); bool TargetAll(int maxTargets = int.MaxValue); bool TargetAction(int actionId, TargettingModifier modifier = TargettingModifier.NA); bool TargetActionAll(int actionId, int maxTargets = int.MaxValue); Targeting API for towers To check tower’s state and support basic projectile shooting, our framework implements following methods. CanShoot return true if the tower is ready to shoot, based on defined cooldown. Shoot fires a projectile at a targeted unit. ShootMultiple shoots at all targeted units. bool CanShoot(); void Shoot(); void ShootMultiple(); Projectile shooting API for towers Friendly units support is handled using following methods. Method GetSpawnedTroopsCount returns count of the spawned units. SpawnFriendly then spawns units based on given type and count. void SpawnFriendly(int id, int count); int GetSpawnedTroopsCount(); Friendly units support for towers Additional methods to for towers regarding visual effects support are following. ApplyVisualEffectTarget and ApplyVisualEffectTargets apply the effect on a single unit targeted for shooting or multiple units. void ApplyVisualEffectTarget(int id, int duration); void ApplyVisualEffectTargets(int id, int duration); Additional API regarding visual effects for towers An example of a basic behavior for a tower only shooting projectiles at units in range can be seen in the example below: local _table = require’globals.lua’; function OnInit(entity) end;

28 function OnUpdate(entity) if (entity.CanShoot() and entity.Target(targettingModifier.Furthest)) then entity.Shoot(); end; end; Example of a simple tower behavior implementation In the presented example we can see the script of a tower called arrow tower 1 from the example game. This tower simply checks if it can shoot – checks if the ability is not on cooldown and if a suitable target exists. If all conditions are satisfied the tower shoots at the targeted unit. local _table = require’globals.lua’; local actions = _table.actions; local troops = _table.troops; maxSpawned = 2; function OnInit(entity) entity.ExecuteAction(actions.spawn_unit, troops.axeman); entity.ExecuteAction(actions.spawn_unit, troops.axeman); end; function OnUpdate(entity) if ((entity.GetSpawnedTroopsCount() < maxSpawned)) then if (entity.CanExecute(actions.spawn_unit)) then entity.ExecuteAction(actions.spawn_unit, troops.axeman); end; end; end; Example of a different tower behavior In the second presented example we can see the script of a tower called troop tower 1 from the example game. This tower makes use of friendly units game mechanic. The script defines that it can spawn the maximum number of two game entities. The OnInit function executes two times the spawn unit game action. Then during the OnUpdate call it checks if another unit can be spawned. If yes it spawns another, otherwise the tower does nothing.

29 2.14 Scripting game actions

All scripts for game actions have to implement a single method, which will be called by our framework whenever the game action is executed.

Execute(target): The function is expecting an instance of IDynamic as ar- gument. Therefore, all methods are called on this instance and game action itself does not need additional scripting interface. local _table = require’globals.lua’; local variables = _table.variables; local sounds = _table.sounds; local effects = _table.effects; dmgValue = 10; function Execute(target) target.ApplyVisualEffectThis(effects.fxFireball, 5000) ; target.PlaySound(sounds.fireball, 1); target[variables.HP] = target[variables.HP] - dmgValue ; end; Example of a simple game action In the presented example we can see the script of a game action called fireball from the example game. It applies a visual effect with name fxFireball for the duration of 5000 milliseconds on the targeted entity. Then the game action plays a sound effect with name fireball on level 1. The last thing the game action does, is that it subtracts 10 hitpoints from the target’s hitpoints. local _table = require’globals.lua’; local variables = _table.variables; local sounds = _table.sounds; duration = 5000; function effectFade(target) target[variables.frozen] = false; end; function Execute() target.PlaySound(sounds.freeze, 1); target[variables.frozen] = true; target.StopWalking(); target.AddEvent(duration, effectFade, target); end; Example of a different game action

30 In the second presented example for game actions we can see a slightly more advanced game action called freeze from the example game. It plays a sound with name freeze on level 1, sets target’s variable with identifier frozen to true, makes the target entity stop walking and registers a delayed callback. The task of the callback is to destruct the game action effect which means setting the variable with the identifier frozen to false.

2.15 Registering for scripting

When referencing variables, game objects, sounds and upgrades we need to have assigned for each of them their an unique integer identifier. Even though each of the mentioned objects is already assigned an unique name, we do not allow the use of string for such referencing. Such usage of string identifiers would create performance bottlenecks and possible pressure on heap. An example of file globals.lua can be seen in the example below: local globals = { variables = { Alive = 1,-- Boolean[Read/Write] HP = 2,-- Int32[Read/Write] MaxHP = 3,-- Int32[Read/Write] Speed = 4,-- Float[Read/Write] Size = 5,-- Float[Read/Write] Cost = 6,-- Int32[Read/Write] Worth = 7,-- Int32[Read/Write] Cooldown = 8,-- Int32[Read/Write] Damage = 9,-- Int32[Read/Write] Range = 10,-- Int32[Read/Write] }, actions = { fireball = 5006 }, troops = { monk = 6000, knight = 6001 }, towers = { arrow_tower_1 = 7004 }, sounds = { sword_slash = 8000, fireball = 8002 }, effects = { fxHeal = 9000, fxFireball = 9001 }, upgrades = { tough_skin = 10002 } } } Example of registering in globals.lua module In the presented example we can see string identifiers being assigned their unique integer identifiers. Displayed variables Alive all the way to Range are required variables by our framework. It means that they need to stay in the file, however, their integer identifiers may be changed if the user needs such change. During the initialization phase framework loads all addresses and from this time on it refers to all objects only using these addresses. If framework finds an error in the file – two files are assigned the same integer identifier itthrowsa ScriptingException.

31 2.16 Adding upgrades

Each upgrade in order to be recognized need to be first defined in the file upgrades.tas. An example of this file can be seen in the Figure 2.7.

# ------| # This file contains definition for all upgrades | # (name) - [string] unique identifier of the upgrade | # (desc) - [string] description of the upgrade | # (type) - [string] affects: UNITS/TOWERS/SPECIALPOWER | # (dep1) - [string] upgrade dependency 1 | # .... | # (depN) - [string] upgrade dependency N | # | # Template for definition: | # (name);(desc);(type);(dep1),...(depN) | # ------| tough_skin;Gain 20% HP increase;UNITS;NULL tougher_skin;Gain 30% HP increase;UNITS;tough_skin

Figure 2.7: Example of file action.tas

In the presented example we can see the definition of two upgrades. The first with name tough skin has description: Gain 20% HP increase. It affects units and has no dependencies. The second upgrade with name tougher skin has descrip- tion: Gain 30% HP increase. Also affects units and has the previously defined upgrade as a dependency. This means that it can not be activated without the previous one.

From within the scripting environment it is possible to check which upgrades are active. This can be used then to create more advanced behaviors.

2.17 Adding maps

Maps for our framework are created using a third party program called InkScape. In this section, we will describe the process of creating a new game map using the mentioned program.

1. Preparation: Create a new file with the design resolution same asthe rendering resolution of the framework. For the map creation use only tools described below. Delete all layers created and do not add new ones. Layers are not supported.

2. Add a path: Choose the Bezier tool and using this tool draw the path as a polygonal chain, starting from the map entrance all the way to the map’s exit. The path needs to consist of one of more connected line segments only. When the path is finished, we need to assign an unique name to it.To perform this, open the properties of the path and fill the textbox labeled as

32 ID with the path’s name. We will need these identifiers later for the level definitions.

3. Add a towerpoint: Choose the Rectangle tool and set the color to yellow (#FFFF00), which is the default for yellow in InkScape. Now draw a rectangle somewhere on the map – this represents a place where towers can be built. Do not worry about its size because only the information about its position will be extracted.

4. Add a spawnpoint: Choose the Rectangle tool and set the color to red (#FF0000), which is the default for red in InkScape. Now draw a rectangle somewhere on the map. This represents the area to use when spawning friendly units. So when drawing a spawnpoint its area is important.

5. Assign spawnpoint to a towerpoint: Choose the Connector tool. Find the tower and the spawnpoint that need to be assigned. Join them using the selected tool.

Steps 2,3,4 and 5 can be repeated multiple times. An example of a map created in InkScape can be seen in the Figure 2.8. The only constraint is that each towerpoint must have exactly one assigned spawnpoint. When we are finished we save the map as a SVG file. For better clarity this process can be split into multiple SVG files, as drawing many paths into a single file can become unmaintainable. The last thing to do is to extract the information from these files into a better format for processing. This is achieved using the utility called MapDataExtractor.exe. Map data information can be generated using the following command: MapDataExtractor.exe map1.svg map1_pt2.svg Command to extract map data The utility expects all files regarding the same map as arguments from command line. The output of the utility is a single file with the extracted map data. The filename of the output has same prefix as the first argument andis concatenated with navi suffix and .tas extension.

33 Figure 2.8: Example of a created map using program InkScape. The yellow rectangles represent the points where towers can be placed. The red rectangles represent the area where friendly units can be spawned. The connected line segments represent paths.

Finished maps are then placed inside the maps folder of the framework. The SVG files are not needed by our framework anymore, it is sufficient to place thereonly files containing extracted map data information.

2.18 Adding levels

All levels in order to be recognized by our framework need to be first defined in the file levels.tas – each level on a single line. An example of this file can be seen in the Figure 2.9. # ------| # This file contains definitions for levels | # (level_name) - [string] unique name of the level | # (starting_resources) - [integer] starting resources count | # (hitpoints) - [integer] hitpoints for this current level | # (map) - [string] unique name of a map | # | # Example: (level_name);(starting_resources);(hitpoints)(map)| # ------| level1;200;3;map1

Figure 2.9: Example of file levels.tas

34 In the presented example we can see the definition of a level with name level1. The players start the level with 200 resources and have 3 hitpoints for this level.

Level descriptions provide all necessary information for our framework about the current level. This file contains information about the data to load, game events to register and user interface setup. An example of this file can be seen in the Figure 2.10.

# ------| # Template of a level definition: | # filename is texture to load as a background for the level | # BACKGROUND;(filename) | # filename is texture to load as an empty tower point | # FREEPOINT;(filename) | # troop_1 to troop_N are units to load for the current level | # TROOPS;(troop_1);...(troop_N) | # tower_1 to tower_M are towers to load for the current level | # TOWERS;(tower_1);...(tower_M) | # towerIcon_1 to towerIcon_L are icons of tower to load; | # these icons will be loaded into user interface in this order| # ICONS;(towerIcon_1);...(towerIcon_L) | # specialPower_1 to specialPower_J are special power icons | # to load; in this specific order together with corresponding | # game actions gameAction_1 to gameAction_J | # SPECIAL;(SP_1),(gameAction_1);...(SP_J),(gameAction_J) | # | # Game events section define what happens in this level | # (GameEvent_1) | # ... | # (GameEvent_K) | # ------| BACKGROUND;map1 FREEPOINT;action_point TROOPS;monk;knight;axeman TOWERS;troop_1;tower_2 ICONS;troop_1 SPECIAL;specialPower1,fireball

00:00:1.0000000;ANNOUNCEMENT;Welcome adventurer! 00:00:12.0000000;SPAWN;knight;path_0

Figure 2.10: Example of a level definition – file level1.tas

In the presented example, we created the definition of the level with name level1. As a background for current level the texture with filename map1 will be loaded. The texture to display on an empty tower place is called action point. Following units will be loaded: monk, knight, axeman together with following towers: tower 1 and tower 2.

35 In addition, our framework needs to assign user interface buttons according to the definition. We loaded two towers but defined only one tower icon. This means that unless tower 2 is not an upgrade from tower 1, the player will not be able to build this tower. Special powers are defined as pairs. The first item is always its texture name, while the other item is the corresponding game action. In the example we can see that we want to load the texture with name specialPower1 and assign to the game action called fireball. The rest of the file is dedicated to the definition of game events. Intheex- ample above, we can see the definition of two events. The first event is of type ANNOUNCEMENT and after the game time passed 1 second, the message Wel- come adventurer! will be displayed. The second game event is of type SPAWN and its task is to spawn an unit with name knight on a path with name path 0, which will happen after the game time passed 12 seconds.

Each level descriptor needs to be added to the project inside the folder named levels. After all the described steps are completed, the level is available to use in our framework.

2.19 Adding sounds

Adding sounds to framework requires the same process as described in the section 2.4. However, sounds must be listed in the file sounds.tas in order to be available for the scripting environment. An example of the file can be seen in the Figure 2.11.

#------| # This file contains filenames for all sounds | # ------| axe_slash sword_slash fireball freeze

Figure 2.11: Example of file sounds.tas

2.20 Adding custom fonts

Fonts are added into framework using the Pipeline tool. To correctly add a font we need to add .spritefont file and, in case of a non-standard font, .ttf file with the actual font. Example of a spritefont file:

36 Roboto-Regular.ttf 9 0 true * ſ Example of font definition to use in MonoGame Fonts in MonoGame are not loaded in a vector format, and therefore are not scalable. According to the values in the spritefont file, the Pipeline tool renders the font onto a texture. The spritefont file serves as a font descriptor, narrowing the characters which need to be rendered.

As we intend to support various Android devices, we need to load more version of the same font. The framework automatically chooses the font based on the device’s DPI. However, for the framework to locate the fonts, we need to create them as follows: Four spritefont files have to be created. The fonts will have following names: font-ldpi, font-mdpi, font-hdpi and font-xhdpi. Where -ldpi are devices with low DPI and -xhdpi are devices with extra high DPI.

2.21 Adding user interface screens

To create a new user interface screen, we need to add a new XAML Window to the views. It is possible to create it from a template screen presented in the section 3.8. In this section we will try to show some examples on how to imple- ment basic user interface screens.

Using of absolute values when defining sizes and locations of user interface components is discouraged. Not following this advice will result in an user interface which can not be scaled. Instead containers and relative sizes should be used.

37