Game Development in Haskell Archive
Game Development in Haskell Archive
FACULTY OF INFORMATICS
BACHELOR'S THESIS
Jan Rychlý
B r n o , S p r i n g 2021
MASARYK UNIVERSITY
FACULTY OF INFORMATICS
BACHELOR'S THESIS
Jan Rychlý
B r n o , S p r i n g 2021
This is where a copy of the official signed thesis assignment and a copy of the
Statement of an Author is located in the printed version of the document.
Declaration
H e r e b y I declare that this p a p e r is m y o r i g i n a l a u t h o r i a l w o r k , w h i c h
I have w o r k e d o u t o n m y o w n . A l l sources, references, a n d literature
u s e d or excerpted d u r i n g e l a b o r a t i o n of this w o r k are p r o p e r l y cited
a n d l i s t e d i n complete reference to the d u e source.
Jan Rychlý
i
Acknowledgements
I w a n t to t h a n k m y a d v i s o r , d o c . M g r . J a n O b d r ž á l e k , P h D . , f o r h i s
invaluable feedback, patience, a n d encouragement. I also w a n t to thank
m y colleagues at K I S K for tolerating m y l o u s y tempo as I was f i n i s h i n g
this thesis. Finally, special thanks go to m y fiancee for p u t t i n g u p w i t h
the lengthy explanations of m y excitement over p r o g r a m m i n g a n d m y
f r i e n d s a n d f a m i l y f o r a l l their s u p p o r t — e s p e c i a l l y m y parents f o r
not letting m e starve to d e a t h w h i l e w o r k i n g o n this thesis.
ii
Abstract
P u r e l y functional p r o g r a m m i n g offers m a n y benefits, like briefer, safer,
a n d m o r e u n d e r s t a n d a b l e code. T h i s thesis a i m s to s h o w that these
benefits also a p p l y to d e v e l o p i n g smaller-scale v i d e o games i n H a s k e l l
a n d , m o r e i m p o r t a n t l y , that the d r a w b a c k s d o not o u t w e i g h t h e m .
W e present t w o i m p l e m e n t a t i o n s of a s i m p l e game. T h e first one
uses E n t i t y - C o m p o n e n t - S y s t e m p r o v i d e d b y the apecs l i b r a r y , a n d
the second focuses o n pure-style, parallelism-capable design. Further-
m o r e , w e c o m p a r e the t w o together w i t h a n a l r e a d y existing i m p e r a -
tive i m p l e m e n t a t i o n . W e s h o w that H a s k e l l ' s p o w e r f u l t y p e s y s t e m ,
i n c l u d i n g its typeclasses a n d m o n a d i c abstraction, is of especially
great value for a g o o d design of real-time interactive applications such
as games. A t last, w e discuss h o w o u r f i n d i n g s m a y scale u p .
iii
Keywords
H a s k e l l , functional p a r a d i g m , game development, E n t i t y - C o m p o n e n t - S y s t e m ,
apecs, p a r a l l e l i s m , m o n a d i c abstraction
iv
Contents
Introduction 1
5 E v a l u a t i o n of the approaches 37
5.1 Comparison 37
5.1.1 F l e x i b i l i t y a n d scalability 37
5.1.2 Expressiveness a n d safeness 38
5.1.3 D e v e l o p m e n t costs 40
5.1.4 Performance 43
v
5.1.5 State abstraction 45
5.1.6 C o d e statistics 47
5.2 Observed dilemmas 48
5.2.1 F r e e d o m v s . safeness 49
5.2.2 A b s t r a c t i o n v s . explicitness 51
Conclusion 54
Bibliography 56
A Electronic attachments 59
B Build instructions 60
vi
List of Tables
2.1 A simple example of ECS represented by a table. 10
2.2 Game objects and their components. 15
5.1 Average FPS in the benchmarks. 44
vii
List of Figures
1.1 Atari Asteroids — Promotional flyer cover [15] and
gatneplay Screenshot [16]. 9
2.1 A Screenshot of hAsteroids gatneplay. 13
2.2 hAsteroids module structure. 14
3.1 A Screenshot of pure-asteroids gameplay. 22
3.2 Data flow of gameLoop in pure-asteroids. 23
3.3 Entity groups and their interactions. 28
4.1 A Screenshot of imp-asteroids. 32
5.1 Total number of lines by project. 47
5.2 Code density by project. 48
5.3 The four discussed qualities of design. 52
viii
Introduction
V i d e o games are a special k i n d of a p p l i c a t i o n that m a n y c o n s i d e r a n
art f o r m a n d r e w a r d i n g to develop. H o w e v e r , they generally involve a
c o m p l e x system w i t h a n o n - t r i v i a l state, a certain a m o u n t of p s e u d o -
r a n d o m n e s s , a n d u s e r / p l a y e r i n p u t h a n d l i n g . T h i s m a k e s for n o n -
d e t e r m i n i s t i c p r o g r a m s that are u s u a l l y i n c r e d i b l y d i f f i c u l t to test
efficiently.
Conversely, f u n c t i o n a l p r o g r a m m i n g strives to eliminate mutable
state a n d make code more deterministic, w h i c h allows for p r o g r a m s to
be safer a n d easier to test. These a n d other benefits have n a t u r a l l y l e d
to p e o p l e t r y i n g out game d e v e l o p m e n t i n f u n c t i o n a l languages, b u t
it remains mostly a matter of passion projects. That s a i d , even t h o u g h
the vast m a j o r i t y of the v i d e o game i n d u s t r y still uses i m p e r a t i v e
languages l i k e C++, the c o m m u n i t i e s are v e r y active, a n d there are
h u n d r e d s of games, b l o g posts, a n d libraries that h e l p w i t h game
p r o g r a m m i n g i n f u n c t i o n a l languages.
The focus of this thesis n a r r o w s d o w n to e x p l o r i n g game develop-
m e n t i n H a s k e l l i n the context of small-scale 2 D games. T h e g o a l is
to give a n o v e r v i e w of the process, t h e n c o m p a r e this a p p r o a c h to a
m o r e c o n v e n t i o n a l a n d i m p e r a t i v e one a n d u l t i m a t e l y h i g h l i g h t the
features of H a s k e l l that are beneficial a n d those that become h u r d l e s
i n the context of p r o g r a m m i n g a v i d e o game.
T h i s is d o n e t h r o u g h r e i m p l e m e n t i n g a single g a m e w i t h a n a l -
r e a d y e x i s t i n g i m p e r a t i v e i m p l e m e n t a t i o n i n H a s k e l l , first u s i n g the
apecs l i b r a r y a n d for a second time w i t h o u t it. A f t e r a further discus-
1
1
i n m o n a d s that lacks the expressiveness a n d a p p a r e n t safeness of
r e g u l a r H a s k e l l . Yet, f r o m the second i m p l e m e n t a t i o n , w e l e a r n that
some use of m o n a d s is beneficial, a n d it makes the code cleaner, more
elegant, a n d more flexible. It c o u l d also be m o d i f i e d to use p a r a l l e l i s m
for w o r l d u p d a t i n g a n d detecting c o l l i s i o n s since the f u n c t i o n s are
all pure a n d compartmentalized. Furthermore, w e discuss w h a t a
m i d d l e - g r o u n d s o l u t i o n m a y l o o k like w i t h the use of typeclasses a n d
m o n a d s , a n d h o w o u r f i n d i n g s m a y scale to larger games. I n b o t h
cases, the d e v e l o p m e n t w a s m o s t l y a s m o o t h experience w i t h o u t a
single major h i c c u p , u n l i k e w h a t often h a p p e n s w h e n d e a l i n g w i t h a
C++ compiler.
2
1 Motivation and used methods
3
i . M O T I V A T I O N A N D USED METHODS
4
i . M O T I V A T I O N A N D USED METHODS
5
i . M O T I V A T I O N A N D USED METHODS
the H a s k e l l l i b r a r y i n c l u d e b o t h h i g h - l e v e l a n d l o w - l e v e l b i n d i n g s ,
m e a n i n g w e c a n enjoy a c o m f o r t a b l e interface yet at the s a m e t i m e
the lower-level b i n d i n g s serve as a n example of the p o w e r f u l F o r e i g n
F u n c t i o n Interface ( F F I ) , w h i c h m a k e s H a s k e l l even m o r e u s e f u l i n
the real w o r l d .
H e r e are the most essential SDL functions w e use i n our two games,
a l l examples of the h i g h - l e v e l b i n d i n g s :
- SDL.createWindow
is u s e d to create a n e w w i n d o w .
- SDL.createRenderer
is u s e d to create a r e n d e r i n g context for a w i n d o w .
- SDL.Font.load
is for l o a d i n g fonts.
- SDL.Image.loadTexture
is for l o a d i n g images as textures.
6
i . M O T I V A T I O N A N D USED METHODS
- SDL.clear
clears the r e n d e r i n g target/context,
- SDL.copy a n d SDL.copyEx
copies o u r l o a d e d textures to the r e n d e r i n g target l i k e s t a m p i n g a
picture o n a canvas.
- SDL.present
displays the current state of the target i n the w i n d o w .
- SDL.pollEvents
is c a l l e d to get i n p u t events.
7
i . M O T I V A T I O N A N D USED METHODS
— the C f u n c t i o n
-> (https://wiki.libsdl.org/SDL_RenderCopy):
— i n t SDL_RenderCopy(SDL_Renderer * renderer,
SDL_Texture * t e x t u r e ,
const SDL_Rect * s r c r e c t ,
const SDL_Rect * d s t r e c t ) ;
8
i . M O T I V A T I O N A N D USED METHODS
9
2 Using the apecs library — hAsteroids
A n d since b o t h U n i t y a n d U n r e a l E n g i n e use E n t i t y - C o m p o n e n t
d e s i g n , w e chose apecs as the current state-of-the-art H a s k e l l l i b r a r y
for the traction it has received i n the c o m m u n i t y despite it not b e i n g
the o n l y E C S l i b r a r y i n existence. 1
1. The making of the Ecstasy library was actually inspired by author's issues w i t h
apecs as she explains on her blog [20].
10
2. U S I N G T H E APECS LIBRARY — HASTEROIDS
To w r i t e a g a m e u s i n g apecs w e m u s t d e f i n e components a n d
systems. Systems also create n e w entities, as creating t h e m means to
w r i t e some c o m p o n e n t s u n d e r a n e w I D .
First, d e f i n i n g a component m e a n s to d e f i n e a n instance of the
typeclass Component, as w e see i n the L i s t i n g 2.1. The Component class
r e q u i r e s u s to state h o w w e w a n t to store the g i v e n c o m p o n e n t b y
a s s i g n i n g a t y p e alias to the specific storage t y p e . W e c a n define o u r
Stores o r use one of those p r o v i d e d w i t h the l i b r a r y : Map, Unique,
G l o b a l ( a n d Cashe). W i t h Map, there c a n b e m u l t i p l e c o m p o n e n t s of
that t y p e , each b e l o n g i n g to a p a r t i c u l a r entity. W i t h Unique, at most
one component m a y exist b e l o n g i n g to a particular entity. Furthermore,
w i t h Global, at most one component instance c a n exist, a n d it belongs
to the s p e c i a l g l o b a l entity together w i t h e v e r y other entity at the
same t i m e . F i n a l l y , w e c a l l makeWorld, w h i c h uses Template H a s k e l l
to generate World p r o d u c t t y p e a l o n g w i t h i n i t W o r l d f u n c t i o n a n d
instances of the Has typeclass n e e d e d f o r a l t e r i n g contents of World
t h r o u g h the other f u n c t i o n s i n apecs. T h e r e s u l t i n g World m a y l o o k
close to s o m e t h i n g as s h o w n i n L i s t i n g 2.2.
data World =
World
{ recordl (Unique P l a y e r )
, record2 (Map Enemy)
, record3 (Map B u l l e t )
, record4 (Map P o s i t i o n )
, record5 (Global Time)
}
11
2. U S I N G T H E APECS LIBRARY — H A S T E R O I D S
L i s t i n g 2.3: C o m p o n e n t m a p s d o c u m e n t a t i o n [21].
— I Maps a f u n c t i o n over a l l e n t i t i e s
w i t h a cx, and w r i t e s t h e i r cy.
cmap :: f o r a l l w m cx cy.
(Get w m cx, Members w m cx, Set w m cy) =>
(cx -> cy) -> SystemT w m ()
— I Monadically i t e r a t e s over a l l e n t i t i e s
w i t h a cx, and w r i t e s t h e i r cy.
cmapM :: f o r a l l w m cx cy.
(Get w m cx, Set w m cy, Members w m cx) =>
(cx -> SystemT w m cy) -> SystemT w m ()
— I Monadically i t e r a t e s over a l l e n t i t i e s w i t h a cx
cmapM_ :: f o r a l l w m c.
(Get w m c, Members w m c) =>
(c -> SystemT w m ( ) ) -> SystemT w m ()
12
2. U S I N G T H E APECS LIBRARY — HASTEROIDS
l o o s e l y i n d i c a t e d d e p e n d e n c i e s — u p p e r m o d u l e s m a y have direct
d e p e n d e n c i e s o n the l o w e r m o d u l e s , a r r o w s s h o w m o s t i m p o r t a n t
ones.
There are m o r e a p p r o a c h e s to d e s i g n i n g c o m p o n e n t s b u t i n h A s -
teroids, w e have three categories of c o m p o n e n t s : " m a r k e r " c o m p o -
nents, " s h a r e d " components, a n d " c o n t r o l " components. M a r k e r c o m -
ponents serve t w o p u r p o s e s : they c o n t a i n i n f o r m a t i o n that is u n i q u e
for a g i v e n t y p e of game object, a n d that w a y , t h e y also m a r k a n e n -
tity as that object. Shared components i n c l u d e characteristics that are
s h a r e d b y m o r e t y p e s of g a m e objects, l i k e p o s i t i o n . Lastly, c o n t r o l
c o m p o n e n t s are a l l g l o b a l a n d are u s e d i n one w a y or another to
c o n t r o l the r u n of the game a n d the transitions b e t w e e n scenes.
13
2. U S I N G T H E APECS LIBRARY — HASTEROIDS
Main
GameLoop
ganneLocp
Initialize Collisions
initializeGame detectAndHandle-Collisions
resetWorld
SdlWrappers
Resources
load Resources
runWitriResources
Utility is imported
everywhere
Utility
SDL
Constants and utilities
F i g u r e 2.2: h A s t e r o i d s m o d u l e structure.
14
2. U S I N G T H E APECS LIBRARY — HASTEROIDS
Object Components
Ship P o s i t i o n , V e l o c i t y , Ship
UFO P o s i t i o n , V e l o c i t y , TimeToLive, Ufo
Bullet P o s i t i o n , V e l o c i t y , TimeToLive, B u l l e t
Asteroid Position, Velocity,Asteroid
15
2. U S I N G T H E APECS LIBRARY — HASTEROIDS
Reacting to input
- cmap $ s t e p K i n e t i c s dT
iterates over a l l entities a n d a d d s their v e l o c i t y vector m u l t i p l i e d
by time dT to their p o s i t i o n vector a n d also takes care of w r a p p i n g
the space — if a n entity flies out of the screen o n one side, it comes
back i n f r o m the other side.
- cmap $ d e c e l e r a t e S h i p dT
s i m p l y applies deceleration to the ship b y scaling d o w n its velocity
vector s l i g h t l y
- cmapM $ s t e p S h i p S t a t e dT
is responsible for transitioning between ship states ( A l i v e , Exploding
Int, Respawning Int, w h e r e the integers serve as c o u n t d o w n timers
for the state transition) a n d the e x p l o s i o n a n i m a t i o n .
- cmapM_ $ u f o s S h o o t dT
iterates over a l l Uf o c o m p o n e n t s d e c r e m e n t i n g the t i m e to shoot,
16
2. U S I N G T H E APECS LIBRARY — HASTEROIDS
- awardLifelf10000
increments s h i p ' s lives b y 1 for r e a c h i n g every 10 000 score points.
- spawnUfos
r a n d o m l y creates n e w U F O entities o n the left side of the screen,
w i t h the chances increasing as the time spent i n one wave (WaveTime)
passes.
- spawnNewAsteroidWavelfCleared
uses c f o l d f r o m apecs to count all asteroids a n d w h e n there are none
it starts c o u n t i n g u p u s i n g the WavePauseTimer. W h e n the t i m e r
reaches 1500 it calls spawnNewAsteroidWave f r o m the I n i t i a l i z e
m o d u l e , w h i c h uses the r a n d o m stateful generators f r o m the WithResources
reader m o n a d to create n e w asteroids.
- cmap $ \ ( T t l t ) -> T t l $ t - dT
s i m p l y subtracts the f r a m e d e l t a t i m e dT f r o m a l l the TimeToLive
components.
- detectAndHandleCollisions
is defined i n its o w n m o d u l e C o l l i s i o n s . The collisions are detected
and h a n d l e d i n d i v i d u a l l y b e t w e e n each entity g r o u p . T h e general
idea is that w e use cmapM_ inside of cmapM_ as a n equivalent of nested
for loops. T h i s way, for every asteroid, w e iterate (or m a p ) over a l l
the other entities, c h e c k i n g for c o l l i s i o n . W e d o the s i m i l a r for the
rest of the c o m b i n a t i o n pairs, u s i n g i n total = 6 slighlty different
17
2. U S I N G T H E APECS LIBRARY — H A S T E R O I D S
D r a w i n g the scene
2.3 Reflection
18
2. U S I N G T H E APECS LIBRARY — HASTEROIDS
— s t e e r and t h r u s t
handleInput input =
cmap $ \ ( S h i p a , V e l o c i t y v e l ) ->
( Ship $ a + s t e e r i n g input
, V e l o c i t y $ v e l + thrust input a
)
— we r e a l i z e d t h a t we a l s o want t o be a b l e t o pause t h e
-> game
handlelnput' input =
cmapM $ \ ( S h i p a , V e l o c i t y v e l ) -> do
when (wasPressed i n p u t escapeKeycode)
( s e t g l o b a l Paused)
pure ( Ship $ a + s t e e r i n g i n p u t
, V e l o c i t y $ v e l + thrust input a
)
19
2. U S I N G T H E APECS LIBRARY — H A S T E R O I D S
20
3 Focusing on functional purity — pure-asteroids
21
3. F O C U S I N G O N F U N C T I O N A L PURITY — PURE-ASTEROIDS
22
3. F O C U S I N G O N F U N C T I O N A L PURITY — PURE-ASTEROIDS
in drawScene
to
"E T3
ID
> a
LU
to
*• World2
to
ID
>
R
to
LU
NewEvents
( IO Input i
23
3. F O C U S I N G O N F U N C T I O N A L PURITY — PURE-ASTEROIDS
— I Game world s t a t e s t r u c t u r e
data World =
World
wShip Ship
wAsteroids Asteroids
wBullets Bullets
wUf os Ufos
wWaveTime Time
wWavePause Time
_wWaveNum Int
wScore Score
— I Ship s t a t e s t r u c t u r e
data Ship =
Ship
{ _ s P o s i t i o n :: P o s i t i o n
, _ s V e l o c i t y :: V e l o c i t y
, _sAngle :: Angle
, _sLives :: I n t
, _sState :: ShipState
data ShipState
= ShipAlive
I ShipExploding Time
I ShipRespawning Time
24
3. F O C U S I N G O N F U N C T I O N A L PURITY — PURE-ASTEROIDS
25
3. F O C U S I N G O N F U N C T I O N A L PURITY — PURE-ASTEROIDS
L i s t i n g 3 . 4 : The stepper f u n c t i o n .
F i g u r e 3 . 3 s h o w s w h i c h events, r e p r e s e n t e d b y their v a l u e c o n -
structors, entities m a y s e n d to others. The w o r k i n g of the i n d i v i d u a l
substeppers c a n be s u m m a r i z e d as f o l l o w s :
- stepShip
changes the ship's angle a n d velocity based o n the i n p u t a n d updates
its p o s i t i o n . It also detects c o l l i s i o n s w i t h asteroids a n d U F O s . I n
the case of a c o l l i s i o n , it a d d s a n event w i t h the entity's i d to the
event package. Moreover, it subtracts a life i n that case a n d changes
the s h i p ' s state attribute, w h i c h results i n a s p i n n i n g e x p l o s i o n
a n i m a t i o n next f e w frames. T h e n a p o s i t i o n reset f o l l o w e d b y a
26
3. F O C U S I N G O N F U N C T I O N A L PURITY — PURE-ASTEROIDS
second of i n v i n c i b i l i t y . A l l of that is d o n e i n s t e p S h i p c o n d i t i o n e d
by the state.
- stepAsteroids
does not send any events, o n l y updates the p o s i t i o n of a l l asteroids.
- stepBullets
first filters out b u l l e t s that r u n out of t i m e to l i v e ( T T L ) , a n d t h e n
it uses t r a v e r s e to c a l l s t e p B u l l e t o n a l l the b u l l e t s , c o l l e c t i n g
all events as a n A p p l i c a t i v e side effect. s t e p B u l l e t then updates
2
- stepUfos
operates s i m i l a r l y to s t e p B u l l e t s . It filters out the ones out of T T L ,
traverses over a l l of t h e m , a n d at the e n d , it r a n d o m l y inserts a
new U F O . D u r i n g the traversal, positions, T T L s , a n d "time-to-shoot"
counters are u p d a t e d . It checks for c o l l i s i o n s w i t h asteroids a n d
sends a n event together w i t h setting its T T L to 0 if that h a p p e n s .
A d d i t i o n a l l y , w h e n the time-to-shoot timer reaches 0, it is refreshed
to 2000 m s , a n d a n event is sent to B u l l e t s as a request to insert
their shot w i t h i n f o r m a t i o n a b o u t the d i r e c t i o n a n d p o s i t i o n . T h e
d i r e c t i o n is c a l c u l a t e d u s i n g one of the same t w o a l g o r i t h m s as i n
hAsteroids.
- stepScore
sends a n event to the s h i p , a w a r d i n g it w i t h a n extra life for every
10 000 p o i n t s g a i n e d .
27
3. F O C U S I N G O N F U N C T I O N A L PURITY — PURE-ASTEROIDS
28
3. F O C U S I N G O N F U N C T I O N A L PURITY — PURE-ASTEROIDS
L i s t i n g 3 . 5 : The event p r o c e s s i n g f u n c t i o n .
- BreakE Int
causes the addressed asteroid to break into t w o or to be deleted if it
is the smallest size.
- HitE | GainLifeE
causes the ship to either lose a life a n d set the state to Exploding or
to g a i n a n extra life.
- DestroyE Int
targets a U F O a n d s i m p l y requests its deletion.
- UfoShootsE P o s i t i o n V e l o c i t y
gives the B u l l e t s a l l the n e e d e d i n f o r m a t i o n for i n s e r t i n g a n e w
bullet shot b y U F O .
- IncreaseE Int
says h o w m a n y p o i n t s s h o u l d be a d d e d to the current score.
29
3. F O C U S I N G O N F U N C T I O N A L PURITY — PURE-ASTEROIDS
3.3 Reflection
O v e r a l l , pure-asteroids achieves w h a t it set out to d o — we can observe
m a n y of the benefits described i n Section 1.1. Because it does not use
m u c h abstraction, the code is p e r c e i v a b l y safer a n d m o r e expressive.
For e x a m p l e , w e c a n l o o k at shoot f r o m the S t e p . B u l l e t s m o d u l e :
30
3. F O C U S I N G O N F U N C T I O N A L PURITY — PURE-ASTEROIDS
31
4 Analyzing an existing C++ implementation
This chapter, describes the imperative i m p l e m e n t a t i o n that w e later use
to compare against i n Chapter 5. W e shall refer to it as " i m p - a s t e r o i d s " .
It w a s m a d e b y J a s o n H a l v e r s o n , a n d its G i t H u b r e p o s i t o r y c a n be
f o u n d at h t t p s : / / g i t h u b . c o m / H a l v e r s o n - J a s o n / A s t e r o i d s . W e cre-
ated a f o r k of this r e p o s i t o r y w i t h a b r a n c h n a m e d o r g a n i z e d [23]
w i t h the o r i g i n a l g a m e w i t h r e o r g a n i z e d a n d r e f o r m a t t e d files for
convenience.
W e acknowledge that C++ m a y not be the most relevant c o m p a r i s o n
as there are other choices for m a k i n g a simple game quickly. However,
we chose this example because it does not use any t h i r d - p a r t y engines.
T h a t w a y , w e c a n easily c o m p a r e it to o u r i m p l e m e n t a t i o n s w i t h o u t
a n extra layer of complexity.
F u r t h e r m o r e , the o p t i o n s available a l l t u r n e d out to be of gener-
ally l o w e r q u a l i t y L i k e o u r t w o i m p l e m e n t a t i o n s , this v e r s i o n is not
flawless, b u t w e p o i n t out its mistakes a n d present t h e m as a possible
1
LA
O
Oh
0
F i g u r e 4.1: A Screenshot of imp-asteroids.
1. The game was made as a school assignment, and f r o m the commented TODOs
throughout the code, we can judge that there were certain time limitations.
32
4. A N A L Y Z I N G A N EXISTING C + + IMPLEMENTATION
33
4. A N A L Y Z I N G A N EXISTING C + + I M P L E M E N T A T I O N
v o i d c a l l B a c k ( c o n s t I n t e r f a c e *pUI, v o i d *p)
{
Game *pGame = (Game *)p;
pGame->advance();
pGame->handleInput(*pUI);
pGame->draw(*pUI);
S t e p p i n g the w o r l d
- Game::advanceBullets()
iterates over a l l the b u l l e t pointers a n d calls advance o n t h e m .
- Game::advanceAsteroids()
iterates over a l l the asteroid pointers a n d calls advance o n t h e m . If
the c o l l e c t i o n is empty, it inserts five n e w large asteroids.
- Game::advanceShip()
calls advance o n the s h i p .
- Game::handleCollisions()
iterates over every bullet a n d asteroid, a n d i n the case of a collision it
marks the bullet a n d the asteroid as d e a d , a n d creates n e w asteroids
unless the destroyed one w a s a l r e a d y the smallest size.
- Game::cleanUpZombies()
checks if entities are d e a d a n d deletes t h e m if so. D e l a y i n g the dele-
tion prevents inconsistencies caused b y serial u p d a t i n g of entities —
this w a y the order of iteration does not matter.
34
4- A N A L Y Z I N G A N E X I S T I N G C++ IMPLEMENTATION
Input h a n d l i n g
Rendering
4.3 Reflection
The game benefits f r o m O O P as most of the top-level f u n c t i o n (method)
calls are v e r y intuitive. It also avoids d u p l i c i t y of code b y u s i n g i n h e r i -
tance for p o s i t i o n u p d a t i n g a n d p o l y m o r p h i s m for u n i v e r s a l c o l l i s i o n
detection. It offers decent s c a l a b i l i t y i n a d d i n g n e w entities or fea-
tures; h o w e v e r , there s h o u l d be separate m a n a g e r classes for each
entity g r o u p . W e also u s e d v a l g r i n d for m e m o r y p r o f i l i n g , a n d it
discovered several usages of u n i n i t i a l i z e d values a n d m e m o r y leaks.
W e also d i s l i k e G L U T ' s use of callbacks a n d g l o b a l state, m a k i n g
things c o n f u s i n g a n d difficult to test. A l t h o u g h , w e u n d e r s t a n d that the
goal of this particular i m p l e m e n t a t i o n was not to be overly a m b i t i o u s
about s c a l a b i l i t y since the game is s t r a i g h t f o r w a r d . M o r e o v e r , side
effects c a n be present a n y w h e r e , a n d m u t a t i o n of the game's state
also is not l i m i t e d v e r y strongly. T h i s is n a t u r a l l y a challenge for a l l
imperative languages.
O n e c o u l d argue that this is n o t a n issue a n d that p r o g r a m m e r s
o n l y n e e d be m o r e c o m p e t e n t about their usage of these p o w e r s . To
combat this, the a l r e a d y q u o t e d J o h n C a r m a c k t a l k e d about h o w be-
i n g a t e c h n i c a l director over m i l l i o n s of lines of c o d e , he s a w h o w
" e v e r y t h i n g that is s y n t a c t i c a l l y l e g a l that the c o m p i l e r w i l l accept,
w i l l eventually w i n d u p i n y o u r codebase." [22] H e also s a i d that "it's
just a m a z i n g h o w m a n y m i s t a k e s , a n d h o w b a d p r o g r a m m e r s c a n
b e . " [22] Because p r o g r a m m e r s are, after a l l , o n l y h u m a n s , systems
35
4. A N A L Y Z I N G A N EXISTING C + + IMPLEMENTATION
36
5 Evaluation of the approaches
I n this chapter, w e first c o m p a r e H a s k e l l to i m p e r a t i v e languages i n
general or specifically to C++, often referencing back to the p r o m i s e d
benefits of H a s k e l l f r o m S e c t i o n 1.1. T h e n w e d i s c u s s the conflicts
observed i n the c o m p a r i s o n s a n d their possible solutions.
5.1 Comparison
T h i s section c o m p a r e s the three e x a m p l e i m p l e m e n t a t i o n s or, m o r e
b r o a d l y , H a s k e l l a n d i m p e r a t i v e l a n g u a g e s r e p r e s e n t e d b y C++. F o r
this, w e reference the p r e v i o u s chapters about i n d i v i d u a l i m p l e m e n t a -
tions. It is important to note that C++ is b y no means meant to represent
i m p e r a t i v e languages f u l l y ; e v e n less so is the c h o s e n i m p e r a t i v e i m -
plementation of A s t e r o i d s (further referred to as imp-asteroids) meant
to represent the i d e a l game d e s i g n i n C++. N o t o n l y it has f l a w s , b u t
it is also a n e v e n s i m p l e r v e r s i o n of the o r i g i n a l game i n s o m e w a y s
t h a n o u r t w o i m p l e m e n t a t i o n s . W e t r y to address this i n e s p e c i a l l y
relevant places; i n others, it is left out for the sake of conciseness a n d
readability.
T h e c o m p a r i s o n is o r g a n i z e d b y q u a l i t i e s i m p o r t a n t i n g a m e de-
v e l o p m e n t : f l e x i b i l i t y a n d scalability, expressiveness a n d safeness,
d e v e l o p m e n t costs, performance. The section is t h e n closed off b y a n
a d d i t i o n a l c o m p a r i s o n of state abstraction a n d f e w statistical observa-
tions about the codebases.
37
5- E V A L U A T I O N O F T H E A P P R O A C H E S
A s w e have a l r e a d y d i s c u s s e d i n C h a p t e r 1, f u n c t i o n a l languages
are d e s i g n e d to b e clearer (expressiveness) a n d to better c o n t r o l side
effects (safeness) t h a n c o n v e n t i o n a l i m p e r a t i v e languages. N o w the
i m p e r a t i v e c o d e c a n b e e v e n m o r e o r less unsafe d e p e n d i n g o n its
type system. C++ is m o s t l y strongly a n d statically t y p e d , p r o v i d i n g a
certain a m o u n t of assurance. Some other languages are not. T h i s c a n
protect u s f r o m t r y i n g to a d d a n object to a n u m b e r , for instance.
M a n y languages also take v a r i o u s steps t o w a r d s c o n t r o l l i n g side
effects. O n e such example c o u l d be the c o n s t k e y w o r d u s e d to define
a v a r i a b l e that cannot b e m u t a t e d . I n C++, this k e y w o r d c a n also be
u s e d o n methods to prevent t h e m f r o m c h a n g i n g the state of the object,
a l l o w i n g us to call these methods even o n c o n s t objects. Usage of this
k e y w o r d w o u l d prevent the author of imp-asteroids f r o m w r i t i n g the
d r a w i n g f u n c t i o n seen i n L i s t i n g 5.1 that u n e x p e c t e d l y also changes
the state of b u l l e t s . H o w e v e r , l a n g u a g e s l i k e Java o r P y t h o n d o n o t
support i m m u t a b l e objects, a n d w e c a n see h o w control of side effects,
i n general, is a " p l a n B " i n the imperative p a r a d i g m .
38
5- E V A L U A T I O N O F T H E A P P R O A C H E S
v o i d Game::draw(const I n t e r f a c e &ui) {
f o r ( i n t i = 0 ; i < b u l l e t s . s i z e ( ) ; i++) {
i f ( b u l l e t s [ i ] -> i s A l i v e ( ) ) {
b u l l e t s [ i ] - >draw();
b u l l e t s [ i ] - >setHealth(); // a s e t t e r ? !
}
}
}
C o n v e r s e l y , since H a s k e l l o r i g i n a t e d as a n a c a d e m i c l a n g u a g e ,
f u n c t i o n a l p u r i t y w a s a l l o w e d to be p l a n A , a n d h a v i n g side effects
w a s a c t u a l l y p l a n B i n this case. W e s a w h o w t h i s , together w i t h the
t y p e s y s t e m , w o r k s out w e l l for expressiveness a n d c l a r i t y i n the
example of pure-asteroids, as showcased o n a n exemplary f u n c t i o n at
the b e g i n n i n g of Section 3.3. A n d because a l l variables are i m m u t a b l e ,
change is m a d e explicit as a new r e t u r n e d v a l u e that we pass f o r w a r d .
M o r e o v e r , a n y i n p u t / o u t p u t side effects are clearly separated b y the
1 0 m o n a d , a n d the rest of the c o d e is e n t i r e l y d e t e r m i n i s t i c , w h i c h
alltogether w i t h strong static t y p i n g makes for a v e r y safe language —
not o n l y there is less p o t e n t i a l sources of b u g s , b u t the correctness of
a p r o g r a m is easier to perceive a n d argue about.
That is if u s e d w e l l — hAsteroids t u r n e d out to be a v e r y interest-
i n g game, apecs m a k e s game p r o g r a m m i n g i n H a s k e l l approachable
and p r o v i d e s excellent performance b y b e i n g strict and imperative. This
i n n e r i m p e r a t i v e n e s s m a k e s p u r i t y sort of a p l a n B a g a i n , a n d the
p r o g r a m m e r has to be clever about u s i n g m o n a d p o l y m o r p h i s m if
they w a n t to keep " t h e d a n g e r of 1 0 " c o n t a i n e d . T h i s has o c c u r r e d
to us i n the m i d d l e of the h A s t e r o i d s d e v e l o p m e n t process, so w e
d e c i d e d to embrace it a n d see w h e r e it leads. If w e h a d redesigned the
types, we c o u l d have reached better safeness a n d even expressiveness.
H o w e v e r , w i t h the game w o r l d state abstracted, it is still not a l w a y s
clear w h a t f u n c t i o n s d o w h e n a p p l i e d t h r o u g h cmapM or cmapM_.
39
5- E V A L U A T I O N O F T H E A P P R O A C H E S
5.1.3 D e v e l o p m e n t costs
Interpreter
F u n c t i o n a l elegance
f u n c t i o n , w h i l e too b e i n g o n l y p a r t i a l l y a p p l i e d . G r a n t e d , other l a n -
guages have structures to m a k e this sort of task at least slightly m o r e
elegant too a n d e v e n C++ itself has s t d : : f o r e a c h , w h i c h c o u l d be
u s e d to make this piece of code more concise. H o w e v e r , this character-
istic extends to the w h o l e H a s k e l l code base — i n b o t h of o u r games
40
5- E V A L U A T I O N O F T H E A P P R O A C H E S
// C++
void Game::advanceAsteroids() {
for (list<Asteroid*>::iterator i t = asteroids.begin();
i t != asteroids.end(); it++) {
(*it)->advance();
}
}
— Haskell
stepAsteroids :: Time -> Asteroids -> Asteroids
stepAsteroids dT = HM.map (stepAsteroid dT)
L i s t i n g 5.2: A s t e r o i d s t e p p i n g w i t h f o r - l o o p a n d m a p .
Testing a n d d e b u g g i n g
41
5- E V A L U A T I O N O F T H E A P P R O A C H E S
// C++
void Game::advanceBullets() {
f o r ( i n t i = 0; i < b u l l e t s . s i z e ( ) ; i++) {
if (bullets[i]->isAlive()) {
bullets[i]->advance();
if (!isOnScreen(bullets[i]->getPoint())) {
bullets[i]->kill();
}
— Haskell
s t e p B u l l e t s : : Time -> W o r l d -> B u l l e t s -> ( W o r l d E v e n t s ,
Bullets)
s t e p B u l l e t s dT w =
t r a v e r s e ( s t e p B u l l e t dT w) . f i l t e r D e a d B u l l e t s
L i s t i n g 5.3: I m p u r e a n d p u r e s t e p p i n g of bullets.
bullets based on the input state, w h i c h happens elsewhere i n the C++ implementa-
tion.
42
5- E V A L U A T I O N O F T H E A P P R O A C H E S
Tools
5.1.4 Performance
43
5- E V A L U A T I O N O F T H E A P P R O A C H E S
10000 41 2 1
500 59 30 16
250 59 46 23
100 59 55 37
50 59 74 92
25 59 117 140
10 59 141 154
44
5- E V A L U A T I O N O F T H E A P P R O A C H E S
less u s e d t i m e a n d a l l o c a t e d m e m o r y t h a n i n p u r e - a s t e r o i d s . T h i s
eliminates the p o s s i b i l i t y of h A s t e r o i d s b e i n g bottlenecked b y d r a w i n g
textures instead of vectors. M o s t i m p o r t a n t l y , it s h o w e d that neither
of the games h a d issues w i t h G a r b a g e C o l l e c t i o n ( G C ) as this c a n
become a p r o b l e m w i t h larger l a z y systems. The p r o d u c t i v i t y reported
by the - s p r o f i l i n g flag was 99.1 % for h A s t e r o i d s a n d 97.6 % for p u r e -
asteroids, m e a n i n g G C is n o t c a u s i n g a n y m e a n i n g f u l delays i n o u r
games.
T h i s b r i n g s us to the t o o l s available a n d ease of o p t i m i z a t i o n i n
general. A s m e n t i o n e d i n the p r e v i o u s subsection, there are v a r i o u s
tools, i n c l u d i n g profilers for H a s k e l l , b u t C++ w i l l have a larger variety.
A n o t h e r advantage for C++ i n this d i s c i p l i n e is its l o w - l e v e l access to
h a r d w a r e a n d m e m o r y m a n a g e m e n t . G e n e r a l l y , the less abstracted
code is easier to o p t i m i z e since it is closer to w h a t the C P U w i l l actually
execute. W i t h m o r e abstraction, m o r e w o r k m u s t be done to f i n d out
w h a t the C P U does i n the e n d . T h i s is especially the case for H a s k e l l ,
w h i c h has a h i g h l e v e l of abstraction a n d d u r i n g c o m p i l a t i o n goes
t h r o u g h three i n t e r m e d i a t e languages, therefore if one desires to see
h o w the code gets "unabstracted", he m u s t first learn at least the first
of the i n t e r m e d i a t e languages ( C o r e ) . To m a k e u p for this at least
partially, as w e have also stated before, G H C can d o a lot of o p t i m i z i n g
o n its o w n , a n d p u r e l y f u n c t i o n a l c o d e is also easier to execute i n
p a r a l l e l a n d concurrently, w h i c h H a s k e l l is v e r y g o o d at.
5.1.5 State a b s t r a c t i o n
6. The profiling results can be found on the mentioned bench branch of our
G i t H u b repository: h t t p s : / / g i t h u b . com/honzaf l a s h / b a - t h e s i s / t r e e / b e n c h /
p u r e - a s t e r o i d s / r e s u l t s and h t t p s : / / g i t h u b . c o m / h o n z a f l a s h / b a - t h e s i s /
t r e e / b e n c h / h A s t e r o i d s / r e s u l t s . Specifically, the profiling of cost centers is i n
folders o p t - p .
45
5- E V A L U A T I O N O F T H E A P P R O A C H E S
46
5- E V A L U A T I O N O F T H E A P P R O A C H E S
A s a b o n u s , w e i n c l u d e f e w s i m p l e statistics a b o u t c o d e l e n g t h . W e
counted the lines, w o r d s a n d characters u s i n g the wc c o m m a n d . T h e n
8
m e n t U F O s , score, s h i p lives, or m e n u s .
3000 counted
l lines
2500
2000
47
5- E V A L U A T I O N O F T H E A P P R O A C H E S
F i g u r e 5.2: C o d e d e n s i t y b y project.
48
5- E V A L U A T I O N O F T H E A P P R O A C H E S
49
5- E V A L U A T I O N O F T H E A P P R O A C H E S
data Resources =
Res
{ textures :: Textures
, random :: RandGen
}
L i s t i n g 5.5: M o d u l a r reader m o n a d d e s i g n .
50
5- E V A L U A T I O N O F T H E A P P R O A C H E S
51
5- E V A L U A T I O N O F T H E A P P R O A C H E S
/ \
Freedom
T
How we perceive it What we can do
be h i d d e n i n a n a p p r o p r i a t e l y n a m e d m o n a d w i t h o u t a n issue. That
way, w e keep expressiveness b u t a l l o w for flexibility. A s a n a d d i t i o n a l
s u p p o r t i n g e x a m p l e , w e consider the f o l l o w i n g t w o f u n c t i o n types:
10. Philip Wadler speaks more on "combining the indulgences of impurity with the
blessings of p u r i t y " by using monads i n his paper Comprehending Monads [25].
11. In a larger game, textures may need to load dynamically; still, they are read-
mostly data.
52
5. E V A L U A T I O N OF T H E APPROACHES
12. A n example of such an approach can be seen i n the Dino Rush game, described in
the blog post A Game in Haskell - Dino Rush [10] mentioned previously i n Section 1.1.2.
53
Conclusion
In this thesis, w e u s e d t w o a p p r o a c h e s to r e i m p l e m e n t A s t e r o i d s
b y A t a r i i n H a s k e l l r e s u l t i n g i n t w o projects: h A s t e r o i d s a n d p u r e -
asteroids. W e have described each i m p l e m e n t a t i o n i n Chapters 2 a n d 3.
A d d i t i o n a l l y , w e p i c k e d a n existing imperative reimplementation f r o m
G i t H u b a n d also o u t l i n e d its operation i n Chapter 4. T h e n , i n Chapter 5,
w e have c o m p a r e d the i m p l e m e n t a t i o n s to d e t e r m i n e w h e t h e r the
f u n c t i o n a l p r o g r a m m i n g p a r a d i g m ' s general benefits a p p l y to game
development.
W e have gathered that o u r t w o approaches are opposite extremes
o n the s p e c t r u m of abstraction a n d explicitness. M o r e o v e r , w e d i s -
cussed the relationship of those characteristics w i t h f r e e d o m of effects
a n d safeness, c o n c l u d i n g that the focus s h o u l d b e o n expressiveness
a n d flexibility. W e a r g u e d that the latter t w o qualities are achieved b y
balancing the former two pairs a n d s h o w e d h o w H a s k e l l ' s typeclasses
c o u l d be u s e d together w i t h m o n a d s to achieve the d e s i r e d balance.
W e have r e d i s c o v e r e d that H a s k e l l c a n b e v e r y i m p e r a t i v e , as ex-
p l a i n e d b y S i m o n P. Jones a n d P h i l i p W a d l e r i n their paper Imperative
Functional Programming [26]. In that paper, they described for the first
time h o w m o n a d s c o u l d be u s e d for i n p u t / o u t p u t operations i n l a z y
languages a n d c o n f i r m e d w h a t w e see as the result i n h A s t e r o i d s
— w i t h the 10 m o n a d , H a s k e l l c a n v e r y c l o s e l y resemble C . Yet, it
keeps the benefits of f u n c t i o n a l style intact b y clearly separating the
imperative f r o m the f u n c t i o n a l .
S i m u l t a n e o u s l y , w h i l e the creators of H a s k e l l argue for laziness,
it c a n cause p e r f o r m a n c e issues. T h i s h a p p e n s w h e n extensive u n -
evaluated data accumulates a n d results i n l o n g delays caused b y the
Garbage C o l l e c t i o n ( G C ) . This is especially of concern for v i d e o games
w h e r e the t i m e to c o m p u t e a n d r e n d e r a frame is l i m i t e d . M o r e o v e r ,
f i n d i n g the sources of those " l a z y m e m o r y l e a k s " a n d d o i n g other
o p t i m i z a t i o n s c a n b e m o r e c h a l l e n g i n g d u e to the language's s t r o n g
abstraction. H o w e v e r , w e d i d n o t experience a n y p r o b l e m s w i t h G C
i n o u r small-scale experiments.
F u r t h e r m o r e , w e have f o u n d that the apecs l i b r a r y m a k e s game
p r o g r a m m i n g i n H a s k e l l s u r p r i s i n g l y accessible. h A s t e r o i d s outper-
f o r m e d pure-asteroids b y u p to 100 % for h i g h entity counts because
54
5- E V A L U A T I O N O F T H E A P P R O A C H E S
of the E n t i t y - C o m p o n e n t - S y s t e m d e s i g n (a d a t a - o r i e n t e d d e s i g n )
p r o v i d e d b y apecs. C r e a t i n g pure-asteroids was more d e m a n d i n g , but
its d e s i g n is clearer, a n d it keeps p a r a l l e l i s m i n m i n d . E v e n t h o u g h
it does n o t a c t u a l l y i m p l e m e n t it, w e p a i d attention to m a k i n g the
architecture easy to m o d i f y for p a r a l l e l c o m p u t a t i o n .
U l t i m a t e l y , w e believe that the game's code c a n be m o r e m o d u l a r ,
i n parts briefer, easier to u n d e r s t a n d a n d to argue about its correct-
ness t h a n its i m p e r a t i v e equivalent. It does c o m e at a h i g h e r u p f r o n t
cost, especially c o n s i d e r i n g the l i m i t e d libraries a n d tools (at least
c o m p a r e d to the rest of the i n d u s t r y ) . Regardless, w e judge o u r devel-
o p m e n t experience as v e r y p o s i t i v e , a n d w e w o u l d encourage others
interested i n g a m e p r o g r a m m i n g to t r y H a s k e l l themselves. It m a y
not c u r r e n t l y be the safest w a y to b r i n g a g a m e to the market, b u t at
the bare m i n i m u m , it is a v a l u a b l e l e a r n i n g experience a n d , at best,a
step for the w h o l e i n d u s t r y t o w a r d s better g a m e engines w i t h a l l of
the p e r k s of p u r e l y f u n c t i o n a l p r o g r a m m i n g .
T h e benefits of p u r e l y f u n c t i o n a l d e s i g n b e c o m e most significant
i n the l o n g t e r m a n d large scale. H o w e v e r , o u r e x a m p l e s are s m a l l
i n scale, a n d so it r e m a i n s to be p r o v e n i n practice that o u r f i n d i n g s
are a p p l i c a b l e to m o r e c o m p l e x games w i t h o u t r u n n i n g i n t o issues
w i t h laziness, for instance. M o r e o v e r , w e w o u l d be c u r i o u s to see
w h e t h e r a d d i n g the p a r a l l e l i s m i n t o pure-asteroids w o u l d better the
performance even at that scale, a n d further, h o w it w o u l d compare to
the data-oriented d e s i g n of apecs as the entity counts g r o w .
55
Bibliography
1. C A R P A Y , Jonas, apecs: Fast Entity-Component-System library for
game programming [online] [ v i s i t e d o n 2021-04-22]. A v a i l a b l e
from: h t t p s : //hackage. h a s k e l l . org/package/apecs.
2. H U G H E S , John. W h y Functional P r o g r a m m i n g Matters. The Com-
puter Journal [online]. 1989, v o l . 32, n o . 2 [visited o n 2021-04-25].
ISSN 0010-4620. A v a i l a b l e f r o m DOI: 1 0 . 1 0 9 3 / c o m j n l / 3 2 . 2 . 9 8 .
3. N I L S S O N , H e n r i k ; C O U R T N E Y , A n o t n y . Yampa: Elegant Func-
tional Reactive Programming Language for Hybrid Systems [online]
[visited o n 2021-05-01]. A v a i l a b l e f r o m : h t t p : / / h a c k a g e . h a s k e l l
org/package/Yampa.
4. C O R R , Zack. Helm: A functionally reactive game engine [online] [vis-
i t e d o n 2021-05-01]. A v a i l a b l e f r o m : h t t p : / / h a c k a g e . h a s k e l l .
org/package/helm.
5. G E R G E L Y , Patai. elerea: A minimalistic FRP library [online] [vis-
i t e d o n 2021-05-01]. A v a i l a b l e f r o m : h t t p : / / h a c k a g e . h a s k e l l .
org/package/elerea.
6. S O Y L E M E Z , E r t u g r u l . netwire: Functional reactive programming
library [online] [ v i s i t e d o n 2021-05-01]. A v a i l a b l e f r o m : h t t p :
//hackage.haskell.org/package/netwire.
7. F U R T A D O , A n d r e . FunGEn: A lightweight, cross-platform, OpenGL-
basedgame engine [online] [visited o n 2021-05-01]. A v a i l a b l e f r o m :
http://hackage.haskell.org/package/FunGEn.
8. K E E R A S T U D I O S . Products and Services [ o n l i n e ] . N o t t i n g h a m
[visited o n 2021-05-04]. A v a i l a b l e f r o m : h t t p s : / / k e e r a . c o . u k /
products-and-services/.
9. P A L F R E Y , Jack. Wayward Tide: Technical Info [online]. C h u c k l e f i s h
[visited o n 2021-05-04]. A v a i l a b l e f r o m : h t t p s : / / c h u c k l e f i s h .
org/blog/wayward-tide-technical-details/.
10. V A R G A S , Joe. A Game in Haskell - Dino Rush [online]. 2018-02-28
[ v i s i t e d o n 2021-05-04]. A v a i l a b l e f r o m : h t t p : / / j x v . i o / b l o g /
2018-02-28-A-Game-in-Haskell.
56
BIBLIOGRAPHY
57
BIBLIOGRAPHY
58
A Electronic attachments
T h e i m p l e m e n t a t i o n s d e s c r i b e d i n this thesis are attached w i t h it i n
a n archive file. T h e contents of the archive are o u t l i n e d here:
implementations
_hAsteroids the h A s t e r o i d s project root
-fPP
L_ M a i n . hs the entry p o i n t
.resources textures a n d fonts
.src library modules
. p a c k a g e . yaml package details i n c l u d i n g dependencies
_ s t a c k . yaml stack c o n f i g u r a t i o n
_pure-asteroids the pure-asteroids project root
^app
1_ M a i n . hs the entry p o i n t
.resources fonts
.src library modules
. p a c k a g e . yaml package details i n c l u d i n g dependencies
. s t a c k . yaml stack c o n f i g u r a t i o n
. README. md r e a d m e file f r o m the G i t H u b repository
The b u i l d instructions are p r o v i d e d i n the f o l l o w i n g a p p e n d i x .
Latest v e r s i o n of projects can be f o u n d at h t t p s : / / g i t h u b . com/honzaf l a s h /
ba-thesis.
59
B Build instructions
The b u i l d process for b o t h h A s t e r o i d s a n d pure-asteroids is v e r y s i m i -
lar. The f o l l o w i n g r e q u i r e m e n t s m u s t be met first.
Haskell Tool Stack
B o t h games are projects m a n a g e d u s i n g the H a s k e l l T o o l Stack; 1
therefore, s t a c k n e e d s to b e i n s t a l l e d . W e r e c o m m e n d r u n n i n g
s t a c k upgrade before a t t e m p t i n g the b u i l d .
S D L libraries
The u s e d H a s k e l l S D L b i n d i n g s r e q u i r e the C l i b r a r i e s to be i n -
stalled. Specifically, b o t h projects n e e d S D L a n d S D L _ t t f , a n d
h A s t e r o i d s also uses S D L _ i m a g e
Operating System
Stack a n d S D L s u p p o r t L i n u x , W i n d o w s , a n d M a c O S . The b u i l d
was tested o n U b u n t u 20.04 a n d W i n d o w s 10 b u i l d 19042.
W i t h that, w e can r u n s t a c k b u i l d i n the project's root directory. This
m a y take a w h i l e as s t a c k d o w n l o a d s a n d installs a l l the d e p e n d e n -
cies. To l a u n c h the g a m e w h e n project is b u i l t successfully, execute
s t a c k r u n or s t a c k exec < n a m e - o f - t h e - e x e c u t a b l e > , a g a i n , i n the
project's root directory. W e were unable to m a k e s t a c k exec w o r k o n
W i n d o w s , so alternatively, w e c a n r u n s t a c k g h c i a n d t h e n r u n the
main f u n c t i o n i n G H C i .
60
C Additional code examples
import Control.Monad.10.Class
import Control.Monad.Reader
type Textures = S t r i n g
type RandGen = [Int]
data Resources =
Res
{ t e x t u r e s :: Textures
, random :: RandGen
}
61
C . ADDITIONAL CODE EXAMPLES
main :: 10 ()
main = do
l e t world = World 10
l e t resources = Res
{ t e x t u r e s = "Current world s t a t e : "
, random = [4, 2]
}
runReaderT (gameLoop world) resources
62
C . ADDITIONAL CODE EXAMPLES
M o r e m a p usage w i t h p a r t i a l l y e v a l u a t e d functions:
63