 Okay, hello peeps, I am Pratik Bhatnagar and I am a UX engineer at Google. I work with Workbox team and I contribute here and there with the PXCLI and other components of React and today I am here to talk about progressive web apps but I just, I am pretty sure you must have heard better talks than mine about progressive web apps, read better blogs, better tweets, better tweet threads and everything. So I am just going to change this to progressive web games instead. Now before we start, let us just have a look at the imaginary arcade gaming timeline or this is how it looks inside my head. So we started with Atari then we moved on to 8 bit era where there was Mario, Contra and loads of loads, other fantastic games. After that came Sega, one of the biggest game manufacturers in the 16 bit era and then we finally moved on to super complex graphics cards, consoles, platforms, PS4s, Xbox, Nintendo's and way many. So this was the time we had game engines, super complex physics engines, collisions, lightning, shaders, custom hardware being made for games like Counter-Strike and after all of this, like all of this brilliant advancements this is what made into our daily lives and into our pockets. Games with taps, with swipes, these all are really huge games and no offenses. The games on console species are still a huge hit and hit me up for if somebody interested in a Counter-Strike match or two after this talk. But this has become a huge contributor to daily gaming era. So some of these are like candy crush where you swap and match the similar looking objects, 4px 1 words which are like you are given 4 images and then few letters at the bottom as buttons, you tap and try to guess the word, then is color switch you again, you do nothing, you just tap and try to make your ball move inside the ring with the matching color and the fourth is the hop where you just simply have to swipe left or right and to keep the bouncing ball on the platform. All of this attributes to one thing the rise of mobile into the computing industry. So like games like these were possible with mobile web for a very very long time but so why did industry and why did companies actually chose native apps instead of doing it on mobile web? Some of these reasons are like app icons, your browser like imagine yourself sitting in your bed in midnight and then if your board you open your phone will you like go to a browser remember a URL type that URL wait for that game to load and then start playing or instead just open your phone whatever icon looks really nice to you go to that game, go to that social network instead. Next up is notifications just before PWA service workers and all of this came into play. Notifications was a far fetched dream for web. So games could not or game developers could not reach back to it's reach back to its users and tell the users that hey come back play it's been really long or we have missed you. Third up is full screen experience. Games inside mobile web were like inside a browser with a URL bar with a button with notifications on top and what not everything to distract you apart from the game. So native apps had full screen experiences from day one. Next up is in app purchases you are trying to buy a power you are trying to buy a character or skin or anything add on for your game and you are redirected to payment app website where you have to type your password in a really really small text. Nobody would want to do that in middle like when you are bored and on top of it you want to do that. So for this comes the payments API the web payments API where you can do it do all of this in just a few tabs and no small fonts or typing passwords. Next up is 60 FPS all know this that web can get tricky with 60 FPS animation. So luckily for us I am talking about progressive games and I will be doing all of this with canvas web GL and open GL. So a lot of it becomes way more easier than doing this with DOM. So combine all of this luckily when service worker came into play when manifest.json came into play and when we started doing progressive apps all of this are now solved for us. App icons add a manifest user will be able to add your app add your game on to its home screen just like any other native app. Next notifications service workers easy tons of code samples out there add your push notification capability to your website. Full screen experiences one single key in your manifest.json and whenever the user opens it from the home screen opens up in full screen. No browser UI no notifications bar no native buttons back home nothing. Next in app purchase as I said the web payments API helps us there and 60 FPS is what we will talk through the rest of the rest of this talk. This like enough of the talking this is the game this is this is the URL where there is the native game out there and we will try to replicate building this one along on the stock. So I will tell you just of this game you as soon as you do touches finger on the screen the ball starts bouncing you have to swipe left or swipe left swipe right and keep try to keep the ball on these jumping platforms. The speed increases as you proceed in the game and it becomes difficult. No nothing fancy nothing complex just simple this stuff. Okay and with any other and like any other app or web app we need tools and I am choosing babylon.js as my game engine Canon.js as my physics engine preact with preact CLI as my for everything that is DOM related and Firebase for authenticating users and hosting this particular thing. You might have a thing in your head that this all of this combined is a huge huge payload like these might not occur as a very wise choice on in your first look. So that is what I hope that you take away from this website. We are going to build super quick and super fast progressive game using all of this. So we will get started. This is the welcome screen for a user nothing just one image two buttons I am using preact and preact material components I included them and made my DOM. Three DOM elements nothing fancy and since there is no code there is nothing fancy in here our interactivity time looks fine it is approximately 1.1600 ms which is on a regular 3g and 10x load on CPU. This is here because obviously we haven't added any code. We haven't added any payload. Next come authenticating about authenticating our users. I will use Firebase for it. So Firebase makes it really easy to authenticate your users with SMS with email with Facebook or whatever over type you want and do a bunch of other things for you also makes it really easy for you to send push notifications other things. Here what I am trying to do is just import Firebase app which is the core file for any Firebase application and the Firebase auth module. I am not using the database or the notifications or any other module just the auth module and mind it I just imported it. I haven't used it, haven't written any code around it. This is our timeline pushes my time to interactivity one second ahead. Now does this make Firebase bad? No because it's a really really useful tool and since we are using it up front and since like it's a game and I have to like show the user an option to login here itself that is why I started using it but we need to fix this. I cannot push my time to interactivity one second even further and this is on a metered network that is I have throttled my network to a regular 3G this can go even bad than this. So I need really need to fix this. This is how I did it. I built a utility function which returned a promise. Next this promise calls the require.ensure of webpacks since I am using the XLA it comes already baked with webpack and it's utility functions. So I call require.ensure which brings Firebase and Firebase auth at a later point of time. Now this require.ensure if you would have used it already takes a callback. So this callback is called when these whatever files you mentioned in the array are downloaded. This callback resolves the first promise with a new function. I am using a closure here. So this function will know of whatever is there outside the scope of this. This function whenever is called actually starts using this using the two files that is Firebase and the Firebase auth. Why I did this? I wanted to download this file as soon as possible like as soon as the game started downloading but I did not want it to do all the parsing. I did not want the parser to pass through all of this file without even if user want to continue as guess I do not want to waste time passing these files. So now exactly when user will click after these files are downloaded we will enable the login with Google button and when user clicks this only then I will call this return function and the parser will pass this thing and do the rest of the code. This is how somewhat the code looks like require.ensure app and auth resolve it this particular returns a new function which resolves the promise and this promise I can use this yeah. This function when it is called when the user clicks on the login with Google and then it is passed and then it is done later on. After this we gain 800 ms of what we lost back in our hands. I still download those files but I never use them so parser do not really pass these JavaScript files and I gain all that time which was being used to pass these things. So now a user can come in he will still get 1600 or 1600 50 ms of time to interactivity but now we can choose not to go through all of this pain and continuous guest and these files will never be passed all together. Now lot of performance talk already did. Now let us see how we start actually building a game after you are done authenticating a user with continuous guest in a dialogue or with the Google. You redirect him to a new route using whatever you want and here on this route we put a simple canvas element canvas element position absolute top left bottom right 0 with 100% height 100% so it takes up the entire space. Now this is your entire stage where we will build this entire game. So much like any other JavaScript module or node module babylon.js also comes with ESX imports and everything. So we will import an engine a scene a light and a camera. We will initiate the engine giving the canvas object just new engine and the canvas object and then we will initiate the scene giving it the engine. So new scene no rocket science just instantiating new objects and then comes an engine render loop. This tells whenever this function is called you need to call scene dot render to continuously re-render your game scene. This will give you a black screen nothing like there is no background color to this canvas it is the babylon.js which has rendered a black screen because there are no lights and just a simple canvas. Next we will add lights. We will add lights to our game we will do a new hemispheric light there are multiple kinds of light point light hemispheric light and other and other stuff which you can go ahead and read what exactly are the use cases of this hemispheric light is like a tube light in the room which evenly spreads on your entire stage. So we will do a new hemispheric light name of the light and a vector where it will be placed where the source of the light will be placed and the scene to which it will be attached. So this dot scene and the intensity of the light. So you can alter this intensity and it will reflect on your objects accordingly. Also we will attach a camera. So camera is what comes and define the viewport of your player that becomes like the eyes of your player where he is standing and where he will be looking at the game from. So again very simple new free camera again a vector where initially the camera is placed and the set target where the camera is looking at. So this is like you are standing at x and looking towards y. This is all an empty room you can imagine right now where you have been just kept at one place and you are looking at another one. There is one line that I have written camera attach inputs dot attach dot mouse as detach control. For my game there is no way where the user can move its viewport or mu look here and there. If you do not do this by default with mouse or with the WASD keys the user can look left right top and bottom since it is a free camera ok. Now we will start adding objects to this particular stage. We will add one platform and ball on top of it and some more platforms and then we will start beginning the you know start the animations and everything. So this is how you add a simple box or a simple platform in babylonjs. You do a mash builder dot create create box you give the name of the box and its size and its height. So this is like babylonjs has its own matrix system. So you might take some time to get used to it it does not really work in pixels its it has its own matrix system. So to on this device might give you a suffice size of your platform. After this we give it a material there are standard material there are reflective materials which will give you a reflection kind of thing and there are there is a water material and more materials like this. So I use standard material give it a color and give it a position. So on X you stand on 0 and on Z you stand on minus 16. So have a we are having a simple box in our room floating on X 0 and towards us since the Z is 6 minus 16. Next up we will put this logic inside a loop and we will build 10 of such 10 of such platforms. So this is like new create new box and we will randomize the X position of it. So that user has the difficulty of swiping left and right and then he has platforms at different places to make the ball jump at and then we will keep incrementing the Z position since we are incrementing the Z position by 8 yes. So the first one is here second one is here third one is here and so goes on into that empty space. So this was all about adding platforms now we are adding a ball. Since we know where we place it is a static thing with this game where we placed our first platform we will create similarly a sphere. So this is how you create a sphere mash builder dot create box was to create a platform or a box mash builder dot create sphere is how you create a sphere out of it. You give it a diameter you give it a scene and it starts rendering a gray or a black ball in your scene depending on your lighting source. Now using the position attribute I again just place this ball exactly in the center of the exactly on the center of the first box. Any anything confusing so far this is like all simple new instantiating new objects and placing them at X or Y just imagine this like placing your DOM at certain positions. Now we need to add texture first is the way babylon.js includes a texture is like you give it the file path and the object which to apply the texture then it will imply like include the file try to download the file and then apply it to the object. What this can do is imagine you have already presented the scene to the user and now babylon.js is taking time to download this particular image or the basketball image that we are using here as a texture. So your user sees like an unstyled sphere in your in your game. This is an equivalent of flash of unstyled content in your daily use apps. So what we did we first download before this game will actually start will first download this image create a canvas of image height and image width what we downloaded never added this canvas to DOM though then we draw then we will draw that image on this canvas and then extract the base 64 string out of it. So with this base 64 string babylon.js gives us separate function to create a texture from base 64 string. So we will give this base 64 string to this function and it will give us in return a texture which we will apply to this particular sphere. So this will give us what we are seeing on the right hand side a green box or 10 green boxes and a sphere sitting on top of it with a particular texture. Now like any other game will need animations to support a game. The first series of animation that we will add is as soon as game opens our platforms will fall down and from opacity 0 to opacity 1 and from a particular height to height 0. There are two kind of animations first is the keyframe animation that we will be doing here. So keyframe animation you say that these are n number of keyframes and these are the stop points. So we will use and for start and end keyframe only. So at frame 0 opacity animation the value of opacity will be 0 and at frame 20th it will become 1. The next one is the dropping animation which is like at frame 0 it will be at height 3 but by frame 20 it would have fallen at height 0. Combine both this is how it will look. But these are just keyframes declared we have not attached to which property will it be applied to to which object will it be applied to. This exactly is how you do it. You instantiate a new animation give it a property name. So like you would want to alter position dot y or opacity with this frame rate with which you would want this animation to run animation type. So this can be float animation or geometry animation where it will be it will be doing matrix kind of matrix manipulations for your animations or color animation since color is a 4 value or a 3 value animation. So that you can choose from here and the type of loop. So will it be a constant loop will it be looping forever. So since we wanted to play just once I have done constant. Next is we add keys to this particular animation the keys that we declared in the previous slide that is from frame 0 it is at height 3 and frame 20 it is height 0. And then to the object we do animations dot push this animation from which frame number to which frame number and will it be will it be appendable. So this appended to box will provide a falling a falling animations you will need to do a say similar kind of code for opacity as well and just do a box dot animation dot push opacity animation as well. So both of them will play together and it will look somewhat what it is looking on the right hand side. Now comes the scary part physics with every game comes in collisions with every game comes in game engine impulse mass restitute and every other kind of horrifying term that you would have heard in your university or your high school if you are afraid of physics. So imagine like implementing all of this by hand this is just too much work to do but this is how JavaScript community works right you throw a problem to it and then npm will shout here are 64 solutions to it. So thanks to JavaScript community nothing is really scary for us there are physics engine which takes care for all of this okay let us now see the code how you add physics again there is no rocket science again just like your load ash or any other kind of dependency just import it babylon.js somehow I am not sure if I am completed right here but expects physics engines to be at windows scope please correct me if I am wrong I was not able really I was not able to scope this to anything other than window. So I did a window dot cannon to cannon cannon is our physics.js physics engine which implements methods for collision how gravity will work how mass will work in with your objects this and this is how you enable physics in your scene. So you have to do scene dot collisions enable true. So now it will your scene will start detecting collisions between objects to which you tell it to do and then enable physics this will start enable normal physics stuff like gravity and all two objects. So one thing to see here is worker collisions true what will do is all your collision computation which is a lot if there are two objects colliding so there is a lot of computation to be done it will refer it to a different web worker all together you do not have to write the web worker babylon.js automatically downloads a web worker for you and does the computation here you just have to do this one line next is you have to add physics imposter. So babylon.js objects in the on the stage them itself cannot do anything related to physics. So there are physics imposters from cannon.js you add there is like a box imposter for box likes objects for a sphere of imposter a cone imposter and a mesh imposter not like the other three which would make sense from their name box space sticks to any shape object. So it is like the most complex imposter and such complex cases you use mesh imposter. So you instantiate a new physics imposter and tell it okay it is a sphere imposter to which object will it does will it check the physics everything and give the mass in restitution. So restitution is if two objects collide how much energy will they still have after the collision. So if you do zero they will just collide and stick to each other if you do one there will be no energy loss and whatever velocity they were colliding with each other it will be just opposite in the opposite direction. So we are not really exact doing a lot of impulse and thing and we will be manually checking for collisions. So I have kept mass and restitution as zero next thing you have to tell the objects that you have to check collisions for you like you should not do all objects colliding with each other and checking with each other because that will be like way too much work. So I am just doing it for I am doing it for the ball and for all the platforms next is the same it is a very similar kind of experience for for the box as well new physics imposter this time the box imposter and to which it is has to be attached box and you have to do the box dot checks check collision dot is equals to two as well next the event listener now our stage is set but nothing is happening there are there is physics enabled but nothing is happening because we have not really started started the game itself. So we will do two DOM listeners one is the touchdowns as soon as the person touchdown I will save it as a reference point and next is the touch move. So when he moves his finger I will use that reference point and check the delta and try to convert it to a babylon js matrix system. This is how our game is going to work ball is at the starting position within 15 frames it rises to hide 5 and with after 30 frames it will fall down to hide 0 this is how a ball will look like it is bouncing in parallel to this I will also adjust the Z position to it while our ball reaches towards 0 again we will check if the ball dot position dot y is less than 0.5 which is like it is somewhere near to the next box and if it is colliding with the next box or not so this is like 10 boxes in an array so I will always check if it is colliding with the box at the index one or not if it is not at this point of time we will let it freely fall to height of minus 20 this is how it will look that the ball will jump and it has fallen down to great height and the player has lost if this thing if this check does not passes if this check passes I will pause the particular animation so that it does not fall below and I will restart the animation with the new Z index values that is from index one box to index two box this is the total animation of 45 frames and this is how it looks inside the code we will check position dot y is less than 5 or not we will check if it intersects with a new mash with which is the box at index one if it if it does we will add we will call the score call back update this course somewhere here and then start a fresh animation next is animation events animation events and babylon is like if this particular frame has played or not so what I have declared is at 40th frame play this animation event and whatever call this finish callback so this finish callback will tell so it was a 45 frame animation and at 30th frame it should have collided with the next box if it has not if 40th frame has actually reached this means that the ball has fallen down and we will tell the user that you have lost so this is how our anime animation events will work to any animation we will just need to do animation name dot add event and this last event so if this animation plays up till the specified frame number then this event will be called now all of this wiring up will give you the game that we saw but here are some few bonus steps a your stage will never be scrollable scroll plus heavy animation does not really go well hand in hand next avoid the mash imposter as I said it is too much computation and it might hurt your frame rate at mobile browsers at this point of time second differ your collisions to web workers that we have like already discussed now progressive web mapping like the whole talk was progressive web games I told you how to build a game but the progressive web thing is still missing at this point of time if you try to trace your trace your game there is a huge six second gap on your on your timeline like user is literally sitting there and waiting for game engine to download your logic to download your assets to sound textures whatever this is bad let's fix this I'll put a prefetch link real prefetch tag into the header so as soon as the user lands on the login screen with the lowest for this prefetch tag starts downloading your game engine and your game logic with the lowest possible priority so that whatever work user is trying to do he keeps on doing that but your game engine is also started to has also started to download in lowest possible lowest priority checking after this now this difference I'm not sure if it's visible but this difference is only two and a half seconds you might say that we optimize for nine eight hundred ms in the beginning of this talk but now we are letting go for two and a half seconds there's a difference in that eight hundred seconds your app was not initialized you could not have shown anything on the screen here you could show a loading screen just like any other gaming device shows this this technique is used even with even by consoles today so you can do a loading screen here you can do a you can do a linear progress bar or a spinner or anything that you want to do here your app is actually initialized you do not need to leave this blank now comes the service worker part much like native apps what they do is they pre-cache everything they install all the things related to your app at first and then give you the app to interact with so let's just be web what we will do is we will install a service worker with minimum possible pre-caching just whatever it is needed to bring our app in offline state and then we'll install runtime caching strategies so what we'll do is when the user will actually starts playing it will then intersect the outgoing request and whatever response comes in then gets cached so our service workers are not really waiting for everything to download rather it's just sitting there with an empty cache and whenever the actual outgoing HTTP request happens it intersects that and then puts it into the cache how do you use services so all of you must have seen multiple service worker talks and other things but since I'm using pre-xcli this becomes super simple there's a file called pre-xcconfig.js and you have to use a pre-xcli hw pre-cache plugin I cannot really seem to remember that although I made it but yeah so there you just have to give this particular setting in a JSON object and it will intersect all outgoing sound and texture file request and whatever response comes in gets stored into the local cache and enabling us enabling our players our users to play this offline from second time last thing do not forget to add a display full screen this one single key gives you a full screen playing capability to your game whenever it's added to home screen and all of this is built and I'll be showing you the small Jeff or a video from it and and the URL but some of and the code is also open source so please feel free to go ahead and contribute to it here are some ideas what you can do while we saw in losing event on that we can capture the entire canvas and maybe share it with friends the high score and how we lost next is challenge our friends with push notifications or even use the point system that is already baked into the game right now to load more and more textures later on that's all I had for today I've been Pratik you have been a great audience thank you we have some time for questions questions I see there the balcony so can you please explain like why using babylon and is better or worse than unity or Unreal Engine because they also provide these capabilities of developing games for across platforms right so I mean is the physics engine really faster than those or they provide some something better honestly I do not really have the benchmark numbers right now but unity and I guess the Unreal Engine uses the WASM as of today to export the game and this is all what I built with JS simple plain JS I guess for unity and unreal you need to go and code in their system with whatever they're in their ecosystem at whatever they give you I'm not really sure if you can just use your JavaScript skills to build a game there so that was the reason I tried looking at unity itself but I wasn't really sure with the entire coding ecosystem and I wasn't very comfortable with it okay somebody has started playing this game okay uh yeah and this is all plain JS question here yeah hey yeah one like can you hold yeah so I saw some like I played some games on Facebook messenger HTML games and they were really they had great graphics and they had like real a native experience on a phone or on a desktop on a phone okay on a phone so you know something about that one and two like like this progressive web game you see that becoming a big market going in future or something on those lines uh so I am not very sure about so his question is there are games on Facebook messenger if what goes on behind the scenes are there am I am I right yeah so I'm not really uh 100% sure about it but heard that it uses some portions of react native as well to you know uh on-flight deploy them and b if progressive web games are becoming a thing so there's this website outweb.io which lists uh good amount of progressive web apps and it has a section which of games you can go and check out the games this was just my trial to bringing this thing in spotlight that we can start making similar kind of game experiences that native games uh provide today 2048 is one of the best game experiences even though I don't know if it gives uh if it uses service worker but it was the first one to come out with abcash and give offline experiences but yeah that was one of the very first and awesome games that I played on there question there um so I've been looking at the documentation and I'm unable to find some like real world examples of like I see this as being one of the examples but I can't find other projects which I really like to have an example to start with right all I see is this playground of babylon js but if I save the file it's just like one html file and they're like tiny examples so yeah so that like you're using esx and all of that right yeah but even as even the npm project doesn't have how to use it as an npm project okay I can take that as a feedback maybe we can start something on uh because yes so babylon js has a playground uh kind of it kind of a repel that uh babyl and other even facebook native gives uh sorry react native gives uh so it has similar kind of thing but not really an end to end documented process on how to use it but uh honestly if you use it from npm it's just like any other npm module just import whatever you need it from baby from babylon and or maybe import star from babylon and just start using it so I tried to build a similar application uh pwa in android marshmallow so I faced the challenge saying it was kind of not working in lollipop and below android versions also there was some problem with redmi custom UI so I was trying to kind of uh uh use different sensors like accelerometer and uh the gyroscope but the sense was not working I was not getting any value so is there any challenge with respect to interaction with your voice and uh so the thing with web apps is that browsers encapsulate a lot of your interactions with sensors interaction with uh as gestures you do so it shouldn't be a direct challenge to os but more of a browser version that we can check if it's not working in I'd be like more than happy to take it back to you handle uh so app icons and iOS still is with uh apple icon manifest and the link tagged with it the manifest does not really work however uh you just have to still give them the same link rail tags to give the icon of the particular web page the display full screen will not work this might this will definitely not work in an uh offline scenario but yeah it's playable still it's still it's playable you just go to this particular or you add it to your home screen whenever you open if you have a network sadly as of now it does what's up offline uh so if you have a network you will be able to play just the way android users play hello yeah hi what about the performance implication when you you know close the application or put it on standby because the animation frame will still be running in the background right so pardon uh what about the performance implications when you you know like close the application not close it completely get a move to another application stuff like that will the animation cycles be running in the background uh mostly as far as I know babylon js has a mode to switch it to request any animation frame so if in that case you switch to other application or you just press home screen request animation frame will not fire anymore and then that will just your game will just be paused and even if it's just a note there even if it's not supported in the uh render loop uh where we uh where we wrote uh scene dot render i'll just quickly this one just wrap this scene dot render inside a request animation frame and you should be good to go since request animation oh it's definitely performance babylon js just happened to be a little more helpful in case of games whereas 3js is a very generic thing for any kind of uh 3d animation I literally build we are animation we are applications with it uh in 3js on a mobile web uh and browser so it works fine it is performance though you might need to do some tweaks here and there but just babylon happens to be a little more friendly for game thank you