 Hey there, my name's Tom Greenway and I'm the game's lead for the Chrome and Web Developer Relations team here at Google. 2020 has been a pretty intense year, I think we all know that. And COVID has forced us to change and reimagine how we approach our lives and our work. Earlier this year, Google and many other companies around the world had to make a difficult decision to cancel the physical presence of our developer conferences. But when Chrome Developer Summit was cancelled, I had an idea. And that idea came from a simple question I asked myself. How can we reimagine the best parts of physical events in the digital world? Well, our solution is adventure, or Chrome Developer Summit adventure to be specific. But I just like to call it adventure. It's a real-time multiplayer web game that reimagines conferences in a post-COVID world. Adventure combines the magic of conferences, like a sense of community and socializing, with the discovery of content and learning. And what better way to engage with users and to drive exploration and discovery than with a game? So in this talk, I'm going to show you how we started with that idea, the prototype I built, and then all of the product and technical decisions and challenges that we tackled from the beginning to the end of this adventure. So let's start with that idea and that original question. How can we reimagine the best parts of physical events in the digital world? So let's focus on the middle part of that. What are the best parts of physical events? You know, this is a subjective topic, but in my personal opinion, I would say first and foremost, it's meeting new people. Of course, at a conference like CDS, it's about meeting other developers, industry folk, or Google is from the Chrome team. And then there's, you know, hallway conversations. It's great to be able to just duck into a private conversation with someone for a business meeting or a catch-up with an old friend. And then there's exploration and learning. It's great when you can enter a conference and you just get to explore everything it has to offer. It's like stepping into a new world and finding demos and content to discover, code labs and product demos, or watching the talks and learning about new announcements and new APIs. And of course, there's the swag as well, right? We can't forget about the swag. Putting pins on your bag or your jacket, accessorizing, it's a ton of fun. And honestly, there's just a lot of other fun that happens at conferences like CDS as well. Fuseball, parties, jazz music. And when you put it all together, a conference is more than the sum of its parts. Hey, wait a second, what is that? On the left-hand side of that top-right image, let's see if we can zoom in on the left. Enhance. Huh. Yes, indeed. It's a dyno costume. It's not a bad idea, actually. Let's come back to that. Anyway, so in reflection, the best parts of a conference, in my opinion, are meeting new people, hallway conversations, exploring a conference, the demos and the content you can discover, and then collecting the swag and having fun. But how did I reimagine all of these ideas from the physical conference in a digital way? Well, you see, I realized that in a way, we've already solved a huge chunk of these problems in the games industry. I mean, all of these things can be achieved in a multiplayer game, right? You know, meeting new people, it's like a multiplayer world. Or having hallway conversations, it's like private chat. Or exploring a conference, it's a bit like exploring a dungeon. And when you walk up to a demo at an event, it's a bit like finding a new stage in a game or stepping into a new world. And then lastly, collecting swag and, you know, collecting pins. I mean, is it really that different to a loot drop in a video game? So let's take a look at my first attempt at combining all of these things. Let's look at the prototype. So I built this in just over a week using the construct game engine and Node.js with web templates on the server. What you see here is a web-based prototype, which gives players a world to explore with just keyboard movement. And that world is effectively an imaginary conference space. There are bots to chat to that give you canned conversation responses when you bump into them. Just like NPCs in a video game. But you can meet other players too, and you can just send text chats freely with them. So you just hit enter and then type whatever you want. And like I said, if you want to interact with anything, you can just walk up to it and bump into it. Computers launch code labs, product demos or documentation pages in a new tab on your computer. And of course, the web is actually the perfect platform for this problem. We can just link out to content from a new direction. And some experiences can even be embedded into the game itself. Just like the lighthouse performance tool here. You know, we built that so we can analyze any web page and it will tell you its performance. And so I leverage the lighthouse API and I call it from the back end of the system. So in this prototype, if you bump into this wizard, he'll ask you for a URL and then he'll start to work his magic. And in the game, you see the results appear above the lighthouse. So everyone experiences it together. And at our physical conferences, we often have experiences just like this that blend the digital with the physical. And what about private conversations? Well, for the prototype, I let users launch straight into Google Meet vehicles through these little tables. Anyone could just jump into a quick chat together if they wanted. Not with a tap or a click, but with a bump. And of course, the prototype wouldn't have been complete without a phishing minigame, right? And what happens when you collect a fish? You get a reward, a fish badge. So in actual fact, this prototype demonstrated that the entire idea was completely achievable. It has everything, a real-time multiplayer, private chat, game world, interactive elements, item collection, and even the humor. So now that I've shown you a prototype, you know, that's just one thing. But going from a prototype to a finished product needs a lot more work. There are many product questions that we need to answer and decisions we need to make along the way. For example, how does this fit in with our traditional digital event strategy? Well, let's take a look at what our digital events normally look like. Well, of course, we have the YouTube livestream, the main talks being broadcast. At the physical event, of course, this is actually a real theory we broadcast from. And we have individual talks as well that can be pre-recorded, all code labs which developers can do at the event or online. And normally at Google, when we run a physical event, we have physical experiences with demo sandboxes. Kind of like that lighthouse example I showed you earlier. But those sandboxes are often a mixture of digital and physical interactions. So that's not really something that's feasible on a traditional website. We also have office hour consults with Googleists and developers that can be scheduled too. So you can see that the web is, like I said, the perfect tool for this problem. In essence, adventure is like a parallel dimension into our conference's content. We can link to all of the same content just from a different direction. And that's really the power and the beauty of the web, right? So it's simple. Adventure will just sit alongside our traditional website and even enable things we lost, like the sandboxes. Okay, but what are the risks of truly open chat? Because let's get realistic here. If we open it to anyone in the world, I think we all know that without good moderation and a bit of vetting, that people can kind of be jerks on the internet. So we made our decision early on that this would be an experiment first and foremost. We decided that we would invite a set of attendees by our regular traditional registration processes for the physical conference. And then we would limit the open chat to only those invited attendees. But we still wanted anyone else in the world to be able to explore the world and listen to those conversations between attendees and Googleists. But that doesn't mean that you have to be completely silent if you're a guest. You can react with emoji to the different conversations between the attendees and to the content of the world itself. It's sort of like a way of putting you in the room where it happened. And normally we can only invite 1,000 people to CBS due to the physical limits of the conference. And this year we'll still invite 1,000 people as attendees. But with the guest feature, we can invite several thousand more to watch. Okay, but how can we also best achieve those hallway conversations I showed you earlier? You know, these sorts of things. Because they happen a lot actually. And what's up with hand gestures? Do they magically make people look more convincing? Anyway, never mind. So we decided to continue exploring that idea. That it should mirror a real conference. In a real conference what happens? You step aside and you step into a private area if you want a private chat. The key to solving this is realizing that since a game world gives us space, that space can mean something. So in the prototype I showed you earlier, I used the concept of a table that could launch a vehicle. But obviously, connecting strangers at a conference via video chat could lead to some not so great situations. So in the end, we embraced the metaphor of the water cooler. Here's how it works. When you stand next to a water cooler, your chat message is instilling transition from being public to private. And only other users standing next to the water cooler can hear you. And by verifying with the server, we can limit the number of people standing next to a water cooler. But I know what you're thinking. Won't people just hold the water cooler? Or actually, we can have a timer on the water cooler that automatically boots users if they stand next to it for more than 10 minutes. It's simple. It's just enough time to have a quick chat and then transition the discussion from, you know, adventure to another platform like Twitter or maybe a video conference. Okay, next. What should we be able to interact with in the game world? Well, for me, the answer to this was pretty simple. Everything we can think of. If you want to encourage exploration, then you should make people feel rewarded for doing it. Books, bots, if you see a plant, you know, all of these things should generate a response if you bump into them. And then the theater entrance and the lighthouse. Of course, if you bump into the book, it should take you to a webpage. If you bump into someone, they should talk to you. If you bump into a plant, something should happen. And the theater entrance, that should take you to the livestream, right? In the lighthouse, we covered it earlier. Okay, but how can we differentiate between attendees, Googlers, and bots? On the left-hand side, we have a Googler with an aura around them. This was our way of differentiating between Googlers and attendees. But what about, you know, the bots? Those NPCs, the non-player-controlled characters from the prototype who responded to users when you bumped into them? Well, we had an idea. What if all the bots who were employed by Google were dressed in the same outfit? And what better outfit than the chrome diner? See, I knew that idea from earlier would come in handy. But if they all looked like this, they would get a bit boring, right? So we decided we could spruce them up. So here you can see some of the swag that players can unlock in the game as well. And we have tons more in the game, actually. And you can unlock different swag for accomplishing different things. Which leads into my next topic. How do we cope with the visual noise? And I'm not talking about the technical back-end scaling, although we will come to that. I'm talking about this, like literally the visual noise. Well, firstly, we decided to limit the rendering of guests on-screen to a maximum of around 20 users. And since the majority of noise is likely to come from those guests, we thought that would be one good step in cutting down the number of users rendered on-screen. And secondly, we designed a kind of micro chat bubble interface. Instead of a chat message taking up a big chunk of space on the screen, we can leverage the fact that chat is sequenced by time and play it word by word. And lastly, we designed the world itself to encourage users to spread out organically. For example, we have distributed spawning locations, and the content in the product rooms themselves are spread out as well. And then there are secrets to discover in different areas. So all of this encourages users to explore. And then we also tied all of that into the item collection, which I talked about a little bit earlier, you know? So if you complete code labs, or if you just find and discover secrets, you'll unlock different swag. So users will be incentivized to explore. Okay, but how can we drive virality in the web game as well? In my Google IOTOR from last year, I actually discussed the power of the URL in web game design. I said that to drive virality, you should leverage the web superpower, the URL. Because there's no other platform that is more viral than the web. When users see a URL, they know what it means. They know that it means you can tap it and be whisked away to something that could be... Well, it could be anything, actually. And yet they completely trust it to tap that link and to jump into something completely unknown. In fact, here's my slide from Google IOTOR on this topic, where I gave examples of game designs you could leverage to integrate with the URL in different ways. For adventure, I leveraged the exploration mechanic. I can share a link that can teleport a friend into the same room as me, and that's exactly what we've done with adventure. But after making all of these decisions, we had to really build the thing, right? And we decided we'd need a full team to finish this adventure. And of course, if you're going to build a game, you're going to want game developers. Well, luckily, I am a game developer. Before Google, I made the award-winning mobile game Duet, a fast-paced, minimalist action game with a mysterious narrative. But I'm just one person. So I collaborated with Setsnail, a game development agency based in Denmark, and they're known for creating the award-winning mobile game Duddy Longwex. So together, Brian, Christopher, Eric, Casper, Morten, Bjark, Rasmus, and I have been working together in the last few months to build the final product. It's not done yet, but we're super proud of the incredible work that Setsnail have done. But before we step into the final result, let's take a look at the work that went on behind the scenes. Let's look at the code, and we're better to start than the backend. Since ultimately this is an experimental new kind of conference, we set ourselves a goal of at most 10,000 users at once across all our user types. Now, you should know I'm recording this talk about eight weeks away from CDS itself. So I hope the technical decisions we've made so far handle that goal effectively, maybe things will have changed. Now, since we knew we'd want WebSockets and we knew exactly how many clients we would be aiming to support, we went with Compute Engine for the servers. It doesn't autoscale, but it does support WebSockets, which is important. And to keep things simple for deployment, we used Docker. And for the application stack, we went with Node.js. We knew we'd want to share game logic between the server and the client, so Node.js was perfect, as maybe we could write TypeScript that could be shared on both sides. And to scale the backend with our Sockets, we went with Redis as a messaging backend. And we're experimenting with using memory store on Google Cloud for this. And to simplify our WebSocket logic and management, we used Socket.io. And finally, all our user data is stored in Firestore, the database system of Firebase, for stuff like avatars and profile information and that kind of thing. But how do all these parts fit together? Well, it starts with our client connecting to a login server, which is also rendered Node.js. The login server connects to Firebase for authentication and also acts as a load balancer for our game servers on the right. And we authenticate with the Google account, and we went with this to keep things simple, but Firebase Auth can support other kinds of federated authentication options, like Facebook, Twitter, or even phone numbers and email logins. And after that, the login server then picks a Node. And the client establishes a direct connection to that Node. And all game logic actions and game state updates fly across that socket connection. And the nodes synchronize with each other by memory store and, of course, Firestore with the long term data. Okay, but what about the front end? For our game client, we knew we wanted a renderer that could handle crisp art with skeletal animations and hopefully 60 frames per second. And we need great flexible UI and a solid authentication system. So we went with Pixi for the graphics renderer. It's a widely used renderer for web games that supports WebGL. And for all of our UI, we went with React because, after all, this is the web, right? HTML and CSS are very expressive and already very capable. We don't need to reinvent the wheel and by using the web, we have better serve for accessibility as well. And we actually picked React because the engineering team are already familiar with it. And also, we plan to test preact as well. And finally, for the authentication, I mentioned this earlier, but we dropped in Firebase. Okay, let's jump into a few of the interesting technical challenges we encountered so far in the project. First, how do we optimize the bandwidth as in the bandwidth of the WebSocket? Well, let's take a look at a representation of a user. These are the basic properties that are visible here. Now, when parts of this data change between the server and the client, we want to obviously synchronize this data. But if we send all of the data, that's wasteful. So a very simple strategy is to just send the delta, right? But can we compress this further? Obviously, this will be compressed with text compression. But maybe we can design our code to compress this amount of data even further because we know something about the way the game works. And maybe we can strip away unnecessary data. What if we used integers to communicate which fields are being updated instead of the key values, and some fields could be updated implicitly based on their order and their position? If we delimit with just commas and then assume the order as the first token, the zero integer, implicitly indicates the type. For example, here, zero is for update. And then the second token, 24601, implicitly is the player ID. Then all the tokens after that can be treated as pairs. So for example, the third and the fourth token represent the key and the value it's updating. So two, being the second field in the user data, which was the y value, is being updated to one, which is communicated in the fourth token. And then you can see the same pattern applies for the fifth and the sixth tokens. So the field or the key to update and then the value. Here in this case, it's changing the player's name. So how much of a saving is this? Well, that's actually 113 bytes versus 29 bytes, a saving of 75% in the data transfer. And this is an interesting note here. It's a standard practice in the game's industry that when you know exactly how your game works and you know exactly you have complete control over the networking design, you can really optimize your network design and the data that you're sending will work for that particular game. But an interesting element is that we haven't actually deployed this optimization yet because like I said, we're still two months out from the event. It's possible then in practice, while we reduce the bandwidth, the CPU complexity will increase too much to support this in a while, because this is effectively a trade-off between bandwidth and CPU. Okay, but what about rendering bottlenecks, you know, in the client itself? This might be a surprise, but Pixi doesn't actually have a built-in concept to implement client-side calling. In other words, we don't want to render an image that's outside of the current camera viewport. This isn't a complicated step to take and it's also the kind of thing you want to optimize based on your game design and the way the rendering works in your game. For example, the strategy could be different if you had a wide variety of different sprites in your world, or if some of your sprites were going to repeat many times. So in our case, we combine the implementation of this with another optimization which I'll come back to. Now, another plugin we use is Pixi Layers. So if you think about it, in the game, we are dynamically sorting based on the Y position of the objects, as in we're dynamically sorting the Z index. Because the camera perspective is not bird's eye, it has a tilt to it. So that means that I can actually walk behind the lighthouse or in front of it. So we need to constantly adjust the sorting of objects for that Z index. And normally in Pixi, when you change the Z value, behind the scenes, it's actually reordering an array of elements. So the thing is, is that with Pixi Layer, with this plugin, we actually don't need to do those array manipulations. And it's more performant. Now, another is Cache as Bitmap. This is an option you can activate on a container to automatically cache all of the sprites beneath it into a single bitmap, which can improve the performance of objects made from the combinations of sprites. Our game characters are skeletal based and assembled from different textures. So we can cache all the textures into a bitmap to improve the rendering performance. Next is Sprite Atlas sorting. We have multiple sprite sheets in the project and naturally there's a mixture of foreground and background elements that we split apart. Asking the renderer to regularly switch between sprite sheets has an overhead. So having a sprite sheet for all of the background images and one for all of the foreground images and then another one for everything that's in between, it's a very good idea. Lastly is Object Pooling, which circles back to the client's side culling as I mentioned at the beginning. As users walk around and sprites pop in and out of the viewport, we don't want to destroy and create new objects in JavaScript as that can be expensive to save on the construction and destruction costs. And lastly, well I don't know what the next optimization will be actually. We're still eight weeks out from the event as I mentioned, so there's probably going to be other stuff we need to solve as we go. We just don't know what they are yet. So what does the game look like so far? Well here's just a glimpse of adventure at the moment. You are in items to discover and all the content is coming together slowly. But the best way to really discover it is to go and explore the adventure yourself. The game is playable on the web during the conference and we're keeping it going for an extra week afterwards. But if you're going to be watching this video after that, you can download the source on GitHub and just run it locally. So now that you've joined me on this adventure and you've seen the power of what happens when you let games intersect with the web, I'd like to give you an adventure of your own. If you're a web developer or a game developer or both, I challenge you to think of what else can the web and game design unlock for us? Because I believe that the web is the best platform for experimentation, for rapid deployment and prototyping. And I think adventure really highlights what is so great about the web. So honestly, don't be afraid to try experimenting in these crazy times we're living in. Because even if things don't go perfectly, even if you make a mess, you know, you might create something fun along the way and that's what really counts. Okay, so how can you get started on hacking in this area? Well, I want to give a quick shout out to Oryx Design Lab. You know, I used their sprite sheets for the original prototype and it saved me a lot of time, so definitely check them out. And of course, what did I build that original prototype with? I mentioned it earlier, but it was construct3, an amazing web-based game engine and editor from CIRA, and I highly recommend it for rapid prototyping. It explores the progressive web apps and cloud platforms like iPhone and Android as well through the Cordova library. And if all goes according to plan, then the game engine and the source code for it, the adventure server and the client, should now be available on GitHub at the link below. If you want to, you can run the adventure experience locally on your machine and the map definition is included in the source as well. But if you're curious about the tools we use to sculpt the game world and to organize the data, we use the editing tools I developed many years ago when I worked on games independently. It's GainKuma, Kuma being the Japanese word for cloud, so GainCloud if you will. It's a general purpose game editor that exports to a generic data description format for games. So thanks so much. If you want to follow me on Twitter, it's TCMG and I hope that I meet you in CDS Adventure as well and that we run into each other.