Thank you everyone. If I can have your attention again please. Because now the fun starts.
We have games, we have drones, we have music. It's finally time to party and the first party
person will talk about gaming in Go. Run for plaza Francesc.
Thank you very much for being here. Before we start, if you want to check the game, it's
available on MazeWorlds.com. If you decide to check it out while you talk, it's fine.
It's still in Earth development so it may have some bugs, it may crash, but don't worry,
just play with it if you want to and have fun. That's why I did it.
So a bit of myself. I'm a Go developer. I've been working in Go in back end mostly for
the past nine years. Before that I was doing JavaScript, Pearl and Ruby. So nothing about
gaming. So I have no knowledge when I started doing this game. Why did I do it? Why did I
decide to build the game for myself? So basically a few years back I was thinking like, oh, I
would like to play a game that I used to play when I was in high school. So when I was in
high school, every Friday with my friends we went to a cyber coffee and we used to play
games like Warcraft or anything like that. And not only Warcraft but mods about Warcraft,
which nowadays some of them have become popular like League of Legends. Maybe you knew about
him. So League of Legends, it came from a mod of Warcraft which is called Dota and also
Dota 2 is a mod that came from Warcraft for the same one. So one of the mods that I used
to play on Warcraft was called Line Toward Wars. And I really loved it, but I've never
been able to find anyone who ported it from the actual implementation to something which
is not reliant to anything of Warcraft because this mod is available in Warcraft 3 which
is from 2007. So remember, it's on Starcraft, it's on Warcraft 3 Reforged which is the new
version that they released. But you always have to have Warcraft as a platform to play
any of these mods. So I said, okay, how hard can it be to do something like that? Based
on that, this mod is not that difficult. So first of all, I started checking out, okay,
I want to build a game and I remember hearing a friend of mine saying, okay, I built a game
for my kid in Lua. So I said, oh, let's check out Lua and see what it has. And with Lua,
I found Lof. This is the name of the library. This library basically is a two-day game engine
and I started doing the tutorial. The first tutorial which is building a small game which
I'm going to show later on. But when I was building the game, I was thinking, okay, I
know what I want to build and I know that we'll need a backend. I know that the backend,
I'm going to build it in Go, I'm not going to do it in Lua. And I most likely need to
share things between the frontend, the client, and the backend. And I don't fancy rewriting
stuff so I said, let's search if there's anything in Go which does the same. And searching
in Go, I found Evitan. Or Evitan, I don't know which is the representation. So an Evitan
in the description is basically a two-day game engine, the same one as Lof. So I said,
oh, that's fine. Let's check the documentation and let's check how it looks like. This is
the simplest, simplest Hello World in a game engine. Hello World is printing Hello World
on the top right of your screen, basically. And as you can see, basically, it has, in
the main, you set the size of the windows that you're going to print out. You set the
title that it will have. Hello World in this case. It's just the title of the windows,
not what it will be inside of it. And then you use Evitan to run the game and then you
pass a stroke. The stroke has to fulfill these four, I guess, three functions. One is for
interface. One is update, draw, and layout. Layout is a simple one. It's basically the
size of the screen outside of where you are. So you can print a small screen on a bigger
screen. Then you have update and draw, which were really interesting for me because were
the same names that the library that I did the first tutorial had. So basically, those
two name functions did the same thing as the ones on love. So I didn't lose my time doing
something in Lua because it was the same. So basically, update where it does is every game
tick, which is 60 times per second, it will call this function. And in this function, you're
supposed to hear for events from the user, like clicking or with a mouse scrolling with
the wheel, clicking, typing anything on the keyboard, you're supposed to hear, to listen
for those events there and do something. And then on the draw function, which is called
every render time of your screen, you're supposed to draw what it was that the user did if you
want to do anything on that. And that's it. That's all the functionality that it gives you.
Aside from all the helpers of listening for stuff, that doesn't matter as it gives you. So if
you want to do anything, you are basically building on top of that. So my first games, I did at
the beginning four games just for me to learn libraries and to be comfortable to then start
doing my own game. So the first one was shoot the enemy. This is the one that I copied from
the Lua library. And just because the a bit in library didn't have any useful at least
at the time. And all the tutorials were examples. So you want to do this? There's an example.
You want to do that? There's an example. It has a lot of examples, but not a tutorial that
kind of drives through all the stuff that you are able to do. So the first one was this one
that I copied from the Lua implementation, which is the only one we're going to play. It's
this one. So you are able to move. The snake is the enemy. It has a life on top left, which
is the number of life, which is 10. And me and the panda. I move the panda with A and
D. And if I play space, I shoot. If it hits, that was lucky. If it hits, it moves faster,
so it's harder for me to finish the game. It's not because I can spam it and just finish
the game easily, but the idea is it's harder for you to finish the game with that. So that
was my first game. This allowed me to know how to print something on the screen, the
image, get the events from my keyboard of moving left and right to move the panda. And
then let me drink a bit and I'm just going to drink. And then having something that moves
automatically, the snake is moving by itself, and then shooting something when they press
something, and that also is moving by itself, which is the bullet, and then detecting the
collision from the bullet to the actual snake and then producing the life. So with that
simple tutorial, you get all that, which is really useful. So then I decided, okay, let's
make something else. I was moving out of the tutorials because that's the basics. As you
saw, the interface is really simple. You have all the updates or whatever you want to do.
So then I decided to make the snake. I'm not going to play this one just because the image
you see is one pixel by one pixel and hitting the actual box is really awkward. So I'm just
going to make a full of my software in that game. But it works. And you have the score
that you have on the top left, so how many of the boxes did you get, and it gets longer,
and then you can go to the edge of the screen and it will appear on the other end. So the
only thing that kills you is eating yourself. So one of the normal snakes. The next one,
the radio, is space and bothers. We all know how it was, so it's basically you can move
the spaceship to the left to the right, you click space, and then you kill the invaders.
Same thing. So nothing much more difficult than the first one, for example, this one.
But then when I finished this, I said, okay, now I know a bit of the basics, but there
are a few things I didn't touch yet on regards of what I want to do, which is the game that
I will tell you later on what it's about. And the thing that I was missing is basically
how units move. So not just moving, but the assets of the unit moving up, moving left,
moving right, and so on. So you print those on the screen, so when you actually do the
movements, you see something moving smoothly, not just the other movements, which are just
moving an image up and down. And not just that, but seeing it move on someone else's
screen. And then you have to have server side, which the client is sending information
to the server, and the server is replicating this state to the other clients and yourself.
So this is a small example of the first implementation that I did. That's an hour on the right side
if I move to the left side. So you can see that the two clients see the same thing, and
there's a server also. But it's the first implementation in which it's simple to see
the things are moving around and doing this stuff. And also the map. This map that you
see in the background is something that I built. It's not complex, but it's something
that then allows me to build what that's the real game that I built, which I called Maze
Wars in this case. So now it looks a bit better. It's a screen show I took maybe a month ago,
so now it looks a bit better, but that's the basics. So what is this game about? Basically
when you start the game, not when you start the app, you have to give it a name, and then
you have to start the game, and then other people join, and it could be up to six people
or minimum of two. In this case, it's two people. So when we are two, you are assigned
one of these lines, up to six. So for example, in this case, I say I'm the one on the left.
The end goal of the game is to steal all the other people's life. Everyone has at least
20 lives. When they start, everyone has 20 lives, and the way I steal those lives is
by sending units. Sending units in the bottom right, you see that there's a screen which
some faces, those are the units. When you click those, the units spawn on the top, gray area,
and they have to pass down until they reach another gray area, which they move to the
next line if there's any, or die. And also when they reach the end, they steal a life
from the other player and they give it to you. That's as simple as that. How to prevent
that? You have to place towers. When you place the towers, the idea is to build the maze for
the units to go through the maze while the towers are attacking the units. And that's
all. That's where I did it, because it's really simple. If you nail it down and reduce it
to the basics, it's something which is really simple. If it were a shooter game or something
like that, I would not even start it because that's another stuff. But this is really easy.
So I said, okay, let's build it. And also this is basically if you ever played any kind of tower
defense, which also came from Warcraft mods, this is basically a tower defense, but that you can
build a path instead of having a predefined path that you have to place towers on. So my list of
things, at least at that time, that I said, okay, I need this in order to do the game. I needed
some assets because I need towers, I need the terrain, I need the units and so on. I need to do the
map. So how is the map of the game? That's the thing that you saw before. Also, I need to be able,
well, the code architecture, so how I'm going to architecture the code in order to not have a
mess later on. So how are things going to be organized and how everything is going to communicate
between each other? That's one of the interesting parts for me. Summoning units, so clicking the unit
and summoning on the other side and then passing down, placing towers, described this, and gold
income and lives, that's also easy, and multiplayer servers and the EXUI. So those are the list and
we are going to go through that and potentially the struggles that I had while that. So the assets.
For the assets, I was searching for something free at the time that was giving me the minimum
kind of interesting assets that I needed. In this case, you need units. You can see that there are
here some of the units that I saw before. On the top right, there's a cycle that is called which
one I, so it had units, at least 10, it has, so it's fine. The hard part is to find towers because
normally on these free assets packs, towers are not something that you were going to find because
it's really specific to this game. So what I used is what you can see on the bottom right, which is
like a sculpture of a monk. So that's what I use as one of the towers and there's another sculpture
as a warrior, which is the other tower that I use. The asset pack is much bigger than this. It's
really, really big. It's just an example that they give you as a few things that we have here.
I'm going to drink a bit more of water.
So yeah, then the map. How did I build the map? The map I use
software which is called Tile, which is basically used for that, to build maps and to be something
for your game. Basically what you do is you import your assets on your bottom right. You see that
those are some of the, some of the map assets of the assets that I showed before and then you are
basically using paints. Let's say this way. You click one of the assets and you can place it on one
of the grid. You see that that's a grid. You can place it. You can, and basically once you have one
line, in my case, I can just copy paste it down because those are all the same. So once I did one,
basically it was to build the map for more play-ups, just copying them. But that's the library that I
use. Once I found it, I was like, okay, that's quite easy and it works really well. Then for the
code architecture, when I was building the game, when I started with Lua, the thing about hearing
for actions, sending actions to somewhere and that somewhere is storing those actions and then
the draw is drawing what happened before. It was really, really ringing my bells on some things I
did before. On the bus, when I was working with JavaScript, I was maybe good at that, but I was
in the train type of React when it came out and React and Redux and all that. When that came out,
I was doing JavaScript, so I was really on tune with that. React before it was using Redux, and I
don't know what it's using now, it used to use Flux, which is the library that Google and
more Facebook are implemented. How it works is basically this is an HTML point of view. The view
is the normal HTML that you have. When the user clicks the view, an action is triggered. This
action is passed to a dispatcher, which is basically serializing all the actions in a specific order
in the order they arrive. Then it's dispatching these actions to the stores. The stores are basically
data maps which listen for those actions. It's a big switch case for the actions that you want to
do actions on with the data that you supposedly have. Once you change your data with the action that
happened, then you trigger an even like I changed. Then the view is hearing for those I change. Then
if it Redux, for example, I react, you change the specific part of the view that it belongs to
a data.change. That's how this works. If you change the view and you add the client that I'm doing,
it's the same stuff. The only difference is that the store is not triggering I change,
though the library does. It's not triggering I change because the draw is already being called
every time that the screen is being refreshed. There's no need for any view to hear from any
changes from the store. Basically, I look for the Flux library in Go. There were some
implementations not fully implemented or not working as expected. I just ported the full
implementation of Flux that is on Google, I don't Facebook for it, and I ported it on Go. If any of
you want to do something like this, there's a library now that works for that. What that gave
me also is a state update, which means that when something changed, I also need to notify the server
that something happened if it's needed for the server to know the data. For example, if I place a
tower, then I can send this action to the server. The server has the same architecture, has a
dispatcher, has the stores, and then the server can apply this information. In my case, that's why
I decide every four times per second, the server is getting these stores, the state that it has,
it serializes the state in JSON, and then it sends this state to all the clients. The clients can
see that someone plays a tower because the state is changed. How this is sent with an action,
I'm using WebSocket. It sends an action via WebSocket to get the action on the client and just
creates an action and push it to the dispatcher, and then everything works as expected.
Yeah, that's architecture that I did. Also, one thing that is really cool that I'm not doing now,
but that could be potentially useful is replayability. If you play a game, some games you
can, you have the ability that after you play the game, you can see, okay, what did I do wrong,
and you can just replay the game. I don't know how this is done, but the only way that I have in
mind of working is something like this, because if I have the actions, I can just replay the actions
in the order that happened, and I have replayability, and that's it. So as long as I'm
replaying on the same moment that happened, I can replay anything at any point of time. So, yeah,
if at some point I want to implement that, I just have it kind of for free. I just have to store
the actions on, that's it. Now, the other interesting part, summoning units. So the first
implementation was the easiest one, so just Y++, just go down, straight down, ignore everything
until you reach the bottom, which is when you die, and then you steal the life, and you give it to
the player. That's fine. I did this implementation just to see that everything was working. You click,
you summon, and it goes on. Fine. Now, the next implementation was when I was already placing
towers. So when I had tower placing, if I summon a unit, it just went straight through the towers,
because it didn't know that those should be avoided. So then I implemented Drieska, just because for
me, like, I have to find the shortest path between point A and point B. I'm going to do that. Well,
I didn't know at the time, but Drieska is not the fastest. If it's a big graph, it takes three
seconds to calculate the path of all the graphs using Drieska. So if we go to the beginning,
you can see the cursor moving. Now I click, now it appears. So it's really slow. And it's
something that basically you cannot play with it. It would be impossible, because also it's blocking
the main thread, because it's doing that. So I was chatting with a friend of mine and said,
okay, this is happening. Do you know something? And he said, yeah, you can try Aster. I don't know
if you test it, but Aster is basically a passing algorithm that is an improvement over Drieska
and based for passing for games. Like, well, that looks like something that is for what I want to
do. So maybe you can notice the difference, but yeah, it's a bit faster than Drieska. I'm
spamming, right? I'm just clicking, clicking, clicking. And you can see it's not going slow. It's
not blocking anything. And it's quite good. Ignore the fact that they are going below the
towers. Just follow the lines. Just ignore the assets at this time. So yeah, I did Drieska.
The only thing that it's noticeable, and I think that now that I changed a few things, it was a
mistake that I did. But basically, the ones that go on this side, you see it basically are doing
edge shapes, which is not good for this game because the towers have a range for attack. So
they're basically going attack me, attack me, attack me, attack me, attack me, and they die.
The good thing would be just doing a diagonal. Let me bring my water.
Right.
So for that, I just tweak a bit A star. Because A star, how it works is basically you have a
Drieska, the same one. But the only difference is that you have, how is it called? A priority queue.
It's time that you want to calculate the distance between, if you want to, it's time you want to
jump to a different node to calculate the graph on that, the path on that node. What you do is you
say, okay, from this node to the end, which is the distance. And from that node to the end,
which is the distance. And then you got all the distance. You push this element to a queue
with the node. And then you get an element from the queue, which is the one that eats more,
more closer to the destination. So basically, if it's just a straight line, it will just
calculate go straight because it's always the fastest route to go straight. And that's how A
star works. What I change about A star, and that's basically my potential, and now it works better
in this way. But what I change is that this algorithm to calculate how close it is, I use
Pythagoras because it's just to have xy and xy just make Pythagoras and go straight line the
difference. But the ideal one that it has to use is Manhattan. Manhattan algorithm is basically
how many jumps left and right, left and right, or pixel, pixel, pixel, pixel, pixel,
no diagonals is the distance between those. And with that, it works much better. But what I did
to change it is basically when I'm pushing elements to this sort of queue, this periodic queue,
what I'm changing is that if the node that I'm pushing isn't the same direction that I was,
I just increase a little bit. So I just decrease the priority. So it's most unlikely that he
will go straightforward or the same direction. And it's more likely that he will switch directions,
basically fiber thing to going on diagonals. And just doing that small change, everything when
like perfectly on the diagonals or whatever. And yeah, that's what I should be for. Placing towers.
Placing towers has not much logic itself, just the fact that when it clicks and how to place it on
the line. The only thing that's noticeable is that the tower is not, you cannot place it
anywhere on the line. You can't place it anywhere on the line. But it has like, you could see that
it's basically jumping around. That is not straight. Why is that? Because when you're building the maze,
it's much better to have something straight because for you, it's easier to finish like the
build that you're doing than if something is one pixel below and someone is one pixel above,
because then most likely you will find that you are blocking the units, which is something that
you cannot do. You cannot block the unit. You cannot just build perpendicular lines and say,
that's it. I finished. That's not possible. You cannot block the path of the units.
So that's another topic. How to detect that the path is blocked.
And how to get the path is blocked. Basically what I do is when you try to place a tower and you
do the action of placing towers, I just try to create a new unit that will go through as
theoretical line with that tower in it. If I don't get any path, then it's wrong. You cannot place
a tower. And if I do get a path, then yes, you can place a tower. And that's for placing towers.
Then I have gold and income, which is easy. You get gold by killing units. You get income by
submitting units. And then every 15 seconds, all the income that you get from submitting units,
from all the game, you get it as gold. And the life is basically subtracting life.
The multiplayer server is something that I spoke with the architecture. But basically,
if you are interested in game servers, this post here is really, really, really interesting.
Because it explains you how different games that you may want to build, for example,
shooter games or things like that, how do they supposed to work in a small scale? For example,
shooter games, the thing that was not useful for me, it's like you are shooting on the past,
you are just shooting on the present, because as everything is happening in life,
the idea on the servers that you are on the past, for example, the implementation is
alternative. Basically, the server is the one ruling everything through the client,
sending information. The client has to override with what the server is sending.
But it's also the server have, the client have a bit of predictions. The unit movement is not
sent with the state. It is, but the one that is doing the movement is the client. So the server
is just sending that this was the path and it didn't change and the client is just
continuing with the path that it was before. And also using Flux and using WebSockets for all of that.
UX UI, first, that was the implementation that I have before, which is really awful.
And then I discover a written UI, which is basically bootstrap. I don't know if you heard
of bootstrap for HTML. Well, it's that. You can create, you can say this container, which
it has rows or it has a grid, and then all the content inside of it will be placed in different
things. And you can do input and you can do buttons and so on. So it's really, really simple for
these types of things. Then cross compilation, which was something that has been discussed with
Go Release before. And this was fun because I never compiled with Cgo enable and this requires
Cgo enable. So I managed to cross compile with Cgo enable for Linux, OS X and Windows.
And using Go Release, just changing a few things on the actual code base and I have to open up
a PR to go release to propose those changes because it's just two lines of changing. And you can
cross compile using Xgo. It's not go, it's Xgo, which is a cross compilation tool. And also you
can play on the browser with Wasm and at some point I will try to do it on Android, which is also
possible. And for the future, the only thing that I, well, from the other things I have to do,
the main one is improving the A star because right now it's the bottleneck. It takes 100
milliseconds to create a path. And if George is spamming it, it's awful for everyone to work with
because everything goes as low. And then add more types of units, add more types of towers and much,
much, much more. That's it. I hope it was interesting for everyone.
Thank you. If you have questions, please ask in the hallway because we want to change speakers
quickly and not wasting any more time. Thank you again and amazing work.