Developing a Football Game for Android - Markus Huhtamäki - Theseus

Page created by Leslie Rios
 
CONTINUE READING
Developing a Football Game for Android - Markus Huhtamäki - Theseus
Developing a Football Game for
Android

Markus Huhtamäki

BACHELOR’S THESIS
March 2021

Degree Programme in ICT Engineering
Software Engineering
Developing a Football Game for Android - Markus Huhtamäki - Theseus
ABSTRACT

Tampereen ammattikorkeakoulu
Tampere University of Applied Sciences
Degree Programme in ICT Engineering
Software Engineering

HUHTAMÄKI, MARKUS:
Developing a Football Game for Android

Bachelor's thesis 57 pages
March 2021

The objective of this thesis work was to develop a football game for the Android
operating system. The game’s basic concept and its features were first outlined
in a game design plan. In the game the user controls a player and tries to score
goals against an AI-controlled goalkeeper. After considering different options, it
was decided to develop the game without any designated game development
tools. The game was developed using Android Studio with Java. GitHub was used
for version control.

For the game, an architecture with three Android activities, three threads and
several custom classes was created. In-game physics and involving mathematics
were developed for the movement and interaction of objects. A touchscreen-
based controller was developed for moving the player. AI was developed for the
computer-controlled goalkeeper. The original game design plan was successfully
implemented in its entirety. Ideas for further development were also considered.

The project started with only a basic understanding of Android development.
There were many challenges and setbacks on the way that served as great
learning experiences. Besides specific technical knowledge, key takeaways
include a better understanding of how to plan an Android development project,
how to better organize and maintain the codebase, and a better understanding
on what additional value can be achieved by using game development
frameworks.

Key words: Android, game development, Java, touchscreen
Developing a Football Game for Android - Markus Huhtamäki - Theseus
TIIVISTELMÄ

Tampereen ammattikorkeakoulu
Tieto- ja viestintätekniikan tutkinto-ohjelma
Ohjelmistotekniikka

HUHTAMÄKI, MARKUS:
Jalkapallopelin kehittäminen Androidille

Opinnäytetyö 57 sivua
Maaliskuu 2021

Opinnäytetyössä kehitettiin jalkapallopeli Android-käyttöjärjestelmälle. Aluksi
tehtiin pelisuunnitelma, jossa hahmoteltiin pelin idea ja ominaisuudet. Pelissä
käyttäjä ohjaa pelaajaa ja yrittää tehdä maaleja tekoälyn ohjaamaa maalivahtia
vastaan. Eri vaihtoehtojen tutkimisen jälkeen peli päätettiin toteuttaa ilman
varsinaisia pelikehitykseen tarkoitettuja työkaluja. Peli kehitettiin Javalla Android
Studiota käyttäen. Versionhallintaan käytettiin GitHubia.

Peliä varten luotiin kolmesta Android-aktiviteetista, kolmesta säikeestä ja useista
eri luokista muodostuva arkkitehtuuri. Olioiden liikkumista ja keskinäistä
vuorovaikutusta varten kehitettiin pelin sisäistä fysiikkaa sekä siihen liittyvää
matematiikkaa. Pelaajan ohjaamista varten kehitettiin kosketusnäyttöä
hyödyntävä ohjain. Tietokoneen ohjaaman maalivahdin tekoälyä kehitettiin.
Lopulta kaikki alkuperäisestä suunnitelmasta saatiin toteutettua onnistuneesti.
Myös jatkokehitysideoita pohdittiin.

Projektin alkaessa Android-kehityksestä oli tiedossa vain perusasiat. Kehityksen
aikana koettiin monia haasteita ja takaiskuja, jotka toimivat erinomaisina
oppimiskokemuksina. Teknisen tietämyksen karttumisen lisäksi tärkeimpiä
löydöksiä olivat parempi ymmärrys siitä, miten Android-kehitysprojekti kannattaa
suunnitella, miten järjestää ja ylläpitää lähdekoodia ja mitä lisäarvoa
pelikehitystyökaluilla voi saavuttaa.

Asiasanat: Android, pelikehitys, Java, kosketusnäyttö
Developing a Football Game for Android - Markus Huhtamäki - Theseus
4

CONTENTS

1 INTRODUCTION .................................................................................. 7
2 GAME DESIGN PLAN .......................................................................... 8
    2.1 Overview ........................................................................................ 8
    2.2 Controlling the player ..................................................................... 9
    2.3 Adjustable attributes..................................................................... 11
          2.3.1 Outfield player attributes ..................................................... 11
          2.3.2 Goalkeeper attributes ......................................................... 12
    2.4 Rejected alternatives.................................................................... 13
3 ANDROID GAME DEVELOPMENT .................................................... 15
    3.1 Mobile game development ........................................................... 15
    3.2 Android application development ................................................. 16
    3.3 Version control ............................................................................. 18
4 CHOSEN DEVELOPMENT TOOLS ................................................... 19
    4.1 Android Studio.............................................................................. 19
    4.2 Java ............................................................................................. 19
    4.3 Git and GitHub ............................................................................. 20
5 GAME ARCHITECTURE .................................................................... 21
    5.1 Activities and Layouts .................................................................. 21
    5.2 Class Structure............................................................................. 24
    5.3 Threads ........................................................................................ 25
    5.4 Global Functions .......................................................................... 26
          5.4.1 EpicalMath .......................................................................... 27
          5.4.2 Collisions ............................................................................ 28
    5.5 Global Constants.......................................................................... 28
6 GAME PHYSICS................................................................................. 30
    6.1 Time management ....................................................................... 30
    6.2 Dimensions and movement .......................................................... 32
    6.3 Collisions ...................................................................................... 33
          6.3.1 Moving objects with stationary objects ............................... 34
          6.3.2 Ball with outfield player ....................................................... 35
          6.3.3 Ball with goalkeeper ........................................................... 36
          6.3.4 Players with each other ...................................................... 37
7 PLAYER CONTROLS ......................................................................... 38
    7.1 Moving the player ......................................................................... 38
    7.2 Pressing the shoot button ............................................................ 39
    7.3 Releasing the shoot button .......................................................... 41
Developing a Football Game for Android - Markus Huhtamäki - Theseus
5

8 AI ........................................................................................................ 43
    8.1 Positioning ................................................................................... 44
    8.2 Saving .......................................................................................... 46
    8.3 Intercepting .................................................................................. 48
    8.4 Player on autopilot ....................................................................... 49
9 FURTHER DEVELOPMENT ............................................................... 51
10 DISCUSSION ..................................................................................... 53
REFERENCES ........................................................................................ 55
Developing a Football Game for Android - Markus Huhtamäki - Theseus
6

ABBREVIATIONS AND TERMS

AI                   artificial intelligence
Android              an operating system for mobile devices
Android Studio       an integrated development environment for native
                     Android development
Cross-platform       implemented on multiple computing platforms
Game loop            the part of the code that updates the game’s state in
                     short time intervals
Global               accessible from all parts of the code
IDE                  integrated development environment
Java                 an object-oriented programming language
Native development   developing exclusively for a specific platform
Touchscreen          a display that receives input on touch
Version control      the practice of tracking and managing changes to
                     software code
Developing a Football Game for Android - Markus Huhtamäki - Theseus
7

1 INTRODUCTION

In recent years mobile games have become the most popular form of gaming
(Green 2019). With global distribution platforms and an increasing number of free
resources, it is easier than ever to design and publish games for world-wide
markets. With free or low-cost game development tools even independent
developers can create games with good production values in terms of graphics
and features.

The purpose of this thesis is to report the stages and outcome of developing a
football game for the Android operating system. The objective was not to use any
game specific development tools, but to create as much as possible from scratch
using only default tools from Android Studio. The main challenges were in
developing the application’s architecture, in-game physics, user controls and AI.

As with all mobile development, the context of mobile devices and the
conventions of the underlying operating system had to be considered. Also, as
the game was developed with only mobiles phones in mind, the limitations of a
smaller screen had to be taken into account. This affected especially the design
of a touchscreen controller.

The motivation for this project was to learn about mobile development for the
Android operating system, especially from game development’s point of view. An
object was also to lay groundwork for future game development projects. The
game was developed independently and without an employer.
Developing a Football Game for Android - Markus Huhtamäki - Theseus
8

2 GAME DESIGN PLAN

2.1 Overview

The purpose of this project was to design and develop a single-player football
game for Android platform. The game received the working title Epical Football.
In the game the user controls an outfield player and tries to score goals against
an AI controlled goalkeeper. For controlling the player, a touchscreen-based
controller was designed.

When the application starts, an opening menu is shown. From the menu the user
can adjust attributes for the outfield player and goalkeeper. Below the attributes
is a button to start the match. During the match, the user will see (a portion of) a
football field with the players and a goal. A total of 10 balls are fed to the field;
whenever a ball goes out of bounds, is captured by the goalkeeper or a goal is
scored, a new ball is fed until the balls run out. Above the field is shown the
number of remaining balls and goals scored so far. Below the field is the section
for controlling the player. The design for the match’s layout is shown in picture 1.
When the match is finished, a result view is shown with the result of the match.
From here the user can navigate back to the opening menu.
9

PICTURE 1. Match layout design

Even though the game would be quite simple and would not even try to cover all
the aspects of football, it should still portray the concepts of football within the
game’s context in a meaningful way; in a sense, capture the essence of the sport.
There should be an overall feel that everything is happening naturally and
realistically; the movement of the players, the physics governing collisions (like
the ball bouncing off a post or net), and the ball’s behaviour in the general. Also,
the goalkeeper should behave intelligently; position itself well, try to intercept if
the player dribbles too near, understand when to disengage not to wander too far
from goal, and move properly when making saves.

2.2 Controlling the player

The outfield player is controlled by pressing on the touchscreen-based controller
section in picture 1. The player will start to accelerate to the direction relative to
the center of the controller. The further from the center the touch is, the higher
the speed the player will try to accelerate to. The bigger circle indicates the limit
for maximum speed, and thus, pressing on it or outside it will result in accelerating
to maximum speed. If the player had speed when the touch was released, it would
10

slow down to a halt. Pressing on the center of controller, on the dot, decelerates
the player to a stop as quickly as possible. Besides the player moving on the field,
there would also be visual feedback to the user from the controller. The pressed
location would be shown as a dot on the screen, and the brightness of the dot
would indicate the desired speed. In the case of decelerating, turning the center
dot brighter would suffice.

The outfield player controls the ball when touching and facing it at the same time.
This interaction attempts to shift the ball all the time towards the player’s bearing,
thus giving more control when moving and turning with the ball. The ball,
however, is never stuck to the player in any sense, but both remain as their
separate physical objects on the field – this is a very important consideration in
making the ball behave realistically. Thus, if the player turns too quickly, the ball
might slip out of control.

When the shoot button is pressed (and held down), the player starts to gather
power for the shot. The gathered power is indicated in the shot power meters.
And when the button is released, the player will shoot the ball the next time it
touches the ball (there is a time limit for this and exceeding that will cancel the
shot). This allows for preparing for the shot even before being near the ball, which
is important, for example, if the user wants to kick a ball that is moving towards
the player. Optimally the best shot is released near the maximum of the power
meters. But if the meters go full, the aim and speed of the shot start to suffer. The
more time passes when the meters are already full, the worse the shot will be.
This is indicated by turning the meters gradually red. And if enough time passes
the shot is cancelled altogether.

Besides taking care of the shot power, the user must also aim the shots. When
the shoot button is pressed, the controller switches to an aiming view. In the
aiming view a target goal moves and bounces off to different directions. The user
needs to use the touchscreen to place a dot in a desired location of the target
goal. The player will attempt to shoot the ball to the location where the dot was
on the target goal upon releasing the shoot button. The aiming direction is also
indicated on the field as an arrow from the player towards the intended target of
the shot.
11

Designing a complex way of controlling the player’s actions required some
amount of planning for the requirements of the controller’s usability. Naturally, the
shoot button, as well as any other button in the application, should be sizeable
enough that even a person with broader fingers could press them easily. Also,
the controller should be sizeable enough to allow the user to give different desired
speeds for the player, all the way from using the center dot to going for maximum
speed. Furthermore, there should be some amount of buffer
outside the maximum, as otherwise trying to touch for maximum speed would
become too precise and difficult.

2.3 Adjustable attributes

The game has nine adjustable attributes for the user-controlled outfield player
and six for the goalkeeper. These will be described here briefly to give a better
understanding of the game’s features.

2.3.1 Outfield player attributes

Reach describes roughly how far the player can reach with the other leg
extended. Thus, this attribute does not only signify the player’s size, but also its
sphere of physical influence. This provides a more relevant interpretation of a
performing athlete compared to just indicating its physical dimensions, as all the
smaller movements, like reaching for the ball, is already built into the abstraction.
Reach also determines how big the player is visually.

Acceleration describes how effectively the player gains or reduces speed.

Speed determines the player’s top speed.

Ball Control describes the player’s ability to keep the ball under control while
turning. For a player with poor ball control the ball might easily slip away when
making sharp turns, while a more proficient player could make quite flamboyant
12

spins with the ball securely by its feet. Ball control also affects how well the player
will stop the ball when receiving it.

Dribbling describes the player’s ability to run fast with the ball in control.

Shot Power determines the theoretical maximum speed for the player’s shots.

Accuracy describes the player’s ability to accurately aim shots in the desired
direction.

Finishing and Long Shots are two attributes describing the player’s mental
capability of creating good shots, visualizing the goal and concentrating on
making a solid contact with the ball when kicking. Finishing would deal with close-
range shots and long shots with long-range.

2.3.2 Goalkeeper attributes

Reach for the goalkeeper is the same as with the outfield player, but with the
difference that now it is be measured from the arms in a reaching position, thus
making the goalkeepers’ spheres of influence bigger.

Agility is the same as acceleration, but with the addition of making the
goalkeeper’s recovery times shorter after making a save.

Speed is identical with outfield player’s speed.

Reflexes describes the goalkeeper’s reaction time when making a save.

Ball Handling describes the goalkeeper’s ability to take the ball into possession
instead of just bouncing it off when making a save. And if the goalkeeper could
not hold onto the ball, this attribute would help direct the bounce into a more
favourable direction.
13

Intelligence is the goalkeeper’s most important attribute. It describes its ability to
position itself in front of the goal and make good decisions about how and when
to try intercepting the ball.

2.4 Rejected alternatives

Before starting the project and deciding that it would be solely for Android
platform, other options were also considered. First there was the decision of
whether to develop the game as a mobile application or as more traditional
computer game. Mobile application was selected because it coincided better with
the developer’s other studies and for the desire to learn more about mobile
development.

Developing solely for iOS platform was never considered, but a cross-platform
solution was. Developing only for Android was selected because the technologies
involved were already familiar to the developer. Also, some consideration was
given to a possible publication of the application; in the cross-platform option two
sets of publishing criteria would have to be met, which would have increased the
workload.

Mobile applications can run on both phones and tablets, and it can also be
decided if it runs only on one of them. This is also a relevant decision as an
application developed with tablets in mind could prove totally unusable for a
normal phone. A tablet would have provided a much bigger screen and therefore
less restrictions for the game’s layouts; this is something that a game with an
isolated touch-screen controller would benefit from. But it was actually due to this
reason that a normal phone sized screen was selected as a reference for
development. Now all the layouts had to be designed with extreme precision,
giving more opportunities to understand the minimum requirements of the visual
and functional components on the screen. However, if the game would continue
to be developed and expanded, and eventually published, it would be done only
to tablets.
14

A multiplayer option was also considered, but this would have shifted a
considerable amount of the project’s focus into setting up the server and
developing the communication between the server and the mobile devices. As a
result, there would have been less time and resources to develop the actual
game, which would have been contrary to the aims of the project.
15

3 ANDROID GAME DEVELOPMENT

3.1 Mobile game development

In the first decades of their development mobile phones were dedicated to
performing phone calls, and due to high prices were used only by a very selected
group of people (Loeffler 2021). It was in the 90’s that the evolution of mobile
phones started to allow for more diversity in content, such as text messaging,
calendars, and along with everything else, first mobile games. Notable landmarks
include variants of Tetris in a few different devices, and Nokia’s Snake that
became extremely popular (Paiva 2020).

Even as mobile phones got more and more popular, the mobile game industry
was stalling because the games needed to be pre-installed. It was first with the
advent of the Wireless Application Protocol (WAP) and later with the digital
distribution platforms, such as App Store and Google Play, that the mobile game
development really took off (Paiva 2020). In recent years, mobile games have
been the most popular form of video gaming, with prospects of an even further
growth (Green 2019).

With the distribution platforms and all the free resources available, nowadays
even amateur developers can develop and publish mobile games for global
markets without a considerable budget. With free game developing frameworks
such as Unity, a developer can create complex and demanding games with
relative ease (Sinicki 2020). Unity is a cross-platform game engine developed by
Unity Technologies that offers many built-in features like a physics engine, 3D
rendering and collision detection (Unity n.d.). Another example of a free game
development tool is libGDX which is an open-source cross-platform Java game
development framework. It also comes with a lot of resources for physics,
graphics, and other important aspects of game development (libGDX: Features
2021).

The alternative to using something like Unity or libGDX is to do everything from
scratch. While this approach can be more laborious, it will give full control for
16

every aspect of the development. As an example, developing a physical model
with moving objects, friction, collisions, and gravity could be quicker and easier
with a built-in physics engine, but as a trade-off the engine might not cater to all
ideas the developer has in mind. Also, if something does not wok as intended, it
might be difficult to find the problem without a good understanding of the engine
itself. An additional benefit in initially doing as much as possible yourself is to
have a better comprehension of what problems game frameworks could solve in
future projects.

For a mobile application developer, it is good to bear in mind the uniqueness of
mobile development and differences from more traditional software development.
These include considering how different the contexts can be for using mobile
applications compared to desktop computers for example, understanding the
limitations and challenges of a touch-based user interface, and taking into
account characteristic security threats of mobile technologies. Also, a mobile
developer should be aware of the importance of user experience and the fact that
most users are accustomed to the design standards of a given operating system.
(Stangarone 2015.)

3.2 Android application development

Android is an open source and Linux-based operating system for mobile devices
such as smartphones and tablet computers and is primarily developed by Google
(Android: What is Android n.d.). Over the years, Android has surpassed all its
initial competitors, such as Symbian, Blackberry and Windows Mobile to become
the most popular operating system for mobile devices (Callaham 2020). As it
stands, Android’s market share is over 70 % with Apple’s iOS left as its only
noteworthy competitor (Statista 2021).

Along with many of its innovative features, one key reason for Android’s
popularity was Google’s commitment to make it an open-source operating
system, allowing it for free to third-party phone makers such as Samsung, LG
and Sony (Callaham 2020). The popularity of Android has produced (and
reciprocally benefited from) a thriving community of developers sharing wisdom
17

online. This includes numerous online resources, such as courses, articles,
guides, and tutorials, some of which were used in this project also.

One big difference – and a challenge – for Android developers is the sheer
number of different kinds of devices the applications need to run on. Compared
to iOS for example, with all the third-party manufacturers there are much more
differences in screen sizes, pixel densities and device capabilities. With the
release of Android Honeycomb, Android also started supporting large screen
devices, such as tablets and smart TVs, which has further complicated the
situation. (Hathibelagal 2016.)

An additional challenge comes from the fact that most Android devices rarely
receive software updates, if at all (Hathibelagal 2016). This means that an
Android developer needs to support older versions of Android, as the most recent
version might be running on just a fraction of all Android devices. The further back
the support is given, the more devices the application will run on, but this might
come at a cost in the form of restricting the development. Ultimately it is a
question of optimization.

Native Android development can be done with Kotlin, Java or C++ using the
Android software development kit (Android SDK) (Android Developers:
Application Fundamentals n.d.). The most popular choice for an integrated
development environment (IDE) for native development is Android Studio
(Android Developers: Meet Android Studio n.d.), with other options include
Eclipse and IntelliJ for example.

Besides native development, applications can also be developed to be published
on multiple operating systems. This is offered through hybrid or cross-platform
technologies such as Flutter, React Native and Xamarin. The benefit of this is to
avoid developing the same application separately for different operating systems.
As a drawback, non-native applications suffer from poorer performance. Also, not
all third-party libraries work in sync with the cross-platform development
frameworks. (Klubnikin 2017.)
18

Android applications can be published and distributed via several different
Android application marketplaces, with Google Play being the most prominent.
With Google Play anyone who has registered for a developer account can submit
an application for publishing by providing the program file along with some
necessary details. The application will be published after going through the
approval process. (Hathibelagal 2016.)

3.3 Version control

One key aspect of software development is version control. Version control, also
known as source control, is the practice of tracking and managing changes to
software code, and version control systems are software tools that help software
teams manage changes to source code over time (Atlassian: What is version
control? n.d.). Version control offers many benefits, including tracking the history
and evolution of the project, making collaboration easier by allowing
simultaneous development and aiding in resolving conflicting versions, and, in
case of an error, providing an easier way to revert to earlier versions (O'Sullivan
2006).

Version control is imperative with many people involved, but even a single person
can benefit from it for the same reasons (O'Sullivan 2006). One other reason, that
is not so often mentioned, is simply to have the code stored in another location
besides the local computer. In case of an accident or a stolen laptop, the whole
project could be lost. In addition, even a project that starts with only one person
might later involve other people as well.

Different options for version control include Git, Apache Subversion (SVN),
Mercurial, Concurrent Versions System (CVS), Perforce, GNU Bazaar and many
more.
19

4 CHOSEN DEVELOPMENT TOOLS

4.1 Android Studio

Android Studio is Google’s official IDE for Android app development (Android
Developers: Meet Android Studio n.d.). It was mainly chosen as the IDE for its
good features and usability. The features include, for example, the possibility to
easily test the applications with both a built-in emulator and a separate mobile
device, and a GitHub integration. In general, the clearest disadvantage of Android
Studio is that it supports only native Android development. But since there was
no plan to go cross-platform, this was not an issue. In fact, it made the choice
even more natural as the necessary tools for Android development were already
bundled in. Android Studio was also familiar to the developer beforehand, thus
easing the learning curve for the project.

Using Unity or libGDX would have definitely provided a readier toolset for making
games, especially in terms of graphics and in-game physics. One great
motivation for the project was however to design as much as possible from
scratch. Only Android’s default packages were used. For example, all the
graphics in the game (besides background images) are simple figures drawn
using Android Graphics. Android Graphics is an API package that provides low-
level graphics tools for drawing to the screen directly (Android Developers:
Android Graphics n.d.).

4.2 Java

Android apps can be written using Kotlin, Java, and C++ languages (Android
Developers: Application Fundamentals n.d.). Even though Google has lately
adopted a Kotlin-first policy, Java has been an official programming language for
Android development for a longer time (Sinicki 2019). Java is an open-source
object-oriented language owned by Oracle (w3schools.com: Java Introduction
n.d.). It is one of the most popular programming languages in the world, and thus
offers an extensive community support. With the assumption that there would be
20

more online material available for developing Android with Java, it was selected
as the programming language for this project.

4.3 Git and GitHub

Since Android Studio already had an integration for it, choosing Git and GitHub
for version control was a natural choice. Git, developed by the Linux Foundation,
is by far the most widely used modern version control system in the world today
(Atlassian: What is Git n.d.). Git is a free and open-source distributed version
control system designed to handle many kinds of projects. Microsoft’s GitHub, on
the other hand, is a code hosting platform for collaboration and version control
that uses Git (w3schools.com: What is GitHub? n.d.)

The basic workflow was to commit code changes, whether they were about
adding new features or fixing bugs, as separate commits to GitHub. Also, as the
code was always safely stored in the GitHub repository, it could be retrieved in
problematic situations for a do-over.
21

5 GAME ARCHITECTURE

5.1 Activities and Layouts

In the core of Android applications are the Activity classes. An activity represents
a single screen with a user interface (Android Developers: Activity n.d.). When an
application is launched, an activity (usually the designated main activity) is
launched to provide the user with a user interface and to handle its input and
output (Android Developers: Introduction to Activities n.d.). Thus, an activity can
be seen as the starting point of the program code. An application can have
multiple activities and they can pass on the control to each other (Android
Developers: Introduction to Activities n.d.).

Three activities were created per the need for three screens in the game design
plan: MenuActivity, MatchActivity and ResultActivity. For these activities
necessary layouts were created. A layout defines the structure for a user interface
in the application (Android Developers: Layouts n.d.). For the menu two layouts
were created as there was a need to switch between setting the player and
goalkeeper attributes.

When the application is launched the menu with the player attributes is shown to
the user (picture 2). Below the title there are two buttons that the user can use to
switch between the player and goalkeeper attributes. The layout for the
goalkeeper attributes can be seen in picture 3. The text on the button is bolded
to signal which attributes are shown. The user can set the value of each attribute
from the plus and minus buttons. The start game button at the bottom starts the
match.
22

PICTURE 2. Menu view with attribute settings for the player

PICTURE 3. Menu view with attribute settings for the goalkeeper

The view of the match can be seen in picture 4. At the top there are two numbers
representing the balls that are left for the player and the scored goals so far.
Below is a view of the playing field. The outfield player (blue) is moving with the
23

ball and the goalkeeper (red) is guarding the goal. Below the field is the control
section. In the middle is the controller that the user can use to move the player.
The magenta dot shows where the user is touching the screen. On either side of
the controller are power bars that indicate the power of a shot. At the bottom is a
button to commence aiming and shooting.

PICTURE 4. Match view

After the user has used all the given balls, the match ends and the result is shown
in the result view (picture 5). Pressing the button at the bottom of the result view
takes the user back to the menu.
24

PICTURE 5. Result view

5.2 Class Structure

Several custom classes were created to implement the actual match. Most of
these are shown in figure 1. A possible parent class (inheritance) is written inside
brackets. For example, OutfieldPlayer class inherits Player class which in turn
inherits Circle class. Circle class was created as a parent to all circular objects,
and similarly Android Graphics’ RectF was used as a parent to all rectangular
objects. In addition to the ones in the figure, Position and Vector classes were
created to be used by any object with a position or movement on the field,
EpicalMath and Collisions classes were created to offer static functions, and
Constans to offer global constants.
25

FIGURE 1. Class architecture

The arrows in figure 1 show what classes a given class calls to create new
objects. Thus, we can see how the match activity is the starting point for initiating
the match. The match activity creates an instance of MatchState that holds all the
functionality of the match, and an instance of MatchSurfaceView that is used to
draw the match’s graphics on the screen, and these go on to create all the other
necessary objects.

The figure does not show dependencies between classes; for example, besides
the match activity also match surface view and match runner need to use the
created match state object directly. This makes the whole architecture more
complex and intertwined. Figuring out the hierarchy and dependencies between
classes was one of the key issues when designing the application, and ultimately
one of the project’s biggest successes.

5.3 Threads

When an Android application is launched, the Android system starts a new Linux
process for the application with a single thread of execution (Android Developers:
Processes and Threads Overview n.d.). A thread can be thought of as a worker
26

for the process (Beatteay 2018). The thread started for the process by default is
called the “main” thread (Android Developers: Processes and Threads Overview
n.d.). The application can be made more efficient by creating new threads inside
the main thread and sharing the workload of the process between the threads.
This is called multithreading (Beatteay 2018). However, as switching control
between threads also takes time, using multithreading in a simple application
might actually slow it down (Beatteay 2018).

Regardless of its impact on efficiency, most Android game development tutorials
and examples found online use at least a separate thread for the game loop. As
some of the game loop’s operations might momentarily block the thread, it is
better to run it in a separately thus keeping the main thread free to process user
input and output; this makes the application more responsive (Goshen n.d.).
Following the example of Cave of Programming’s tutorial (2016), a separate
thread for the game loop is created (as an instance of the MatchRunner class)
when the match surface view is created.

Additionally, one more thread was designed to handle the decisions of the AI
controlled goalkeeper (an instance of the AIRunner class). This in turn is created
when the match state is created. In terms of efficiency or responsivity there was
no need for this thread, and it was designed solely for educational purposes.
However, if the game would eventually be expanded to have several AI players
with complex decision algorithms, using a dedicated thread for AI would be
completely justified.

5.4 Global Functions

Global functions, or functions that could be used anywhere in the program, were
offered as static functions from two classes EpicalMath and Collisions.
EpicalMath was designed to offer functions for all the necessary mathematical
calculations for the game, and Collisions was designed to offer functions for all
interactions between objects on the football field. Although technically not
meeting the criteria of libraries, in a practical sense these classes were used as
custom libraries.
27

5.4.1 EpicalMath

In the early stages of developing the program, mathematical calculations were
written directly to their place in the code or occasionally separated as functions
to be used only in that one class. But as the mathematical modelling became
more ambitious and calculations grew in terms of code lines, and as similar
calculations started to appear in different parts of the program, it became evident
that the code needed to be reorganized. The solution was to offer mathematical
calculations globally from a separate class as static functions. This class was
named EpicalMath.

The mathematical functions gathered in EpicalMath mostly dealt with analytic
geometry, aiding in calculating directions, distances, positions and checking
potential intersections on the two-dimensional field; for example, determining the
distance between two coordinate positions, calculating a new direction if a given
direction was shifted towards a reference direction, or as shown in source code
1, determining the midway point of two given positions.

public static Position getPositionBetweenPositions(Position position1, Position position2) {
    float x = (position1.getX() + position2.getX()) / 2;
    float y = (position1.getY() + position2.getY()) / 2;
    return new Position(x, y);
}

SOURCE CODE 1. Determining the midway point of two given positions

Besides making the code clearer, another advantage of separating calculations
to their own class was that those calculations could now be easily used in other
projects as well. In fact, this has laid groundwork for creating a mathematics
library for games with a similar approach to using moving objects in a two-
dimensional plane. However, there was still many calculations in the code, mostly
trigonometrical in nature, that with a different kind of mindset could have also
been abstracted and moved to EpicalMath. In fact, one of the key takeaways from
this project was to recognize the value developing separate classes with static
functions; with better planning and a more consistent approach, the quality of the
28

code would have been better and one of the outcomes would have been a solid
groundwork for a mathematics library for two-dimensional games.

5.4.2 Collisions

In similar fashion, Collisions was designed to take care of all the interaction
between objects when they intersect with each other. There was a need to write
a separate collision function to almost all possible combinations of participants.
For example, the ball would react differently when colliding with the outfield
player, goalkeeper, goal post or goal net, but also the outfield player would react
different when colliding with the goalkeeper, goal post or goal net.

As there was a certain ambition to make the events seem realistic, and thus many
things needed to be taken into consideration, the functions grew quite long and
complex. Especially the interaction between the ball and the outfield player had
to entail, besides just bouncing the ball off properly, the ways the player could
influence the ball via dribbling, shooting or controlling it. Developing, testing and
improving these collision functions was one of the most arduous segments of the
whole project.

If the purpose for EpicalMath was to lay groundwork for a mathematics library for
two-dimensional games, Collisions could have done the same for a physics
library. But the way of handling the collisions became very particular for this game
and not nearly as universal, and therefore not as transferable to other games.
And since only few classes ended up handling collisions, there was no need to
offer them as static. In retrospect, offering the collisions from a normal class
would have sufficed and would have been a better solution.

5.5 Global Constants

In the early stages of development many constants were written directly in the
code (hard coded). As it became increasingly harder to locate them, there was
an attempt to move some of them to the beginning of classes. This approach still
29

left a few problems; for example, if the game wanted to be tested with a different
set of constant values, changes needed to be made to multiple files. Furthermore,
some of these values were supposed to be the same across different classes.

A need for a separate file containing all constant values was recognized. A class
called Constants was created and all the values were gathered there to be offered
as global static values. Now everything could be controlled from one class. In
addition to values that were used to configure the game’s behaviour (such as the
radius of a ball, or what shape of speed curve and accelerating player has), also
often used mathematical values were included, such as the radian value of the
direction left or values of often used numbers. The class ended up having over
two hundred constants and as a result the code became much more readable.
30

6 GAME PHYSICS

6.1 Time management

One important component of computer games is the game loop that updates the
game’s state in cycles. The key question in designing the game loop was how to
set the time intervals so the game would behave optimally. Different ideas from
various sources were examined for this project, but all of them seemed to have
shortcomings. In the end, an original logic was developed in an attempt to
combine the best ideas while discarding the shortcomings.

A simple game loop would update the game’s state in fixed increments. That is
to say, in every cycle an object moving at a constant speed would move the same
amount. The benefit of this would be that the code would become much simpler
as, comparing to the case where the increments would be relative, the size of the
increments would not have to be considered at all. The game’s speed could be
adjusted by having the thread sleep for a moment in every cycle; the length of
sleep would determine how fast or slow the game would advance.

The problem with this is, however, that how the game runs would depend on the
device’s performance; the speed of the game would alter all the time depending
on how much resources the device has for running it. Also, a well-performing
device would run the game faster compared to slower devices. This is the reason
why using relative increments is better, and why the length of the increments
(usually measured in milliseconds) must be considered in the code when
updating the game’s state.

One solution was to give the increments as the length of how much time has
elapsed from the last time the game’s state was updated. Theoretically, this will
keep the game running smoothly. Because this would make the loop run as fast
as possible, heavily taxing the device’s performance and battery, a good addition
is to, once again, make the thread sleep for a moment every cycle.
31

This game loop is far better than the first one but has problems too. Because the
lengths of increments are not controlled in any way, in turn, they would vary too
widely depending on the device’s performance. For example, when a ball
advances towards a goal post, the length of the increments will determine how
far it can travel inside the post before a collision is detected and handled. This
would make the game’s physics behave differently depending on the device’s
performance. Another problem is that the sleep serves no purpose if a relatively
long time has passed after the last update.

The game loop developed this for game used both described approaches. The
game’s state is updated by the elapsed time from the last update, thus making
the game run smoothly. But as an addition the length of sleep is set by how much
time has passed to run the current cycle, making the cycles almost identical in
duration, solving the problem in the game’s physics. The final form of the game
loop is in source code 2.

long   lastTime = System.currentTimeMillis();
long   elapsed;
long   begin;
long   delta;

while(running) {
    begin = System.currentTimeMillis();
    elapsed = begin - lastTime;
    lastTime = begin;

    matchState.updateGameState(elapsed);
    matchSurfaceView.drawOnSurface();

    delta = System.currentTimeMillis() - begin;

    if (delta < GAME_UPDATE_TIME) {
        try {
            Thread.sleep(GAME_UPDATE_TIME - delta);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

SOURCE CODE 2. The game loop

The constant GAME_UPDATE_TIME is the target time for the cycles’ durations.
If the time executing the cycle exceeds this, the sleep is skipped, once again
introducing the problem of varying increments. But when the constant is selected
sensibly, it will cover almost all situations ensuring a smooth gameplay. It was set
at 30 ms.
32

An additional precaution would have been to set an upper limit for the time
increment to be applied. This would have been to ensure that if the device is not
functioning properly, the game would not update at all. This would momentarily
freeze the game until normal conditions were resumed. Freezing the game would
be more user-friendly than to let the game run when it is basically unplayable; if
the time increments are too long, all movement will be choppy, and the game’s
physics will not behave as intended.

The time increments of approximately 30 ms proved to be satisfactory for most
situations of the field. However, when the ball was moving very fast, the time
increment was too long. Especially, as a really fast ball can travel over a meter in
that time frame, it might skip through the nets and posts that had to be kept
reasonably narrow. The solution was to process everything else first, then
process everything to do with the ball separately by dividing the time increment
into even smaller increments. This made the ball move in extremely short steps.
Another solution would have been to make the whole cycle run in smaller
increments, but as there is a limit on how quick cycles the device can perform,
and as the ball was the only perpetrator, this would have been a poor solution.

This logic of dividing the time increment in fractions could have also been used
selectively to combat time increments that are too long. For example, when the
match state’s update is about to ensue, the length of the time increment would
be checked and then decided in how many smaller pieces to divide it. This would
have solved the case of ill-behaving physics but not choppy graphics, as updating
the graphics would still be tied to the original time increment. Ultimately, probably
the best solution would be to combine both of the ideas: to start dividing the
increments when they escalate and to freeze the game if they get too long.

6.2 Dimensions and movement

With no height dimension – or depth from the user’s point of view – the game is
both visually and structurally completely two-dimensional. The metrics of the field
were coded in the constants file. In other parts of the code, the goal’s width and
33

the penalty box’s height were used as references, and all the logic worked in
relation to them. Thus, even with different values than the official 7.32 m and 16.5
m, the game would still work, including building the goal frame from nets and
posts and how the goalkeeper’s AI functions.

To have the metrics correspond to the background image, the width of the goal,
height of the penalty box and the height from the top to the touchline were
calculated from the image along with the total height and width of the image as
amounts of pixels. Setting the touchline as the x-axis, with readily made formulas
only these pixel amounts needed to be set in the constants and all the visuals
locked into place. This was very convenient when auditioning different
background images.

All the positions on the field are expressed as x and y coordinates, and all the
speeds and accelerations as vectors with direction and magnitude. The first step
of moving an object is to determine its acceleration. All objects have a base
deceleration to slow them down by default, and otherwise the players’
acceleration come from either user controls or AI (depending on the relevant
attributes as well). The next step is to update the speed with the acceleration by
the given time increment. And finally, to update the position with the speed by the
given time increment.

6.3 Collisions

One key aspect of the game’s physics was to determine how the objects would
interact with each other when coming into contact. These collisions are detected
by checking every cycle whether the objects intersect. For example, if the ball
intersects with the goalkeeper, or the outfield player intersects with any of the
goal nets or posts. Most of these instances needed to be designed separately,
but in some cases, the same method is used for different combinations of objects.
Naturally, there is no need to check collisions between stationary objects.

One vital decision regarding the realism of the physical model was whether to
implement inertia. As the game was to be relatively simple and the ball’s mass
34

would be relatively insignificant comparing the mass of the players, it was decided
that inertia would not be considered.

6.3.1 Moving objects with stationary objects

The collisions between the outfield player or the goalkeeper with rectangles like
goal nets and the field’s outer boundaries could be handled with the same
collision method. To put it simply, first is checked from which side of the rectangle
the player tries to penetrate it, then the player is instantly moved outside the
rectangle to that direction, and finally the component of the player’s speed to that
direction is removed. This will make the player stop or slide along the rectangle’s
side without ever ending up inside it.

For the ball the process is similar but, instead of reducing a component of the
speed, it is bounced off with reduced speed. The faster the ball’s original speed,
the more it was reduced; this would make the nets behave in a less elastic way.

In terms of physics, this model was satisfactory. However, since the goalkeeper’s
AI was not sophisticated enough to plot routes, it would get stuck running against
the net if ending up to the wrong side of it with the ball. As a shortcut, the
goalkeeper is made to slide down every time it touches a net. This would hasten
its return to the field.

The handling of collisions between the players and the goal posts are similar to
those with nets, except now the objects are both circles. The speed component
towards the center of the post is removed, but instead of just moving the player
outside of the post, it is also shifted a little towards the field. The reason for this
was that it was easy for the player to get stuck in the nearly invisible “pocket”
between the net and the post, and this helps to guide the player away from it. For
the goalkeeper this is necessary for both this reason and for the reason with the
nets.

With the ball, again instead of removing the speed component towards the post
its direction is bounced off the post and speed reduced. Additionally, this time
35

both the original speed and the angle of the collision would determine how much
the speed is reduced. The method handling the collision between the ball and a
goal post is shown in source code 3. It also illustrates the use of EpicalMath and
the global constants.

public static void handleBallGoalPostCollision(GoalPost goalPost, Ball ball) {
    if (EpicalMath.checkIntersect(goalPost, ball)) {
        float radiusSum = goalPost.getRadius() + ball.getRadius();
        float goalPostToBallDirection =
                EpicalMath.convertToDirection(goalPost.getPosition(), ball.getPosition());
        float goalPostToBallBallSpeedAngle = EpicalMath.absoluteAngleBetweenDirections(
                goalPostToBallDirection,
                ball.getSpeed().getDirection()
        );

        if (goalPostToBallBallSpeedAngle > QUARTER_CIRCLE) {
            ball.getSpeed().bounceDirection(goalPostToBallDirection);
            float multiplierAngle = goalPostToBallBallSpeedAngle - QUARTER_CIRCLE;
            float speedMultiplier = FULL - (float)Math.sin(multiplierAngle)
                    * (FULL - GOAL_POST_COLLISION_SPEED_MULTIPLIER);
            ball.getSpeed().setMagnitude(speedMultiplier * ball.getSpeed().getMagnitude()
                    * (FULL - ball.getSpeed().getMagnitude()
                    / BALL_COLLISION_REFERENCE_MAX_SPEED
                    * BALL_COLLISION_SPEED_REDUCTION_BY_SPEED_FACTOR));
        }

        ball.getPosition().copyFromPosition(goalPost.getPosition());
        ball.getPosition().addPositionVector(goalPostToBallDirection, radiusSum);
    }
}

SOURCE CODE 3. Collision between the ball and a goal post

6.3.2 Ball with outfield player

The interaction between the ball and the outfield player turned out to be of the
most complicated pieces of the game. Whether the player can shoot is checked
first. If this is true, handling of the collision return true and the shot is handled
elsewhere, otherwise the method continues.

Next, whether the player and the ball are moving towards each other or whether
the player is either touching a stationary ball or gaining on the ball that is moving
away from it is determined. In case of moving towards each other a bounce
occurs and the ball’s speed is decreased. If the ball bounces when the player is
facing the ball, the speed’s reduction along with a small shift to the bounce’s angle
depend on the player’s ball control attribute – so more skilful players have more
control in receiving the ball. If the ball bounces and the player is not facing the
36

ball the reduction depends on the ball’s speed and the collisions angle, as with
goal posts (only that players are softer and reduce the speed more). Furthermore,
in all cases the impulse caused by the player’s own movement is added to the
ball’s movement. And finally, the ball is always moved out of the player’s sphere.

If the player moves constantly towards the ball, the impulse caused by the player
keeps moving the ball forwards, thus making dribbling possible. However, if there
is nothing to keep the ball in front of the player, it would simply slip aside. And
since after the collision the ball is moved outside the player, the contact is
automatically broken, making having the ball follow the player’s intentions while
turning practically impossible.

This was solved by adding a “control cone” as an extension of the player’s “face”.
The reach of the cone depends on the ball control attribute. Whenever the ball
was intersecting with this cone, the player would impose some amount of control
to the ball, depending on the player’s ball control attribute. The cone constantly
shifts the ball both closer to the player and nearer the direction the player is
facing. This makes dribbling and turning with the ball far easier. However, the ball
can still slip away if the turn is too sudden especially with players of poor ball
control. Also, when the player is dribbling, its maximum speed is reduced
depending on its dribbling attribute.

6.3.3 Ball with goalkeeper

As with the outfield player, the interaction between the ball and the goalkeeper is
quite complicated. One outcome of the collision is that the goalkeeper captures
the ball, thus ending the play until a new is fed. This would occur if in the collision
the ball is standing still, the goalkeeper gains on a moving ball or the goalkeeper
makes a successful save. Also, in the special case of the goalkeeper touching
the ball outside of the penalty box it would only kick the ball away (as per the
rules it cannot touch the ball with its hands).

When the collision occurs inside the box and the ball is moving towards the
goalkeeper, the goalkeeper attempts to capture the ball. A somewhat complex
You can also read